Initial commit with existing blueprints

This commit is contained in:
2026-01-22 01:46:04 +03:00
commit 35f11d7e30
17 changed files with 5760 additions and 0 deletions

View File

@@ -0,0 +1,220 @@
blueprint:
name: "Custom: Multi-Sensor Alarm & Notification"
description: >
Triggers notifications and alarm actions when any of the configured binary sensors
change to "on". Supports per-sensor notification texts, optional alarm switch,
melody and volume selectors.
domain: automation
input:
devices:
name: "Devices"
collapsed: false
input:
binary_sensors:
name: Binary Sensors
description: List of sensors to monitor
selector:
entity:
domain:
- binary_sensor
- input_boolean
multiple: true
binary_sensors_decay_duration:
name: Binary Sensors Decay Duration (seconds)
description: Minimum time a sensor must stay ON before considered active
default: 5
selector:
number:
min: 0
max: 30
unit_of_measurement: "s"
notification:
name: "Notification"
collapsed: false
input:
notify_target:
name: Notification Target (optional)
description: Device or service to send notifications
default: null
selector:
entity:
domain: notify
notify_texts:
name: Notification Texts
description: One line per binary sensor, aligned with sensor list
default: []
selector:
text:
multiple: true
alarm_group:
name: "Alarm"
collapsed: false
input:
alarm_switch:
name: Alarm Switch (optional)
description: Switch entity to toggle alarm device
default: null
selector:
entity:
domain: switch
melody_id:
name: Melody Identifier
description: Static melody identifier string
default: ""
selector:
text:
melody_select:
name: Melody Selector (optional)
description: Input select entity pointing to melody list
default: ""
selector:
entity:
domain:
- input_select
- select
volume_id:
name: Volume Identifier
description: Static volume identifier string
default: ""
selector:
text:
volume_select:
name: Volume Selector (optional)
description: Input select entity pointing to volume list
default: ""
selector:
entity:
domain:
- input_select
- select
mode: restart
trigger:
- platform: state
entity_id: !input binary_sensors
to: "on"
for:
seconds: !input binary_sensors_decay_duration
- platform: state
entity_id: !input binary_sensors
to: "off"
action:
- variables:
binary_sensors: !input binary_sensors
notify_target: !input notify_target
melody_select: !input melody_select
volume_select: !input volume_select
alarm_switch: !input alarm_switch
enabled_sensors: "{{ binary_sensors | list | select('is_state','on') | list }}"
is_any_sensor_on: "{{ enabled_sensors | length != 0 }}"
are_all_sensors_off: "{{ enabled_sensors | length == 0 }}"
delay_between_setters_in_ms: 100
is_debug: false
# Debug info (log if required)
- choose:
- conditions:
- condition: template
value_template: "{{ is_debug }}"
sequence:
- service: persistent_notification.create
data:
title: "Debug Info"
message: >
binary_sensors = {{ binary_sensors }},
enabled_sensors = {{ enabled_sensors }}
- choose:
- conditions:
- condition: template
value_template: "{{ is_any_sensor_on and notify_target is not none }}"
sequence:
- variables:
notify_texts: !input notify_texts
messages: "{{ notify_texts | list }}"
sensor: "{{ trigger.entity_id }}"
idx: "{{ (binary_sensors | list).index(sensor) }}"
message: >
{% if messages | length > idx %}
{{ messages[idx] }}
{% else %}
Sensor {{ sensor }} triggered
{% endif %}
- service: notify.send_message
target:
entity_id: !input notify_target
data:
message: "{{ message }}"
- choose:
- conditions:
- condition: template
value_template: "{{ alarm_switch is not none }}"
sequence:
- variables:
melody_select: !input melody_select
melody_id: !input melody_id
volume_select: !input volume_select
volume_id: !input volume_id
- choose:
- conditions:
- condition: template
value_template: "{{ melody_select is not none }}"
sequence:
- service: select.select_option
target:
entity_id: !input melody_select
data:
option: !input melody_id
- delay:
milliseconds: "{{ delay_between_setters_in_ms }}"
- choose:
- conditions:
- condition: template
value_template: "{{ volume_select is not none }}"
sequence:
- service: select.select_option
target:
entity_id: !input volume_select
data:
option: !input volume_id
- delay:
milliseconds: "{{ delay_between_setters_in_ms }}"
- choose:
- conditions:
- condition: template
value_template: "{{ is_any_sensor_on }}"
sequence:
- service: switch.turn_on
target:
entity_id: !input alarm_switch
- conditions:
- condition: template
value_template: "{{ are_all_sensors_off }}"
sequence:
- service: switch.turn_off
target:
entity_id: !input alarm_switch

View File

@@ -0,0 +1,371 @@
blueprint:
name: "Custom: Climate Device Control"
description: >
Controls device based on window/door sensors with decay duration
and current_valueerature threshold.
domain: automation
input:
primary_group:
name: "General"
collapsed: false
input:
device_switch:
name: Device Switch
description: Switch associated with device
selector:
entity:
domain: switch
control_switch:
name: Control Switch
description: Controls if the device can work or not
selector:
entity:
domain:
- binary_sensor
- input_boolean
doors_group:
name: "Doors & Windows"
collapsed: false
input:
house_windows:
name: House Window Sensors
description: Sensors of whole house
default: []
selector:
entity:
domain: binary_sensor
multiple: true
room_windows:
name: Room Window Sensors
description: Window sensors of the device room
default: []
selector:
entity:
domain: binary_sensor
multiple: true
room_doors:
name: Room Door Sensors
description: Door sensors of the device room
default: []
selector:
entity:
domain: binary_sensor
multiple: true
decay_duration:
name: Decay Duration (seconds)
default: 3
selector:
number:
min: 0
max: 600
unit_of_measurement: seconds
mode: slider
env_group:
name: "Environment"
collapsed: false
input:
env_sensors:
name: Room Value Sensors
description: Sensors that controls room value
default: []
selector:
entity:
domain: sensor
multiple: true
target_value_entity:
name: Target Value Entity
description: Entity (e.g. input_number) that defines target value dynamically.
selector:
entity:
domain: input_number
value_threshold:
name: Value Threshold
description: If value falls below the threshold then device will be turned on (not taking into account other conditions)
default: 0
selector:
number:
min: 0
max: 100
mode: slider
value_is_low_entity:
name: "Low Value Entity (optional)"
description: The entity will contain state of low value
default: null
selector:
entity:
domain:
- input_boolean
schedule_group:
name: "Schedules"
collapsed: false
input:
schedule_entities:
name: Schedules (optional)
description: One or more schedule entities that define when device may run. Leave empty for always.
default: []
selector:
entity:
domain: schedule
multiple: true
power_group:
name: "Power"
collapsed: false
input:
power_sensor:
name: Power Sensor
description: Sensor reporting device power usage (W)
selector:
entity:
domain: sensor
power_threshold:
name: Power Threshold (W)
description: Below this value, device is considered as problematic
default: 10
selector:
number:
min: 0
max: 50
unit_of_measurement: "W"
power_decay_duration:
name: Power Decay Duration (s)
description: Time to wait after power is changed before entering problematic power mode.
default: 10
selector:
number:
min: 1
max: 50
unit_of_measurement: "s"
power_problematic_indicator_entity:
name: Indicator Entity (optional)
description: "If step then the automation with toggle the entity whenever the device enters power problematic state"
default: null
selector:
entity:
domain: input_boolean
mode: single
trigger:
# Control switch
- platform: state
entity_id: !input control_switch
# House window
- platform: state
entity_id: !input house_windows
for:
seconds: !input decay_duration
# Room window
- platform: state
entity_id: !input room_windows
for:
seconds: !input decay_duration
# Room door
- platform: state
entity_id: !input room_doors
for:
seconds: !input decay_duration
# Target value entity
- platform: state
entity_id: !input target_value_entity
# Room env sensor
- platform: state
entity_id: !input env_sensors
# Power sensor
- platform: numeric_state
entity_id: !input power_sensor
below: !input power_threshold
for:
seconds: !input power_decay_duration
condition: []
action:
- variables:
env_sensors: !input env_sensors
control_switch: !input control_switch
device_switch: !input device_switch
threshold: !input value_threshold
value_is_low_entity: !input value_is_low_entity
# Target value.
target_value_entity: !input target_value_entity
target_value: "{{ states(target_value_entity) | int }}"
# Values/threshold
value_stats: >
{% set result = [] %}
{% if env_sensors | length > 0 %}
{% set values = expand(env_sensors) | map(attribute='state') | map('float') | list %}
{% if threshold != 0 %}
{% set result = result + [values | select('lt', threshold) | list | count] %}
{% else %}
{% set result = result + [0] %}
{% endif %}
{% if target_value != 0 %}
{% set result = result + [values | select('lt', target_value) | list | count] %}
{% else %}
{% set result = result + [0] %}
{% endif %}
{% else %}
{% set result = [0, 0] %}
{% endif %}
{{ result }}
is_value_below_threshold: "{{ (value_stats[0] | int) > 0 }}"
is_value_below_target_value: "{{ (value_stats[1] | int) > 0 }}"
# Power
power_threshold: !input power_threshold
power_sensor: !input power_sensor
power_problematic_indicator_entity: !input power_problematic_indicator_entity
power_decay_duration: !input power_decay_duration
power: "{{ states(power_sensor) | float(0) }}"
is_power_not_ok: "{{ (power > 0 and power < power_threshold) if power_threshold != 0 else false }}"
# doors/windows
house_windows: !input house_windows
room_windows: !input room_windows
room_doors: !input room_doors
decay: !input decay_duration
house_closed: >
{% set ns = namespace(res = true) %}
{% for i in range(house_windows | count) %}
{% set it = house_windows[i] %}
{% set ns.res = ns.res and (is_state(it, 'off') and (now() - states[it].last_changed).total_seconds() > decay) %}
{% endfor %}
{{ ns.res }}
room_closed: >
{% if (room_windows | count) or (room_doors | count) == 0 %}
{{ false }}
{% else %}
{% set ns = namespace(res = true) %}
{% for i in range(room_windows | count) %}
{% set it = room_windows[i] %}
{% set ns.res = ns.res and (is_state(it, 'off') and (now() - states[it].last_changed).total_seconds() > decay) %}
{% endfor %}
{% for i in range(room_doors | count) %}
{% set it = room_doors[i] %}
{% set ns.res = ns.res and (is_state(it, 'off') and (now() - states[it].last_changed).total_seconds() > decay) %}
{% endfor %}
{{ ns.res }}
{% endif %}
# Schedules
schedule_entities: !input schedule_entities
schedule_active: >
{% if schedule_entities | length > 0 %}
{{ schedule_entities | select('is_state','on') | list | length > 0 }}
{% else %}
true
{% endif %}
is_debug: false
# Debug message
- choose:
- conditions: "{{ is_debug }}"
sequence:
- service: persistent_notification.create
data:
title: "Climate (debug)"
message: >
room_closed = {{ room_closed }},
house_closed = {{ house_closed }}
# Power problematic.
- choose:
- conditions:
- condition: template
value_template: "{{ is_state(device_switch, 'on') and power_problematic_indicator_entity is not none }}"
sequence:
- variables:
timeout_elapsed: >
{% set last = as_timestamp(states[power_sensor].last_changed) %}
{{ (as_timestamp(now()) - last) > power_decay_duration }}
- condition: template
value_template: "{{ timeout_elapsed }}"
- choose:
- conditions: "{{ is_power_not_ok }}"
sequence:
- service: input_boolean.turn_on
target:
entity_id: "{{ power_problematic_indicator_entity }}"
default:
- service: input_boolean.turn_off
target:
entity_id: "{{ power_problematic_indicator_entity }}"
# `value_is_low_entity` entity control
- choose:
- conditions:
- condition: template
value_template: "{{ value_is_low_entity is not none }}"
sequence:
- choose:
- conditions:
- condition: template
value_template: "{{ is_value_below_threshold }}"
sequence:
- service: input_boolean.turn_on
target:
entity_id: !input value_is_low_entity
default:
- service: input_boolean.turn_off
target:
entity_id: !input value_is_low_entity
- choose:
# Value is not ok override
- conditions:
- condition: template
value_template: "{{ is_value_below_threshold }}"
sequence:
- service: switch.turn_on
target:
entity_id: !input device_switch
# Control is not enabled
- conditions:
- condition: template
value_template: "{{ is_state(control_switch, 'off') }}"
sequence:
- service: switch.turn_off
target:
entity_id: !input device_switch
# Windows/doors closed with decay
- conditions:
- condition: template
value_template: "{{ (house_closed or room_closed) and schedule_active and is_value_below_target_value }}"
sequence:
- service: switch.turn_on
target:
entity_id: !input device_switch
default:
- service: switch.turn_off
target:
entity_id: !input device_switch

