2512 lines
77 KiB
YAML
2512 lines
77 KiB
YAML
- id: als_auto_error_cleanup
|
||
alias: ALS - Auto Error Cleanup
|
||
description: Automatically clears resolved errors after 1 hour
|
||
mode: restart
|
||
trigger:
|
||
- trigger: time_pattern
|
||
hours: /1
|
||
condition:
|
||
- condition: state
|
||
entity_id: binary_sensor.als_system_error_detected
|
||
state: 'on'
|
||
action:
|
||
- repeat:
|
||
for_each:
|
||
- bedroom
|
||
- kitchen
|
||
- bathroom
|
||
- hallway
|
||
- laundry
|
||
- livingroom
|
||
sequence:
|
||
- variables:
|
||
room: '{{ repeat.item }}'
|
||
error_entity: input_text.als_error_{{ room }}
|
||
- if:
|
||
- condition: template
|
||
value_template: '{{ states(error_entity) not in ['''', ''unknown'', ''unavailable'']
|
||
}}'
|
||
- condition: template
|
||
value_template: '{% set room_name = room | replace(''livingroom'', ''living_room'')
|
||
%} {% if room == ''laundry'' %}{% set room_name = ''laundry_room'' %}{%
|
||
endif %} {% set target_sensor = ''sensor.'' ~ room_name ~ ''_target_brightness''
|
||
%} {{ states(target_sensor) not in [''unknown'', ''unavailable''] }}'
|
||
then:
|
||
- action: input_text.set_value
|
||
target:
|
||
entity_id: '{{ error_entity }}'
|
||
data:
|
||
value: ''
|
||
- id: als_teach_button_bridge
|
||
alias: ALS - Teach Button Bridge
|
||
mode: single
|
||
trigger:
|
||
- trigger: state
|
||
entity_id: input_button.als_teach_now
|
||
action:
|
||
- variables:
|
||
sel: '{{ states(''input_select.als_teaching_room'') }}'
|
||
room_key: "{% set map = {\n 'Bedroom':'bedroom',\n 'Kitchen':'kitchen',\n\
|
||
\ 'Living Room':'livingroom',\n 'Hallway':'hallway',\n 'Bathroom':'bathroom',\n\
|
||
\ 'Laundry':'laundry'\n} %} {{ map.get(sel, 'kitchen') }}"
|
||
brightness: '{{ states(''input_number.als_teaching_brightness'') | int(50) }}'
|
||
- action: pyscript.als_teach_room
|
||
data:
|
||
room: '{{ room_key }}'
|
||
brightness: '{{ brightness }}'
|
||
- action: input_text.set_value
|
||
target:
|
||
entity_id: input_text.als_last_teach_status
|
||
data:
|
||
value: Taught {{ room_key }} → {{ brightness }}% at {{ now().strftime('%H:%M:%S')
|
||
}}
|
||
- id: als_reload_pyscript_button
|
||
alias: ALS - Reload Pyscript Button
|
||
mode: single
|
||
trigger:
|
||
- trigger: state
|
||
entity_id: input_button.als_reload_pyscript
|
||
action:
|
||
- action: pyscript.reload
|
||
- action: input_text.set_value
|
||
target:
|
||
entity_id: input_text.als_last_teach_status
|
||
data:
|
||
value: Pyscript reloaded at {{ now().strftime('%H:%M:%S') }}
|
||
- id: als_run_test_engine_button
|
||
alias: ALS - Run Test Engine Now
|
||
mode: single
|
||
trigger:
|
||
- trigger: state
|
||
entity_id: input_button.als_run_test_engine
|
||
action:
|
||
- action: pyscript.parallel_test_run_now
|
||
- action: input_text.set_value
|
||
target:
|
||
entity_id: input_text.als_last_teach_status
|
||
data:
|
||
value: Test engine wrote values at {{ now().strftime('%H:%M:%S') }}
|
||
- id: home_state_evaluation
|
||
alias: Home State Evaluation
|
||
triggers:
|
||
- trigger: time_pattern
|
||
minutes: /5
|
||
- trigger: state
|
||
entity_id:
|
||
- binary_sensor.working_today
|
||
- device_tracker.iphone15
|
||
- device_tracker.work_iphone
|
||
conditions:
|
||
- condition: template
|
||
value_template: '{{ not is_state(''input_select.home_state'',''Night'') }}'
|
||
- condition: template
|
||
value_template: '{{ not is_state(''input_boolean.manual_home_state_override'',''on'')
|
||
}}'
|
||
- condition: template
|
||
value_template: '{{ states(''sensor.calculated_home_mode'') not in [''unknown'',''unavailable'']
|
||
}}'
|
||
actions:
|
||
- action: script.evaluate_home_mode
|
||
- id: apple_tv_night_mode_trigger
|
||
alias: Apple TV → Night Mode (20:00–23:00 Only)
|
||
triggers:
|
||
- trigger: state
|
||
entity_id: media_player.bedroom
|
||
to:
|
||
- playing
|
||
- paused
|
||
- idle
|
||
from:
|
||
- 'off'
|
||
- unknown
|
||
- unavailable
|
||
- standby
|
||
for:
|
||
seconds: 8
|
||
conditions:
|
||
- condition: time
|
||
after: '20:00:00'
|
||
before: '23:00:00'
|
||
- condition: state
|
||
entity_id: binary_sensor.both_phones_home
|
||
state: 'on'
|
||
- condition: state
|
||
entity_id: input_boolean.apple_tv_bedroom_night_control
|
||
state: 'on'
|
||
- condition: template
|
||
value_template: '{{ not is_state(''input_select.home_state'',''Night'') }}'
|
||
actions:
|
||
- action: input_select.select_option
|
||
target:
|
||
entity_id: input_select.home_state
|
||
data:
|
||
option: Night
|
||
- id: night_mode_11pm_failsafe
|
||
alias: Night Mode 11 PM Failsafe
|
||
triggers:
|
||
- trigger: time
|
||
at: '23:00:00'
|
||
conditions:
|
||
- condition: state
|
||
entity_id: binary_sensor.both_phones_home
|
||
state: 'on'
|
||
- condition: template
|
||
value_template: '{{ not is_state(''input_select.home_state'',''Night'') }}'
|
||
actions:
|
||
- action: input_select.select_option
|
||
target:
|
||
entity_id: input_select.home_state
|
||
data:
|
||
option: Night
|
||
- id: learn_evening_transition_time
|
||
alias: Learn Evening Transition Time
|
||
triggers:
|
||
- trigger: state
|
||
entity_id: input_boolean.evening_mode_override
|
||
to: 'on'
|
||
actions:
|
||
- action: input_number.set_value
|
||
target:
|
||
entity_id: input_number.manual_evening_elevation_setting
|
||
data:
|
||
value: '{{ state_attr(''sun.sun'',''elevation'') }}'
|
||
- id: reset_evening_override_at_night
|
||
alias: Reset Evening Override at Night
|
||
triggers:
|
||
- trigger: state
|
||
entity_id: input_select.home_state
|
||
to: Night
|
||
conditions:
|
||
- condition: state
|
||
entity_id: input_boolean.evening_mode_override
|
||
state: 'on'
|
||
actions:
|
||
- action: input_boolean.turn_off
|
||
target:
|
||
entity_id: input_boolean.evening_mode_override
|
||
- id: als_end_early_morning_mode
|
||
alias: ALS - Transition from Early Morning to Day
|
||
triggers:
|
||
- trigger: state
|
||
entity_id: binary_sensor.als_morning_transition_ready
|
||
to: 'on'
|
||
conditions:
|
||
- condition: state
|
||
entity_id: input_select.home_state
|
||
state: Early Morning
|
||
actions:
|
||
- action: input_select.select_option
|
||
target:
|
||
entity_id: input_select.home_state
|
||
data:
|
||
option: Day
|
||
- id: sun_elevation_history_tracker
|
||
alias: Sun Elevation History Tracker
|
||
description: Updates sun elevation history every 15 minutes for rate calculation
|
||
triggers:
|
||
- trigger: time_pattern
|
||
minutes: /15
|
||
actions:
|
||
- action: input_number.set_value
|
||
target:
|
||
entity_id: input_number.sun_elevation_history
|
||
data:
|
||
value: '{{ state_attr(''sun.sun'',''elevation'') | float(0) }}'
|
||
- id: enhanced_8am_failsafe
|
||
alias: Enhanced 8 AM Failsafe
|
||
description: Force Day mode at 8 AM if not already in Day or Away mode
|
||
triggers:
|
||
- trigger: time
|
||
at: 08:00:00
|
||
conditions:
|
||
- condition: not
|
||
conditions:
|
||
- condition: state
|
||
entity_id: input_select.home_state
|
||
state:
|
||
- Day
|
||
- Away
|
||
- condition: state
|
||
entity_id: binary_sensor.both_phones_home
|
||
state: 'on'
|
||
actions:
|
||
- action: input_select.select_option
|
||
target:
|
||
entity_id: input_select.home_state
|
||
data:
|
||
option: Day
|
||
- action: logbook.log
|
||
data:
|
||
name: 8 AM Failsafe
|
||
message: 'WARNING: Forced Day mode - system was stuck in {{ trigger.from_state.state
|
||
}} mode'
|
||
- id: sleep_in_ramp_start
|
||
alias: Sleep-In Ramp - Start
|
||
description: Starts the sleep-in ramp with calculate-once smart duration
|
||
mode: single
|
||
triggers:
|
||
- trigger: state
|
||
entity_id: input_boolean.sleep_in_ramp_active
|
||
to: 'on'
|
||
conditions:
|
||
- condition: state
|
||
entity_id: input_boolean.sleep_in_ramp_system_enable
|
||
state: 'on'
|
||
- condition: state
|
||
entity_id: input_select.home_state
|
||
state: Night
|
||
actions:
|
||
- variables:
|
||
current_sun: '{{ state_attr(''sun.sun'', ''elevation'') | float(0) }}'
|
||
sun_rate: '{{ states(''sensor.sun_elevation_rate'') | float(0.03) }}'
|
||
target_el: '{{ states(''input_number.current_day_threshold'') | float(10) }}'
|
||
rate_based_minutes: '{{ ((target_el - current_sun) / sun_rate) | round(0) if
|
||
sun_rate > 0.005 and sun_rate < 0.2 else 999 }}'
|
||
elevation_based_minutes: '{{ states(''sensor.minutes_to_day_mode_elevation'')
|
||
| int(999) }}'
|
||
motion_time: '{{ now() }}'
|
||
motion_hour: '{{ motion_time.hour }}'
|
||
motion_minute: '{{ motion_time.minute }}'
|
||
is_work_window: '{{ (motion_hour == 4 and motion_minute >= 50) or (motion_hour
|
||
== 5 and motion_minute == 0) }}'
|
||
work_base: '{{ states(''input_number.workday_ramp_base_duration'') | int(50)
|
||
}}'
|
||
off_base: '{{ states(''input_number.offday_ramp_base_duration'') | int(75) }}'
|
||
base_duration: '{{ work_base if is_work_window else off_base }}'
|
||
calculated_duration: "{% if 10 <= rate_based_minutes <= 180 %}\n {{ rate_based_minutes\
|
||
\ }}\n{% elif 10 <= elevation_based_minutes <= 240 %}\n {{ elevation_based_minutes\
|
||
\ }}\n{% else %}\n {% set season = states('sensor.current_season') %}\n \
|
||
\ {{ 60 if season == 'Winter' else 45 if season in ['Spring', 'Fall'] else\
|
||
\ 30 }}\n{% endif %}"
|
||
final_duration: "{% if calculated_duration < 30 %}\n {{ [calculated_duration\
|
||
\ * 0.8, 15] | max }}\n{% elif calculated_duration < 60 %}\n {{ [calculated_duration\
|
||
\ * 0.9, 25] | max }}\n{% else %}\n {% set season = states('sensor.current_season')\
|
||
\ %}\n {% set multiplier = 1.3 if season == 'Winter' else 0.8 if season ==\
|
||
\ 'Summer' else 1.0 %}\n {{ [base_duration * multiplier, 120] | min }}\n\
|
||
{% endif %}"
|
||
- action: input_datetime.set_datetime
|
||
target:
|
||
entity_id: input_datetime.ramp_start_time
|
||
data:
|
||
datetime: '{{ now().strftime(''%Y-%m-%d %H:%M:%S'') }}'
|
||
- action: input_number.set_value
|
||
target:
|
||
entity_id: input_number.calculated_ramp_duration
|
||
data:
|
||
value: '{{ final_duration | round(0) }}'
|
||
- action: input_datetime.set_datetime
|
||
target:
|
||
entity_id: input_datetime.ramp_calculated_end_time
|
||
data:
|
||
datetime: '{{ (now() + timedelta(minutes=final_duration|int)).strftime(''%Y-%m-%d
|
||
%H:%M:%S'') }}'
|
||
- action: input_datetime.set_datetime
|
||
target:
|
||
entity_id: input_datetime.first_kitchen_motion_today
|
||
data:
|
||
datetime: '{{ now().strftime(''%Y-%m-%d %H:%M:%S'') }}'
|
||
- action: input_boolean.turn_on
|
||
target:
|
||
entity_id: input_boolean.daily_motion_lock
|
||
- action: input_select.select_option
|
||
target:
|
||
entity_id: input_select.home_state
|
||
data:
|
||
option: Early Morning
|
||
- id: sleep_in_ramp_complete
|
||
alias: Sleep-In Ramp - Complete
|
||
description: Completes the ramp when 100% progress is reached OR Day mode begins
|
||
mode: single
|
||
triggers:
|
||
- trigger: template
|
||
value_template: "{{ is_state('input_boolean.sleep_in_ramp_active', 'on') and\n\
|
||
\ states('sensor.sleep_in_ramp_progress') | float(0) >= 100 }}\n"
|
||
for:
|
||
seconds: 5
|
||
- trigger: state
|
||
entity_id: sensor.calculated_home_mode
|
||
to: Day
|
||
conditions:
|
||
- condition: state
|
||
entity_id: input_boolean.sleep_in_ramp_active
|
||
state: 'on'
|
||
actions:
|
||
- variables:
|
||
motion_time_str: '{{ states(''input_datetime.first_kitchen_motion_today'') }}'
|
||
is_non_work_day: "{% if motion_time_str not in ['unknown', 'unavailable', '']\
|
||
\ %}\n {% set motion_time = as_datetime(motion_time_str) %}\n {% set motion_hour\
|
||
\ = motion_time.hour %}\n {% set motion_minute = motion_time.minute %}\n\
|
||
\ {% set is_work_window = (motion_hour == 4 and motion_minute >= 50) or (motion_hour\
|
||
\ == 5 and motion_minute == 0) %}\n {{ not is_work_window }}\n{% else %}\n\
|
||
\ {{ not is_state('binary_sensor.working_today', 'on') }}\n{% endif %}"
|
||
- action: input_boolean.turn_off
|
||
target:
|
||
entity_id: input_boolean.sleep_in_ramp_active
|
||
- action: input_select.select_option
|
||
target:
|
||
entity_id: input_select.home_state
|
||
data:
|
||
option: Day
|
||
- if:
|
||
- condition: template
|
||
value_template: '{{ is_non_work_day }}'
|
||
- condition: state
|
||
entity_id: input_boolean.kitchen_wled_enable
|
||
state: 'on'
|
||
then:
|
||
- action: light.turn_off
|
||
target:
|
||
entity_id:
|
||
- light.sink_wled
|
||
- light.frig_strip
|
||
- action: logbook.log
|
||
data:
|
||
name: WLED Control
|
||
message: Kitchen WLED turned off at end of non-work day ramp
|
||
- action: logbook.log
|
||
data:
|
||
name: Sleep-In Ramp
|
||
message: 'Ramp complete - Triggered by: {{ trigger.platform }} | Non-work day:
|
||
{{ is_non_work_day }}'
|
||
- id: daily_motion_reset
|
||
alias: Daily Motion Reset
|
||
description: Resets daily motion lock and tracking at midnight
|
||
triggers:
|
||
- trigger: time
|
||
at: 00:00:00
|
||
actions:
|
||
- action: input_boolean.turn_off
|
||
target:
|
||
entity_id: input_boolean.daily_motion_lock
|
||
- action: input_datetime.set_datetime
|
||
target:
|
||
entity_id: input_datetime.first_kitchen_motion_today
|
||
data:
|
||
datetime: ''
|
||
- id: evening_temperature_ramp_start
|
||
alias: ALS - Evening Temperature Ramp Start
|
||
description: Starts the evening temperature ramp when Evening mode begins
|
||
mode: single
|
||
triggers:
|
||
- trigger: state
|
||
entity_id: input_select.home_state
|
||
to: Evening
|
||
conditions:
|
||
- condition: state
|
||
entity_id: input_boolean.enable_evening_temperature_ramp
|
||
state: 'on'
|
||
- condition: state
|
||
entity_id: input_select.home_state
|
||
state: Evening
|
||
actions:
|
||
- action: input_datetime.set_datetime
|
||
target:
|
||
entity_id: input_datetime.evening_ramp_started
|
||
data:
|
||
datetime: '{{ now() }}'
|
||
- action: input_number.set_value
|
||
target:
|
||
entity_id: input_number.evening_ramp_start_temp
|
||
data:
|
||
value: '{{ states(''sensor.intelligent_temperature_master'') | int(4000) }}'
|
||
- id: evening_temperature_ramp_apply_existing
|
||
alias: ALS - Apply Ramp to Already-On Lights
|
||
description: Updates lights that are already on when Evening mode starts
|
||
mode: single
|
||
triggers:
|
||
- trigger: state
|
||
entity_id: input_select.home_state
|
||
to: Evening
|
||
conditions:
|
||
- condition: state
|
||
entity_id: input_boolean.enable_evening_temperature_ramp
|
||
state: 'on'
|
||
actions:
|
||
- delay:
|
||
seconds: 2
|
||
- if:
|
||
- condition: or
|
||
conditions:
|
||
- condition: state
|
||
entity_id: light.lamp_1
|
||
state: 'on'
|
||
- condition: state
|
||
entity_id: light.lamp_2
|
||
state: 'on'
|
||
then:
|
||
- action: light.turn_on
|
||
target:
|
||
entity_id:
|
||
- light.lamp_1
|
||
- light.lamp_2
|
||
data:
|
||
color_temp_kelvin: '{{ states(''sensor.evening_temperature_ramp'') | int(4000)
|
||
}}'
|
||
transition: 10
|
||
- if:
|
||
- condition: state
|
||
entity_id: light.closet
|
||
state: 'on'
|
||
then:
|
||
- action: light.turn_on
|
||
target:
|
||
entity_id: light.closet
|
||
data:
|
||
color_temp_kelvin: '{{ states(''sensor.evening_temperature_ramp'') | int(4000)
|
||
}}'
|
||
transition: 10
|
||
- id: evening_temperature_ramp_cleanup
|
||
alias: ALS - Evening Temperature Ramp Cleanup
|
||
description: Cleans up ramp data when Evening ends or at midnight reset
|
||
mode: restart
|
||
triggers:
|
||
- trigger: state
|
||
entity_id: input_select.home_state
|
||
from: Evening
|
||
id: mode_change
|
||
- trigger: time
|
||
at: 00:00:00
|
||
id: midnight_reset
|
||
conditions:
|
||
- condition: state
|
||
entity_id: input_boolean.enable_evening_temperature_ramp
|
||
state: 'on'
|
||
actions:
|
||
- action: input_datetime.set_datetime
|
||
target:
|
||
entity_id: input_datetime.evening_ramp_started
|
||
data:
|
||
datetime: ''
|
||
- action: input_number.set_value
|
||
target:
|
||
entity_id: input_number.evening_ramp_start_temp
|
||
data:
|
||
value: 4000
|
||
- id: evening_smooth_temperature_ramp_start
|
||
alias: Evening - Start Smooth Temperature Ramp
|
||
description: Starts smooth temperature ramping for all evening lights
|
||
mode: single
|
||
triggers:
|
||
- trigger: state
|
||
entity_id: input_select.home_state
|
||
to: Evening
|
||
- trigger: state
|
||
entity_id: sensor.evening_temperature_ramp
|
||
id: sensor_change
|
||
conditions:
|
||
- condition: state
|
||
entity_id: input_select.home_state
|
||
state: Evening
|
||
- condition: state
|
||
entity_id: input_boolean.enable_evening_temperature_ramp
|
||
state: 'on'
|
||
- condition: or
|
||
conditions:
|
||
- condition: state
|
||
entity_id: light.lamp_1
|
||
state: 'on'
|
||
- condition: state
|
||
entity_id: light.lamp_2
|
||
state: 'on'
|
||
- condition: state
|
||
entity_id: light.closet
|
||
state: 'on'
|
||
actions:
|
||
- action: script.turn_on
|
||
target:
|
||
entity_id: script.evening_smooth_temperature_ramp
|
||
- id: evening_smooth_temperature_ramp_stop
|
||
alias: Evening - Stop Smooth Temperature Ramp
|
||
description: Stops smooth temperature ramping when Evening ends
|
||
mode: restart
|
||
triggers:
|
||
- trigger: state
|
||
entity_id: input_select.home_state
|
||
from: Evening
|
||
actions:
|
||
- action: script.turn_off
|
||
target:
|
||
entity_id: script.evening_smooth_temperature_ramp
|
||
- action: logbook.log
|
||
data:
|
||
name: Evening Automation
|
||
message: ✅ Evening smooth temperature ramp stopped - home state changed from
|
||
Evening
|
||
- id: kitchen_pyscript_morning_ramp_trigger
|
||
alias: Kitchen - Morning Ramp PyScript Trigger (motion)
|
||
mode: single
|
||
trigger:
|
||
- trigger: state
|
||
entity_id:
|
||
- binary_sensor.aqara_motion_sensor_p1_occupancy
|
||
- binary_sensor.kitchen_iris_frig_occupancy
|
||
to: 'on'
|
||
condition:
|
||
- condition: state
|
||
entity_id: input_boolean.sleep_in_ramp_system_enable
|
||
state: 'on'
|
||
- condition: state
|
||
entity_id: input_select.home_state
|
||
state: Night
|
||
action:
|
||
- action: pyscript.morning_ramp_first_motion
|
||
data:
|
||
sensor: '{{ trigger.entity_id }}'
|
||
- id: livingroom_auto_lights_main
|
||
alias: Living Room - Auto Control
|
||
description: Controls living room lighting based on home state and weather
|
||
mode: restart
|
||
triggers:
|
||
- trigger: state
|
||
entity_id: input_select.home_state
|
||
- trigger: state
|
||
entity_id: sensor.living_room_target_brightness
|
||
conditions:
|
||
- condition: state
|
||
entity_id: input_boolean.livingroom_auto_lights_enable
|
||
state: 'on'
|
||
- condition: not
|
||
conditions:
|
||
- condition: state
|
||
entity_id: input_select.home_state
|
||
state: Away
|
||
actions:
|
||
- variables:
|
||
target_brightness: '{{ states(''sensor.living_room_target_brightness'') | int(0)
|
||
}}'
|
||
target_temperature: '{{ states(''sensor.evening_temperature_ramp'') | int(3000)
|
||
}}'
|
||
- choose:
|
||
- conditions:
|
||
- condition: template
|
||
value_template: '{{ target_brightness > 0 }}'
|
||
sequence:
|
||
- action: light.turn_on
|
||
target:
|
||
entity_id:
|
||
- light.lamp_1
|
||
- light.lamp_2
|
||
data:
|
||
brightness_pct: '{{ target_brightness }}'
|
||
color_temp_kelvin: '{{ target_temperature }}'
|
||
- conditions:
|
||
- condition: template
|
||
value_template: '{{ target_brightness == 0 }}'
|
||
sequence:
|
||
- action: light.turn_off
|
||
target:
|
||
entity_id:
|
||
- light.lamp_1
|
||
- light.lamp_2
|
||
data:
|
||
transition: 5
|
||
- id: living_room_weather_transition
|
||
alias: Living Room - Smooth Weather Transition
|
||
description: Slowly adjusts brightness when weather conditions change and lights
|
||
are already on.
|
||
mode: restart
|
||
triggers:
|
||
- trigger: state
|
||
entity_id: sensor.living_room_target_brightness
|
||
conditions:
|
||
- condition: state
|
||
entity_id: input_boolean.enable_weather_transitions
|
||
state: 'on'
|
||
- condition: or
|
||
conditions:
|
||
- condition: state
|
||
entity_id: light.lamp_1
|
||
state: 'on'
|
||
- condition: state
|
||
entity_id: light.lamp_2
|
||
state: 'on'
|
||
- condition: state
|
||
entity_id: input_select.home_state
|
||
state: Day
|
||
- condition: template
|
||
value_template: '{{ (trigger.to_state.state | int(0) - trigger.from_state.state
|
||
| int(0)) | abs > 10 }}'
|
||
actions:
|
||
- variables:
|
||
transition_seconds: '{{ states(''input_number.weather_transition_duration_minutes'')
|
||
| int(5) * 60 }}'
|
||
- action: light.turn_on
|
||
target:
|
||
entity_id:
|
||
- light.lamp_1
|
||
- light.lamp_2
|
||
data:
|
||
brightness_pct: '{{ trigger.to_state.state | int(0) }}'
|
||
transition: '{{ transition_seconds }}'
|
||
- id: living_room_evening_ramp_control
|
||
alias: Living Room - Evening Ramp Control
|
||
description: Starts or stops the evening lighting ramp based on home state.
|
||
mode: single
|
||
triggers:
|
||
- trigger: state
|
||
entity_id: input_select.home_state
|
||
to: Evening
|
||
id: start
|
||
- trigger: state
|
||
entity_id: input_select.home_state
|
||
from: Evening
|
||
id: stop
|
||
conditions:
|
||
- condition: state
|
||
entity_id: input_boolean.living_room_evening_ramp_enabled
|
||
state: 'on'
|
||
actions:
|
||
- choose:
|
||
- conditions:
|
||
- condition: trigger
|
||
id: start
|
||
sequence:
|
||
- action: script.turn_on
|
||
target:
|
||
entity_id: script.als_living_room_evening_ramp
|
||
- conditions:
|
||
- condition: trigger
|
||
id: stop
|
||
sequence:
|
||
- action: script.turn_off
|
||
target:
|
||
entity_id: script.als_living_room_evening_ramp
|
||
- id: laundry_motion_lights
|
||
alias: Laundry Room - Motion Lights
|
||
description: Motion-triggered lighting with adaptive/intelligent brightness control
|
||
mode: restart
|
||
triggers:
|
||
- trigger: state
|
||
entity_id: binary_sensor.laundry_iris_occupancy
|
||
to: 'on'
|
||
conditions:
|
||
- condition: state
|
||
entity_id: input_boolean.laundry_motion_automation
|
||
state: 'on'
|
||
- condition: not
|
||
conditions:
|
||
- condition: state
|
||
entity_id: input_select.home_state
|
||
state: Away
|
||
- condition: template
|
||
value_template: "{{ trigger.from_state is not none and\n trigger.from_state.state\
|
||
\ not in ['unknown', 'unavailable'] }}\n"
|
||
actions:
|
||
- action: light.turn_on
|
||
target:
|
||
entity_id: light.laundry_room
|
||
data:
|
||
brightness_pct: '{{ states(''sensor.laundry_room_target_brightness'') | int
|
||
}}'
|
||
- id: laundry_motion_off
|
||
alias: Laundry Room - Motion Off
|
||
description: Turns off laundry lights after motion timeout
|
||
mode: restart
|
||
triggers:
|
||
- trigger: state
|
||
entity_id: binary_sensor.laundry_iris_occupancy
|
||
to: 'off'
|
||
for:
|
||
seconds: '{{ states(''input_number.laundry_motion_timeout'') | int(30) }}'
|
||
conditions:
|
||
- condition: state
|
||
entity_id: input_boolean.laundry_motion_automation
|
||
state: 'on'
|
||
- condition: state
|
||
entity_id: light.laundry_room
|
||
state: 'on'
|
||
- condition: not
|
||
conditions:
|
||
- condition: state
|
||
entity_id: input_select.home_state
|
||
state: Away
|
||
actions:
|
||
- action: light.turn_off
|
||
target:
|
||
entity_id: light.laundry_room
|
||
data:
|
||
transition: 3
|
||
- id: laundry_mode_transitions
|
||
alias: Laundry Room - Mode Transitions
|
||
description: Handles lighting changes when home mode changes
|
||
mode: restart
|
||
triggers:
|
||
- trigger: state
|
||
entity_id: input_select.home_state
|
||
actions:
|
||
- choose:
|
||
- conditions: '{{ trigger.to_state.state == ''Away'' }}'
|
||
sequence:
|
||
- action: light.turn_off
|
||
target:
|
||
entity_id: light.laundry_room
|
||
- conditions: '{{ trigger.to_state.state == ''Night'' and is_state(''light.laundry_room'',
|
||
''on'') }}'
|
||
sequence:
|
||
- action: light.turn_on
|
||
target:
|
||
entity_id: light.laundry_room
|
||
data:
|
||
brightness_pct: '{{ states(''sensor.laundry_room_target_brightness'') |
|
||
int }}'
|
||
transition: 5
|
||
- id: hallway_motion_lights
|
||
alias: Hallway - Motion Lights
|
||
description: Motion-triggered lighting with adaptive/intelligent brightness control
|
||
mode: restart
|
||
triggers:
|
||
- trigger: state
|
||
entity_id: binary_sensor.hallway_iris_occupancy
|
||
to: 'on'
|
||
conditions:
|
||
- condition: state
|
||
entity_id: input_boolean.hallway_motion_automation
|
||
state: 'on'
|
||
- condition: not
|
||
conditions:
|
||
- condition: state
|
||
entity_id: input_select.home_state
|
||
state: Away
|
||
- condition: template
|
||
value_template: "{{ trigger.from_state is not none and\n trigger.from_state.state\
|
||
\ not in ['unknown', 'unavailable'] }}\n"
|
||
actions:
|
||
- action: light.turn_on
|
||
target:
|
||
entity_id: light.hallway
|
||
data:
|
||
brightness_pct: '{{ states(''sensor.hallway_target_brightness'') | int }}'
|
||
- id: hallway_motion_off
|
||
alias: Hallway - Motion Off
|
||
description: Turns off hallway lights after motion timeout
|
||
mode: restart
|
||
triggers:
|
||
- trigger: state
|
||
entity_id: binary_sensor.hallway_iris_occupancy
|
||
to: 'off'
|
||
for:
|
||
seconds: '{{ states(''input_number.hallway_motion_timeout'') | int(30) }}'
|
||
conditions:
|
||
- condition: state
|
||
entity_id: input_boolean.hallway_motion_automation
|
||
state: 'on'
|
||
- condition: state
|
||
entity_id: light.hallway
|
||
state: 'on'
|
||
- condition: not
|
||
conditions:
|
||
- condition: state
|
||
entity_id: input_select.home_state
|
||
state: Away
|
||
actions:
|
||
- action: light.turn_off
|
||
target:
|
||
entity_id: light.hallway
|
||
data:
|
||
transition: 3
|
||
- id: bedroom_motion_lights
|
||
alias: Bedroom - Motion Lights
|
||
description: 'Primary automation: Turns on the closet light when motion is detected.'
|
||
mode: restart
|
||
triggers:
|
||
- trigger: state
|
||
entity_id: binary_sensor.bedroom_x_occupancy
|
||
to: 'on'
|
||
conditions:
|
||
- condition: state
|
||
entity_id: input_boolean.bedroom_motion_automation
|
||
state: 'on'
|
||
- condition: not
|
||
conditions:
|
||
- condition: state
|
||
entity_id: input_select.home_state
|
||
state: Away
|
||
- condition: template
|
||
value_template: "{{ trigger.from_state is not none and\n trigger.from_state.state\
|
||
\ not in ['unknown', 'unavailable'] }}\n"
|
||
actions:
|
||
- action: light.turn_on
|
||
target:
|
||
entity_id: light.closet
|
||
data:
|
||
brightness_pct: '{{ states(''sensor.bedroom_target_brightness'') | int }}'
|
||
color_temp_kelvin: '{{ state_attr(''sensor.bedroom_target_brightness'', ''temperature'')
|
||
| int(3000) }}'
|
||
- id: bedroom_motion_off
|
||
alias: Bedroom - Motion Off
|
||
description: Turns off closet light after motion timeout.
|
||
mode: restart
|
||
triggers:
|
||
- trigger: state
|
||
entity_id: binary_sensor.bedroom_x_occupancy
|
||
to: 'off'
|
||
for:
|
||
seconds: '{{ states(''input_number.bedroom_motion_timeout'') | int(30) }}'
|
||
conditions:
|
||
- condition: state
|
||
entity_id: input_boolean.bedroom_motion_automation
|
||
state: 'on'
|
||
- condition: state
|
||
entity_id: light.closet
|
||
state: 'on'
|
||
- condition: not
|
||
conditions:
|
||
- condition: state
|
||
entity_id: input_select.home_state
|
||
state: Away
|
||
actions:
|
||
- action: light.turn_off
|
||
target:
|
||
entity_id: light.closet
|
||
data:
|
||
transition: 2
|
||
- id: bedroom_mode_transitions
|
||
alias: Bedroom - Mode Transitions
|
||
description: Handles lighting changes when home mode changes (e.g., to Away or Night).
|
||
mode: restart
|
||
triggers:
|
||
- trigger: state
|
||
entity_id: input_select.home_state
|
||
actions:
|
||
- choose:
|
||
- conditions: '{{ trigger.to_state.state == ''Away'' }}'
|
||
sequence:
|
||
- action: light.turn_off
|
||
target:
|
||
entity_id: light.closet
|
||
- conditions: '{{ trigger.to_state.state == ''Night'' and is_state(''light.closet'',
|
||
''on'') }}'
|
||
sequence:
|
||
- action: light.turn_on
|
||
target:
|
||
entity_id: light.closet
|
||
data:
|
||
brightness_pct: '{{ states(''sensor.bedroom_target_brightness'') | int }}'
|
||
color_temp_kelvin: '{{ state_attr(''sensor.bedroom_target_brightness'',
|
||
''temperature'') | int(3000) }}'
|
||
- id: bathroom_motion_on
|
||
alias: Bathroom - Motion Detected
|
||
mode: single
|
||
triggers:
|
||
- trigger: state
|
||
entity_id: binary_sensor.bathroom_motion_combined
|
||
to: 'on'
|
||
conditions:
|
||
- condition: state
|
||
entity_id: input_boolean.bathroom_motion_automation
|
||
state: 'on'
|
||
- condition: not
|
||
conditions:
|
||
- condition: state
|
||
entity_id: input_select.home_state
|
||
state: Away
|
||
- condition: template
|
||
value_template: "{{ trigger.from_state is not none and\n trigger.from_state.state\
|
||
\ not in ['unknown', 'unavailable'] }}\n"
|
||
actions:
|
||
- action: light.turn_on
|
||
target:
|
||
entity_id: light.bathroom_2_main_lights
|
||
data:
|
||
brightness_pct: '{{ states(''sensor.bathroom_target_brightness'') | int }}'
|
||
- id: bathroom_door_closes
|
||
alias: Bathroom - Door Closes
|
||
description: When door closes, set lights to 100% and enable hold mode
|
||
mode: single
|
||
triggers:
|
||
- trigger: state
|
||
entity_id: binary_sensor.bathroom_contact_contact
|
||
to: 'off'
|
||
for:
|
||
seconds: 2
|
||
conditions:
|
||
- condition: state
|
||
entity_id: input_boolean.bathroom_motion_automation
|
||
state: 'on'
|
||
- condition: not
|
||
conditions:
|
||
- condition: state
|
||
entity_id: input_select.home_state
|
||
state: Away
|
||
actions:
|
||
- action: input_boolean.turn_on
|
||
target:
|
||
entity_id: input_boolean.bathroom_100_percent_hold
|
||
- action: light.turn_on
|
||
target:
|
||
entity_id: light.bathroom_2_main_lights
|
||
data:
|
||
brightness_pct: 100
|
||
- id: bathroom_door_opens
|
||
alias: Bathroom - Door Opens
|
||
description: When door opens, disable hold mode and transition lights back to smart
|
||
brightness
|
||
mode: single
|
||
triggers:
|
||
- trigger: state
|
||
entity_id: binary_sensor.bathroom_contact_contact
|
||
to: 'on'
|
||
for:
|
||
seconds: 2
|
||
conditions:
|
||
- condition: state
|
||
entity_id: input_boolean.bathroom_motion_automation
|
||
state: 'on'
|
||
- condition: state
|
||
entity_id: light.bathroom_2_main_lights
|
||
state: 'on'
|
||
- condition: not
|
||
conditions:
|
||
- condition: state
|
||
entity_id: input_select.home_state
|
||
state: Away
|
||
actions:
|
||
- action: input_boolean.turn_off
|
||
target:
|
||
entity_id: input_boolean.bathroom_100_percent_hold
|
||
- action: light.turn_on
|
||
target:
|
||
entity_id: light.bathroom_2_main_lights
|
||
data:
|
||
brightness_pct: '{{ states(''sensor.bathroom_target_brightness'') | int }}'
|
||
transition: 5
|
||
- id: bathroom_motion_clear
|
||
alias: Bathroom - Motion Clears
|
||
description: Turn off lights after 30s of no motion, but ONLY if door is open
|
||
mode: restart
|
||
triggers:
|
||
- trigger: state
|
||
entity_id: binary_sensor.bathroom_motion_combined
|
||
to: 'off'
|
||
for:
|
||
seconds: 30
|
||
conditions:
|
||
- condition: state
|
||
entity_id: input_boolean.bathroom_motion_automation
|
||
state: 'on'
|
||
- condition: state
|
||
entity_id: light.bathroom_2_main_lights
|
||
state: 'on'
|
||
- condition: state
|
||
entity_id: binary_sensor.bathroom_contact_contact
|
||
state: 'on'
|
||
actions:
|
||
- action: light.turn_off
|
||
target:
|
||
entity_id: light.bathroom_2_main_lights
|
||
data:
|
||
transition: 3
|
||
- id: bathroom_hold_mode_timeout
|
||
alias: Bathroom - Hold Mode Timeout Failsafe
|
||
description: Turns off 100% hold mode after a set duration to prevent it getting
|
||
stuck
|
||
mode: single
|
||
triggers:
|
||
- trigger: state
|
||
entity_id: input_boolean.bathroom_100_percent_hold
|
||
to: 'on'
|
||
for:
|
||
minutes: '{{ states(''input_number.bathroom_hold_timeout'') | int(30) }}'
|
||
conditions:
|
||
- condition: state
|
||
entity_id: input_boolean.bathroom_100_percent_hold
|
||
state: 'on'
|
||
actions:
|
||
- action: input_boolean.turn_off
|
||
target:
|
||
entity_id: input_boolean.bathroom_100_percent_hold
|
||
- action: logbook.log
|
||
data:
|
||
name: Bathroom Hold Mode
|
||
message: ⏰ Hold mode timed out and was automatically disabled.
|
||
- id: als_system_error_capture
|
||
alias: ALS - System Error Capture
|
||
description: Captures system log errors and classifies them by room/system
|
||
mode: queued
|
||
max_exceeded: silent
|
||
triggers:
|
||
- trigger: event
|
||
event_type: system_log_event
|
||
event_data:
|
||
level: ERROR
|
||
- trigger: event
|
||
event_type: system_log_event
|
||
event_data:
|
||
level: CRITICAL
|
||
- trigger: event
|
||
event_type: system_log_event
|
||
event_data:
|
||
level: WARNING
|
||
conditions:
|
||
- condition: state
|
||
entity_id: input_boolean.als_diagnostics_enabled
|
||
state: 'on'
|
||
actions:
|
||
- action: pyscript.process_als_error
|
||
data:
|
||
message: '{{ trigger.event.data.message }}'
|
||
level: '{{ trigger.event.data.level }}'
|
||
source: '{{ trigger.event.data.name | default(''Unknown'') }}'
|
||
- id: routine_timing_capture
|
||
alias: Routine Timing - Completion Detection
|
||
description: Detects routine completion when living room lights are turned off during
|
||
Early Morning mode
|
||
mode: single
|
||
triggers:
|
||
- trigger: state
|
||
entity_id:
|
||
- light.lamp_1
|
||
- light.lamp_2
|
||
to: 'off'
|
||
for:
|
||
seconds: 5
|
||
conditions:
|
||
- condition: state
|
||
entity_id: input_select.home_state
|
||
state: Early Morning
|
||
- condition: state
|
||
entity_id: light.lamp_1
|
||
state: 'off'
|
||
- condition: state
|
||
entity_id: light.lamp_2
|
||
state: 'off'
|
||
- condition: template
|
||
value_template: "{{ (now() - states.light.lamp_1.last_changed).total_seconds()\
|
||
\ > 30 and\n (now() - states.light.lamp_2.last_changed).total_seconds() >\
|
||
\ 30 }}\n"
|
||
actions:
|
||
- variables:
|
||
completion_time: '{{ now().strftime(''%H:%M:%S'') }}'
|
||
day_type: '{{ ''work'' if is_state(''binary_sensor.workday_sensor'', ''on'')
|
||
else ''weekend'' }}
|
||
|
||
'
|
||
- action: pyscript.store_routine_timing
|
||
data:
|
||
completion_time_str: '{{ completion_time }}'
|
||
confidence_pct: 90.0
|
||
- action: logbook.log
|
||
data:
|
||
name: Routine Learning
|
||
message: 📊 Captured routine completion at {{ completion_time }} ({{ day_type
|
||
}} day)
|
||
- if:
|
||
- condition: state
|
||
entity_id: input_boolean.als_verbose_logging
|
||
state: 'on'
|
||
then:
|
||
- action: notify.persistent_notification
|
||
data:
|
||
title: 🎯 Routine Learning
|
||
message: Learned routine completion at {{ completion_time }} on {{ day_type
|
||
}} day
|
||
data:
|
||
tag: routine_learning
|
||
- id: manual_routine_completion
|
||
alias: Routine Timing - Manual Completion
|
||
description: Manually trigger routine completion capture
|
||
triggers:
|
||
- trigger: state
|
||
entity_id: input_boolean.manual_routine_capture
|
||
to: 'on'
|
||
conditions:
|
||
- condition: state
|
||
entity_id: input_select.home_state
|
||
state: Early Morning
|
||
actions:
|
||
- variables:
|
||
completion_time: '{{ now().strftime(''%H:%M:%S'') }}'
|
||
- action: pyscript.store_routine_timing
|
||
data:
|
||
completion_time_str: '{{ completion_time }}'
|
||
confidence_pct: 75.0
|
||
- action: logbook.log
|
||
data:
|
||
name: Routine Learning
|
||
message: 📊 Manual routine completion captured at {{ completion_time }}
|
||
- action: input_boolean.turn_off
|
||
target:
|
||
entity_id: input_boolean.manual_routine_capture
|
||
- id: health_pills_auto_refresh
|
||
alias: Health Pills Auto Refresh
|
||
description: Automatically refresh health pills when error feeds are updated
|
||
mode: queued
|
||
max_exceeded: silent
|
||
triggers:
|
||
- trigger: state
|
||
entity_id:
|
||
- input_text.als_error_feed_kitchen
|
||
- input_text.als_error_feed_bedroom
|
||
- input_text.als_error_feed_livingroom
|
||
- input_text.als_error_feed_bathroom
|
||
- input_text.als_error_feed_hallway
|
||
- input_text.als_error_feed_laundry
|
||
- trigger: state
|
||
entity_id:
|
||
- input_text.als_error_kitchen
|
||
- input_text.als_error_bedroom
|
||
- input_text.als_error_livingroom
|
||
- input_text.als_error_bathroom
|
||
- input_text.als_error_hallway
|
||
- input_text.als_error_laundry
|
||
conditions:
|
||
- condition: template
|
||
value_template: '{{ trigger.from_state.state != trigger.to_state.state }}'
|
||
actions:
|
||
- delay: 00:00:01
|
||
- action: pyscript.refresh_all_health_calculations
|
||
data: {}
|
||
- id: periodic_health_validation
|
||
alias: Periodic Health System Validation
|
||
description: Run health system tests every 6 hours
|
||
triggers:
|
||
- trigger: time_pattern
|
||
hours: /6
|
||
conditions:
|
||
- condition: state
|
||
entity_id: input_boolean.health_monitoring_auto_test
|
||
state: 'on'
|
||
actions:
|
||
- action: script.verify_health_system_accuracy
|
||
data: {}
|
||
- id: smart_health_status_notifications
|
||
alias: Smart Health Status Notifications
|
||
description: Context-aware notifications for health status changes with cooldown
|
||
management
|
||
mode: single
|
||
max_exceeded: silent
|
||
triggers:
|
||
- trigger: state
|
||
entity_id: sensor.global_health_status
|
||
for:
|
||
seconds: 30
|
||
conditions:
|
||
- condition: state
|
||
entity_id: input_boolean.smart_notifications_enabled
|
||
state: 'on'
|
||
- condition: template
|
||
value_template: '{{ trigger.from_state.state != trigger.to_state.state }}'
|
||
- condition: template
|
||
value_template: '{{ trigger.from_state.state not in [''unknown'', ''unavailable'']
|
||
}}'
|
||
actions:
|
||
- action: pyscript.handle_health_status_notification
|
||
data:
|
||
current_status: '{{ trigger.to_state.state }}'
|
||
previous_status: '{{ trigger.from_state.state }}'
|
||
status_attributes: "{{\n {\n 'status_text': state_attr('sensor.global_health_status',\
|
||
\ 'status_text'),\n 'affected_rooms': state_attr('sensor.global_health_status',\
|
||
\ 'affected_rooms'),\n 'total_error_count': state_attr('sensor.global_health_status',\
|
||
\ 'total_error_count'),\n 'summary': state_attr('sensor.global_health_status',\
|
||
\ 'summary')\n } | to_json\n}}"
|
||
- id: test_smart_notifications
|
||
alias: Test Smart Notifications
|
||
description: Manual trigger to test notification system
|
||
mode: single
|
||
triggers:
|
||
- trigger: state
|
||
entity_id: input_boolean.notification_debug_mode
|
||
from: 'off'
|
||
to: 'on'
|
||
conditions:
|
||
- condition: state
|
||
entity_id: input_boolean.smart_notifications_enabled
|
||
state: 'on'
|
||
actions:
|
||
- action: pyscript.test_notification_system
|
||
data: {}
|
||
- delay: 00:00:05
|
||
- action: input_boolean.turn_off
|
||
target:
|
||
entity_id: input_boolean.notification_debug_mode
|
||
- id: update_quiet_hours_status
|
||
alias: Update Quiet Hours Status
|
||
description: Track whether we're currently in quiet hours
|
||
mode: single
|
||
triggers:
|
||
- trigger: time_pattern
|
||
minutes: '*'
|
||
- trigger: state
|
||
entity_id:
|
||
- input_datetime.quiet_hours_start
|
||
- input_datetime.quiet_hours_end
|
||
- input_boolean.quiet_hours_enabled
|
||
actions:
|
||
- action: pyscript.update_quiet_hours_status
|
||
data: {}
|
||
- id: diagnostic_dashboard_auto_refresh
|
||
alias: Diagnostic Dashboard Auto Refresh
|
||
description: Automatically refresh dashboard when key data changes
|
||
mode: queued
|
||
max_exceeded: silent
|
||
triggers:
|
||
- trigger: state
|
||
entity_id:
|
||
- sensor.global_health_status
|
||
- input_text.als_learning_status
|
||
- input_text.learning_performance_metrics
|
||
- trigger: time_pattern
|
||
minutes: /5
|
||
conditions:
|
||
- condition: state
|
||
entity_id: input_boolean.diagnostic_dashboard_enabled
|
||
state: 'on'
|
||
actions:
|
||
- delay: 00:00:01
|
||
- action: script.refresh_dashboard_data
|
||
data: {}
|
||
- id: learning_status_monitor
|
||
alias: Learning Status Monitor
|
||
description: Monitor and update ALS learning system status
|
||
mode: restart
|
||
triggers:
|
||
- trigger: time_pattern
|
||
minutes: /2
|
||
conditions:
|
||
- condition: state
|
||
entity_id: input_boolean.als_diagnostics_enabled
|
||
state: 'on'
|
||
actions:
|
||
- action: pyscript.update_learning_system_status
|
||
data: {}
|
||
- action: pyscript.update_learning_performance_metrics
|
||
data: {}
|
||
- id: health_status_change_handler
|
||
alias: Health Status Change Handler
|
||
description: Handle health status changes with smart notifications
|
||
mode: queued
|
||
triggers:
|
||
- trigger: state
|
||
entity_id: sensor.global_health_status
|
||
from:
|
||
- 🟩
|
||
- 🟨
|
||
- 🟥
|
||
to:
|
||
- 🟩
|
||
- 🟨
|
||
- 🟥
|
||
conditions:
|
||
- condition: template
|
||
value_template: '{{ trigger.from_state.state != trigger.to_state.state }}'
|
||
- condition: state
|
||
entity_id: input_boolean.smart_notifications_enabled
|
||
state: 'on'
|
||
actions:
|
||
- delay: 00:00:30
|
||
- action: pyscript.handle_health_status_notification
|
||
data:
|
||
current_status: '{{ trigger.to_state.state }}'
|
||
previous_status: '{{ trigger.from_state.state }}'
|
||
status_attributes: '{{ trigger.to_state.attributes | to_json }}'
|
||
- id: quiet_hours_status_updater
|
||
alias: Quiet Hours Status Updater
|
||
description: Update quiet hours suppression status
|
||
mode: restart
|
||
triggers:
|
||
- trigger: time_pattern
|
||
minutes: /5
|
||
- trigger: state
|
||
entity_id:
|
||
- input_boolean.quiet_hours_enabled
|
||
- input_datetime.quiet_hours_start
|
||
- input_datetime.quiet_hours_end
|
||
actions:
|
||
- action: pyscript.update_quiet_hours_status
|
||
data: {}
|
||
- id: diagnostic_system_maintenance
|
||
alias: Diagnostic System Maintenance
|
||
description: Periodic maintenance and cleanup for diagnostic system
|
||
triggers:
|
||
- trigger: time_pattern
|
||
hours: /4
|
||
conditions:
|
||
- condition: state
|
||
entity_id: input_boolean.als_diagnostics_enabled
|
||
state: 'on'
|
||
actions:
|
||
- action: pyscript.perform_diagnostic_maintenance
|
||
data: {}
|
||
- action: script.refresh_dashboard_data
|
||
data: {}
|
||
- id: diagnostic_config_change_handler
|
||
alias: Diagnostic Configuration Change Handler
|
||
description: Handle configuration changes and refresh system
|
||
mode: restart
|
||
triggers:
|
||
- trigger: state
|
||
entity_id:
|
||
- input_number.error_retention_days
|
||
- input_number.max_errors_per_room
|
||
- input_number.health_check_interval
|
||
- input_number.error_threshold_warning
|
||
- input_number.error_threshold_critical
|
||
actions:
|
||
- delay: 00:00:02
|
||
- action: script.refresh_dashboard_data
|
||
data: {}
|
||
- action: logbook.log
|
||
data:
|
||
name: ALS Diagnostics
|
||
message: ⚙️ Configuration updated - dashboard refreshed
|
||
- id: maintenance_periodic_health_check
|
||
alias: 'Maintenance: Periodic Health Check'
|
||
description: Run health validation every 15 minutes
|
||
trigger:
|
||
- platform: time_pattern
|
||
minutes: /15
|
||
condition:
|
||
- condition: state
|
||
entity_id: input_boolean.maintenance_auto_cleanup_enabled
|
||
state: 'on'
|
||
action:
|
||
- service: pyscript.maintenance_health_check
|
||
data:
|
||
debug_mode: '{{ is_state(''input_boolean.maintenance_debug_mode'', ''on'') }}'
|
||
- service: logbook.log
|
||
data:
|
||
name: ALS Maintenance
|
||
message: Periodic health check completed
|
||
- id: maintenance_periodic_cleanup
|
||
alias: 'Maintenance: Automated Cleanup'
|
||
description: Run automated cleanup based on configured interval
|
||
trigger:
|
||
- platform: time_pattern
|
||
hours: /1
|
||
condition:
|
||
- condition: state
|
||
entity_id: input_boolean.maintenance_auto_cleanup_enabled
|
||
state: 'on'
|
||
- condition: template
|
||
value_template: "{% set last_cleanup = states('input_datetime.maintenance_last_cleanup_time')\
|
||
\ %} {% set interval_hours = states('input_number.maintenance_cleanup_interval_hours')\
|
||
\ | int %} {% if last_cleanup == 'unknown' %}\n true\n{% else %}\n {% set\
|
||
\ last_time = strptime(last_cleanup, '%Y-%m-%d %H:%M:%S') %}\n {% set now =\
|
||
\ now() %}\n {% set hours_since = (now - last_time).total_seconds() / 3600\
|
||
\ %}\n {{ hours_since >= interval_hours }}\n{% endif %}\n"
|
||
action:
|
||
- service: pyscript.maintenance_automated_cleanup
|
||
data:
|
||
retention_days: '{{ states(''input_number.maintenance_error_retention_days'')
|
||
| int }}'
|
||
max_entries: '{{ states(''input_number.maintenance_max_error_entries'') | int
|
||
}}'
|
||
debug_mode: '{{ is_state(''input_boolean.maintenance_debug_mode'', ''on'') }}'
|
||
- service: input_datetime.set_datetime
|
||
target:
|
||
entity_id: input_datetime.maintenance_last_cleanup_time
|
||
data:
|
||
datetime: '{{ now() }}'
|
||
- service: counter.increment
|
||
target:
|
||
entity_id: counter.maintenance_cleanup_runs
|
||
- service: logbook.log
|
||
data:
|
||
name: ALS Maintenance
|
||
message: Automated cleanup completed
|
||
- id: maintenance_performance_alert
|
||
alias: 'Maintenance: Performance Alert'
|
||
description: Alert when system performance is degraded
|
||
trigger:
|
||
- platform: numeric_state
|
||
entity_id: sensor.maintenance_system_health
|
||
below: 50
|
||
for:
|
||
minutes: 5
|
||
condition:
|
||
- condition: state
|
||
entity_id: input_boolean.maintenance_performance_monitoring
|
||
state: 'on'
|
||
action:
|
||
- service: persistent_notification.create
|
||
data:
|
||
title: ALS System Performance Warning
|
||
message: 'System health is at {{ states(''sensor.maintenance_system_health'')
|
||
}}%. Consider running manual cleanup or adjusting retention settings.
|
||
|
||
'
|
||
notification_id: als_performance_warning
|
||
- service: logbook.log
|
||
data:
|
||
name: ALS Maintenance
|
||
message: 'Performance alert triggered - Health: {{ states(''sensor.maintenance_system_health'')
|
||
}}%'
|
||
entity_id: sensor.maintenance_system_health
|
||
- id: maintenance_data_buildup_prevention
|
||
alias: 'Maintenance: Data Buildup Prevention'
|
||
description: Prevent excessive data buildup
|
||
trigger:
|
||
- platform: numeric_state
|
||
entity_id: sensor.als_total_error_count
|
||
above: '{{ states(''input_number.maintenance_max_error_entries'') | int }}'
|
||
condition:
|
||
- condition: state
|
||
entity_id: input_boolean.maintenance_auto_cleanup_enabled
|
||
state: 'on'
|
||
action:
|
||
- service: pyscript.maintenance_emergency_cleanup
|
||
data:
|
||
target_count: '{{ (states(''input_number.maintenance_max_error_entries'') |
|
||
int * 0.8) | int }}'
|
||
debug_mode: '{{ is_state(''input_boolean.maintenance_debug_mode'', ''on'') }}'
|
||
- service: persistent_notification.create
|
||
data:
|
||
title: ALS Emergency Cleanup Triggered
|
||
message: 'Error count exceeded limit. Emergency cleanup performed. Reduced to
|
||
{{ (states(''input_number.maintenance_max_error_entries'') | int * 0.8) |
|
||
int }} entries.
|
||
|
||
'
|
||
notification_id: als_emergency_cleanup
|
||
- service: logbook.log
|
||
data:
|
||
name: ALS Maintenance
|
||
message: Emergency cleanup triggered - Error count exceeded limit
|
||
- id: unlock_door_on_arrival
|
||
alias: Unlock door when either iPhone arrives home
|
||
description: Auto unlock front door when either phone enters home zone
|
||
triggers:
|
||
- trigger: zone
|
||
entity_id: device_tracker.iphone15
|
||
zone: zone.home
|
||
event: enter
|
||
- trigger: zone
|
||
entity_id: device_tracker.work_iphone
|
||
zone: zone.home
|
||
event: enter
|
||
conditions:
|
||
- condition: state
|
||
entity_id: input_boolean.smart_lock_auto_unlock
|
||
state: 'on'
|
||
actions:
|
||
- action: lock.unlock
|
||
target:
|
||
entity_id: lock.aqara_smart_lock_u100_lock
|
||
- action: notify.mobile_app_iphone15
|
||
data:
|
||
message: The front door was unlocked.
|
||
- action: notify.mobile_app_rrvqklh23h_iphone
|
||
data:
|
||
message: The front door was unlocked.
|
||
mode: single
|
||
- id: smart_switch_1_manual_amber_activate
|
||
alias: Smart Switch 1 - Manual Amber Activate
|
||
triggers:
|
||
- trigger: state
|
||
entity_id: input_boolean.smart_switch_1_manual_amber_trigger
|
||
to: 'on'
|
||
conditions:
|
||
- condition: state
|
||
entity_id: input_boolean.smart_switch_1_amber_mode_enable
|
||
state: 'on'
|
||
actions:
|
||
- action: script.smart_switch_1_amber_sequence
|
||
- action: input_boolean.turn_off
|
||
target:
|
||
entity_id: input_boolean.smart_switch_1_manual_amber_trigger
|
||
- action: logbook.log
|
||
data:
|
||
name: Smart Switch 1 Amber
|
||
message: Manual amber mode activated
|
||
entity_id: light.smart_switch_1
|
||
- id: smart_switch_2_manual_amber_activate
|
||
alias: Smart Switch 2 - Manual Amber Activate
|
||
triggers:
|
||
- trigger: state
|
||
entity_id: input_boolean.smart_switch_2_manual_amber_trigger
|
||
to: 'on'
|
||
conditions:
|
||
- condition: state
|
||
entity_id: input_boolean.smart_switch_2_amber_mode_enable
|
||
state: 'on'
|
||
actions:
|
||
- action: script.smart_switch_2_amber_sequence
|
||
- action: input_boolean.turn_off
|
||
target:
|
||
entity_id: input_boolean.smart_switch_2_manual_amber_trigger
|
||
- action: logbook.log
|
||
data:
|
||
name: Smart Switch 2 Amber
|
||
message: Manual amber mode activated
|
||
entity_id: light.smart_switch_2
|
||
- id: smart_switch_1_amber_button
|
||
alias: Smart Switch 1 - Amber Button
|
||
triggers:
|
||
- trigger: state
|
||
entity_id: input_button.smart_switch_1_activate_amber
|
||
actions:
|
||
- action: script.smart_switch_1_amber_sequence
|
||
- id: smart_switch_1_normal_button
|
||
alias: Smart Switch 1 - Normal Button
|
||
triggers:
|
||
- trigger: state
|
||
entity_id: input_button.smart_switch_1_normal_mode
|
||
actions:
|
||
- action: light.turn_on
|
||
target:
|
||
entity_id: light.smart_switch_1
|
||
data:
|
||
brightness_pct: 80
|
||
color_temp_kelvin: 4000
|
||
- id: smart_switch_2_amber_button
|
||
alias: Smart Switch 2 - Amber Button
|
||
triggers:
|
||
- trigger: state
|
||
entity_id: input_button.smart_switch_2_activate_amber
|
||
actions:
|
||
- action: script.smart_switch_2_amber_sequence
|
||
- id: smart_switch_2_normal_button
|
||
alias: Smart Switch 2 - Normal Button
|
||
triggers:
|
||
- trigger: state
|
||
entity_id: input_button.smart_switch_2_normal_mode
|
||
actions:
|
||
- action: light.turn_on
|
||
target:
|
||
entity_id: light.smart_switch_2
|
||
data:
|
||
brightness_pct: 80
|
||
color_temp_kelvin: 4000
|
||
- id: both_switches_amber_button
|
||
alias: Both Switches - Amber Button
|
||
triggers:
|
||
- trigger: state
|
||
entity_id: input_button.both_switches_amber
|
||
actions:
|
||
- action: script.both_switches_amber_mode
|
||
- id: both_switches_normal_button
|
||
alias: Both Switches - Normal Button
|
||
triggers:
|
||
- trigger: state
|
||
entity_id: input_button.both_switches_normal
|
||
actions:
|
||
- action: light.turn_on
|
||
target:
|
||
entity_id:
|
||
- light.smart_switch_1
|
||
- light.smart_switch_2
|
||
data:
|
||
brightness_pct: 80
|
||
color_temp_kelvin: 4000
|
||
- id: als_auto_error_cleanup
|
||
alias: ALS - Auto Error Cleanup
|
||
description: Automatically clears resolved errors after 1 hour
|
||
mode: restart
|
||
trigger:
|
||
- trigger: time_pattern
|
||
hours: /1
|
||
condition:
|
||
- condition: state
|
||
entity_id: binary_sensor.als_system_error_detected
|
||
state: 'on'
|
||
action:
|
||
- repeat:
|
||
for_each:
|
||
- bedroom
|
||
- kitchen
|
||
- bathroom
|
||
- hallway
|
||
- laundry
|
||
- livingroom
|
||
sequence:
|
||
- variables:
|
||
room: '{{ repeat.item }}'
|
||
error_entity: input_text.als_error_{{ room }}
|
||
- if:
|
||
- condition: template
|
||
value_template: '{{ states(error_entity) not in ['''', ''unknown'', ''unavailable'']
|
||
}}'
|
||
- condition: template
|
||
value_template: '{% set room_name = room | replace(''livingroom'', ''living_room'')
|
||
%} {% if room == ''laundry'' %}{% set room_name = ''laundry_room'' %}{%
|
||
endif %} {% set target_sensor = ''sensor.'' ~ room_name ~ ''_target_brightness''
|
||
%} {{ states(target_sensor) not in [''unknown'', ''unavailable''] }}'
|
||
then:
|
||
- action: input_text.set_value
|
||
target:
|
||
entity_id: '{{ error_entity }}'
|
||
data:
|
||
value: ''
|
||
- id: als_teach_button_bridge
|
||
alias: ALS - Teach Button Bridge
|
||
mode: single
|
||
trigger:
|
||
- trigger: state
|
||
entity_id: input_button.als_teach_now
|
||
action:
|
||
- variables:
|
||
sel: '{{ states(''input_select.als_teaching_room'') }}'
|
||
room_key: "{% set map = {\n 'Bedroom':'bedroom',\n 'Kitchen':'kitchen',\n\
|
||
\ 'Living Room':'livingroom',\n 'Hallway':'hallway',\n 'Bathroom':'bathroom',\n\
|
||
\ 'Laundry':'laundry'\n} %} {{ map.get(sel, 'kitchen') }}"
|
||
brightness: '{{ states(''input_number.als_teaching_brightness'') | int(50) }}'
|
||
- action: pyscript.als_teach_room
|
||
data:
|
||
room: '{{ room_key }}'
|
||
brightness: '{{ brightness }}'
|
||
- action: input_text.set_value
|
||
target:
|
||
entity_id: input_text.als_last_teach_status
|
||
data:
|
||
value: Taught {{ room_key }} → {{ brightness }}% at {{ now().strftime('%H:%M:%S')
|
||
}}
|
||
- id: als_reload_pyscript_button
|
||
alias: ALS - Reload Pyscript Button
|
||
mode: single
|
||
trigger:
|
||
- trigger: state
|
||
entity_id: input_button.als_reload_pyscript
|
||
action:
|
||
- action: pyscript.reload
|
||
- action: input_text.set_value
|
||
target:
|
||
entity_id: input_text.als_last_teach_status
|
||
data:
|
||
value: Pyscript reloaded at {{ now().strftime('%H:%M:%S') }}
|
||
- id: als_run_test_engine_button
|
||
alias: ALS - Run Test Engine Now
|
||
mode: single
|
||
trigger:
|
||
- trigger: state
|
||
entity_id: input_button.als_run_test_engine
|
||
action:
|
||
- action: pyscript.parallel_test_run_now
|
||
- action: input_text.set_value
|
||
target:
|
||
entity_id: input_text.als_last_teach_status
|
||
data:
|
||
value: Test engine wrote values at {{ now().strftime('%H:%M:%S') }}
|
||
- id: pyscript_to_home_state_ui_authoritative
|
||
alias: 'Home State (Authoritative): Controller → UI'
|
||
mode: restart
|
||
trigger:
|
||
- trigger: state
|
||
entity_id: pyscript.home_state
|
||
condition:
|
||
- condition: template
|
||
value_template: '{{ states(''pyscript.home_state'') != states(''input_select.home_state'')
|
||
}}'
|
||
action:
|
||
- action: input_select.select_option
|
||
target:
|
||
entity_id: input_select.home_state
|
||
data:
|
||
option: '{{ states(''pyscript.home_state'') }}'
|
||
- id: home_state_ui_to_pyscript_override_only
|
||
alias: 'Home State (Override Only): UI → Controller'
|
||
mode: single
|
||
trigger:
|
||
- trigger: state
|
||
entity_id: input_select.home_state
|
||
condition:
|
||
- condition: state
|
||
entity_id: input_boolean.manual_home_state_override
|
||
state: 'on'
|
||
- condition: template
|
||
value_template: '{{ states(''input_select.home_state'') != states(''pyscript.home_state'')
|
||
}}'
|
||
action:
|
||
- action: pyscript.set_home_mode
|
||
data:
|
||
mode: '{{ states(''input_select.home_state'') }}'
|
||
- id: home_state_ui_guard_override_off_strict
|
||
alias: 'Home State Guard: Snap UI Back (Override OFF)'
|
||
mode: restart
|
||
trigger:
|
||
- trigger: state
|
||
entity_id: input_select.home_state
|
||
condition:
|
||
- condition: state
|
||
entity_id: input_boolean.manual_home_state_override
|
||
state: 'off'
|
||
- condition: template
|
||
value_template: '{{ states(''input_select.home_state'') != states(''pyscript.home_state'')
|
||
}}'
|
||
action:
|
||
- action: input_select.select_option
|
||
target:
|
||
entity_id: input_select.home_state
|
||
data:
|
||
option: '{{ states(''pyscript.home_state'') }}'
|
||
- id: home_state_reconciler_authoritative
|
||
alias: Home State Reconciler (Controller Wins)
|
||
mode: restart
|
||
trigger:
|
||
- trigger: state
|
||
entity_id: binary_sensor.home_state_diverged
|
||
to: 'on'
|
||
condition:
|
||
- condition: state
|
||
entity_id: input_boolean.manual_home_state_override
|
||
state: 'off'
|
||
action:
|
||
- action: input_select.select_option
|
||
target:
|
||
entity_id: input_select.home_state
|
||
data:
|
||
option: '{{ states(''pyscript.home_state'') }}'
|
||
- id: home_state_startup_sync
|
||
alias: 'Home State Startup Sync: Controller → UI'
|
||
mode: single
|
||
trigger:
|
||
- trigger: homeassistant
|
||
event: start
|
||
- trigger: event
|
||
event_type: pyscript_reload
|
||
action:
|
||
- choose:
|
||
- conditions:
|
||
- condition: template
|
||
value_template: '{{ states(''pyscript.home_state'') not in [''unknown'',''unavailable'','''']
|
||
}}'
|
||
sequence:
|
||
- action: input_select.select_option
|
||
target:
|
||
entity_id: input_select.home_state
|
||
data:
|
||
option: '{{ states(''pyscript.home_state'') }}'
|
||
- id: sleep_in_ramp_start
|
||
alias: Sleep-In Ramp - Start
|
||
description: Starts the sleep-in ramp with calculate-once smart duration
|
||
mode: single
|
||
triggers:
|
||
- trigger: state
|
||
entity_id: input_boolean.sleep_in_ramp_active
|
||
to: 'on'
|
||
conditions:
|
||
- condition: state
|
||
entity_id: input_boolean.sleep_in_ramp_system_enable
|
||
state: 'on'
|
||
- condition: state
|
||
entity_id: input_select.home_state
|
||
state: Night
|
||
actions:
|
||
- variables:
|
||
current_sun: '{{ state_attr(''sun.sun'', ''elevation'') | float(0) }}'
|
||
sun_rate: '{{ states(''sensor.sun_elevation_rate'') | float(0.03) }}'
|
||
target_el: '{{ states(''input_number.current_day_threshold'') | float(10) }}'
|
||
rate_based_minutes: '{{ ((target_el - current_sun) / sun_rate) | round(0) if
|
||
sun_rate > 0.005 and sun_rate < 0.2 else 999 }}'
|
||
elevation_based_minutes: '{{ states(''sensor.minutes_to_day_mode_elevation'')
|
||
| int(999) }}'
|
||
motion_time: '{{ now() }}'
|
||
motion_hour: '{{ motion_time.hour }}'
|
||
motion_minute: '{{ motion_time.minute }}'
|
||
is_work_window: '{{ (motion_hour == 4 and motion_minute >= 50) or (motion_hour
|
||
== 5 and motion_minute == 0) }}'
|
||
work_base: '{{ states(''input_number.workday_ramp_base_duration'') | int(50)
|
||
}}'
|
||
off_base: '{{ states(''input_number.offday_ramp_base_duration'') | int(75) }}'
|
||
base_duration: '{{ work_base if is_work_window else off_base }}'
|
||
calculated_duration: "{% if 10 <= rate_based_minutes <= 180 %}\n {{ rate_based_minutes\
|
||
\ }}\n{% elif 10 <= elevation_based_minutes <= 240 %}\n {{ elevation_based_minutes\
|
||
\ }}\n{% else %}\n {% set season = states('sensor.current_season') %}\n \
|
||
\ {{ 60 if season == 'Winter' else 45 if season in ['Spring', 'Fall'] else\
|
||
\ 30 }}\n{% endif %}"
|
||
final_duration: "{% if calculated_duration < 30 %}\n {{ [calculated_duration\
|
||
\ * 0.8, 15] | max }}\n{% elif calculated_duration < 60 %}\n {{ [calculated_duration\
|
||
\ * 0.9, 25] | max }}\n{% else %}\n {% set season = states('sensor.current_season')\
|
||
\ %}\n {% set multiplier = 1.3 if season == 'Winter' else 0.8 if season ==\
|
||
\ 'Summer' else 1.0 %}\n {{ [base_duration * multiplier, 120] | min }}\n\
|
||
{% endif %}"
|
||
- action: input_datetime.set_datetime
|
||
target:
|
||
entity_id: input_datetime.ramp_start_time
|
||
data:
|
||
datetime: '{{ now().strftime(''%Y-%m-%d %H:%M:%S'') }}'
|
||
- action: input_number.set_value
|
||
target:
|
||
entity_id: input_number.calculated_ramp_duration
|
||
data:
|
||
value: '{{ final_duration | round(0) }}'
|
||
- action: input_datetime.set_datetime
|
||
target:
|
||
entity_id: input_datetime.ramp_calculated_end_time
|
||
data:
|
||
datetime: '{{ (now() + timedelta(minutes=final_duration|int)).strftime(''%Y-%m-%d
|
||
%H:%M:%S'') }}'
|
||
- action: input_datetime.set_datetime
|
||
target:
|
||
entity_id: input_datetime.first_kitchen_motion_today
|
||
data:
|
||
datetime: '{{ now().strftime(''%Y-%m-%d %H:%M:%S'') }}'
|
||
- action: input_boolean.turn_on
|
||
target:
|
||
entity_id: input_boolean.daily_motion_lock
|
||
- action: input_select.select_option
|
||
target:
|
||
entity_id: input_select.home_state
|
||
data:
|
||
option: Early Morning
|
||
- id: sleep_in_ramp_complete
|
||
alias: Sleep-In Ramp - Complete
|
||
description: Completes the ramp when 100% progress is reached OR Day mode begins
|
||
mode: single
|
||
triggers:
|
||
- trigger: template
|
||
value_template: "{{ is_state('input_boolean.sleep_in_ramp_active', 'on') and\n\
|
||
\ states('sensor.sleep_in_ramp_progress') | float(0) >= 100 }}\n"
|
||
for:
|
||
seconds: 5
|
||
- trigger: state
|
||
entity_id: sensor.calculated_home_mode
|
||
to: Day
|
||
conditions:
|
||
- condition: state
|
||
entity_id: input_boolean.sleep_in_ramp_active
|
||
state: 'on'
|
||
actions:
|
||
- variables:
|
||
motion_time_str: '{{ states(''input_datetime.first_kitchen_motion_today'') }}'
|
||
is_non_work_day: "{% if motion_time_str not in ['unknown', 'unavailable', '']\
|
||
\ %}\n {% set motion_time = as_datetime(motion_time_str) %}\n {% set motion_hour\
|
||
\ = motion_time.hour %}\n {% set motion_minute = motion_time.minute %}\n\
|
||
\ {% set is_work_window = (motion_hour == 4 and motion_minute >= 50) or (motion_hour\
|
||
\ == 5 and motion_minute == 0) %}\n {{ not is_work_window }}\n{% else %}\n\
|
||
\ {{ not is_state('binary_sensor.working_today', 'on') }}\n{% endif %}"
|
||
- action: input_boolean.turn_off
|
||
target:
|
||
entity_id: input_boolean.sleep_in_ramp_active
|
||
- action: input_select.select_option
|
||
target:
|
||
entity_id: input_select.home_state
|
||
data:
|
||
option: Day
|
||
- if:
|
||
- condition: template
|
||
value_template: '{{ is_non_work_day }}'
|
||
- condition: state
|
||
entity_id: input_boolean.kitchen_wled_enable
|
||
state: 'on'
|
||
then:
|
||
- action: light.turn_off
|
||
target:
|
||
entity_id:
|
||
- light.sink_wled
|
||
- light.frig_strip
|
||
- action: logbook.log
|
||
data:
|
||
name: WLED Control
|
||
message: Kitchen WLED turned off at end of non-work day ramp
|
||
- action: logbook.log
|
||
data:
|
||
name: Sleep-In Ramp
|
||
message: 'Ramp complete - Triggered by: {{ trigger.platform }} | Non-work day:
|
||
{{ is_non_work_day }}'
|
||
- id: daily_motion_reset
|
||
alias: Daily Motion Reset
|
||
description: Resets daily motion lock and tracking at midnight
|
||
triggers:
|
||
- trigger: time
|
||
at: 00:00:00
|
||
actions:
|
||
- action: input_boolean.turn_off
|
||
target:
|
||
entity_id: input_boolean.daily_motion_lock
|
||
- action: input_datetime.set_datetime
|
||
target:
|
||
entity_id: input_datetime.first_kitchen_motion_today
|
||
data:
|
||
datetime: ''
|
||
- id: kitchen_pyscript_morning_ramp_trigger
|
||
alias: Kitchen - Morning Ramp PyScript Trigger (motion)
|
||
mode: single
|
||
trigger:
|
||
- trigger: state
|
||
entity_id:
|
||
- binary_sensor.aqara_motion_sensor_p1_occupancy
|
||
- binary_sensor.kitchen_iris_frig_occupancy
|
||
to: 'on'
|
||
condition:
|
||
- condition: state
|
||
entity_id: input_boolean.sleep_in_ramp_system_enable
|
||
state: 'on'
|
||
- condition: state
|
||
entity_id: pyscript.home_state
|
||
state: Night
|
||
action:
|
||
- action: pyscript.morning_ramp_first_motion
|
||
data:
|
||
sensor: '{{ trigger.entity_id }}'
|
||
- id: unlock_door_on_arrival
|
||
alias: Unlock door when either iPhone arrives home
|
||
description: Auto unlock front door when either phone enters the home zone
|
||
triggers:
|
||
- trigger: zone
|
||
entity_id: device_tracker.iphone15
|
||
zone: zone.home
|
||
event: enter
|
||
- trigger: zone
|
||
entity_id: device_tracker.work_iphone
|
||
zone: zone.home
|
||
event: enter
|
||
conditions:
|
||
- condition: state
|
||
entity_id: input_boolean.smart_lock_auto_unlock
|
||
state: 'on'
|
||
actions:
|
||
- action: logbook.log
|
||
data:
|
||
name: Smart Lock
|
||
message: Arrival unlock triggered by {{ trigger.entity_id or trigger.platform
|
||
}}
|
||
entity_id: lock.aqara_smart_lock_u100_lock
|
||
- action: lock.unlock
|
||
target:
|
||
entity_id: lock.aqara_smart_lock_u100_lock
|
||
- action: notify.mobile_app_iphone15
|
||
data:
|
||
message: The front door was unlocked (arrival).
|
||
- action: notify.mobile_app_rrvqklh23h_iphone
|
||
data:
|
||
message: The front door was unlocked (arrival).
|
||
mode: single
|
||
- id: auto_lock_when_door_closes
|
||
alias: Auto-lock instantly when front door closes
|
||
description: Locks immediately when contact sensor reports closed
|
||
triggers:
|
||
- trigger: state
|
||
entity_id: binary_sensor.front_door_contact_contact
|
||
from: 'on'
|
||
to: 'off'
|
||
conditions:
|
||
- condition: state
|
||
entity_id: input_boolean.smart_lock_auto_lock
|
||
state: 'on'
|
||
- condition: state
|
||
entity_id: lock.aqara_smart_lock_u100_lock
|
||
state: unlocked
|
||
actions:
|
||
- action: logbook.log
|
||
data:
|
||
name: Smart Lock
|
||
message: Door closed → locking now
|
||
entity_id: lock.aqara_smart_lock_u100_lock
|
||
- action: lock.lock
|
||
target:
|
||
entity_id: lock.aqara_smart_lock_u100_lock
|
||
- action: notify.mobile_app_iphone15
|
||
data:
|
||
message: The front door auto-locked instantly after closing.
|
||
- action: notify.mobile_app_rrvqklh23h_iphone
|
||
data:
|
||
message: The front door auto-locked instantly after closing.
|
||
mode: restart
|
||
- id: track_last_departed_phone
|
||
alias: Track last phone departed
|
||
triggers:
|
||
- trigger: zone
|
||
entity_id: device_tracker.iphone15
|
||
zone: zone.home
|
||
event: leave
|
||
id: iphone15_leave
|
||
- trigger: zone
|
||
entity_id: device_tracker.work_iphone
|
||
zone: zone.home
|
||
event: leave
|
||
id: work_iphone_leave
|
||
actions:
|
||
- choose:
|
||
- conditions:
|
||
- condition: trigger
|
||
id: iphone15_leave
|
||
sequence:
|
||
- action: input_text.set_value
|
||
target:
|
||
entity_id: input_text.smart_lock_last_departed
|
||
data:
|
||
value: iphone15
|
||
- action: logbook.log
|
||
data:
|
||
name: Smart Lock
|
||
message: Last departed set to iphone15
|
||
- conditions:
|
||
- condition: trigger
|
||
id: work_iphone_leave
|
||
sequence:
|
||
- action: input_text.set_value
|
||
target:
|
||
entity_id: input_text.smart_lock_last_departed
|
||
data:
|
||
value: work_iphone
|
||
- action: logbook.log
|
||
data:
|
||
name: Smart Lock
|
||
message: Last departed set to work_iphone
|
||
mode: restart
|
||
- id: away_enforce_after_5min
|
||
alias: Away enforce after 5 minutes
|
||
description: After 5 minutes away, lock if needed and notify only the last departed
|
||
phone
|
||
triggers:
|
||
- trigger: state
|
||
entity_id: binary_sensor.both_phones_home
|
||
to: 'off'
|
||
for:
|
||
minutes: 5
|
||
conditions:
|
||
- condition: state
|
||
entity_id: input_boolean.smart_lock_away_enforce
|
||
state: 'on'
|
||
- condition: state
|
||
entity_id: binary_sensor.both_phones_home
|
||
state: 'off'
|
||
- condition: state
|
||
entity_id: binary_sensor.front_door_contact_contact
|
||
state: 'off'
|
||
actions:
|
||
- action: logbook.log
|
||
data:
|
||
name: Smart Lock
|
||
message: Away 5-min check running
|
||
entity_id: lock.aqara_smart_lock_u100_lock
|
||
- choose:
|
||
- conditions:
|
||
- condition: state
|
||
entity_id: lock.aqara_smart_lock_u100_lock
|
||
state: unlocked
|
||
sequence:
|
||
- action: lock.lock
|
||
target:
|
||
entity_id: lock.aqara_smart_lock_u100_lock
|
||
- choose:
|
||
- conditions:
|
||
- condition: template
|
||
value_template: '{{ states(''input_text.smart_lock_last_departed'') ==
|
||
''iphone15'' }}'
|
||
sequence:
|
||
- action: notify.mobile_app_iphone15
|
||
data:
|
||
message: 'Away check: Door was still unlocked after 5 minutes, locking
|
||
now.'
|
||
- conditions:
|
||
- condition: template
|
||
value_template: '{{ states(''input_text.smart_lock_last_departed'') ==
|
||
''work_iphone'' }}'
|
||
sequence:
|
||
- action: notify.mobile_app_rrvqklh23h_iphone
|
||
data:
|
||
message: 'Away check: Door was still unlocked after 5 minutes, locking
|
||
now.'
|
||
mode: single
|
||
- id: away_door_left_open
|
||
alias: Away alert if door left open
|
||
description: If both phones are away and door stays open >2 minutes, notify last
|
||
departed phone
|
||
triggers:
|
||
- trigger: state
|
||
entity_id: binary_sensor.front_door_contact_contact
|
||
to: 'on'
|
||
for:
|
||
minutes: 2
|
||
conditions:
|
||
- condition: state
|
||
entity_id: binary_sensor.both_phones_home
|
||
state: 'off'
|
||
actions:
|
||
- action: logbook.log
|
||
data:
|
||
name: Smart Lock
|
||
message: Door left open 2+ min while away
|
||
entity_id: lock.aqara_smart_lock_u100_lock
|
||
- choose:
|
||
- conditions:
|
||
- condition: template
|
||
value_template: '{{ states(''input_text.smart_lock_last_departed'') == ''iphone15''
|
||
}}'
|
||
sequence:
|
||
- action: notify.mobile_app_iphone15
|
||
data:
|
||
message: 'Away alert: The front door has been left open for 2 minutes.'
|
||
- conditions:
|
||
- condition: template
|
||
value_template: '{{ states(''input_text.smart_lock_last_departed'') == ''work_iphone''
|
||
}}'
|
||
sequence:
|
||
- action: notify.mobile_app_rrvqklh23h_iphone
|
||
data:
|
||
message: 'Away alert: The front door has been left open for 2 minutes.'
|
||
mode: single
|
||
- id: smart_switch_1_manual_amber_activate
|
||
alias: Smart Switch 1 - Manual Amber Activate
|
||
triggers:
|
||
- trigger: state
|
||
entity_id: input_boolean.smart_switch_1_manual_amber_trigger
|
||
to: 'on'
|
||
conditions:
|
||
- condition: state
|
||
entity_id: input_boolean.smart_switch_1_amber_mode_enable
|
||
state: 'on'
|
||
actions:
|
||
- action: script.smart_switch_1_amber_sequence
|
||
- action: input_boolean.turn_off
|
||
target:
|
||
entity_id: input_boolean.smart_switch_1_manual_amber_trigger
|
||
- action: logbook.log
|
||
data:
|
||
name: Smart Switch 1 Amber
|
||
message: Manual amber mode activated
|
||
entity_id: light.smart_switch_1
|
||
- id: smart_switch_2_manual_amber_activate
|
||
alias: Smart Switch 2 - Manual Amber Activate
|
||
triggers:
|
||
- trigger: state
|
||
entity_id: input_boolean.smart_switch_2_manual_amber_trigger
|
||
to: 'on'
|
||
conditions:
|
||
- condition: state
|
||
entity_id: input_boolean.smart_switch_2_amber_mode_enable
|
||
state: 'on'
|
||
actions:
|
||
- action: script.smart_switch_2_amber_sequence
|
||
- action: input_boolean.turn_off
|
||
target:
|
||
entity_id: input_boolean.smart_switch_2_manual_amber_trigger
|
||
- action: logbook.log
|
||
data:
|
||
name: Smart Switch 2 Amber
|
||
message: Manual amber mode activated
|
||
entity_id: light.smart_switch_2
|
||
- id: smart_switch_1_amber_button
|
||
alias: Smart Switch 1 - Amber Button
|
||
triggers:
|
||
- trigger: state
|
||
entity_id: input_button.smart_switch_1_activate_amber
|
||
actions:
|
||
- action: script.smart_switch_1_amber_sequence
|
||
- id: smart_switch_1_normal_button
|
||
alias: Smart Switch 1 - Normal Button
|
||
triggers:
|
||
- trigger: state
|
||
entity_id: input_button.smart_switch_1_normal_mode
|
||
actions:
|
||
- action: light.turn_on
|
||
target:
|
||
entity_id: light.smart_switch_1
|
||
data:
|
||
brightness_pct: 80
|
||
color_temp_kelvin: 4000
|
||
- id: smart_switch_2_amber_button
|
||
alias: Smart Switch 2 - Amber Button
|
||
triggers:
|
||
- trigger: state
|
||
entity_id: input_button.smart_switch_2_activate_amber
|
||
actions:
|
||
- action: script.smart_switch_2_amber_sequence
|
||
- id: smart_switch_2_normal_button
|
||
alias: Smart Switch 2 - Normal Button
|
||
triggers:
|
||
- trigger: state
|
||
entity_id: input_button.smart_switch_2_normal_mode
|
||
actions:
|
||
- action: light.turn_on
|
||
target:
|
||
entity_id: light.smart_switch_2
|
||
data:
|
||
brightness_pct: 80
|
||
color_temp_kelvin: 4000
|
||
- id: both_switches_amber_button
|
||
alias: Both Switches - Amber Button
|
||
triggers:
|
||
- trigger: state
|
||
entity_id: input_button.both_switches_amber
|
||
actions:
|
||
- action: script.both_switches_amber_mode
|
||
- id: both_switches_normal_button
|
||
alias: Both Switches - Normal Button
|
||
triggers:
|
||
- trigger: state
|
||
entity_id: input_button.both_switches_normal
|
||
actions:
|
||
- action: light.turn_on
|
||
target:
|
||
entity_id:
|
||
- light.smart_switch_1
|
||
- light.smart_switch_2
|
||
data:
|
||
brightness_pct: 80
|
||
color_temp_kelvin: 4000
|
||
- id: trial_gate_yaml_home_state_eval
|
||
alias: TRIAL – Gate YAML Home State Evaluation
|
||
mode: restart
|
||
triggers:
|
||
- trigger: state
|
||
entity_id: input_boolean.use_pyscript_home_state
|
||
actions:
|
||
- choose:
|
||
- conditions:
|
||
- condition: state
|
||
entity_id: input_boolean.use_pyscript_home_state
|
||
state: 'on'
|
||
sequence:
|
||
- action: automation.turn_off
|
||
target:
|
||
entity_id: automation.home_state_evaluation
|
||
- action: logbook.log
|
||
data:
|
||
name: TRIAL
|
||
message: Disabled YAML Home State Evaluation (toggle ON)
|
||
- conditions:
|
||
- condition: state
|
||
entity_id: input_boolean.use_pyscript_home_state
|
||
state: 'off'
|
||
sequence:
|
||
- action: automation.turn_on
|
||
target:
|
||
entity_id: automation.home_state_evaluation
|
||
- action: logbook.log
|
||
data:
|
||
name: TRIAL
|
||
message: Enabled YAML Home State Evaluation (toggle OFF)
|
||
- alias: Monitor Dryer Running State
|
||
id: monitor_dryer_running
|
||
description: Track when dryer starts and stops running
|
||
mode: restart
|
||
triggers:
|
||
- trigger: numeric_state
|
||
entity_id: sensor.dryer_dryer_electric_w_value
|
||
above: 50
|
||
id: dryer_start
|
||
- trigger: numeric_state
|
||
entity_id: sensor.dryer_dryer_electric_w_value
|
||
below: 50
|
||
for:
|
||
minutes: 2
|
||
id: dryer_stop
|
||
actions:
|
||
- choose:
|
||
- conditions:
|
||
- condition: trigger
|
||
id: dryer_start
|
||
sequence:
|
||
- action: input_boolean.turn_on
|
||
target:
|
||
entity_id: input_boolean.dryer_running
|
||
- action: logbook.log
|
||
data:
|
||
name: Dryer Status
|
||
message: Dryer started running
|
||
- conditions:
|
||
- condition: trigger
|
||
id: dryer_stop
|
||
sequence:
|
||
- action: input_boolean.turn_off
|
||
target:
|
||
entity_id: input_boolean.dryer_running
|
||
- action: logbook.log
|
||
data:
|
||
name: Dryer Status
|
||
message: Dryer finished running
|
||
- action: script.send_dryer_done_notification
|
||
- alias: Simple Washer Done Notification
|
||
id: simple_washer_done
|
||
description: Alexa announces and iPhone notifies when washer is done, checks if
|
||
dryer is running
|
||
mode: single
|
||
triggers:
|
||
- trigger: numeric_state
|
||
entity_id: sensor.washer_power
|
||
below: 8
|
||
for:
|
||
minutes: 1
|
||
conditions:
|
||
- condition: state
|
||
entity_id: input_boolean.washer_notifications
|
||
state: 'on'
|
||
- condition: state
|
||
entity_id: input_boolean.dryer_reminder_enable
|
||
state: 'on'
|
||
actions:
|
||
- action: script.send_washer_done_notification
|
||
- alias: Dryer Reminder Every 15min
|
||
id: dryer_reminder_every_15min
|
||
description: Keep reminding every 15min until clothes moved to dryer
|
||
mode: restart
|
||
triggers:
|
||
- trigger: time_pattern
|
||
minutes: /15
|
||
conditions:
|
||
- condition: state
|
||
entity_id: input_boolean.washer_notifications
|
||
state: 'on'
|
||
- condition: state
|
||
entity_id: input_boolean.dryer_reminder_enable
|
||
state: 'on'
|
||
- condition: state
|
||
entity_id: input_boolean.clothes_in_dryer_pending
|
||
state: 'on'
|
||
- condition: time
|
||
after: 08:00:00
|
||
before: '21:00:00'
|
||
actions:
|
||
- action: script.send_iphone_notification
|
||
data:
|
||
title: '🔔 Reminder: Dryer?'
|
||
message: Don't forget - did you move the clothes to the dryer?
|
||
actions:
|
||
- action: CLOTHES_IN_DRYER_YES
|
||
title: ✅ Yes, all moved!
|
||
- action: CLOTHES_REMIND_30MIN
|
||
title: ⏰ Remind me later
|
||
- alias: Handle Clothes in Dryer Confirmed
|
||
id: handle_clothes_in_dryer_yes
|
||
description: Stop reminders when user confirms clothes in dryer
|
||
mode: single
|
||
triggers:
|
||
- trigger: event
|
||
event_type: mobile_app_notification_action
|
||
event_data:
|
||
action: CLOTHES_IN_DRYER_YES
|
||
actions:
|
||
- action: script.handle_confirmation
|
||
data:
|
||
boolean_entity: input_boolean.clothes_in_dryer_pending
|
||
title: 👍 Perfect!
|
||
message: Great job! No more reminders.
|
||
- alias: Handle Dryer Remind 30min
|
||
id: handle_dryer_remind_30min
|
||
description: Snooze dryer reminder for 30 minutes
|
||
mode: restart
|
||
triggers:
|
||
- trigger: event
|
||
event_type: mobile_app_notification_action
|
||
event_data:
|
||
action: CLOTHES_REMIND_30MIN
|
||
actions:
|
||
- action: script.handle_snooze
|
||
data:
|
||
boolean_entity: input_boolean.clothes_in_dryer_pending
|
||
snooze_title: ⏰ Snoozed!
|
||
snooze_message: I'll remind you again in 30 minutes.
|
||
reminder_title: 🔔 Snooze Over!
|
||
reminder_message: Did you move the clothes to the dryer now?
|
||
reminder_actions:
|
||
- action: CLOTHES_IN_DRYER_YES
|
||
title: ✅ Yes, all moved!
|
||
- action: CLOTHES_REMIND_30MIN
|
||
title: ⏰ Remind me later
|
||
- alias: Washer Cleaning Reminder - Check After Cycle
|
||
id: washer_cleaning_after_cycle
|
||
description: Check if washer needs cleaning after each wash cycle (every 30 days)
|
||
mode: single
|
||
triggers:
|
||
- trigger: numeric_state
|
||
entity_id: sensor.washer_power
|
||
below: 8
|
||
for:
|
||
minutes: 1
|
||
conditions:
|
||
- condition: state
|
||
entity_id: input_boolean.washer_notifications
|
||
state: 'on'
|
||
- condition: state
|
||
entity_id: input_boolean.washer_cleaning_reminder_enable
|
||
state: 'on'
|
||
- condition: state
|
||
entity_id: input_boolean.washer_cleaning_pending
|
||
state: 'off'
|
||
- condition: time
|
||
after: 08:00:00
|
||
before: '21:00:00'
|
||
actions:
|
||
- variables:
|
||
last_cleaned: '{{ states(''input_datetime.washer_last_cleaned'') }}'
|
||
days_since_cleaned: "{% if last_cleaned != 'unknown' %}\n {{ ((as_timestamp(now())\
|
||
\ - as_timestamp(last_cleaned)) / 86400) | round(0) }}\n{% else %}\n 31\n\
|
||
{% endif %}"
|
||
- if:
|
||
- condition: template
|
||
value_template: '{{ days_since_cleaned >= 30 }}'
|
||
then:
|
||
- action: input_boolean.turn_on
|
||
target:
|
||
entity_id: input_boolean.washer_cleaning_pending
|
||
- action: script.send_iphone_notification
|
||
data:
|
||
title: 🧽 Washer Maintenance Time!
|
||
message: '{% if last_cleaned != ''unknown'' %} It''s been {{ days_since_cleaned
|
||
}} days since you last cleaned the washer. Time for a cleaning cycle? {%
|
||
else %} When did you last clean the washer? It''s been a while - time for
|
||
a maintenance cycle? {% endif %}'
|
||
actions:
|
||
- action: WASHER_CLEANED_YES
|
||
title: ✅ Just cleaned it!
|
||
- action: WASHER_CLEAN_REMIND_LATER
|
||
title: 🌙 Remind me tonight
|
||
- alias: Washer Cleaning Reminder - Nag Every Hour
|
||
id: washer_cleaning_nag_hourly
|
||
description: Keep reminding about washer cleaning every hour until confirmed
|
||
mode: restart
|
||
triggers:
|
||
- trigger: time_pattern
|
||
minutes: 0
|
||
conditions:
|
||
- condition: state
|
||
entity_id: input_boolean.washer_notifications
|
||
state: 'on'
|
||
- condition: state
|
||
entity_id: input_boolean.washer_cleaning_reminder_enable
|
||
state: 'on'
|
||
- condition: state
|
||
entity_id: input_boolean.washer_cleaning_pending
|
||
state: 'on'
|
||
- condition: time
|
||
after: 09:00:00
|
||
before: '21:00:00'
|
||
actions:
|
||
- action: script.send_iphone_notification
|
||
data:
|
||
title: 🔔 Cleaning Reminder
|
||
message: Don't forget - your washer needs a cleaning cycle soon!
|
||
actions:
|
||
- action: WASHER_CLEANED_YES
|
||
title: ✅ Just cleaned it!
|
||
- action: WASHER_CLEAN_REMIND_LATER
|
||
title: 🌙 Remind me tonight
|
||
- alias: Handle Washer Cleaned Confirmed
|
||
id: handle_washer_cleaned_yes
|
||
description: Stop reminders when user confirms washer was cleaned
|
||
mode: single
|
||
triggers:
|
||
- trigger: event
|
||
event_type: mobile_app_notification_action
|
||
event_data:
|
||
action: WASHER_CLEANED_YES
|
||
actions:
|
||
- action: input_boolean.turn_off
|
||
target:
|
||
entity_id: input_boolean.washer_cleaning_pending
|
||
- action: input_datetime.set_datetime
|
||
target:
|
||
entity_id: input_datetime.washer_last_cleaned
|
||
data:
|
||
date: '{{ now().strftime(''%Y-%m-%d'') }}'
|
||
- action: script.handle_confirmation
|
||
data:
|
||
boolean_entity: input_boolean.washer_cleaning_pending
|
||
title: 🌟 Excellent!
|
||
message: Thanks! I'll remind you again in 30 days.
|
||
- alias: Handle Washer Clean Remind Tonight
|
||
id: handle_washer_clean_remind_tonight
|
||
description: Snooze washer cleaning reminder until evening
|
||
mode: restart
|
||
triggers:
|
||
- trigger: event
|
||
event_type: mobile_app_notification_action
|
||
event_data:
|
||
action: WASHER_CLEAN_REMIND_LATER
|
||
actions:
|
||
- action: script.handle_snooze
|
||
data:
|
||
boolean_entity: input_boolean.washer_cleaning_pending
|
||
snooze_title: 🌙 Got it!
|
||
snooze_message: I'll remind you tonight about washer cleaning.
|
||
delay_time: '19:00:00'
|
||
reminder_title: 🌆 Evening Reminder!
|
||
reminder_message: Good time to run a washer cleaning cycle tonight?
|
||
reminder_actions:
|
||
- action: WASHER_CLEANED_YES
|
||
title: ✅ Just cleaned it!
|
||
- action: WASHER_CLEAN_REMIND_LATER
|
||
title: 📅 Maybe tomorrow
|