You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
281 lines
11 KiB
281 lines
11 KiB
######################################################################
|
|
# @CCOSTAN - Follow Me on X
|
|
# For more info visit https://www.vcloudinfo.com/click-here
|
|
# Original Repo : https://github.com/CCOSTAN/Home-AssistantConfig
|
|
# -------------------------------------------------------------------
|
|
# LLM Vision - garage cans and front-door package checks
|
|
# Trigger with input_button.llmvision_garbage_check, input_button.llmvision_front_door_package_check, or front door person activity to update vision-backed package sensors.
|
|
# -------------------------------------------------------------------
|
|
# Notes: LLMVision analyzes camera.garagecam; expects strict "on"/"off" output.
|
|
# Notes: Front-door package detection waits 3 minutes after person activity or 20 seconds after the front door relocks, then analyzes a short live stream for better package accuracy.
|
|
# Docs: https://llmvision.gitbook.io/getting-started/usage/image-analyzer
|
|
######################################################################
|
|
|
|
input_button:
|
|
llmvision_garbage_check:
|
|
name: "LLM Vision: Garage cans check"
|
|
icon: mdi:delete-variant
|
|
llmvision_front_door_package_check:
|
|
name: "LLM Vision: Front door package check"
|
|
icon: mdi:package-variant-closed-check
|
|
|
|
input_boolean:
|
|
garbage_cans_out:
|
|
name: "Garbage Cans Out"
|
|
icon: mdi:trash-can
|
|
front_door_packages_present:
|
|
name: "Front Door Packages Present"
|
|
icon: mdi:package-variant-closed
|
|
|
|
input_text:
|
|
llmvision_garbage_last_response:
|
|
name: "LLM Vision garage response"
|
|
max: 255
|
|
llmvision_garbage_last_keyframe:
|
|
name: "LLM Vision garage key frame"
|
|
max: 255
|
|
llmvision_front_door_last_response:
|
|
name: "LLM Vision front door response"
|
|
max: 255
|
|
llmvision_front_door_last_keyframe:
|
|
name: "LLM Vision front door key frame"
|
|
max: 255
|
|
|
|
input_datetime:
|
|
llmvision_garbage_last_run:
|
|
name: "LLM Vision garage last run"
|
|
has_date: true
|
|
has_time: true
|
|
llmvision_front_door_last_run:
|
|
name: "LLM Vision front door last run"
|
|
has_date: true
|
|
has_time: true
|
|
|
|
template:
|
|
- binary_sensor:
|
|
- name: "Garbage Cans Out"
|
|
unique_id: llmvision_garbage_cans_out
|
|
device_class: presence
|
|
state: "{{ is_state('input_boolean.garbage_cans_out', 'on') }}"
|
|
attributes:
|
|
last_run: "{{ states('input_datetime.llmvision_garbage_last_run') }}"
|
|
last_response: "{{ states('input_text.llmvision_garbage_last_response') }}"
|
|
last_key_frame: "{{ states('input_text.llmvision_garbage_last_keyframe') }}"
|
|
source_camera: camera.garagecam
|
|
|
|
- name: "Front Door Packages Present"
|
|
unique_id: llmvision_front_door_packages_present
|
|
device_class: presence
|
|
state: "{{ is_state('input_boolean.front_door_packages_present', 'on') }}"
|
|
attributes:
|
|
last_run: "{{ states('input_datetime.llmvision_front_door_last_run') }}"
|
|
last_response: "{{ states('input_text.llmvision_front_door_last_response') }}"
|
|
last_key_frame: "{{ states('input_text.llmvision_front_door_last_keyframe') }}"
|
|
source_camera: camera.frontdoorbell
|
|
|
|
automation:
|
|
- alias: LLM Vision - Garbage cans out
|
|
id: d88a2e6d-78f3-4bb7-9d9f-c4d06e6eb5a9
|
|
mode: restart
|
|
trigger:
|
|
- platform: state
|
|
entity_id: input_button.llmvision_garbage_check
|
|
variables:
|
|
prompt_text: >
|
|
Examine the image. I have taped a reflective X on the right wall. Look for the reflective X on the right wall. If you clearly see the X, respond exactly: on. If you cannot see the X, respond exactly: off. No other words.
|
|
action:
|
|
- service: llmvision.data_analyzer
|
|
response_variable: llmvision_result
|
|
data:
|
|
provider: !secret llmvision_provider_entry
|
|
model: gpt-4.1-nano
|
|
message: "{{ prompt_text }}"
|
|
sensor_entity: input_boolean.garbage_cans_out
|
|
image_entity:
|
|
- camera.garagecam
|
|
include_filename: false
|
|
target_width: 1280
|
|
max_tokens: 16
|
|
expose_images: true
|
|
- service: input_text.set_value
|
|
target:
|
|
entity_id: input_text.llmvision_garbage_last_response
|
|
data:
|
|
value: "{{ (llmvision_result.response_text | default('unknown'))[:250] }}"
|
|
- choose:
|
|
- conditions: "{{ llmvision_result is defined and llmvision_result.key_frame is defined }}"
|
|
sequence:
|
|
- service: input_text.set_value
|
|
target:
|
|
entity_id: input_text.llmvision_garbage_last_keyframe
|
|
data:
|
|
value: "{{ llmvision_result.key_frame }}"
|
|
default:
|
|
- service: input_text.set_value
|
|
target:
|
|
entity_id: input_text.llmvision_garbage_last_keyframe
|
|
data:
|
|
value: ""
|
|
- service: input_datetime.set_datetime
|
|
target:
|
|
entity_id: input_datetime.llmvision_garbage_last_run
|
|
data:
|
|
datetime: "{{ now() }}"
|
|
|
|
- alias: LLM Vision - Front door packages
|
|
id: 8647b555-7ba0-41d5-98de-cfd3094e5b4f
|
|
mode: restart
|
|
trigger:
|
|
- platform: numeric_state
|
|
entity_id: sensor.frontdoorbell_person_active_count_2
|
|
above: 0
|
|
id: person_count
|
|
- platform: state
|
|
entity_id: lock.front_door
|
|
from: unlocked
|
|
to: locked
|
|
id: front_door_locked
|
|
- platform: state
|
|
entity_id: input_button.llmvision_front_door_package_check
|
|
id: manual_check
|
|
variables:
|
|
trigger_source: >-
|
|
{% if trigger.id == 'manual_check' %}
|
|
manual button
|
|
{% elif trigger.id == 'front_door_locked' %}
|
|
front door relock
|
|
{% else %}
|
|
front door person activity
|
|
{% endif %}
|
|
prompt_text: >-
|
|
Examine these front door camera frames for delivery packages. Focus on the porch and doorstep area
|
|
near the wall and doormat in the lower-right part of the image. Treat cardboard boxes, padded mailers,
|
|
poly bags, and shopping bags as packages. Ignore the street, cars, landscaping, and anything not resting
|
|
on the porch or doorstep. If any package is clearly visible, respond exactly: on. If no package is
|
|
clearly visible, respond exactly: off. No other words.
|
|
action:
|
|
- choose:
|
|
- conditions:
|
|
- condition: template
|
|
value_template: "{{ trigger.id == 'person_count' }}"
|
|
sequence:
|
|
- delay: "00:03:00"
|
|
- conditions:
|
|
- condition: template
|
|
value_template: "{{ trigger.id == 'front_door_locked' }}"
|
|
sequence:
|
|
- delay: "00:00:20"
|
|
- service: llmvision.stream_analyzer
|
|
response_variable: llmvision_result
|
|
data:
|
|
provider: !secret llmvision_provider_entry
|
|
model: gpt-4.1-mini
|
|
message: "{{ prompt_text }}"
|
|
image_entity:
|
|
- camera.frontdoorbell
|
|
duration: 6
|
|
max_frames: 5
|
|
include_filename: false
|
|
target_width: 1920
|
|
max_tokens: 16
|
|
expose_images: true
|
|
- variables:
|
|
normalized_response: "{{ llmvision_result.response_text | default('') | trim | lower }}"
|
|
- choose:
|
|
- conditions:
|
|
- condition: template
|
|
value_template: >-
|
|
{{ normalized_response in ['on', 'yes', 'true']
|
|
or normalized_response.startswith('on')
|
|
or normalized_response.startswith('yes') }}
|
|
sequence:
|
|
- service: input_boolean.turn_on
|
|
target:
|
|
entity_id: input_boolean.front_door_packages_present
|
|
- conditions:
|
|
- condition: template
|
|
value_template: >-
|
|
{{ normalized_response in ['off', 'no', 'false']
|
|
or normalized_response.startswith('off')
|
|
or normalized_response.startswith('no') }}
|
|
sequence:
|
|
- service: input_boolean.turn_off
|
|
target:
|
|
entity_id: input_boolean.front_door_packages_present
|
|
- service: input_text.set_value
|
|
target:
|
|
entity_id: input_text.llmvision_front_door_last_response
|
|
data:
|
|
value: "{{ (llmvision_result.response_text | default('unknown'))[:250] }}"
|
|
- choose:
|
|
- conditions: "{{ llmvision_result is defined and llmvision_result.key_frame is defined }}"
|
|
sequence:
|
|
- service: input_text.set_value
|
|
target:
|
|
entity_id: input_text.llmvision_front_door_last_keyframe
|
|
data:
|
|
value: "{{ llmvision_result.key_frame }}"
|
|
default:
|
|
- service: input_text.set_value
|
|
target:
|
|
entity_id: input_text.llmvision_front_door_last_keyframe
|
|
data:
|
|
value: ""
|
|
- service: input_datetime.set_datetime
|
|
target:
|
|
entity_id: input_datetime.llmvision_front_door_last_run
|
|
data:
|
|
datetime: "{{ now() }}"
|
|
- service: script.send_to_logbook
|
|
data:
|
|
topic: PACKAGES
|
|
message: >-
|
|
Front door package vision check ran via {{ trigger_source }}
|
|
and returned {{ llmvision_result.response_text | default(states('input_boolean.front_door_packages_present')) | lower }}.
|
|
- choose:
|
|
- conditions:
|
|
- condition: template
|
|
value_template: "{{ trigger.id == 'manual_check' }}"
|
|
sequence:
|
|
- service: script.notify_engine
|
|
data:
|
|
title: Front door package test
|
|
value1: >-
|
|
LLM Vision returned {{ llmvision_result.response_text | default(states('input_boolean.front_door_packages_present')) | lower }}
|
|
for the front door package check.
|
|
who: carlo
|
|
group: information
|
|
level: active
|
|
camera_entity: camera.frontdoorbell
|
|
|
|
- alias: LLM Vision - Front door package notify
|
|
id: 0ddf0fb5-4600-4eff-9236-95b2af3739a6
|
|
mode: restart
|
|
trigger:
|
|
- platform: state
|
|
entity_id: input_boolean.front_door_packages_present
|
|
to: 'on'
|
|
for: "00:01:00"
|
|
action:
|
|
- variables:
|
|
package_message: >-
|
|
Front door camera thinks a package may be waiting at the door.
|
|
notify_target: >-
|
|
{% if is_state('group.family', 'home') %}
|
|
family
|
|
{% else %}
|
|
carlo
|
|
{% endif %}
|
|
- service: script.notify_engine
|
|
data:
|
|
title: Package check
|
|
value1: "{{ package_message }}"
|
|
who: "{{ notify_target }}"
|
|
group: information
|
|
level: active
|
|
camera_entity: camera.frontdoorbell
|
|
- service: script.send_to_logbook
|
|
data:
|
|
topic: PACKAGES
|
|
message: "{{ package_message }}"
|