View File

@@ -0,0 +1,142 @@
blueprint:
name: "Custom: Day Scene Controller"
description: "Allows to control time of day scenes"
domain: automation
input:
states_group:
name: States
collapsed: false
input:
time_of_day_state:
name: Time of Day state selector
description: The input_select entity that holds the current time-of-day state
selector:
entity:
domain: input_select
control_switch:
name: Control Switch
description: Controls if scenes switch must work or default scene should be applied
selector:
entity:
domain:
- binary_sensor
- input_boolean
scenes_group:
name: Scenes
collapsed: false
input:
scenes:
name: Scenes
description: Ordered list of scenes (each scene per time of day state list)
selector:
entity:
domain:
- scene
multiple: true
default_scene:
name: Default Scene
description: Scene enabled when enable switch is off
selector:
entity:
domain:
- scene
enable_default_scene_on_transition:
name: Enable Default Scene On Transition
description: Controls if default scene should be enabled on scene transition (i.e. before moving to other scene use default scene)
default: true
selector:
boolean:
actions_group:
name: Actions
collapsed: true
input:
scene_applied_callback:
name: Scene Applied Callback
description: Set of action invoked whenever active scene is applied
default: []
selector:
action: {}
default_scene_applied_callback:
name: Default Scene Applied Callback
description: Set of action invoked whenever default scene is applied
default: []
selector:
action: {}
mode: restart
trigger:
- platform: state
entity_id: !input time_of_day_state
- platform: state
entity_id: !input control_switch
variables:
# Constants
is_debug: false
# Declarations
control_switch: !input control_switch
time_of_day_state: !input time_of_day_state
enable_default_scene_on_transition: !input enable_default_scene_on_transition
# Values
tod_state: "{{ states(time_of_day_state) }}"
tod_options: "{{ state_attr(time_of_day_state, 'options') or [] }}"
tod_index: "{{ tod_options.index(tod_state) if tod_state in tod_options else -1 }}"
control_on: "{{ states(control_switch) in ['on','true','1'] }}"
scenes_list: !input scenes
default_scene: !input default_scene
action:
# Debug info (log if required)
- choose:
- conditions:
- condition: template
value_template: "{{ is_debug }}"
sequence:
- service: persistent_notification.create
data:
title: "Debug Info"
message: >
tod_index = {{ tod_index }},
control_ok = {{ control_ok }}
- choose:
- conditions:
- condition: template
value_template: "{{ tod_index == -1 }}"
sequence:
stop: "Scene index is invalid. Check your state-to-scene mapping"
default:
sequence:
- variables:
result_scene: >
{% if control_on %}
{{ scenes_list[tod_index] }}
{% else %}
{{ default_scene }}
{% endif %}
- choose:
- conditions:
- condition: template
value_template: "{{ enable_default_scene_on_transition and result_scene != default_scene }}"
sequence:
- service: scene.turn_on
target:
entity_id: "{{ default_scene }}"
- service: scene.turn_on
target:
entity_id: "{{ result_scene }}"

198
Common/Home Presense.yaml Normal file
View File

@@ -0,0 +1,198 @@
blueprint:
name: "Custom: Home Presence Controller"
description: "Allows to control time of day scenes"
domain: automation
input:
result_group:
name: Output
collapsed: false
input:
result_value_entity:
name: Result Value
description: Helper object that will contain result
selector:
entity:
domain: input_boolean
control_switch:
name: Control Switch
description: Gatekeeper switch
selector:
entity:
domain:
- input_boolean
- binary_sensor
door_group:
name: Door
collapsed: false
input:
door_sensors:
name: Door Sensor(s)
description: Select the door sensor(s) to monitor
default: []
selector:
entity:
multiple: true
domain:
- binary_sensor
device_class: door
door_sensor_threshold:
name: Door Sensor Duration Threshold
description: Select the door sensor threshold
default: 60
selector:
number:
min: 0
max: 600
unit_of_measurement: seconds
mode: slider
presense_group:
name: Presense
collapsed: false
input:
presence_sensors:
name: Presense Sensors
description: Select the presense sensors to monitor
default: []
selector:
entity:
domain: person
multiple: true
motion_sensors:
name: Motion Sensors
description: Select the motion sensors to monitor
default: []
selector:
entity:
domain: binary_sensor
multiple: true
wifi_group:
name: Wi-Fi
collapsed: false
input:
wifi_id_sensors:
name: Wi-Fi ID Sensors
description: Select the sensors that reports Wi-Fi ID(s)
default: []
selector:
entity:
domain: sensor
multiple: true
home_wifi_ids:
name: Home Wi-Fi ID(s)
description: Select the home Wi-Fi ID(s)
default: []
selector:
text:
multiple: true
mode: restart
trigger:
# Door
- platform: state
entity_id: !input door_sensors
id: 'door_trigger'
# Presense
- platform: state
entity_id: !input presence_sensors
# Motion
- platform: state
entity_id: !input motion_sensors
# Control switch
- platform: state
entity_id: !input control_switch
# Wi-Fi sensors
- platform: state
entity_id: !input wifi_id_sensors
variables:
is_debug: false
wifi_id_sensors: !input wifi_id_sensors
home_wifi_ids: !input home_wifi_ids
control_switch: !input control_switch
result_value_entity: !input result_value_entity
motion_sensors: !input motion_sensors
presence_sensors: !input presence_sensors
door_sensors: !input door_sensors
door_sensor_threshold: !input door_sensor_threshold
door_on: >
{% set ns = namespace(items=[]) %}
{% for s in door_sensors %}
{% if states(s) not in ['unknown','unavailable'] and (now() - states[s].last_changed).total_seconds() < door_sensor_threshold %}
{% set ns.items = ns.items + [s] %}
{% endif %}
{% endfor %}
{{ ns.items | count > 0 }}
presence_on: >
{{ (presence_sensors | select('is_state', 'home') | list | length > 0) | bool
if presence_sensors | length > 0 else false }}
motion_on: >
{{ (motion_sensors | select('is_state', 'on') | list | length > 0) | bool
if motion_sensors | length > 0 else false }}
wifi_on: >
{{ expand(wifi_id_sensors)
| map(attribute='state')
| select('in', home_wifi_ids)
| list
| length > 0 }}
in_on_except_door: "{{ (motion_on or presence_on or wifi_on) and is_state(control_switch, 'on') }}"
is_on: "{{ in_on_except_door or door_on }}"
action:
# Debug info (log if required)
- choose:
- conditions:
- condition: template
value_template: "{{ is_debug }}"
sequence:
- service: persistent_notification.create
data:
title: "Debug Info"
message: >
motion_on = {{ motion_on }},
door_on = {{ door_on }},
presence_on = {{ presence_on }},
wifi_on = {{ wifi_on }}
# Setup result value.
- choose:
- conditions:
- condition: template
value_template: "{{ is_on }}"
sequence:
- service: input_boolean.turn_on
target:
entity_id: "{{ result_value_entity }}"
default:
- service: input_boolean.turn_off
target:
entity_id: "{{ result_value_entity }}"
# If it was door sensor then wait and turn on default scene after delay. On restart it will be retriggered.
- condition: template
value_template: "{{ (not in_on_except_door) and trigger.id == 'door_trigger' }}"
- delay:
seconds: "{{ door_sensor_threshold }}"
- service: input_boolean.turn_off
target:
entity_id: "{{ result_value_entity }}"

594
Common/Motion Light.yaml Normal file
View File

