initial commit
This commit is contained in:
@@ -0,0 +1,118 @@
|
||||
################################################################################
|
||||
# cat_medication_tracker_ha.yaml
|
||||
#
|
||||
# Home Assistant companion automations for the ESPHome cat medication tracker.
|
||||
# The device itself resets at midnight; this package adds HA-side controls,
|
||||
# status sensors, and reminder notifications.
|
||||
################################################################################
|
||||
|
||||
input_button:
|
||||
reset_cat_medications:
|
||||
name: "Reset Cat Medications"
|
||||
icon: mdi:pill-off
|
||||
|
||||
template:
|
||||
- sensor:
|
||||
- name: "Cats Medicated Today"
|
||||
unique_id: cats_medicated_today
|
||||
icon: mdi:cat
|
||||
state: >
|
||||
{% set meds = [
|
||||
states('switch.cat_medication_tracker_penelope_medicated'),
|
||||
states('switch.cat_medication_tracker_tess_medicated')
|
||||
] %}
|
||||
{{ meds | select('equalto', 'on') | list | count }}
|
||||
|
||||
- name: "Cats Still Needing Medication"
|
||||
unique_id: cats_still_needing_medication
|
||||
icon: mdi:pill-off
|
||||
state: >
|
||||
{{ 2 - (states('sensor.cats_medicated_today') | int(0)) }}
|
||||
|
||||
automation:
|
||||
- id: cat_medication_tracker_reset_from_ha
|
||||
alias: "Cat Medication Tracker - Reset from HA"
|
||||
trigger:
|
||||
- platform: state
|
||||
entity_id: input_button.reset_cat_medications
|
||||
action:
|
||||
- service: switch.turn_off
|
||||
target:
|
||||
entity_id: switch.cat_medication_tracker_penelope_medicated
|
||||
- service: switch.turn_off
|
||||
target:
|
||||
entity_id: switch.cat_medication_tracker_tess_medicated
|
||||
|
||||
- id: cat_medication_tracker_all_done_notify
|
||||
alias: "Cat Medication Tracker - All cats medicated"
|
||||
trigger:
|
||||
- platform: state
|
||||
entity_id: binary_sensor.cat_medication_tracker_all_cats_medicated
|
||||
to: "on"
|
||||
action:
|
||||
- service: notify.notify
|
||||
data:
|
||||
title: "Cat meds done"
|
||||
message: "Penelope and Tess have both been marked medicated today."
|
||||
|
||||
- id: cat_medication_tracker_cat_medicated_notify
|
||||
alias: "Cat Medication Tracker - Cat medicated notification"
|
||||
trigger:
|
||||
- platform: state
|
||||
entity_id: switch.cat_medication_tracker_penelope_medicated
|
||||
from: "off"
|
||||
to: "on"
|
||||
id: penelope
|
||||
- platform: state
|
||||
entity_id: switch.cat_medication_tracker_tess_medicated
|
||||
from: "off"
|
||||
to: "on"
|
||||
id: tess
|
||||
action:
|
||||
- variables:
|
||||
cat_name: >
|
||||
{% if trigger.id == 'penelope' %}Penelope
|
||||
{% else %}Tess{% endif %}
|
||||
- service: notify.mobile_app_joshuas_iphone_of_pain
|
||||
data:
|
||||
title: "Cat medication given"
|
||||
message: "{{ cat_name }} has been marked medicated."
|
||||
- service: notify.mobile_app_pollys_iphone
|
||||
data:
|
||||
title: "Cat medication given"
|
||||
message: "{{ cat_name }} has been marked medicated."
|
||||
|
||||
- id: cat_medication_tracker_evening_reminder
|
||||
alias: "Cat Medication Tracker - 6PM medication reminder"
|
||||
trigger:
|
||||
- platform: time
|
||||
at: "18:00:00"
|
||||
condition:
|
||||
- condition: state
|
||||
entity_id: binary_sensor.cat_medication_tracker_all_cats_medicated
|
||||
state: "off"
|
||||
action:
|
||||
- service: notify.mobile_app_joshuas_iphone_of_pain
|
||||
data:
|
||||
title: "Cat meds still needed"
|
||||
message: >
|
||||
{% set ns = namespace(cats=[]) %}
|
||||
{% if is_state('switch.cat_medication_tracker_penelope_medicated', 'off') %}
|
||||
{% set ns.cats = ns.cats + ['Penelope'] %}
|
||||
{% endif %}
|
||||
{% if is_state('switch.cat_medication_tracker_tess_medicated', 'off') %}
|
||||
{% set ns.cats = ns.cats + ['Tess'] %}
|
||||
{% endif %}
|
||||
{{ ns.cats | join(' and ') }} still need medication.
|
||||
- service: notify.mobile_app_pollys_iphone
|
||||
data:
|
||||
title: "Cat meds still needed"
|
||||
message: >
|
||||
{% set ns = namespace(cats=[]) %}
|
||||
{% if is_state('switch.cat_medication_tracker_penelope_medicated', 'off') %}
|
||||
{% set ns.cats = ns.cats + ['Penelope'] %}
|
||||
{% endif %}
|
||||
{% if is_state('switch.cat_medication_tracker_tess_medicated', 'off') %}
|
||||
{% set ns.cats = ns.cats + ['Tess'] %}
|
||||
{% endif %}
|
||||
{{ ns.cats | join(' and ') }} still need medication.
|
||||
@@ -0,0 +1,222 @@
|
||||
################################################################################
|
||||
# chore-tracker-ha.yaml (AUTO-GENERATED — edit chores_config.yaml)
|
||||
# Kids: Jordyn, Declan, Chloe
|
||||
#
|
||||
# BIDIRECTIONAL SYNC:
|
||||
# Screen to HA: Each switch calls homeassistant.service on toggle
|
||||
# HA to Screen: ESPHome native API handles this automatically
|
||||
################################################################################
|
||||
|
||||
input_button:
|
||||
jordyn_reset_chores:
|
||||
name: "Reset Jordyn's Chores"
|
||||
icon: mdi:restart
|
||||
declan_reset_chores:
|
||||
name: "Reset Declan's Chores"
|
||||
icon: mdi:restart
|
||||
chloe_reset_chores:
|
||||
name: "Reset Chloe's Chores"
|
||||
icon: mdi:restart
|
||||
reset_all_chores:
|
||||
name: "Reset All Chores"
|
||||
icon: mdi:restart-alert
|
||||
|
||||
template:
|
||||
- sensor:
|
||||
- name: "Jordyn Chores Done Today"
|
||||
unique_id: jordyn_chores_done_today
|
||||
icon: mdi:check-circle
|
||||
state: >
|
||||
{% set chores = [states('switch.chore_tracker_jordyn_put_on_underwear'), states('switch.chore_tracker_jordyn_brush_teeth'), states('switch.chore_tracker_jordyn_fill_water_bowls'), states('switch.chore_tracker_jordyn_restock_cat_food_cans')] %}
|
||||
{{ chores | select('equalto', 'on') | list | count }}
|
||||
|
||||
- name: "Jordyn All Chores Done"
|
||||
unique_id: jordyn_all_chores_done
|
||||
icon: mdi:check-all
|
||||
state: >
|
||||
{{ states('sensor.jordyn_chores_done_today') | int == 4 }}
|
||||
|
||||
- name: "Declan Chores Done Today"
|
||||
unique_id: declan_chores_done_today
|
||||
icon: mdi:check-circle
|
||||
state: >
|
||||
{% set chores = [states('switch.chore_tracker_declan_take_morning_pill'), states('switch.chore_tracker_declan_scoop_dog_poop')] %}
|
||||
{{ chores | select('equalto', 'on') | list | count }}
|
||||
|
||||
- name: "Declan All Chores Done"
|
||||
unique_id: declan_all_chores_done
|
||||
icon: mdi:check-all
|
||||
state: >
|
||||
{{ states('sensor.declan_chores_done_today') | int == 2 }}
|
||||
|
||||
- name: "Chloe Chores Done Today"
|
||||
unique_id: chloe_chores_done_today
|
||||
icon: mdi:check-circle
|
||||
state: >
|
||||
{% set chores = [states('switch.chore_tracker_chloe_fill_kitty_feeders'), states('switch.chore_tracker_chloe_scoop_kitty_litter'), states('switch.chore_tracker_chloe_replace_kitty_litter_bags')] %}
|
||||
{{ chores | select('equalto', 'on') | list | count }}
|
||||
|
||||
- name: "Chloe All Chores Done"
|
||||
unique_id: chloe_all_chores_done
|
||||
icon: mdi:check-all
|
||||
state: >
|
||||
{{ states('sensor.chloe_chores_done_today') | int == 3 }}
|
||||
|
||||
|
||||
automation:
|
||||
- id: jordyn_reset_from_ha
|
||||
alias: "Chore Tracker - Reset Jordyn's chores from HA"
|
||||
trigger:
|
||||
- platform: state
|
||||
entity_id: input_button.jordyn_reset_chores
|
||||
action:
|
||||
- service: switch.turn_off
|
||||
target:
|
||||
entity_id: switch.chore_tracker_jordyn_put_on_underwear
|
||||
- service: switch.turn_off
|
||||
target:
|
||||
entity_id: switch.chore_tracker_jordyn_brush_teeth
|
||||
- service: switch.turn_off
|
||||
target:
|
||||
entity_id: switch.chore_tracker_jordyn_fill_water_bowls
|
||||
- service: switch.turn_off
|
||||
target:
|
||||
entity_id: switch.chore_tracker_jordyn_restock_cat_food_cans
|
||||
|
||||
- id: declan_reset_from_ha
|
||||
alias: "Chore Tracker - Reset Declan's chores from HA"
|
||||
trigger:
|
||||
- platform: state
|
||||
entity_id: input_button.declan_reset_chores
|
||||
action:
|
||||
- service: switch.turn_off
|
||||
target:
|
||||
entity_id: switch.chore_tracker_declan_take_morning_pill
|
||||
- service: switch.turn_off
|
||||
target:
|
||||
entity_id: switch.chore_tracker_declan_scoop_dog_poop
|
||||
|
||||
- id: chloe_reset_from_ha
|
||||
alias: "Chore Tracker - Reset Chloe's chores from HA"
|
||||
trigger:
|
||||
- platform: state
|
||||
entity_id: input_button.chloe_reset_chores
|
||||
action:
|
||||
- service: switch.turn_off
|
||||
target:
|
||||
entity_id: switch.chore_tracker_chloe_fill_kitty_feeders
|
||||
- service: switch.turn_off
|
||||
target:
|
||||
entity_id: switch.chore_tracker_chloe_scoop_kitty_litter
|
||||
- service: switch.turn_off
|
||||
target:
|
||||
entity_id: switch.chore_tracker_chloe_replace_kitty_litter_bags
|
||||
|
||||
- id: reset_all_from_ha
|
||||
alias: "Chore Tracker - Reset ALL chores from HA"
|
||||
trigger:
|
||||
- platform: state
|
||||
entity_id: input_button.reset_all_chores
|
||||
action:
|
||||
- service: switch.turn_off
|
||||
target:
|
||||
entity_id: switch.chore_tracker_jordyn_put_on_underwear
|
||||
- service: switch.turn_off
|
||||
target:
|
||||
entity_id: switch.chore_tracker_jordyn_brush_teeth
|
||||
- service: switch.turn_off
|
||||
target:
|
||||
entity_id: switch.chore_tracker_jordyn_fill_water_bowls
|
||||
- service: switch.turn_off
|
||||
target:
|
||||
entity_id: switch.chore_tracker_jordyn_restock_cat_food_cans
|
||||
- service: switch.turn_off
|
||||
target:
|
||||
entity_id: switch.chore_tracker_declan_take_morning_pill
|
||||
- service: switch.turn_off
|
||||
target:
|
||||
entity_id: switch.chore_tracker_declan_scoop_dog_poop
|
||||
- service: switch.turn_off
|
||||
target:
|
||||
entity_id: switch.chore_tracker_chloe_fill_kitty_feeders
|
||||
- service: switch.turn_off
|
||||
target:
|
||||
entity_id: switch.chore_tracker_chloe_scoop_kitty_litter
|
||||
- service: switch.turn_off
|
||||
target:
|
||||
entity_id: switch.chore_tracker_chloe_replace_kitty_litter_bags
|
||||
|
||||
- id: jordyn_all_done_notify
|
||||
alias: "Chore Tracker - Jordyn all done!"
|
||||
trigger:
|
||||
- platform: state
|
||||
entity_id: sensor.jordyn_all_chores_done
|
||||
to: "True"
|
||||
action:
|
||||
- service: notify.notify
|
||||
data:
|
||||
title: "Jordyn finished all chores!"
|
||||
message: "Jordyn completed all 4 chores today!"
|
||||
|
||||
- id: declan_all_done_notify
|
||||
alias: "Chore Tracker - Declan all done!"
|
||||
trigger:
|
||||
- platform: state
|
||||
entity_id: sensor.declan_all_chores_done
|
||||
to: "True"
|
||||
action:
|
||||
- service: notify.notify
|
||||
data:
|
||||
title: "Declan finished all chores!"
|
||||
message: "Declan completed all 2 chores today!"
|
||||
|
||||
- id: chloe_all_done_notify
|
||||
alias: "Chore Tracker - Chloe all done!"
|
||||
trigger:
|
||||
- platform: state
|
||||
entity_id: sensor.chloe_all_chores_done
|
||||
to: "True"
|
||||
action:
|
||||
- service: notify.notify
|
||||
data:
|
||||
title: "Chloe finished all chores!"
|
||||
message: "Chloe completed all 3 chores today!"
|
||||
|
||||
- id: chore_reminder_evening
|
||||
alias: "Chore Tracker - Evening reminder"
|
||||
trigger:
|
||||
- platform: time
|
||||
at: "18:00:00"
|
||||
action:
|
||||
- if:
|
||||
condition: template
|
||||
value_template: "{{ states('sensor.jordyn_all_chores_done') != 'True' }}"
|
||||
then:
|
||||
- service: notify.notify
|
||||
data:
|
||||
title: "Jordyn has unfinished chores"
|
||||
message: >
|
||||
Jordyn has done
|
||||
{{ states('sensor.jordyn_chores_done_today') }}/4 chores today.
|
||||
- if:
|
||||
condition: template
|
||||
value_template: "{{ states('sensor.declan_all_chores_done') != 'True' }}"
|
||||
then:
|
||||
- service: notify.notify
|
||||
data:
|
||||
title: "Declan has unfinished chores"
|
||||
message: >
|
||||
Declan has done
|
||||
{{ states('sensor.declan_chores_done_today') }}/2 chores today.
|
||||
- if:
|
||||
condition: template
|
||||
value_template: "{{ states('sensor.chloe_all_chores_done') != 'True' }}"
|
||||
then:
|
||||
- service: notify.notify
|
||||
data:
|
||||
title: "Chloe has unfinished chores"
|
||||
message: >
|
||||
Chloe has done
|
||||
{{ states('sensor.chloe_chores_done_today') }}/3 chores today.
|
||||
|
||||
|
||||
File diff suppressed because it is too large
Load Diff
@@ -0,0 +1,315 @@
|
||||
# =============================================================================
|
||||
# LITTER BOX MONITORING - MQTT Sensors & Automations
|
||||
# =============================================================================
|
||||
# Receives analysis results from litter_box_analyzer.py via MQTT and
|
||||
# exposes them as Home Assistant entities with notifications.
|
||||
#
|
||||
# MQTT topics (published by the Python analyzer):
|
||||
# litter_box/status/cat_present -> ON/OFF
|
||||
# litter_box/status/motion_detected -> ON/OFF
|
||||
# litter_box/status/motion_score -> float
|
||||
# litter_box/status/box_state -> open/closed/unknown
|
||||
# litter_box/status/box_diff_score -> float
|
||||
# litter_box/status/litter_box_stuck -> ON/OFF
|
||||
# litter_box/status/needs_scooping -> ON/OFF
|
||||
# litter_box/status/cleanliness_score -> 0-100
|
||||
# litter_box/status/status_message -> text
|
||||
# =============================================================================
|
||||
|
||||
# ---------------------------------------------------------------------------
|
||||
# MQTT Binary Sensors
|
||||
# ---------------------------------------------------------------------------
|
||||
mqtt:
|
||||
binary_sensor:
|
||||
- name: "Litter Box - Cat Present"
|
||||
unique_id: litter_box_cat_present
|
||||
state_topic: "litter_box/status/cat_present"
|
||||
payload_on: "ON"
|
||||
payload_off: "OFF"
|
||||
device_class: occupancy
|
||||
icon: "mdi:cat"
|
||||
|
||||
- name: "Litter Box - Motion Detected"
|
||||
unique_id: litter_box_motion_detected
|
||||
state_topic: "litter_box/status/motion_detected"
|
||||
payload_on: "ON"
|
||||
payload_off: "OFF"
|
||||
device_class: motion
|
||||
icon: "mdi:motion-sensor"
|
||||
|
||||
- name: "Litter Box - Stuck Closed"
|
||||
unique_id: litter_box_stuck_closed
|
||||
state_topic: "litter_box/status/litter_box_stuck"
|
||||
payload_on: "ON"
|
||||
payload_off: "OFF"
|
||||
device_class: problem
|
||||
icon: "mdi:alert-circle"
|
||||
|
||||
- name: "Litter Box - Needs Scooping"
|
||||
unique_id: litter_box_needs_scooping
|
||||
state_topic: "litter_box/status/needs_scooping"
|
||||
payload_on: "ON"
|
||||
payload_off: "OFF"
|
||||
device_class: problem
|
||||
icon: "mdi:shovel"
|
||||
|
||||
# ---------------------------------------------------------------------------
|
||||
# MQTT Numeric Sensors
|
||||
# ---------------------------------------------------------------------------
|
||||
sensor:
|
||||
- name: "Litter Box - Motion Score"
|
||||
unique_id: litter_box_motion_score
|
||||
state_topic: "litter_box/status/motion_score"
|
||||
unit_of_measurement: "%"
|
||||
icon: "mdi:chart-bell-curve"
|
||||
|
||||
- name: "Litter Box - Cleanliness Score"
|
||||
unique_id: litter_box_cleanliness_score
|
||||
state_topic: "litter_box/status/cleanliness_score"
|
||||
unit_of_measurement: "%"
|
||||
icon: "mdi:star"
|
||||
|
||||
- name: "Litter Box - Box Diff Score"
|
||||
unique_id: litter_box_box_diff_score
|
||||
state_topic: "litter_box/status/box_diff_score"
|
||||
icon: "mdi:compare"
|
||||
|
||||
# MQTT text/state sensors
|
||||
- name: "Litter Box - Box State"
|
||||
unique_id: litter_box_box_state
|
||||
state_topic: "litter_box/status/box_state"
|
||||
icon: "mdi:state-machine"
|
||||
|
||||
- name: "Litter Box - Status Message"
|
||||
unique_id: litter_box_status_message
|
||||
state_topic: "litter_box/status/status_message"
|
||||
icon: "mdi:message-text"
|
||||
|
||||
# ---------------------------------------------------------------------------
|
||||
# Helper Toggles (for notification cooldown tracking)
|
||||
# ---------------------------------------------------------------------------
|
||||
input_boolean:
|
||||
litter_box_stuck_notified:
|
||||
name: "Litter Box Stuck - Notification Sent"
|
||||
icon: "mdi:bell-off"
|
||||
|
||||
litter_box_cat_notified:
|
||||
name: "Litter Box Cat - Notification Cooldown"
|
||||
icon: "mdi:cat"
|
||||
|
||||
litter_box_scoop_notified:
|
||||
name: "Litter Box Scoop - Notification Cooldown"
|
||||
icon: "mdi:shovel"
|
||||
|
||||
# ---------------------------------------------------------------------------
|
||||
# Timers for cooldown resets
|
||||
# ---------------------------------------------------------------------------
|
||||
timer:
|
||||
litter_box_cat_cooldown:
|
||||
name: "Cat Visit Cooldown"
|
||||
duration: "00:15:00"
|
||||
restore: true
|
||||
|
||||
litter_box_scoop_cooldown:
|
||||
name: "Scoop Reminder Cooldown"
|
||||
duration: "04:00:00"
|
||||
restore: true
|
||||
|
||||
# ---------------------------------------------------------------------------
|
||||
# Automations
|
||||
# ---------------------------------------------------------------------------
|
||||
automation:
|
||||
|
||||
# --- Keep IR on at night so the camera can see the litter box ---
|
||||
- id: litter_box_ir_on_at_sunset
|
||||
alias: "Litter Box Camera - IR On At Sunset"
|
||||
triggers:
|
||||
- trigger: sun
|
||||
event: sunset
|
||||
actions:
|
||||
- action: light.turn_on
|
||||
target:
|
||||
entity_id: light.litter_box_camera_ir_night_vision
|
||||
mode: single
|
||||
|
||||
- id: litter_box_ir_off_at_sunrise
|
||||
alias: "Litter Box Camera - IR Off At Sunrise"
|
||||
triggers:
|
||||
- trigger: sun
|
||||
event: sunrise
|
||||
actions:
|
||||
- action: light.turn_off
|
||||
target:
|
||||
entity_id: light.litter_box_camera_ir_night_vision
|
||||
mode: single
|
||||
|
||||
# --- Initialize ESPHome analysis entities so alerts can trigger from known off/clean states ---
|
||||
- id: litter_box_initialize_analysis_status
|
||||
alias: "Litter Box Camera - Initialize Analysis Status"
|
||||
triggers:
|
||||
- trigger: homeassistant
|
||||
event: start
|
||||
- trigger: time_pattern
|
||||
minutes: "/30"
|
||||
conditions:
|
||||
- condition: template
|
||||
value_template: >-
|
||||
{{ states('binary_sensor.litter_box_camera_cat_present') in ['unknown', 'unavailable']
|
||||
or states('binary_sensor.litter_box_camera_needs_scooping') in ['unknown', 'unavailable']
|
||||
or states('binary_sensor.litter_box_camera_litter_level_low') in ['unknown', 'unavailable']
|
||||
or states('sensor.litter_box_camera_cleanliness_score') in ['unknown', 'unavailable'] }}
|
||||
actions:
|
||||
- action: esphome.litter_box_cam_update_status
|
||||
data:
|
||||
cat_present: false
|
||||
needs_scooping: false
|
||||
litter_level_low: false
|
||||
cleanliness_score: 100
|
||||
mode: single
|
||||
|
||||
# --- Request a camera capture after IR turns on so analysis has a lit frame at night ---
|
||||
- id: litter_box_capture_after_ir_on
|
||||
alias: "Litter Box Camera - Capture After IR Turns On"
|
||||
triggers:
|
||||
- trigger: state
|
||||
entity_id: light.litter_box_camera_ir_night_vision
|
||||
to: "on"
|
||||
actions:
|
||||
- delay: "00:00:05"
|
||||
- action: button.press
|
||||
target:
|
||||
entity_id: button.litter_box_camera_capture_now
|
||||
mode: single
|
||||
|
||||
# --- Cat Detected Notification ---
|
||||
- id: litter_box_cat_detected
|
||||
alias: "Litter Box - Cat Detected Alert"
|
||||
triggers:
|
||||
- trigger: state
|
||||
entity_id: binary_sensor.litter_box_camera_cat_present
|
||||
from: "off"
|
||||
to: "on"
|
||||
conditions:
|
||||
- condition: state
|
||||
entity_id: input_boolean.litter_box_cat_notified
|
||||
state: "off"
|
||||
actions:
|
||||
- action: input_boolean.turn_on
|
||||
target:
|
||||
entity_id: input_boolean.litter_box_cat_notified
|
||||
- action: timer.start
|
||||
target:
|
||||
entity_id: timer.litter_box_cat_cooldown
|
||||
- action: notify.mobile_app_joshuas_iphone_of_pain
|
||||
data:
|
||||
message: "🐱 A cat is using the litter box right now!"
|
||||
title: "Litter Box Activity"
|
||||
mode: single
|
||||
|
||||
# --- Reset cat notification cooldown ---
|
||||
- id: litter_box_cat_cooldown_reset
|
||||
alias: "Litter Box - Reset Cat Notification Cooldown"
|
||||
triggers:
|
||||
- trigger: event
|
||||
event_type: timer.finished
|
||||
event_data:
|
||||
entity_id: timer.litter_box_cat_cooldown
|
||||
actions:
|
||||
- action: input_boolean.turn_off
|
||||
target:
|
||||
entity_id: input_boolean.litter_box_cat_notified
|
||||
mode: single
|
||||
|
||||
# --- Stuck Closed Alert (status text confirms rotated closed) ---
|
||||
- id: litter_box_stuck_alert
|
||||
alias: "Litter Box - Stuck Closed Alert"
|
||||
initial_state: true
|
||||
triggers:
|
||||
- trigger: state
|
||||
entity_id: sensor.litter_box_camera_status_message
|
||||
conditions:
|
||||
- condition: template
|
||||
value_template: >-
|
||||
{{ 'stuck' in states('sensor.litter_box_camera_status_message') | lower
|
||||
or 'closed' in states('sensor.litter_box_camera_status_message') | lower }}
|
||||
- condition: state
|
||||
entity_id: input_boolean.litter_box_stuck_notified
|
||||
state: "off"
|
||||
actions:
|
||||
- action: input_boolean.turn_on
|
||||
target:
|
||||
entity_id: input_boolean.litter_box_stuck_notified
|
||||
- action: notify.mobile_app_joshuas_iphone_of_pain
|
||||
data:
|
||||
message: "⚠️ The litter box is STUCK ROTATED CLOSED! Visual state is 'closed' — check the mechanism."
|
||||
title: "Litter Box STUCK CLOSED!"
|
||||
- action: notify.mobile_app_pollys_iphone
|
||||
data:
|
||||
message: "⚠️ The litter box is STUCK ROTATED CLOSED! Visual state is 'closed' — check the mechanism."
|
||||
title: "Litter Box STUCK CLOSED!"
|
||||
- action: notify.mailgun_smtp
|
||||
data:
|
||||
message: "The litter box camera detects the box in a rotated/closed position. The mechanism may be stuck mid-cycle."
|
||||
title: "Litter Box Stuck Closed!"
|
||||
target: "joshua@cnjmail.com"
|
||||
mode: single
|
||||
|
||||
# --- Reset stuck notification when status returns to normal/open ---
|
||||
- id: litter_box_stuck_reset
|
||||
alias: "Litter Box - Reset Stuck Notification on Open"
|
||||
initial_state: true
|
||||
triggers:
|
||||
- trigger: state
|
||||
entity_id: sensor.litter_box_camera_status_message
|
||||
conditions:
|
||||
- condition: template
|
||||
value_template: >-
|
||||
{{ states('sensor.litter_box_camera_status_message') | lower in ['ok', 'calibrated. monitoring started.', 'image sent for analysis']
|
||||
or 'open' in states('sensor.litter_box_camera_status_message') | lower }}
|
||||
- condition: state
|
||||
entity_id: input_boolean.litter_box_stuck_notified
|
||||
state: "on"
|
||||
actions:
|
||||
- action: input_boolean.turn_off
|
||||
target:
|
||||
entity_id: input_boolean.litter_box_stuck_notified
|
||||
mode: single
|
||||
|
||||
# --- Needs Scooping Alert ---
|
||||
- id: litter_box_needs_scooping_alert
|
||||
alias: "Litter Box - Needs Scooping Alert"
|
||||
triggers:
|
||||
- trigger: state
|
||||
entity_id: binary_sensor.litter_box_camera_needs_scooping
|
||||
from: "off"
|
||||
to: "on"
|
||||
conditions:
|
||||
- condition: state
|
||||
entity_id: input_boolean.litter_box_scoop_notified
|
||||
state: "off"
|
||||
actions:
|
||||
- action: input_boolean.turn_on
|
||||
target:
|
||||
entity_id: input_boolean.litter_box_scoop_notified
|
||||
- action: timer.start
|
||||
target:
|
||||
entity_id: timer.litter_box_scoop_cooldown
|
||||
- action: notify.mobile_app_joshuas_iphone_of_pain
|
||||
data:
|
||||
message: "🧹 The litter box could use a scoop! Cleanliness: {{ states('sensor.litter_box_camera_cleanliness_score') }}%"
|
||||
title: "Litter Box Needs Scooping"
|
||||
mode: single
|
||||
|
||||
# --- Reset scoop notification cooldown ---
|
||||
- id: litter_box_scoop_cooldown_reset
|
||||
alias: "Litter Box - Reset Scoop Notification Cooldown"
|
||||
triggers:
|
||||
- trigger: event
|
||||
event_type: timer.finished
|
||||
event_data:
|
||||
entity_id: timer.litter_box_scoop_cooldown
|
||||
actions:
|
||||
- action: input_boolean.turn_off
|
||||
target:
|
||||
entity_id: input_boolean.litter_box_scoop_notified
|
||||
mode: single
|
||||
@@ -0,0 +1,190 @@
|
||||
# Unified Home Assistant-managed alarms for ESPHome voice satellites.
|
||||
# This keeps one consistent alarm UX across Jarvis and ReSpeaker devices.
|
||||
#
|
||||
# The assist_satellite entity IDs below are derived from the ESPHome device names:
|
||||
# - office-jarvis-satellite -> assist_satellite.office_jarvis_satellite_assist_satellite
|
||||
# - respeaker-satellite-fr -> assist_satellite.respeaker_satellite_fr_assist_satellite
|
||||
# - respeaker-satellite-lr -> assist_satellite.respeaker_satellite_lr_assist_satellite
|
||||
# - respeaker-satellite-mbr -> assist_satellite.respeaker_satellite_mbr_assist_satellite
|
||||
# If Home Assistant generated different entity IDs in your instance, adjust them here
|
||||
# and in dashboards/views/voice-alarms-dashboard.yaml.
|
||||
|
||||
input_boolean:
|
||||
voice_alarm_office_jarvis_enabled:
|
||||
name: Office Jarvis Alarm Enabled
|
||||
icon: mdi:alarm
|
||||
|
||||
voice_alarm_respeaker_family_room_enabled:
|
||||
name: ReSpeaker Family Room Alarm Enabled
|
||||
icon: mdi:alarm
|
||||
|
||||
voice_alarm_respeaker_living_room_enabled:
|
||||
name: ReSpeaker Living Room Alarm Enabled
|
||||
icon: mdi:alarm
|
||||
|
||||
voice_alarm_respeaker_master_bedroom_enabled:
|
||||
name: ReSpeaker Master Bedroom Alarm Enabled
|
||||
icon: mdi:alarm
|
||||
|
||||
input_datetime:
|
||||
voice_alarm_office_jarvis_time:
|
||||
name: Office Jarvis Alarm Time
|
||||
has_date: false
|
||||
has_time: true
|
||||
|
||||
voice_alarm_respeaker_family_room_time:
|
||||
name: ReSpeaker Family Room Alarm Time
|
||||
has_date: false
|
||||
has_time: true
|
||||
|
||||
voice_alarm_respeaker_living_room_time:
|
||||
name: ReSpeaker Living Room Alarm Time
|
||||
has_date: false
|
||||
has_time: true
|
||||
|
||||
voice_alarm_respeaker_master_bedroom_time:
|
||||
name: ReSpeaker Master Bedroom Alarm Time
|
||||
has_date: false
|
||||
has_time: true
|
||||
|
||||
script:
|
||||
voice_satellite_alarm_announce:
|
||||
alias: Voice Satellite Alarm Announce
|
||||
description: Repeat an alarm announcement on a specific Assist satellite.
|
||||
mode: parallel
|
||||
fields:
|
||||
satellite_entity:
|
||||
name: Assist satellite entity
|
||||
required: true
|
||||
selector:
|
||||
entity:
|
||||
filter:
|
||||
domain: assist_satellite
|
||||
device_name:
|
||||
name: Device name
|
||||
required: true
|
||||
selector:
|
||||
text:
|
||||
message:
|
||||
name: Message
|
||||
required: false
|
||||
selector:
|
||||
text:
|
||||
sequence:
|
||||
- repeat:
|
||||
count: 3
|
||||
sequence:
|
||||
- action: assist_satellite.announce
|
||||
target:
|
||||
entity_id: "{{ satellite_entity }}"
|
||||
data:
|
||||
message: >-
|
||||
{% set custom_message = message | default('', true) %}
|
||||
{{ custom_message if custom_message else 'Alarm. Attention in ' ~ device_name ~ '.' }}
|
||||
preannounce: true
|
||||
- delay: "00:00:08"
|
||||
|
||||
test_voice_alarm_office_jarvis:
|
||||
alias: Test Voice Alarm - Office Jarvis
|
||||
mode: single
|
||||
sequence:
|
||||
- action: script.voice_satellite_alarm_announce
|
||||
data:
|
||||
satellite_entity: assist_satellite.office_jarvis_satellite_assist_satellite
|
||||
device_name: Office Jarvis
|
||||
message: This is a test alarm for Office Jarvis.
|
||||
|
||||
test_voice_alarm_respeaker_family_room:
|
||||
alias: Test Voice Alarm - ReSpeaker Family Room
|
||||
mode: single
|
||||
sequence:
|
||||
- action: script.voice_satellite_alarm_announce
|
||||
data:
|
||||
satellite_entity: assist_satellite.respeaker_satellite_fr_assist_satellite
|
||||
device_name: ReSpeaker Family Room
|
||||
message: This is a test alarm for the ReSpeaker in the family room.
|
||||
|
||||
test_voice_alarm_respeaker_living_room:
|
||||
alias: Test Voice Alarm - ReSpeaker Living Room
|
||||
mode: single
|
||||
sequence:
|
||||
- action: script.voice_satellite_alarm_announce
|
||||
data:
|
||||
satellite_entity: assist_satellite.respeaker_satellite_lr_assist_satellite
|
||||
device_name: ReSpeaker Living Room
|
||||
message: This is a test alarm for the ReSpeaker in the living room.
|
||||
|
||||
test_voice_alarm_respeaker_master_bedroom:
|
||||
alias: Test Voice Alarm - ReSpeaker Master Bedroom
|
||||
mode: single
|
||||
sequence:
|
||||
- action: script.voice_satellite_alarm_announce
|
||||
data:
|
||||
satellite_entity: assist_satellite.respeaker_satellite_mbr_assist_satellite
|
||||
device_name: ReSpeaker Master Bedroom
|
||||
message: This is a test alarm for the ReSpeaker in the master bedroom.
|
||||
|
||||
automation:
|
||||
- id: voice_alarm_office_jarvis_daily
|
||||
alias: Voice Alarm - Office Jarvis
|
||||
triggers:
|
||||
- trigger: time
|
||||
at: input_datetime.voice_alarm_office_jarvis_time
|
||||
conditions:
|
||||
- condition: state
|
||||
entity_id: input_boolean.voice_alarm_office_jarvis_enabled
|
||||
state: "on"
|
||||
actions:
|
||||
- action: script.voice_satellite_alarm_announce
|
||||
data:
|
||||
satellite_entity: assist_satellite.office_jarvis_satellite_assist_satellite
|
||||
device_name: Office Jarvis
|
||||
mode: single
|
||||
|
||||
- id: voice_alarm_respeaker_family_room_daily
|
||||
alias: Voice Alarm - ReSpeaker Family Room
|
||||
triggers:
|
||||
- trigger: time
|
||||
at: input_datetime.voice_alarm_respeaker_family_room_time
|
||||
conditions:
|
||||
- condition: state
|
||||
entity_id: input_boolean.voice_alarm_respeaker_family_room_enabled
|
||||
state: "on"
|
||||
actions:
|
||||
- action: script.voice_satellite_alarm_announce
|
||||
data:
|
||||
satellite_entity: assist_satellite.respeaker_satellite_fr_assist_satellite
|
||||
device_name: ReSpeaker Family Room
|
||||
mode: single
|
||||
|
||||
- id: voice_alarm_respeaker_living_room_daily
|
||||
alias: Voice Alarm - ReSpeaker Living Room
|
||||
triggers:
|
||||
- trigger: time
|
||||
at: input_datetime.voice_alarm_respeaker_living_room_time
|
||||
conditions:
|
||||
- condition: state
|
||||
entity_id: input_boolean.voice_alarm_respeaker_living_room_enabled
|
||||
state: "on"
|
||||
actions:
|
||||
- action: script.voice_satellite_alarm_announce
|
||||
data:
|
||||
satellite_entity: assist_satellite.respeaker_satellite_lr_assist_satellite
|
||||
device_name: ReSpeaker Living Room
|
||||
mode: single
|
||||
|
||||
- id: voice_alarm_respeaker_master_bedroom_daily
|
||||
alias: Voice Alarm - ReSpeaker Master Bedroom
|
||||
triggers:
|
||||
- trigger: time
|
||||
at: input_datetime.voice_alarm_respeaker_master_bedroom_time
|
||||
conditions:
|
||||
- condition: state
|
||||
entity_id: input_boolean.voice_alarm_respeaker_master_bedroom_enabled
|
||||
state: "on"
|
||||
actions:
|
||||
- action: script.voice_satellite_alarm_announce
|
||||
data:
|
||||
satellite_entity: assist_satellite.respeaker_satellite_mbr_assist_satellite
|
||||
device_name: ReSpeaker Master Bedroom
|
||||
mode: single
|
||||
Reference in New Issue
Block a user