3d15f481a0
- Add optional debug notifications for trigger and light-branch decisions - Document index-based action/entity mapping and two-topic support - Add configuration reference table and debug-mode section to README
316 lines
11 KiB
YAML
316 lines
11 KiB
YAML
# MQTT Button Control Blueprint
|
|
# Controls lights and switches using Zigbee2MQTT button devices.
|
|
# See README.md for detailed documentation.
|
|
#
|
|
# Author: Alexei Dolgolyov (dolgolyov.alexei@gmail.com)
|
|
|
|
blueprint:
|
|
name: "Custom: MQTT Button Control"
|
|
description: >
|
|
Control a Zigbee2MQTT device with multiple actions: toggle lights,
|
|
switches and input_booleans, and optionally remember the entity that
|
|
was last interacted with in an input_text helper.
|
|
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 (Optional)
|
|
description: >
|
|
Additional MQTT topic for a second button.
|
|
Leave as default placeholder if not using.
|
|
default: "blueprint/disabled/mqtt_button_control"
|
|
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"
|
|
|
|
# -------------------------------------------------------------------------
|
|
# Debug
|
|
# -------------------------------------------------------------------------
|
|
debug_group:
|
|
name: "Debug"
|
|
collapsed: true
|
|
input:
|
|
enable_debug_notifications:
|
|
name: Enable Debug Notifications
|
|
description: >
|
|
Send persistent notifications for debugging automation behavior.
|
|
Shows received action, resolved target entity and blink decision.
|
|
default: false
|
|
selector:
|
|
boolean:
|
|
|
|
trigger:
|
|
- platform: mqtt
|
|
topic: !input mqtt_topic
|
|
id: button_1
|
|
- platform: mqtt
|
|
topic: !input mqtt_topic2
|
|
id: button_2
|
|
enabled: "{{ mqtt_topic2 not in ['', 'blueprint/disabled/mqtt_button_control'] }}"
|
|
|
|
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
|
|
last_interacted_text: !input last_interacted_text
|
|
is_debug: !input enable_debug_notifications
|
|
|
|
# Resolve action_id → switch index. Whitespace-controlled and coerced
|
|
# to int so subscripting `switches[target_index]` is safe.
|
|
target_index: >-
|
|
{%- if action_id in action_ids -%}
|
|
{{ action_ids.index(action_id) }}
|
|
{%- else -%}
|
|
-1
|
|
{%- endif -%}
|
|
# Bounds-check the index: action_ids may have more entries than switches.
|
|
target_entity: >-
|
|
{%- set idx = target_index | int(-1) -%}
|
|
{%- if idx >= 0 and idx < (switches | length) -%}
|
|
{{ switches[idx] }}
|
|
{%- else -%}
|
|
{{ none }}
|
|
{%- endif -%}
|
|
has_last_interacted_text: "{{ last_interacted_text is string and last_interacted_text | trim != '' }}"
|
|
|
|
# ---------------------------------------------------------------------------
|
|
# Debug: trigger received
|
|
# ---------------------------------------------------------------------------
|
|
- choose:
|
|
- conditions:
|
|
- condition: template
|
|
value_template: "{{ is_debug }}"
|
|
sequence:
|
|
- service: persistent_notification.create
|
|
data:
|
|
notification_id: "mqtt_button_control_debug"
|
|
title: "MQTT Button Control Debug"
|
|
message: >
|
|
Trigger: {{ trigger.id }}
|
|
|
|
Topic: {{ trigger.topic }}
|
|
|
|
action_id: {{ action_id }}
|
|
|
|
action_ids: {{ action_ids }}
|
|
|
|
switches: {{ switches }}
|
|
|
|
target_index: {{ target_index | int(-1) }}
|
|
|
|
target_entity: {{ target_entity if target_entity is not none else 'none' }}
|
|
|
|
has_last_interacted_text: {{ has_last_interacted_text }}
|
|
|
|
- choose:
|
|
- conditions:
|
|
- condition: template
|
|
value_template: "{{ target_entity is not none }}"
|
|
sequence:
|
|
- variables:
|
|
entity_type: "{{ target_entity.split('.')[0] }}"
|
|
|
|
# Persist last interacted entity only when a helper is configured.
|
|
- choose:
|
|
- conditions:
|
|
- condition: template
|
|
value_template: "{{ has_last_interacted_text }}"
|
|
sequence:
|
|
- 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
|
|
blink_count: !input blink_count
|
|
blink_timeout: !input blink_interval
|
|
is_light_on: "{{ is_state(target_entity, 'on') }}"
|
|
# Inline state access — HA stringifies State objects when
|
|
# stored in `variables:`, so `.last_changed` must be read
|
|
# within a single template render.
|
|
seconds_elapsed: >-
|
|
{%- set s = states[target_entity] -%}
|
|
{%- if s is not none -%}
|
|
{{ (as_timestamp(now()) - as_timestamp(s.last_changed)) | int(0) }}
|
|
{%- else -%}
|
|
0
|
|
{%- endif -%}
|
|
# Blink only when both the idle timeout AND a positive
|
|
# blink count are configured; otherwise fall through to a
|
|
# plain toggle (a 0 count would otherwise run an empty
|
|
# repeat and leave the light untouched).
|
|
should_blink: >-
|
|
{{ timeout_for_indication_blink != 0
|
|
and (blink_count | int(0)) > 0
|
|
and (seconds_elapsed | int(0)) > timeout_for_indication_blink }}
|
|
|
|
# Debug: light branch state
|
|
- choose:
|
|
- conditions:
|
|
- condition: template
|
|
value_template: "{{ is_debug }}"
|
|
sequence:
|
|
- service: persistent_notification.create
|
|
data:
|
|
notification_id: "mqtt_button_control_debug_light"
|
|
title: "MQTT Button Control Debug (light)"
|
|
message: >
|
|
target_entity: {{ target_entity }}
|
|
|
|
is_light_on: {{ is_light_on }}
|
|
|
|
seconds_elapsed: {{ seconds_elapsed }}
|
|
|
|
timeout_for_indication_blink: {{ timeout_for_indication_blink }}
|
|
|
|
should_blink: {{ should_blink }}
|
|
|
|
blink_count: {{ blink_count }}
|
|
|
|
blink_timeout (ms): {{ blink_timeout }}
|
|
|
|
- choose:
|
|
# Blink (indicate light is already on after idle timeout)
|
|
- 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 }}"
|