@@ -0,0 +1,594 @@
blueprint:
name: "Custom: Motion Light"
description: >
Smart motion sensor automation blueprint.
Note: by default will not run if light was already ON. If light was turned ON during automation running the automation will enter manual state and will not triiger untill the light will be turned off.
Note:
- Not tested when motion sensors and state sensors are used at the same time.
domain: automation
input:
controls:
name: "Controls"
collapsed: false
input:
motion_sensors:
name: Motion sensors
description: Select one or more motion sensors. Light is ON if any of the objects is ON.
default: []
selector:
entity:
domain:
- binary_sensor
- switch
- group
- light
- binary_sensor
multiple: true
condition_switches:
name: Condition switches
description: >
Automation will not trigger if any of switches is off
default: []
selector:
entity:
domain:
- input_boolean
- switch
- group
- light
- binary_sensor
multiple: true
devices_group:
name: "Devices"
collapsed: false
input:
target_light:
name: Target Light (optional)
description: "Light to control. Setup no light or single light."
default: []
selector:
entity:
domain: light
multiple: true
target_light_data:
name: Light Data Dictionary (optional)
default: ""
description: >
Provide a YAML dictionary of light.turn_on parameters. If parameter not specified then last set if taken.
Example:
brightness: 200
color_temp: 350
rgb_color: [255, 0, 0]
effect: rainbow
selector:
object: {}
brightness_threshold:
name: Brightness Threshold
description: 'Will trigger automation only if brightness of enabled light is lower then the threshold value'
default: 0
selector:
number:
min: 0
max: 255
step: 1
target_switch:
name: Target Switch (optional)
description: "Switch to control. Setup no switch or single switch."
default: []
selector:
entity:
domain: switch
multiple: true
timeout_delay:
name: Timeout delay (seconds)
description: Optional delay for motion sensors before turning off the light after all motion sensors are OFF
default: 0
selector:
number:
min: 0
max: 3600
step: 1
unit_of_measurement: seconds
persistent_state:
name: "Persistent State"
collapsed: true
input:
automation_state_entity:
name: Automation state entity
description: "`input_text` that stores the light automation state in JSON format. `Doesn't require specific initial state, values of the entity can be empty. For now each automation must have it's personal entity.`"
selector:
entity:
domain: input_text
automation_state_placeholder_key:
name: Automation state placeholder key
description: Overrides key for persistent storage if not empty. By default uses identifier of target light, otherwise uses constant. `Don't override it if you don't understand the meaning`
default: ''
selector:
text:
luminance:
name: "Luminance"
collapsed: true
input:
luminance_sensor:
name: Luminance sensor (optional)
description: Sensor reporting ambient light level (lux)
default: null
selector:
entity:
domain: sensor
luminance_threshold:
name: Luminance threshold (optional)
description: Light will only turn on if sensor value is below this threshold
default: 100
selector:
number:
min: 0
max: 10000
step: 1
unit_of_measurement: "lux"
luminance_enable_switch:
name: Luminance control enable switch (optional)
description: Switch or input_boolean to enable/disable luminance control
default: null
selector:
entity:
domain:
- switch
- input_boolean
actions:
name: "Actions"
collapsed: true
input:
user_condition:
name: Condition block
description: Optional condition(s) that must pass for actions to run
default: []
selector:
condition: {}
enable_action:
name: Enable callback action (optional)
description: Runs when light is turned on
default: []
selector:
action: {}
disable_action:
name: Disable callback action (optional)
description: Runs when light is turned off
default: []
selector:
action: {}
manual_action_runs_disable_action:
name: Manual also runs disable action
description: >
If checked, executing `Manual Action` will combine it with `Disable Action`.
default: false
selector:
boolean: {}
manual_action:
name: Manual callback action (optional)
description: >
Runs when light state is changed during automation running.
Works only in case if `Automation state entity` is set.
default: []
selector:
action: {}
mode: restart
trigger:
# Motion sensors ON/OFF
- platform: state
entity_id: !input motion_sensors
id: "motion_sensor"
# Condition switches ON/OFF
- platform: state
entity_id: !input condition_switches
# Light ON/OFF
- platform: state
entity_id: !input target_light
id: "light_state_changed"
# Switches ON/OFF
- platform: state
entity_id: !input target_switch
id: "switch_state_changed"
# Luminance sensor ON/OFF
- platform: template
value_template: >
{% if luminance_sensor %}
{{ states(luminance_sensor) not in ['unknown','unavailable'] }}
{% else %}
false
{% endif %}
- platform: template
value_template: >
{% if luminance_enable_switch %}
{{ states(luminance_enable_switch) not in ['unknown','unavailable'] }}
{% else %}
false
{% endif %}
condition: !input user_condition
# TOFIX:
# - state_sensors
# - might be problems with storing persistent state
variables:
# Constants
is_debug: false
is_base_debug: false
# JSON state constants
automation_state_invalid: '-1'
automation_state_none: '0'
automation_state_enabled: '1'
automation_state_enabling: '2'
automation_state_manual: '3'
state_motion_light_state: 'mls'
state_motion_light_last_action_timestamp: 'mllat'
state_motion_light_last_brightness: 'mllb'
date_time_now: "{{ now() }}"
trigger_id: "{{ trigger.id }}"
# Defines
sensors: !input motion_sensors
condition_switches: !input condition_switches
timeout: !input timeout_delay
brightness_threshold: !input brightness_threshold
# Light
light_entities: !input target_light
light_entity: "{{ light_entities[0] if light_entities | length != 0 else none }}"
# Switch
switch_entities: !input target_switch
switch_entity: "{{ switch_entities[0] if switch_entities | length != 0 else none }}"
# JSON global state.
automation_state_entity: !input automation_state_entity
automation_state_global: >
{% set text = states(automation_state_entity) | string %}
{% if text in ['unknown','unavailable','none',''] %}
{{ dict() }}
{% else %}
{{ text | from_json }}
{% endif %}
automation_state_placeholder_key: !input automation_state_placeholder_key
automation_state_key: >
{% if automation_state_placeholder_key != '' %}
{{ automation_state_placeholder_key }}
{% elif switch_entity is not none %}
{{ switch_entity }}
{% elif light_entity is not none %}
{{ light_entity }}
{% else %}
'default_motion_light_placeholder'
{% endif %}
automation_state: "{{ automation_state_global.get(automation_state_key, dict()) if light_entity != '' else dict() }}"
motion_light_state: "{{ automation_state.get(state_motion_light_state, automation_state_none) }}"
motion_light_last_action_timestamp: >
{% if trigger_id == 'state_motion' %}
{{ date_time_now }}
{% else %}
{{ (automation_state.get(state_motion_light_last_action_timestamp, none)) }}
{% endif %}
state_is_none: "{{ ((motion_light_state | string) == automation_state_none) }}"
state_is_enabled: "{{ (motion_light_state | string) == automation_state_enabled }}"
state_is_enabling: "{{ (motion_light_state | string) == automation_state_enabling }}"
state_is_manual: "{{ (motion_light_state | string) == automation_state_manual }}"
# Actions
manual_action: !input manual_action
disable_action: !input disable_action
enable_action: !input enable_action
manual_action_runs_disable_action: !input manual_action_runs_disable_action
light_data: !input target_light_data
# Luminance
luminance_sensor: !input luminance_sensor
luminance_threshold: !input luminance_threshold
luminance_enable_switch: !input luminance_enable_switch
luminance_ok: >
{% if luminance_sensor is not none and luminance_threshold is not none %}
{% set val = states(luminance_sensor) | float(0) %}
{% set enabled = true %}
{% if luminance_enable_switch %}
{% set enabled = is_state(luminance_enable_switch, 'on') %}
{% endif %}
{{ enabled and val < luminance_threshold }}
{% else %}
true
{% endif %}
# Trigger details
all_of_condition_switches_on: >
{% set e = condition_switches if condition_switches is iterable else [condition_switches] %}
{{ (e | select('is_state', 'on') | list | length) == condition_switches | length }}
count_of_enabled_sensor: >
{% set e = sensors if sensors is iterable else [sensors] %}
{{ e | select('is_state', 'on') | list | length }}
motion_on: "{{ count_of_enabled_sensor > 0 }}"
motion_all_off: "{{ count_of_enabled_sensor == 0 }}"
must_be_enabled_preview: >
{{ (all_of_condition_switches_on and luminance_ok and motion_on) | bool }}
must_be_enabled_guard: "{{ state_is_none }}"
must_be_enabled: >
{{ must_be_enabled_preview and must_be_enabled_guard }}
must_be_disabled_preview: >
{{ ((not all_of_condition_switches_on) or motion_all_off) | bool }}
must_be_disabled_guard: "{{ state_is_enabled }}"
must_be_disabled: >
{{ must_be_disabled_preview and must_be_disabled_guard }}
action:
# Debug info.
- choose:
- conditions:
- condition: template
value_template: "{{ is_base_debug }}"
sequence:
- service: persistent_notification.create
data:
title: "Debug Info"
message: >
must_be_enabled_preview: {{ must_be_enabled_preview }},
must_be_disabled_preview: {{ must_be_disabled_preview }},
must_be_disabled: {{ must_be_disabled }},
must_be_disabled_guard: {{ must_be_disabled_guard }},
id: {{ trigger.id }}
# Guard for 1 light.
- choose:
conditions:
- condition: template
value_template: "{{ light_entities | length > 1}}"
sequence:
stop: "Only one light is supported currently"
# Guard for 1 switch.
- choose:
conditions:
- condition: template
value_template: "{{ switch_entities | length > 1}}"
sequence:
stop: "Only one switch is supported currently"
- choose:
# Disable automation flag if light was changed during automation
- conditions:
- condition: template
value_template: "{{ trigger_id == 'light_state_changed' or trigger_id == 'switch_state_changed' }}"
sequence:
- choose:
# Disable state if light was turned OFF (no matter how)
- conditions:
- condition: template
value_template: >
{% set res = false %}
{% if light_entity is not none %}
{% set brightness = state_attr(light_entity, 'brightness') %}
{% set res = res and (is_state(light_entity, 'off') or brightness | int < brightness_threshold) %}
{% endif %}
{% if switch_entity is not none %}
{% set res = res and is_state(switch_entity, 'off') %}
{% endif %}
{{ res }}
sequence:
- service: input_text.set_value
target:
entity_id: "{{ automation_state_entity }}"
data:
value: >
{% set new_automation_state = (automation_state | combine({ state_motion_light_state: automation_state_none })) %}
{{ automation_state_global | combine({ automation_state_key: new_automation_state }) | tojson }}
# This call goes DIRECTLY from the automation
- conditions:
- condition: template
value_template: "{{ state_is_enabling }}"
sequence:
- service: input_text.set_value
target:
entity_id: "{{ automation_state_entity }}"
data:
value: >
{% set new_automation_state = (automation_state | combine({ state_motion_light_state: automation_state_enabled })) %}
{{ automation_state_global | combine({ automation_state_key: new_automation_state }) | tojson }}
# If the control was taken by the user
- conditions:
- condition: template
value_template: "{{ state_is_enabled }}"
sequence:
- service: input_text.set_value
target:
entity_id: "{{ automation_state_entity }}"
data: >
{% set new_automation_state = (automation_state | combine({ state_motion_light_state: automation_state_manual })) %}
{{ automation_state_global | combine({ automation_state_key: new_automation_state }) | tojson }}
# Call disable action if required
- choose:
- conditions: "{{ manual_action_runs_disable_action and disable_action != [] }}"
sequence: !input disable_action
# Call manual action
- choose:
- conditions: "{{ manual_action != [] }}"
sequence: !input manual_action
# Enable path
- conditions:
- condition: template
value_template: "{{ must_be_enabled }}"
sequence:
- choose:
# Guard: stop if light already ON and automation_flag exists
- conditions:
- condition: template
value_template: >
{% set res = false %}
{% if light_entity is not none %}
{% set res = res or ((is_state(light_entity, 'on') or state_attr(light_entity, 'brightness') | int > brightness_threshold)) %}
{% endif %}
{% if switch_entity is not none %}
{% set res = res or is_state(switch_entity, 'on') %}
{% endif %}
{{ res }}
sequence:
- stop: "Light is already ON when sensors were triggered"
# Enable the light
default:
# Debug info.
- choose:
- conditions:
- condition: template
value_template: "{{ is_debug }}"
sequence:
- service: persistent_notification.create
data:
title: "Debug Info (Must Be Enabled)"
message: >
Enabled. light_entity: {{ light_entity }}
- variables:
last_brightness: >
{% if (light_entity is none) or is_state(light_entity, 'off') %}
0
{% else %}
{{ state_attr(light_entity, 'brightness') }}
{% endif %}
# Turn ON the light
- choose:
- conditions:
- condition: template
value_template: "{{ light_entity is not none }}"
sequence:
- service: light.turn_on
target:
entity_id: "{{ light_entity }}"
data: "{{ light_data }}"
# Enable the switch.
- choose:
- conditions:
- condition: template
value_template: "{{ switch_entity is not none }}"
sequence:
- service: switch.turn_on
target:
entity_id: "{{ switch_entity }}"
- service: input_text.set_value
target:
entity_id: "{{ automation_state_entity }}"
data:
value: >
{% set new_automation_state = (automation_state | combine({ state_motion_light_state: automation_state_enabling, state_motion_light_last_action_timestamp: date_time_now, state_motion_light_last_brightness: last_brightness })) %}
{{ automation_state_global | combine({ automation_state_key: new_automation_state }) | tojson }}
# Enable action
- choose:
- conditions:
- condition: template
value_template: "{{ enable_action != [] }}"
sequence: !input enable_action
# Disable path
- conditions:
- condition: template
value_template: "{{ must_be_disabled }}"
sequence:
# Debug info.
- choose:
- conditions:
- condition: template
value_template: "{{ is_debug }}"
sequence:
- service: persistent_notification.create
data:
title: "Debug Info (Must Be Disabled)"
message: >
Disabled. light_entity: {{ light_entity }}
- delay:
seconds: "{{ timeout }}"
# Disable the light.
- choose:
- conditions:
- condition: template
value_template: "{{ light_entity is not none }}"
sequence:
- variables:
last_brightness: "{{ automation_state.get(state_motion_light_last_brightness, 0) }}"
- choose:
- conditions:
- condition: template
value_template: "{{ last_brightness > 0 }}"
sequence:
- service: light.turn_on
target:
entity_id: "{{ light_entity }}"
data:
brightness: "{{ last_brightness }}"
default:
- service: light.turn_off
target:
entity_id: "{{ light_entity }}"
# Disable the switch.
- choose:
- conditions:
- condition: template
value_template: "{{ switch_entity is not none }}"
sequence:
- service: switch.turn_off
target:
entity_id: "{{ switch_entity }}"
# Modify automation entity.
- service: input_text.set_value
target:
entity_id: "{{ automation_state_entity }}"
data:
value: >
{% set new_automation_state = (automation_state | combine({ state_motion_light_state: automation_state_none })) %}
{{ automation_state_global | combine({ automation_state_key: new_automation_state }) | tojson }}
- choose:
- conditions:
- condition: template
value_template: "{{ disable_action != [] }}"
sequence: !input disable_action

