Hi everyone! I wanted to share a cool automation I recently built using the Aqara Camera G5, Home Assistant, and a bit of AI magi* to help me remember to take out the trash and recycling,without any manual effort.
Every hour, Home Assistant checks if we are within ±12 hours of a scheduled trash or recycling pickup (based on calendar events). If we are, and the corresponding bin hasn’t been marked as “already at the curb,” then the system triggers a snapshot from the G5 camera, pointed at my driveway.
This snapshot is then analyzed by AI (via the google_generative_ai_conversation
integration). The AI is asked a very specific question:
“Is the black (trash) or blue (recycling) bin closer to the street than to the house?”
If the AI says true, that means the bin is already at the curb, and an input_boolean
is turned on to reflect that. If the AI says false, then Home Assistant sends me a notification to remind me to take the bin out.
This runs automatically and quietly in the background, with zero false positives once the bin is detected.
If the bin is already out, no unnecessary notifications are sent.
It works independently for both trash and recycling, based on my calendar.
This has been incredibly helpful for keeping up with pickup days; especially when life gets busy and routines change. It’s a great example of how Aqara’s devices can work beautifully with Home Assistant and modern AI tools to solve small everyday problems in a smart way.
alias: AI – Trash & Recycling at the Curb
description: >
Every hour, if we're within ±12 hours of a 'trash' or 'recycling' event AND the corresponding boolean is OFF,
a photo is taken, AI is queried, and the boolean is updated accordingly, with a notification sent.
trigger:
- minutes: "59"
trigger: time_pattern
condition:
- condition: state
entity_id: input_boolean.automatisation_poubelle_recyclage
state: "on"
action:
- if:
- condition: and
conditions:
- condition: template
value_template: >-
{% set start = as_timestamp(state_attr('calendar.poubelle','start_time')) %}
{% set now_ts = now().timestamp() %}
{{ start is not none and now_ts >= start - 43200 and now_ts <= start + 43200 }}
- condition: state
entity_id: input_boolean.tg_poubelle_recyclage_poubelle_au_chemin
state: "off"
then:
- target:
entity_id: camera.aq_cam_stationnement
data:
filename: www/stationnement_snapshot.jpg
action: camera.snapshot
- data:
filenames:
- www/stationnement_snapshot.jpg
prompt: >-
Examine only this image. The street is at the top and the house is at the bottom.
If the **black** trash bin is closer to the street than to the house, respond strictly true.
Otherwise, respond strictly false. Only reply with true or false, in lowercase, with no quotes or line breaks.
response_variable: ia_response
action: google_generative_ai_conversation.generate_content
- if:
- condition: template
value_template: |
{{ ia_response.text.strip().lower() == 'true' }}
then:
- target:
entity_id: input_boolean.tg_poubelle_recyclage_poubelle_au_chemin
action: input_boolean.turn_on
- data:
title: AI – Trash Pickup
message: >
The **black** bin has been detected at the curb →
input_boolean.tg_poubelle_recyclage_poubelle_au_chemin **turned on**.
action: notify.persistent_notification
else:
- data:
title: AI – Trash Pickup
message: The **black** bin is not at the curb.
action: notify.persistent_notification
- if:
- condition: and
conditions:
- condition: template
value_template: >-
{% set start = as_timestamp(state_attr('calendar.recyclage','start_time')) %}
{% set now_ts = now().timestamp() %}
{{ start is not none and now_ts >= start - 43200 and now_ts <= start + 43200 }}
- condition: state
entity_id: input_boolean.tg_poubelle_recyclage_recyclage_au_chemin
state: "off"
then:
- target:
entity_id: camera.aq_cam_stationnement
data:
filename: www/stationnement_snapshot.jpg
action: camera.snapshot
- data:
filenames:
- www/stationnement_snapshot.jpg
prompt: >-
Examine only this image. The street is at the top and the house is at the bottom.
If the **blue** recycling bin is closer to the street than to the house, respond strictly true.
Otherwise, respond strictly false. Only reply with true or false, in lowercase, with no quotes or line breaks.
response_variable: ia_response
action: google_generative_ai_conversation.generate_content
- if:
- condition: template
value_template: |
{{ ia_response.text.strip().lower() == 'true' }}
then:
- target:
entity_id: input_boolean.tg_poubelle_recyclage_recyclage_au_chemin
action: input_boolean.turn_on
- data:
title: AI – Recycling Pickup
message: >
The **blue** bin has been detected at the curb →
input_boolean.tg_poubelle_recyclage_recyclage_au_chemin **turned on**.
action: notify.persistent_notification
else:
- data:
title: AI – Recycling Pickup
message: >
The **blue** bin is not at the curb →
input_boolean.tg_poubelle_recyclage_recyclage_au_chemin **remains off**.
action: notify.persistent_notification
mode: single