116
Common/Refrigerator.yaml Normal file
View File

@@ -0,0 +1,116 @@
blueprint:
name: "Custom: Refrigerator Express Mode Control"
description: >
Turns on express mode if the refrigerator temperature is too far from target.
Sends a notification when the difference exceeds the allowed threshold.
domain: automation
input:
door_sensor:
name: Door Sensor
description: Binary sensor for refrigerator door
selector:
entity:
domain: binary_sensor
temp_sensor:
name: Temperature Sensor
description: Sensor reporting current refrigerator temperature
selector:
entity:
domain: sensor
climate_entity:
name: Refrigerator Climate Entity
description: Climate entity that provides target temperature
selector:
entity:
domain: climate
device_name:
name: Device Name
description: Name of the device
default: 'Refrigerator'
selector:
text:
express_switch:
name: Express Mode Switch
description: Switch entity to enable express mode
selector:
entity:
domain: switch
max_diff:
name: Max Allowed Temperature Difference
description: Maximum difference between target and actual temperature before express mode is enabled
default: 3
selector:
number:
min: 1
max: 10
step: 0.5
unit_of_measurement: "°C"
notify_target:
name: Notification Target
description: Device or service to send notifications
default: []
selector:
entity:
domain: notify
multiple: true
mode: restart
trigger:
- platform: state
entity_id: !input temp_sensor
- platform: state
entity_id: !input door_sensor
- platform: state
entity_id: !input climate_entity
attribute: temperature
variables:
temp_sensor: !input temp_sensor
climate_entity: !input climate_entity
door_sensor: !input door_sensor
notify_target: !input notify_target
device_name: !input device_name
max_diff: !input max_diff
express_switch: !input express_switch
curr_temp: "{{ states(temp_sensor) | float(0) }}"
target_temp: "{{ state_attr(climate_entity, 'temperature') | float(0) }}"
diff: "{{ (curr_temp - target_temp) | abs }}"
temp_is_not_ok: "{{ diff > max_diff and is_state(door_sensor, 'off') }}"
action:
- choose:
- conditions:
- condition: template
value_template: "{{ temp_is_not_ok and is_state(express_switch, 'off') }}"
sequence:
- service: switch.turn_on
target:
entity_id: !input express_switch
- service: notify.send_message
target:
entity_id: !input notify_target
data:
message: >
{{ device_name }}: обнаружена проблема температурного режима.
Текущая {{ curr_temp }}°C, Целевая {{ target_temp }}°C,
Разница {{ diff }}°C. Включение экпресс режима.
- conditions:
- condition: template
value_template: "{{ not temp_is_not_ok }}"
sequence:
- service: switch.turn_off
target:
entity_id: !input express_switch

View File

@@ -0,0 +1,164 @@
blueprint:
name: "Custom: Telegram Commands"
description: >
Sends a Telegram message with inline keyboard buttons to multiple chat IDs
when executed manually, and reacts to button presses by performing
the corresponding action (one per button).
domain: automation
input:
commands_group:
name: "Commands"
collapsed: false
input:
commands:
name: Commands
description: List of commands
default: []
selector:
text:
multiple: true
answers:
name: Answers
description: List of answers (optional)
default: []
selector:
text:
multiple: true
callbacks_group:
name: "Callbacks"
collapsed: false
input:
button_1_callback:
name: Button 1 Callback
default: []
selector:
action: {}
button_2_callback:
name: Button 2 Callback
default: []
selector:
action: {}
button_3_callback:
name: Button 3 Callback
default: []
selector:
action: {}
button_4_callback:
name: Button 4 Callback
default: []
selector:
action: {}
button_5_callback:
name: Button 5 Callback
default: []
selector:
action: {}
button_6_callback:
name: Button 6 Callback
default: []
selector:
action: {}
button_7_callback:
name: Button 7 Callback
default: []
selector:
action: {}
button_8_callback:
name: Button 8 Callback
default: []
selector:
action: {}
mode: parallel
variables:
commands: !input commands
answers: !input answers
is_debug: false
command: "{{ trigger.event.data.command }}"
chat_id: "{{ trigger.event.data.chat_id }}"
trigger:
- platform: event
event_type: telegram_command
action:
- variables:
command_index: >
{% set res = -1 %}
{% if (commands | length >= 1 and command == commands[0] and button_1_callback != []) %}
{% set res = 0 %}
{% elif (commands | length >= 2 and command == commands[1] and button_2_callback != []) %}
{% set res = 1 %}
{% elif (commands | length >= 3 and command == commands[2] and button_3_callback != []) %}
{% set res = 2 %}
{% elif (commands | length >= 4 and command == commands[3] and button_4_callback != []) %}
{% set res = 3 %}
{% elif (commands | length >= 5 and command == commands[4] and button_5_callback != []) %}
{% set res = 4 %}
{% elif (commands | length >= 6 and command == commands[5] and button_6_callback != []) %}
{% set res = 5 %}
{% elif (commands | length >= 7 and command == commands[6] and button_7_callback != []) %}
{% set res = 6 %}
{% elif (commands | length >= 8 and command == commands[7] and button_8_callback != []) %}
{% set res = 7 %}
{% endif %}
{{ res }}
- choose:
- conditions: "{{ command_index == 0 }}"
sequence: !input button_1_callback
- conditions: "{{ command_index == 1 }}"
sequence: !input button_2_callback
- conditions: "{{ command_index == 2 }}"
sequence: !input button_3_callback
- conditions: "{{ command_index == 3 }}"
sequence: !input button_4_callback
- conditions: "{{ command_index == 4 }}"
sequence: !input button_5_callback
- conditions: "{{ command_index == 5 }}"
sequence: !input button_6_callback
- conditions: "{{ command_index == 6 }}"
sequence: !input button_7_callback
- conditions: "{{ command_index == 7 }}"
sequence: !input button_8_callback
- variables:
message: >
{% if command_index == -1 or answers | length <= command_index %}
{% else %}
{{ answers[command_index] }}
{% endif %}
# Debug info (log if required)
- choose:
- conditions:
- condition: template
value_template: "{{ is_debug }}"
sequence:
- service: persistent_notification.create
data:
title: "Debug Info (Telegram Commands)"
message: >
command_index = {{ command_index }},
commands = {{ commands }},
answers = {{ answers }},
message = {{ message }}
- choose:
- conditions: "{{ message != '' }}"
sequence:
- service: telegram_bot.send_message
data:
target: "{{ chat_id }}"
message: "{{ message }}"

View File

@@ -0,0 +1,244 @@
blueprint:
name: "Custom: Telegram Keyboard Action"
description: >
Sends a Telegram message with inline keyboard buttons to multiple chat IDs
when executed manually, and reacts to button presses by performing
the corresponding action (one per button).
domain: automation
input:
chat_group:
name: "Chats"
collapsed: false
input:
chat_ids:
name: Telegram Chat IDs
description: List of chat IDs
default: []
selector:
text:
multiple: true
chat_entities:
name: Telegram Notification Targets
description: "List of notification entities (entity friendly names must be in format `<Name> (<ChatID>)`, for example `Alex (2132562465)` )"
default: []
selector:
entity:
domain: notify
multiple: true
message_group:
name: "Message"
collapsed: false
input:
keyboard_id:
name: Keyboard ID
description: Identifier of the keyboard. This identifier should be unique to distinguish keyboards.
default: 'keyboard'
selector:
text:
message_text:
name: Message Text
description: Text of the message
default: '✉︎ Hey, that a new message'
selector:
text:
buttons:
name: Buttons
description: List of buttons texts
default:
- "✔"
- "✖"
selector:
text:
multiple: true
answers:
name: Answers
description: List of answers (optional)
default: []
selector:
text:
multiple: true
hide_keyboard_on_press:
name: Hide Keyboard On Any Button Press
description: Controls if keyboard must be hidden after any button press
default: true
selector:
boolean:
hide_message_on_press:
name: Hide Message On Any Button Press
description: Control if the message must be hidden after any button press
default: false
selector:
boolean:
callbacks_group:
name: "Callbacks"
collapsed: false
input:
button_1_callback:
name: Button 1 Callback
default: []
selector:
action: {}
button_2_callback:
name: Button 2 Callback
default: []
selector:
action: {}
button_3_callback:
name: Button 3 Callback
default: []
selector:
action: {}
button_4_callback:
name: Button 4 Callback
default: []
selector:
action: {}
mode: parallel
variables:
buttons: !input buttons
keyboard_id: !input keyboard_id
hide_keyboard_on_press: !input hide_keyboard_on_press
hide_message_on_press: !input hide_message_on_press
answers: !input answers
is_action: "{{ trigger.platform is none }}"
should_call_keyboard_callback: >
{% if trigger.platform is none%}
false
{% else %}
{% set button_id = trigger.event.data.data %}
{{ button_id.startswith('/' ~ keyboard_id) }}
{% endif %}
is_debug: false
trigger:
- platform: event
event_type: telegram_callback
action:
# Debug info (log if required)
- choose:
- conditions:
- condition: template
value_template: "{{ is_debug }}"
sequence:
- service: persistent_notification.create
data:
title: "Debug Info"
message: >
should_call_keyboard_callback = {{ should_call_keyboard_callback}}
- choose:
- conditions:
condition: template
value_template: "{{ should_call_keyboard_callback | bool }}"
sequence:
- variables:
callback_data: "{{ trigger.event.data.data }}"
chat_id: "{{ trigger.event.data.chat_id }}"
idx: "{{ callback_data[callback_data | length - 1] | int }}"
- choose:
- conditions: "{{ idx == 0 and button_1_callback != [] }}"
sequence: !input button_1_callback
- conditions: "{{ idx == 1 and button_2_callback != [] }}"
sequence: !input button_2_callback
- conditions: "{{ idx == 2 and button_3_callback != [] }}"
sequence: !input button_3_callback
- conditions: "{{ idx == 3 and button_4_callback != [] }}"
sequence: !input button_4_callback
- choose:
- conditions: "{{ idx != -1 and answers | length > idx and answers[idx] | length > 0 }}"
sequence:
- choose:
- conditions: "{{ hide_message_on_press }}"
sequence:
- service: telegram_bot.send_message
data:
target: "{{ chat_id }}"
message: "{{ answers[idx] }}"
default:
- service: telegram_bot.send_message
data:
target: "{{ chat_id }}"
message: "{{ answers[idx] }}"
reply_to_message_id: "{{ trigger.event.data.message.message_id }}"
- choose:
# Remove keyboard.
- conditions: "{{ hide_message_on_press }}"
sequence:
- service: telegram_bot.delete_message
data:
chat_id: "{{ trigger.event.data.chat_id }}"
message_id: "{{ trigger.event.data.message.message_id }}"
# Remove keyboard.
- conditions: "{{ hide_keyboard_on_press }}"
sequence:
- service: telegram_bot.edit_replymarkup
data:
chat_id: "{{ trigger.event.data.chat_id }}"
message_id: "{{ trigger.event.data.message.message_id }}"
inline_keyboard: []
- conditions:
condition: template
value_template: "{{ is_action }}"
sequence:
- variables:
chat_entities: !input chat_entities
chat_ids_from_entities: >
{% set ns = namespace(numbers=[]) %}
{% for e in chat_entities %}
{% set friendly_name = state_attr(e, 'friendly_name') %}
{% set ns.numbers = ns.numbers + [ friendly_name | regex_findall_index('\((\d+)\)', 0) ] %}
{% endfor %}
{{ ns.numbers }}
chat_ids: !input chat_ids
result_chat_ids: "{{ chat_ids + chat_ids_from_entities }}"
message_text: !input message_text
keyboard_text: >
{% set ns = namespace(result = []) %}
{% for i in range(buttons|length) %}
{% set ns.result = ns.result + [(buttons[i] ~ ':/' ~ keyboard_id ~ i)] %}
{% endfor %}
{{ ns.result }}
- choose:
# Broadcast
- conditions:
condition: template
value_template: "{{ result_chat_ids | length == 0 }}"
sequence:
- stop: "No chat ID(s) were resolved. No message will be sent."
# Target
- conditions:
condition: template
value_template: "{{ result_chat_ids | length != 0 }}"
sequence:
- service: telegram_bot.send_message
data:
target: "{{ result_chat_ids }}"
message: "{{ message_text }}"
inline_keyboard: "{{ keyboard_text }}"

View File

@@ -0,0 +1,80 @@
blueprint:
name: Time of Day State Machine (with Sensors)
description: >
Map a list of time-of-day states (input_select options) to a list of time entities or sensors.
At each threshold, set the input_select to the corresponding state.
Index-to-index mapping is guaranteed (state[0] ↔ time[0], state[1] ↔ time[1], etc).
Times can be input_datetime or sensors reporting HH:MM[:SS] values (e.g. sunset).
domain: automation
input:
tod_select:
name: Time of Day selector
description: The input_select entity that holds the current time-of-day state
selector:
entity:
domain: input_select
tod_states:
name: Time of Day states
description: Ordered list of state names (must match input_select options)
selector:
text:
multiple: true
tod_times:
name: Time of Day times/sensors
description: Ordered list of input_datetime or sensor entities (same length as states)
selector:
entity:
multiple: true
mode: restart
trigger:
# Trigger whenever any time-of-day entity changes
- platform: state
entity_id: !input tod_times
# Also trigger every minute to re-evaluate
- platform: time_pattern
minutes: "/1"
variables:
states: !input tod_states
times: !input tod_times
tod_select: !input tod_select
# Convert each entity state into seconds since midnight
thresholds: >
{% set out = [] %}
{% for t in times %}
{% set val = states(t) | as_datetime %}
{% if val is not none %}
{% set sec = dt.hour * 3600 + dt.minute * 60 + dt.second %}
{% set out = out + [sec] %}
{% endif %}
{% endfor %}
{{ out }}
now_sec: >
{% set n = now() %}
{{ n.hour * 3600 + n.minute * 60 + n.second }}
# Find the correct index based on current time
current_index: >
{% set idx = 0 %}
{% for i in range(thresholds|length) %}
{% if now_sec >= thresholds[i] %}
{% set idx = i %}
{% endif %}
{% endfor %}
{{ idx }}
current_state: "{{ states[current_index] }}"
action:
- service: input_select.select_option
target:
entity_id: "{{ tod_select }}"
data:
option: "{{ current_state }}"

View File

@@ -0,0 +1,79 @@
blueprint:
name: "Custom: Power Spike Tracker"
description: >
Monitors a list of power sensors and triggers when consumption spikes
beyond a defined ratio compared to the previous reading. Optionally
turns off the associated switch.
domain: automation
input:
power_sensors:
name: Power Sensors
description: 'List of power sensors to monitor. Switch entity ids will be calculated by replacing `sensor.` and `_power` substrings. I.e. for `sensor.my_switch_power` switch entity must be `switch.my_switch`.'
selector:
entity:
domain: sensor
multiple: true
spike_ratio:
name: Power Spike Ratio
description: Ratio threshold (e.g. 2.0 means power doubled)
default: 2.0
selector:
number:
min: 1.0
max: 10.0
step: 0.1
threshold_value:
name: Minimum Power Threshold
description: Ignore spikes if current power is below this value
default: 5
selector:
number:
min: 0
max: 5000
step: 1
unit_of_measurement: "W"
auto_turn_off:
name: Auto Turn Off Switch
description: 'If true, turn off the switch linked to the sensor that spiked'
default: false
selector:
boolean:
mode: restart
trigger:
- platform: state
entity_id: !input power_sensors
variables:
spike_ratio: !input spike_ratio
auto_turn_off: !input auto_turn_off
threshold_value: !input threshold_value
entity: "{{ trigger.entity_id }}"
prev: "{{ trigger.from_state.state | float(0) }}"
curr: "{{ trigger.to_state.state | float(0) }}"
# Derive switch name if convention is consistent (sensor.<name>_power → switch.<name>)
switch_entity: >
{{ entity | regex_replace('^sensor\\.', 'switch.') | regex_replace('_power$', '') }}
condition:
- condition: template
value_template: >
{{ curr > threshold_value and prev > 0 and (curr / prev) >= spike_ratio }}
action:
- service: notify.notify
data:
message: >
Power spike detected on {{ entity }}:
{{ prev }}W → {{ curr }}W (ratio {{ (curr/prev) | round(2) }})
- choose:
- conditions: "{{ auto_turn_off }}"
sequence:
- service: switch.turn_off
target:
entity_id: "{{ switch_entity }}"

374
Common/Washing Machine.yaml Normal file
View File

@@ -0,0 +1,374 @@
blueprint:
name: "Custom: Washing Machine Notifications"
description: >
Sends notifications when washing starts (with mode details),
when errors occur, and when run completes.
domain: automation
input:
time_group:
name: "Time"
collapsed: false
input:
remaining_time_sensor:
name: Remaining Time Sensor
description: "Sensor that contains remaining time in format `hh:mm::ss`. Note: `-`, 'unknown' values means remaining time is not available."
selector:
entity:
domain: sensor
run_state_sensor:
name: Run State Sensor
description: "Sensor that run state of the device"
selector:
entity:
domain: sensor
run_state_completion_id:
name: Run State Completion Id
description: "Identifier of run state that indicates that run is completed"
default: 'Цикл завершен.'
selector:
text:
notify_time_to_end:
name: Notify Time-to-End (minutes)
description: "Send notification if run is about to be finished"
default: 10
selector:
number:
min: 1
max: 60
unit_of_measurement: minutes
mode: slider
persistent_state:
name: "Persistent State"
collapsed: false
input:
automation_state_entity:
name: Automation state entity
description: "`input_text` that stores the automation state in JSON format. Required for all features proper functioning. `Doesn't require specific initial state, values of the entity can be empty`"
selector:
entity:
domain: input_text
automation_state_placeholder_key:
name: Automation state placeholder key
description: Overrides key for persistent storage if not empty. By default uses identifier of target light, otherwise uses constant. `Don't override it if you don't understand the meaning`
default: ''
selector:
text:
notification_group:
name: "Notification"
collapsed: false
input:
input_device_name:
name: "Device Name"
description: Device name (used for notifications)
default: "Стиральная машина"
selector:
text:
notify_target:
name: Notification Target
description: Device or service to send notifications
selector:
entity:
domain: notify
info_group:
name: "Info"
collapsed: false
input:
non_running_state_ids:
name: Non Running State ID(s)
description: "List of run state ID(s) that indicates that device is not actually doing its direct job"
default: []
selector:
text:
multiple: true
preparation_state_id:
name: Preparation Mode State ID (optional)
description: "Optional run state ID that indicates that device is preparing to run"
default: 'Подготовка к сушке'
selector:
text:
error_message_sensor:
name: Error Message Sensor
description: "Sensor that reports possible error message"
selector:
entity:
domain: sensor
tub_clean_counter_sensor:
name: Tub Clean Counter Sensor (Optional)
description: "Sensor that reports tub clean counter value"
selector:
entity:
domain:
- sensor
- input_number
tub_clean_counter_threshold:
name: Tub Clean Counter Threshold
description: "Threshold for tub clean counter value when notification should be sent. Zero means no reports."
default: 30
selector:
number:
min: 0
max: 100
mode: slider
details_group:
name: "Details"
collapsed: false
input:
startup_info_sensors:
name: Startup Info Sensors (Optional)
description: "A list of sensor with some details that will be reported on machine startup notification"
default: []
selector:
entity:
domain:
- sensor
- binary_sensor
multiple: true
startup_info_texts:
name: Startup Info Texts
description: "List of texts associated with `Startup Info Sensors` (one per sensor)"
default: []
selector:
text:
multiple: true
mode: restart
trigger:
# Remaining time changes
- platform: state
entity_id: !input remaining_time_sensor
# Error message appears
- platform: state
entity_id: !input error_message_sensor
# Run state
- platform: state
entity_id: !input run_state_sensor
# Tub clean sensor changed
- platform: state
entity_id: !input tub_clean_counter_sensor
condition: []
variables:
# JSON state constants
state_notification_about_renaming_time_sent: 'nart'
state_notification_about_start_sent: 'nass'
state_notification_about_preparation_sent: 'naps'
# Inputs
run_state_sensor: !input run_state_sensor
non_running_state_ids: !input non_running_state_ids
preparation_state_id: !input preparation_state_id
error_message_sensor: !input error_message_sensor
remaining_time_sensor: !input remaining_time_sensor
notify_target: !input notify_target
notify_time_to_end: !input notify_time_to_end
input_device_name: !input input_device_name
tub_clean_counter_sensor: !input tub_clean_counter_sensor
tub_clean_counter_threshold: !input tub_clean_counter_threshold
run_state_completion_id: !input run_state_completion_id
# States
remaining: "{{ states(remaining_time_sensor) }}"
device_name: "{{ input_device_name }}"
run_state: "{{ states(run_state_sensor) }}"
is_running: >
{{ run_state not in ['unknown', 'unavailable', 'waiting', '-']
and run_state not in non_running_state_ids
and run_state != preparation_state_id
and run_state != run_state_completion_id
and remaining not in ['unknown', 'unavailable'] }}
remaining_time_in_minutes: >
{% if remaining not in ['unknown', 'unavailable'] %}
{% set parts = remaining.split(':') %}
{% set total = parts[0]|int * 60 + parts[1]|int %}
{{ total }}
{% else %}
0
{% endif %}
# JSON global state.
automation_state_entity: !input automation_state_entity
automation_state_global: >
{% set text = states(automation_state_entity) | string %}
{% if text in ['unknown','unavailable','none',''] %}
{{ dict() }}
{% else %}
{{ text | from_json }}
{% endif %}
automation_state_placeholder_key: !input automation_state_placeholder_key
automation_state_key: >
{% if automation_state_placeholder_key != '' %}
{{ automation_state_placeholder_key }}
{% else %}
{{ remaining_time_sensor }}
{% endif %}
automation_state: "{{ automation_state_global.get(automation_state_key, dict()) }}"
is_debug: false
action:
# Debug info (log if required)
- choose:
- conditions:
- condition: template
value_template: "{{ is_debug }}"
sequence:
- service: persistent_notification.create
data:
title: "Debug Info"
message: >
run_state = {{ run_state }},
non_running_state_ids = {{ non_running_state_ids }},
remaining_time = {{ states(remaining_time_sensor) }},
is_running = {{ is_running }},
t = {{ automation_state.get(state_notification_about_start_sent, false) }}
- choose:
# 🟢 Case 1: Washing started
- conditions:
- condition: template
value_template: "{{ not automation_state.get(state_notification_about_start_sent, false) and is_running }}"
sequence:
- variables:
startup_info_sensors: !input startup_info_sensors
startup_info_texts: !input startup_info_texts
message: >
{% set ns = namespace(text = '🧺 ' ~ device_name ~ ': старт. Длительность: `' ~ remaining ~ '`.') %}
{% for i in range(startup_info_sensors | count) %}
{% set ns.text = ns.text ~ ' ' ~ startup_info_texts[i] ~ ': [' ~ states(startup_info_sensors[i]) ~ '].' %}
{% endfor %}
{{ ns.text }}
- service: notify.send_message
target:
entity_id: !input notify_target
data:
message: "{{ message }}"
- service: input_text.set_value
target:
entity_id: "{{ automation_state_entity }}"
data:
value: >
{% set new_automation_state = (automation_state | combine({ state_notification_about_start_sent: true })) %}
{{ automation_state_global | combine({ automation_state_key: new_automation_state }) | tojson }}
# ✅ Case 2: Run completed
- conditions:
- condition: template
value_template: >
{{ not is_running
and automation_state.get(state_notification_about_start_sent, false)
and (states(run_state_sensor) in [run_state_completion_id, 'unknown', '-'] or states(remaining_time_sensor) in ['unknown', '-']) }}
sequence:
- service: notify.send_message
target:
entity_id: !input notify_target
data:
message: >
🟢 {{ device_name }}: завершено. Не забудьте достать вещи!
# Reset the state.
- service: input_text.set_value
target:
entity_id: "{{ automation_state_entity }}"
data:
value: >
{% set new_automation_state = (automation_state | combine({ state_notification_about_renaming_time_sent: false, state_notification_about_start_sent: false, state_notification_about_preparation_sent: false })) %}
{{ automation_state_global | combine({ automation_state_key: new_automation_state }) | tojson }}
# ✅ Case 3: Preparation
- conditions:
- condition: template
value_template: >
{{ preparation_state_id != ''
and states(run_state_sensor) == preparation_state_id
and not automation_state.get(state_notification_about_preparation_sent, false) }}
sequence:
# Reset the state.
- service: input_text.set_value
target:
entity_id: "{{ automation_state_entity }}"
data:
value: >
{% set new_automation_state = (automation_state | combine({ state_notification_about_preparation_sent: true })) %}
{{ automation_state_global | combine({ automation_state_key: new_automation_state }) | tojson }}
- service: notify.send_message
target:
entity_id: !input notify_target
data:
message: >
⚙️ {{ device_name }}: подготовка активирована!
# 🔴 Case 4: Error message
- conditions:
- condition: template
value_template: "{{ trigger.entity_id == error_message_sensor and error|length > 0 }}"
sequence:
- variables:
error: "{{ states(error_message_sensor) }}"
- service: notify.send_message
target:
entity_id: !input notify_target
data:
message: >
⚠️ {{ device_name }}: ошибка. Детали: {{ error }}. Для более подробной информации обратитесь к приложению LG ThinQ.
# ⏰ Case 5: Notify before end
- conditions:
- condition: template
value_template: >
{% if not automation_state.get(state_notification_about_renaming_time_sent, false) and is_running %}
{{ remaining_time_in_minutes <= notify_time_to_end }}
{% else %}
{{ false }}
{% endif %}
sequence:
- service: input_text.set_value
target:
entity_id: "{{ automation_state_entity }}"
data:
value: >
{% set new_automation_state = (automation_state | combine({ state_notification_about_renaming_time_sent: true })) %}
{{ automation_state_global | combine({ automation_state_key: new_automation_state }) | tojson }}
- service: notify.send_message
target:
entity_id: !input notify_target
data:
message: >
🟢 {{ device_name }}: завершение через {{ remaining.split(':')[1] }} минут.
# 🔴 Case 6: Tub clean notification
- conditions:
- condition: template
value_template: "{{ trigger.entity_id == tub_clean_counter_sensor and tub_clean_counter_threshold != 0 and (states(tub_clean_counter_sensor) | int) > tub_clean_counter_threshold }}"
sequence:
- service: notify.send_message
target:
entity_id: !input notify_target
data:
message: >
⚠️ {{ device_name }}: внимание. Необходима чистка барабана.
Число стирок: {{ states(tub_clean_counter_sensor) | int }}.
Допустимый предел: {{ tub_clean_counter_threshold }}.

32
Test/TestBp.yaml Normal file
View File

@@ -0,0 +1,32 @@
blueprint:
name: MQTT Multi-Topic Listener
domain: automation
input:
mqtt_topics:
name: MQTT Topics
description: List of topics to react to
selector:
text:
multiple: true
default: []
trigger:
- platform: mqtt
topic: "#"
action:
- variables:
mqtt_topics: !input mqtt_topics
received_topic: "{{ trigger.topic }}"
received_payload: "{{ trigger.payload }}"
- choose:
- conditions:
- condition: template
value_template: >
{{ received_topic in mqtt_topics }}
sequence:
- service: persistent_notification.create
data:
title: "Debug Info"
message: >
{{ trigger.topic }}

View File

@@ -0,0 +1,216 @@
blueprint:
name: "Custom: MQTT Button Control"
description: Control a Zigbee2MQTT device with multiple actions, that allows to toggle lights and switches and store entity identifier of last interructed switch/light.
domain: automation
input:
mqtt_group:
name: "MQTT"
collapsed: false
input:
mqtt_topic:
name: MQTT Topic
description: The MQTT topic for your Zigbee button (e.g., zigbee2mqtt/my_button1).
selector:
text:
mqtt_topic2:
name: MQTT Topic 2
description: The MQTT topic for your Zigbee button (e.g., zigbee2mqtt/my_button2).
default: fake
selector:
text:
devices:
name: "Primary"
collapsed: false
input:
action_ids:
name: Action IDs
description: The action IDs that must map to lights (action → light)
default: []
selector:
text:
multiple: true
switches:
name: Switches
description: "The list of switches to control. Next types are supported: `light`, `switch`, `input_boolean`"
default: []
selector:
entity:
domain:
- light
- switch
- input_boolean
multiple: true
outputs:
name: "Outputs"
collapsed: false
input:
last_interacted_text:
name: Last Interacted Entity Text Helper (optional)
description: "`input_text` entity that will store last enabled entity"
default: ""
selector:
entity:
domain: input_text
common:
name: "Common"
collapsed: false
input:
timeout_for_indication_blink:
name: "Timeout for indicator blink"
description: If not zero does blink when button with already enabled light is pressed to indicate that the light is active now if elapsed time from last action is greater then the specified value
default: 10
selector:
number:
min: 0
max: 100
step: 1
unit_of_measurement: "s"
blink_count:
name: Count of blinks
description: "Count of blinks to indicate active light"
default: 3
selector:
number:
min: 0
max: 5
step: 1
blink_interval:
name: Interval between blinks
description: "Interval between indicator blinks (in ms)"
default: 250
selector:
number:
min: 0
max: 1000
step: 50
unit_of_measurement: "ms"
trigger:
- platform: mqtt
topic: !input mqtt_topic
- platform: mqtt
topic: !input mqtt_topic2
enabled: "{{ mqtt_topic2 != '' }}"
mode: restart
condition:
- condition: template
value_template: "{{ 'action' in trigger.payload_json }}"
action:
- variables:
action_id: "{{ trigger.payload_json.action }}"
switches: !input switches
action_ids: !input action_ids
target_index: >
{% if action_id in action_ids %}
{{ action_ids.index(action_id) }}
{% else %}
-1
{% endif %}
target_entity: "{{ switches[target_index] if target_index != -1 else none }}"
last_interacted_text: !input last_interacted_text
is_debug: false
- choose:
- conditions:
- condition: template
value_template: "{{ target_entity is not none }}"
sequence:
- variables:
entity_type: "{{ target_entity.split('.')[0] }}"
- service: input_text.set_value
data:
entity_id: "{{ last_interacted_text }}"
value: "{{ target_entity }}"
- choose:
# Light
- conditions:
- condition: template
value_template: "{{ entity_type == 'light' }}"
sequence:
- variables:
timeout_for_indication_blink: !input timeout_for_indication_blink
seconds_elapsed: >
{{ (as_timestamp(now()) - as_timestamp(states[target_entity].last_changed)) | int }}
should_blink: "{{ timeout_for_indication_blink != 0 and seconds_elapsed > timeout_for_indication_blink }}"
blink_count: !input blink_count
blink_timeout: !input blink_interval
is_light_on: "{{ is_state(target_entity, 'on') }}"
# Debug
- choose:
- conditions:
- condition: template
value_template: "{{ is_debug }}"
sequence:
- service: persistent_notification.create
data:
title: "Debug Info"
message: >
seconds_elapsed = {{ seconds_elapsed }},
should_blink = {{ should_blink }}
- choose:
# Blink
- conditions:
- condition: template
value_template: "{{ should_blink and is_light_on }}"
sequence:
- repeat:
count: "{{ blink_count }}"
sequence:
- service: light.turn_off
target:
entity_id: "{{ target_entity }}"
data:
transition: 0
- delay:
milliseconds: "{{ blink_timeout }}"
- service: light.turn_on
target:
entity_id: "{{ target_entity }}"
data:
transition: 0
- delay:
milliseconds: "{{ blink_timeout }}"
# Actually toggle
default:
- service: light.toggle
target:
entity_id: "{{ target_entity }}"
# Switch
- conditions:
- condition: template
value_template: "{{ entity_type == 'switch' }}"
sequence:
- service: switch.toggle
target:
entity_id: "{{ target_entity }}"
# Input Boolean
- conditions:
- condition: template
value_template: "{{ entity_type == 'input_boolean' }}"
sequence:
- service: input_boolean.toggle
target:
entity_id: "{{ target_entity }}"

View File

@@ -0,0 +1,213 @@
blueprint:
name: "Custom: MQTT Generic Control"
description: >
Triggered by MQTT messages. Supports up to 8 custom action IDs with optional callbacks.
domain: automation
input:
mqtt_group:
name: "MQTT"
collapsed: false
input:
mqtt_topic:
name: MQTT Topic 1
description: The MQTT topic to listen to
selector:
text: {}
mqtt_topic2:
name: MQTT Topic 2
description: The MQTT topic to listen to
default: 'fake'
selector:
text: {}
mqtt_topic3:
name: MQTT Topic 3
description: The MQTT topic to listen to
default: 'fake'
selector:
text: {}
mqtt_topic4:
name: MQTT Topic 4
description: The MQTT topic to listen to
default: 'fake'
selector:
text: {}
actions_group:
name: "Actions"
collapsed: false
input:
action_id_1:
name: Action ID 1
description: Value of `payload_json.action` that triggers callback 1
default: ""
selector:
text: {}
action_callback_1:
name: Action Callback 1
description: Actions to run when Action ID 1 is received
default: []
selector:
action: {}
action_id_2:
name: Action ID 2
default: ""
selector:
text: {}
action_callback_2:
name: Action Callback 2
default: []
selector:
action: {}
action_id_3:
name: Action ID 3
default: ""
selector:
text: {}
action_callback_3:
name: Action Callback 3
default: []
selector:
action: {}
action_id_4:
name: Action ID 4
default: ""
selector:
text: {}
action_callback_4:
name: Action Callback 4
default: []
selector:
action: {}
action_id_5:
name: Action ID 5
default: ""
selector:
text: {}
action_callback_5:
name: Action Callback 5
default: []
selector:
action: {}
action_id_6:
name: Action ID 6
default: ""
selector:
text: {}
action_callback_6:
name: Action Callback 6
default: []
selector:
action: {}
action_id_7:
name: Action ID 7
default: ""
selector:
text: {}
action_callback_7:
name: Action Callback 7
default: []
selector:
action: {}
action_id_8:
name: Action ID 8
default: ""
selector:
text: {}
action_callback_8:
name: Action Callback 8
default: []
selector:
action: {}
mode: restart
trigger:
- platform: mqtt
topic: !input mqtt_topic
- platform: mqtt
topic: !input mqtt_topic2
enabled: "{{ mqtt_topic2 != '' }}"
- platform: mqtt
topic: !input mqtt_topic3
enabled: "{{ mqtt_topic3 != '' }}"
- platform: mqtt
topic: !input mqtt_topic4
enabled: "{{ mqtt_topic4 != '' }}"
variables:
action_id: "{{ trigger.payload_json.action }}"
action_id_1: !input action_id_1
action_id_2: !input action_id_2
action_id_3: !input action_id_3
action_id_4: !input action_id_4
action_id_5: !input action_id_5
action_id_6: !input action_id_6
action_id_7: !input action_id_7
action_id_8: !input action_id_8
is_debug: false
action:
# Debug info (log if required)
- choose:
- conditions:
- condition: template
value_template: "{{ is_debug }}"
sequence:
- service: persistent_notification.create
data:
title: "Debug Info"
message: >
action = {{ action_id }},
1 = {{ action_id_1 }}
- choose:
- conditions:
- condition: template
value_template: "{{ action_id_1 != '' and action_id == action_id_1 }}"
sequence: !input action_callback_1
- conditions:
- condition: template
value_template: "{{ action_id_2 != '' and action_id == action_id_2 }}"
sequence: !input action_callback_2
- conditions:
- condition: template
value_template: "{{ action_id_3 != '' and action_id == action_id_3 }}"
sequence: !input action_callback_3
- conditions:
- condition: template
value_template: "{{ action_id_4 != '' and action_id == action_id_4 }}"
sequence: !input action_callback_4
- conditions:
- condition: template
value_template: "{{ action_id_5 != '' and action_id == action_id_5 }}"
sequence: !input action_callback_5
- conditions:
- condition: template
value_template: "{{ action_id_6 != '' and action_id == action_id_6 }}"
sequence: !input action_callback_6
- conditions:
- condition: template
value_template: "{{ action_id_7 != '' and action_id == action_id_7 }}"
sequence: !input action_callback_7
- conditions:
- condition: template
value_template: "{{ action_id_8 != '' and action_id == action_id_8 }}"
sequence: !input action_callback_8

File diff suppressed because it is too large Load Diff

View File

@@ -0,0 +1,372 @@
blueprint:
name: "Custom: MQTT Light Selector"
description: >
Cycle through a list of lights using MQTT button events (up/down).
Selected light is stored in an input_text helper and flashes N times
with Z interval when selected.
domain: automation
input:
devices:
name: "Devices"
collapsed: false
input:
mqtt_topic:
name: MQTT Topic
description: Topic where button events are published
selector:
text: {}
mqtt_topic2:
name: MQTT Topic
description: Topic where button events are published
default: 'fake'
selector:
text: {}
lights:
name: "Lights"
collapsed: false
input:
lights:
name: Lights
description: List of lights to cycle through
selector:
entity:
domain: light
multiple: true
persistent_state:
name: "Persiatent State"
collapsed: false
input:
selected_light_helper:
name: Selected Light Helper
description: Input_text entity to store the selected light
selector:
entity:
domain: input_text
automation_state_entity:
name: Automation state entity
description: The `input_text` entity will store state of the automation in JSON format. `Doesn't require any initial state, can be empty. For now each automation must have it's personal entity.`
default: null
selector:
entity:
domain:
- input_text
action_ids:
name: "Action IDs"
collapsed: false
input:
action_up:
name: Up Action Identifier
description: Payload string for "next light"
default: ''
selector:
text: {}
action_down:
name: Down Action Identifier
description: Payload string for "previous light"
default: ''
selector:
text: {}
action_remind:
name: Remind Action Identifier
description: Payload string for "current light"
default: ''
selector:
text: {}
params:
name: "Parameters"
collapsed: false
input:
transition:
name: Transition Time (ms)
description: Duration of brightness transition
default: 0
selector:
number:
min: 0
max: 500
step: 10
unit_of_measurement: ms
remind_using_up_down_delay:
name: Force Remind Using Up/Down Delay
description: "If specified then `Up`/`Down` action will work like `Remind` in case if duration from the last action was greater then this value"
default: 0
selector:
number:
min: 0
max: 100
step: 1
unit_of_measurement: s
flash_count:
name: Flash Count
description: Number of times to flash selected light
default: 2
selector:
number:
min: 1
max: 10
step: 1
flash_interval_ms:
name: Flash Interval (ms)
description: Interval between flashes in milliseconds
default: 500
selector:
number:
min: 100
max: 2000
step: 100
unit_of_measurement: ms
actions_group:
name: "Actions"
collapsed: false
input:
condition_action:
name: Extra Condition
description: Optional condition to check before running actions
default: []
selector:
condition: {}
callback_action:
name: Callback Action
description: Optional action to run after main sequence
default: []
selector:
action: {}
trigger:
- platform: mqtt
topic: !input mqtt_topic
id: "mqtt"
- platform: mqtt
topic: !input mqtt_topic2
id: "mqtt"
condition: !input condition_action
mode: restart
variables:
# Constants.
is_debug: false
# Defines.
lights: !input lights
helper: !input selected_light_helper
action_up: !input action_up
action_down: !input action_down
action_remind: !input action_remind
flash_count: !input flash_count
flash_interval_ms: !input flash_interval_ms
transition: !input transition
remind_using_up_down_delay: !input remind_using_up_down_delay
mqtt_topic: !input mqtt_topic
# JSON global state.
state_key_last_was_on: 'lwo'
state_key_last_light: 'll'
state_key_last_select_action_datetime: 'lsadt'
automation_state_entity: !input automation_state_entity
automation_state_global: >
{% if automation_state_entity is not none %}
{% set text = states(automation_state_entity) | string %}
{% if text in ['unknown','unavailable','none',''] %}
{{ dict() }}
{% else %}
{{ text | from_json }}
{% endif %}
{% else %}
{{ dict() }}
{% endif %}
current_datetime: "{{ now() }}"
# TODO alexeid: it's better to use mqtt_topic as key, but cyrilic characters require use of tranliteration
automation_state_key: "mqtt_light_selector:{{ lights[0] }}"
automation_state: "{{ automation_state_global.get(automation_state_key, dict()) if automation_state_key != '' else dict() }}"
state_last_was_on: "{{ automation_state.get(state_key_last_was_on, false) | bool }}"
state_last_light: "{{ automation_state.get(state_key_last_light, '') | string }}"
state_last_select_action_datetime: "{{ as_datetime(automation_state.get(state_key_last_select_action_datetime, current_datetime)) }}"
# Current index from helper (fallback to 0 if empty)
current_light: >
{% set entity_id = states(helper) %}
{{ entity_id if entity_id in lights else none }}
current_index: >
{% set idx = lights.index(current_light) if current_light in lights else 0 %}
{{ idx }}
action:
# Debug info (log if required)
- choose:
- conditions:
- condition: template
value_template: "{{ is_debug }}"
sequence:
- service: persistent_notification.create
data:
title: "Debug Info"
message: "automation_state_key = {{ automation_state_key }}"
- choose:
# MQTT -> handle the message
- conditions:
- condition: template
value_template: "{{ trigger.id == 'mqtt' }}"
sequence:
- variables:
action_id: "{{ trigger.payload_json.action }}"
# Don't forget to restore last light state
- choose:
- conditions:
- condition: template
value_template: "{{ state_last_light != '' }}"
sequence:
- choose:
- conditions:
- condition: template
value_template: "{{ state_last_was_on }}"
sequence:
- service: light.turn_on
target:
entity_id: "{{ state_last_light }}"
data:
transition: "{{ transition }}"
- conditions:
- condition: template
value_template: "{{ not state_last_was_on }}"
sequence:
- service: light.turn_off
target:
entity_id: "{{ state_last_light }}"
data:
transition: "{{ transition }}"
# Save persistent state.
- choose:
- conditions:
- condition: template
value_template: "{{ automation_state_entity is not none }}"
sequence:
- service: input_text.set_value
target:
entity_id: "{{ automation_state_entity }}"
data:
value: >
{% set new_automation_state = (automation_state | combine({ state_key_last_light: '' })) %}
{% set new_automation_state = (new_automation_state | combine({ state_key_last_was_on: new_on })) %}
{% set new_automation_state = (new_automation_state | combine({ state_key_last_select_action_datetime: current_datetime })) %}
{{ automation_state_global | combine({ automation_state_key: new_automation_state }) | tojson }}
# Do actual selection
- choose:
- conditions:
- condition: template
value_template: "{{ (action_id != '') and (action_id == action_up or action_id == action_down or action_id == action_remind) }}"
sequence:
- variables:
datetime_diff_seconds: >
{% set diff = current_datetime - state_last_select_action_datetime %}
{{ diff.total_seconds() }}
step: >
{% if remind_using_up_down_delay != 0 and datetime_diff_seconds < remind_using_up_down_delay %}
0
{% elif action_up != '' and action_id == action_up %}
1
{% elif action_down != '' and action_id == action_down %}
-1
{% else %}
0
{% endif %}
new_index: "{{ (current_index + step) % lights|length }}"
new_light: "{{ lights[new_index] }}"
new_on: "{{ is_state(new_light, 'on') }}"
# Save persistent state.
- choose:
- conditions:
- condition: template
value_template: "{{ automation_state_entity is not none }}"
sequence:
- service: input_text.set_value
target:
entity_id: "{{ automation_state_entity }}"
data:
value: >
{% set new_automation_state = (automation_state | combine({ state_key_last_light: new_light })) %}
{% set new_automation_state = (new_automation_state | combine({ state_key_last_was_on: new_on })) %}
{{ automation_state_global | combine({ automation_state_key: new_automation_state }) | tojson }}
# Run callback only if user provided it: think if we need to invoke callback here
- choose:
- conditions:
- condition: template
value_template: "{{ callback_action is defined and (callback_action|length > 0) }}"
sequence: !input callback_action
# Assign new light entity id to helper value
- service: input_text.set_value
target:
entity_id: "{{ helper }}"
data:
value: "{{ new_light }}"
- repeat:
count: "{{ flash_count }}"
sequence:
- service: light.turn_off
target:
entity_id: "{{ new_light }}"
data:
transition: "{{ transition }}"
- delay:
milliseconds: "{{ flash_interval_ms }}"
- service: light.turn_on
target:
entity_id: "{{ new_light }}"
data:
transition: "{{ transition }}"
- delay:
milliseconds: "{{ flash_interval_ms }}"
# Optionally turn off the light.
- choose:
- conditions:
- condition: template
value_template: "{{ not new_on }}"
sequence:
- service: light.turn_off
target:
entity_id: "{{ new_light }}"
data:
transition: "{{ transition }}"
# Save persistent state.
- choose:
- conditions:
- condition: template
value_template: "{{ automation_state_entity is not none }}"
sequence:
- service: input_text.set_value
target:
entity_id: "{{ automation_state_entity }}"
data:
value: >
{% set new_automation_state = (automation_state | combine({ state_key_last_light: '' })) %}
{% set new_automation_state = (new_automation_state | combine({ state_key_last_was_on: new_on })) %}
{{ automation_state_global | combine({ automation_state_key: new_automation_state }) | tojson }}

View File

@@ -0,0 +1,69 @@
blueprint:
name: "Custom: MQTT Knob Media Controller (Dynamic Step)"
description: >
Control a media player using a knob switch via MQTT.
- `toggle` pauses/unpauses
- `rotate_left` decreases volume
- `rotate_right` increases volume
- Volume step is taken from `action_step` in the MQTT payload
domain: automation
input:
mqtt_topic:
name: MQTT Topic
description: The topic your knob publishes to (e.g., zigbee2mqtt/knob1/action)
selector:
text:
media_player:
name: Media Player
selector:
entity:
domain: media_player
trigger:
- platform: mqtt
topic: !input mqtt_topic
variables:
media: !input media_player
action: "{{ trigger.payload_json.action }}"
step: >-
{% set key = 'action_step_size' %}
{% if key in trigger.payload_json %}
{{ (trigger.payload_json[key] | float(0)) / 500 }}
{% else %}
0
{% endif %}
action:
- choose:
- conditions:
- condition: template
value_template: "{{ action == 'toggle' }}"
sequence:
- service: media_player.media_play_pause
target:
entity_id: "{{ media }}"
- conditions:
- condition: template
value_template: "{{ action == 'brightness_step_down' }}"
sequence:
- variables:
current: "{{ state_attr(media, 'volume_level') | float(0) }}"
new: "{{ [0, current - step] | max }}"
- service: media_player.volume_set
target:
entity_id: "{{ media }}"
data:
volume_level: "{{ new }}"
- conditions:
- condition: template
value_template: "{{ action == 'brightness_step_up' }}"
sequence:
- variables:
current: "{{ state_attr(media, 'volume_level') | float(0) }}"
new: "{{ [current + step, 1] | min }}"
- service: media_player.volume_set
target:
entity_id: "{{ media }}"
data:
volume_level: "{{ new }}"