Skip to content

Instantly share code, notes, and snippets.

@nmbgeek
Last active September 8, 2024 19:59
Show Gist options
  • Save nmbgeek/d8a8bd47f1bab9d3f7fe55352820c45c to your computer and use it in GitHub Desktop.
Save nmbgeek/d8a8bd47f1bab9d3f7fe55352820c45c to your computer and use it in GitHub Desktop.
blueprint:
name: 'Inovelli Blue (Zigbee2MQTT) LED Notification Automation'
description: >
Monitor entity state changes and create notifications using LED effects for Inovelli Blue Series Switches using Zigbee2MQTT.
Setting an "End Trigger" will clear the LED notifications when triggered.
This blueprint is designed to work with the Inovelli Blue Series Switches using Zigbee2MQTT. It will monitor an entity for a specific state change to trigger LED notifications. Customize LED color, brightness, effect, and duration for the notification.
Parts of this script are pulled and created from [State Notifications and Actions Blueprint by Blacky](https://community.home-assistant.io/t/state-notifications-actions/612617) and [Inovelli Blue LED Notification Script by Zanix](https://community.home-assistant.io/t/z2m-inovelli-blue-series-switch-led-notification-script-vzm31-sn-vzm35-sn/489620)
✅ Supported Models:
- Inovelli 2-in-1 switch + dimmer (VZM31-SN)
- Inovelli Fan Controller (VZM35-SN)
domain: automation
author: nmbgeek
homeassistant:
min_version: 2024.6.0
input:
start_trigger_settings:
name: 'Start Trigger'
icon: mdi:play-circle-outline
collapsed: false
input:
start_trigger_state:
name: Start Trigger - State
description: >
Please select what state you would like for your trigger.
You can choose from ten options available in the dropdown menu.
If your option is not in the dropdown menu then just type the state you would like to use in and click the save button.
1 - Button Or Any State
2 - ON
3 - OFF
4 - Unavailable
5 - Unknown
6 - Home
7 - Not Home
8 - Numeric State - Above
9 - Numeric State - Below
10 - Numeric State - Above & Below
A numbering system has been implemented to facilitate navigation within the dropdown selections. Each number corresponds to a specific configuration,
aiding users in identifying and adjusting the settings used within each selection. For instance, when selecting "8 - Numeric State - Above"
as a dropdown option, settings marked "Used in options 8, 9 or 10" are required for that respective selection because number 8 is included in those options.
default: button_any_state
selector:
select:
custom_value: true
mode: dropdown
options:
- label: 1 - Button Or Any State
value: 'button_any_state'
- label: 2 - ON
value: 'on'
- label: 3 - OFF
value: 'off'
- label: 4 - Unavailable
value: 'unavailable'
- label: 5 - Unknown
value: 'unknown'
- label: 6 - Home
value: 'home'
- label: 7 - Not Home
value: 'not_home'
- label: 8 - Numeric State - Above
value: 'numeric_state_above'
- label: 9 - Numeric State - Below
value: 'numeric_state_below'
- label: 10 - Numeric State - Above & Below
value: 'numeric_state_above_below'
start_trigger_state_entity:
name: State Entities
description: >
**Used in options 1, 2, 3, 4, 5, 6 or 7**.
Enter the entities that will trigger the automation on state change.
default: []
selector:
entity:
multiple: true
start_trigger_numeric_entity:
name: Numeric State Entities
description: >
**Used in options 8, 9 or 10**.
Enter the entities that will trigger the automation numeric state change.
default: []
selector:
entity:
multiple: true
start_above_state:
name: Numeric State Above Option
description: >
**Used in options 8, or 10**.
Set the above value. The numeric state trigger will be when the value crosses over to above the set value.
default: 0
selector:
number:
min: -20
max: 100
step: 1
unit_of_measurement: value
start_below_state:
name: Numeric State Below Option
description: >
**Used in options 9 or 10**.
Set the below value.
The numeric state trigger will be when the value crosses over to below the set value.
default: 0
selector:
number:
min: -20
max: 100
step: 1
unit_of_measurement: value
start_time_delay_state:
name: Time Delay
description: >
**Used in options 1, 2, 3, 4, 5, 6, 7, 8, 9 or 10**
Specifies the duration that the trigger must maintain its state before the automation is executed.
The automation will only proceed if the trigger condition is met continuously for this entire time delay.
default:
hours: 0
minutes: 0
seconds: 0
selector:
duration:
end_trigger_settings:
name: 'End Trigger'
icon: mdi:stop-circle-outline
collapsed: true
input:
end_trigger_state:
name: End Trigger - State
description: >
Please select what state you would like for your trigger.
You can choose from ten options available in the dropdown menu.
If your option is not in the dropdown menu then just type the state you would like to use in and click the save button.
1 - Button Or Any State
2 - ON
3 - OFF
4 - Unavailable
5 - Unknown
6 - Home
7 - Not Home
8 - Numeric State - Above
9 - Numeric State - Below
10 - Numeric State - Above & Below
A numbering system has been implemented to facilitate navigation within the dropdown selections. Each number corresponds to a specific configuration,
aiding users in identifying and adjusting the settings used within each selection. For instance, when selecting "8 - Numeric State - Above"
as a dropdown option, settings marked "Used in options 8, 9 or 10" are required for that respective selection because number 8 is included in those options.
default: button_any_state
selector:
select:
custom_value: true
mode: dropdown
options:
- label: 1 - Button Or Any State
value: 'button_any_state'
- label: 2 - ON
value: 'on'
- label: 3 - OFF
value: 'off'
- label: 4 - Unavailable
value: 'unavailable'
- label: 5 - Unknown
value: 'unknown'
- label: 6 - Home
value: 'home'
- label: 7 - Not Home
value: 'not_home'
- label: 8 - Numeric State - Above
value: 'numeric_state_above'
- label: 9 - Numeric State - Below
value: 'numeric_state_below'
- label: 10 - Numeric State - Above & Below
value: 'numeric_state_above_below'
end_trigger_state_entity:
name: State Entities
description: >
**Used in options 1, 2, 3, 4, 5, 6 or 7**.
Enter the entities that will trigger the automation on state change.
default: []
selector:
entity:
multiple: true
end_trigger_numeric_entity:
name: Numeric State Entities
description: >
**Used in options 8, 9 or 10**.
Enter the entities that will trigger the automation numeric state change.
default: []
selector:
entity:
multiple: true
end_above_state:
name: Numeric State Above Option
description: >
**Used in options 8, or 10**.
Set the above value. The numeric state trigger will be when the value crosses over to above the set value.
default: 0
selector:
number:
min: -20
max: 100
step: 1
unit_of_measurement: value
end_below_state:
name: Numeric State Below Option
description: >
**Used in options 9 or 10**.
Set the below value.
The numeric state trigger will be when the value crosses over to below the set value.
default: 0
selector:
number:
min: -20
max: 100
step: 1
unit_of_measurement: value
end_time_delay_state:
name: Time Delay
description: >
**Used in options 1, 2, 3, 4, 5, 6, 7, 8, 9 or 10**
Specifies the duration that the trigger must maintain its state before the automation is executed.
The automation will only proceed if the trigger condition is met continuously for this entire time delay.
default:
hours: 0
minutes: 0
seconds: 0
selector:
duration:
global_conditions_settings:
name: 'Global Conditions'
icon: mdi:earth
collapsed: true
input:
global_conditions:
name: Global Conditions
description: >
Enter any global conditions you would like to apply to the automation.
default: []
selector:
condition:
led_notification_settings:
name: 'Inovelli Notification Settings'
icon: mdi:cog-outline
collapsed: false
input:
target:
name: Target
description: Inovelli devices, entities, and/or areas with Inovelli devices to set effects.
selector:
target:
device:
integration: mqtt
manufacturer: Inovelli
entity:
integration: mqtt
domain:
- light
- fan
led:
name: LED
description: Choose which LED to control. Default is All. (LED 1 is at the bottom)
default: All
selector:
select:
custom_value: true
options:
- All
- Led 1
- Led 2
- Led 3
- Led 4
- Led 5
- Led 6
- Led 7
color:
name: LED Color
default: Red
selector:
select:
custom_value: true
options:
- Red
- Orange
- Yellow
- Green
- Cyan
- Teal
- Blue
- Purple
- Light Pink
- Pink
- White
level:
name: Brightness level
description: Value from 0 (off) to 100 (100% brightness).
default: 100
selector:
number:
min: 0
max: 100
effect:
name: 'Effect'
description: Choose LED effect to apply.
default: Clear
selector:
select:
custom_value: true
options:
- 'Off'
- 'Clear'
- 'Solid'
- 'Aurora'
- 'Slow Chase'
- 'Chase'
- 'Fast Chase'
- 'Slow Blink'
- 'Medium Blink'
- 'Fast Blink'
- 'Slow Falling'
- 'Medium Falling'
- 'Fast Falling'
- 'Open/Close'
- 'Pulse'
- 'Slow Rising'
- 'Medium Rising'
- 'Fast Rising'
- 'Slow Siren'
- 'Fast Siren'
- 'Small to Big'
duration:
name: Duration
description: How long should the effect run?
default: Indefinitely
selector:
select:
custom_value: true
options:
- 1 Second
- 2 Seconds
- 3 Seconds
- 4 Seconds
- 5 Seconds
- 6 Seconds
- 7 Seconds
- 8 Seconds
- 9 Seconds
- 10 Seconds
- 15 Seconds
- 20 Seconds
- 25 Seconds
- 30 Seconds
- 35 Seconds
- 40 Seconds
- 45 Seconds
- 50 Seconds
- 55 Seconds
- 1 Minute
- 2 Minutes
- 3 Minutes
- 4 Minutes
- 5 Minutes
- 6 Minutes
- 7 Minutes
- 8 Minutes
- 9 Minutes
- 10 Minutes
- 15 Minutes
- 20 Minutes
- 25 Minutes
- 30 Minutes
- 35 Minutes
- 40 Minutes
- 45 Minutes
- 50 Minutes
- 55 Minutes
- 1 Hour
- 2 Hours
- 3 Hours
- 4 Hours
- 5 Hours
- 6 Hours
- 7 Hours
- 8 Hours
- 9 Hours
- 10 Hours
- 15 Hours
- 20 Hours
- 1 Day
- 2 Days
- 3 Days
- 4 Days
- 5 Days
- Indefinitely
- Forever
variables:
start_trigger_state: !input start_trigger_state
start_trigger_state_entity: !input start_trigger_state_entity
start_trigger_numeric_entity: !input start_trigger_numeric_entity
start_above_state: !input start_above_state
start_below_state: !input start_below_state
start_time_delay_state: !input start_time_delay_state
end_trigger_state: !input end_trigger_state
end_trigger_state_entity: !input end_trigger_state_entity
end_trigger_numeric_entity: !input end_trigger_numeric_entity
end_above_state: !input end_above_state
end_below_state: !input end_below_state
end_time_delay_state: !input end_time_delay_state
global_conditions: !input global_conditions
my_targets: !input target
my_color: !input color
my_effect: !input effect
my_duration: !input duration
my_led: !input led
my_level: !input level
domains:
- light
- fan
models:
- VZM31-SN
- VZM35-SN
targets: '{{ my_targets|default([])|map(lower) }}'
floor: '{{ my_targets.floor_id|default([])|lower }}'
area: '{{ my_targets.area_id|default([])|lower }}'
device: '{{ my_targets.device_id|default([])|lower }}'
entity: '{{ my_targets.entity_id|default([])|lower }}'
label: '{{ my_targets.label_id|default([])|lower }}'
# Parse target selector for entities
entity_list: >
{% set switch = namespace(entities=[]) %}
{# Floors #}
{% set floors = namespace(floors=[]) %}
{% if floor %}
{# Convert to a list #}
{% if ',' in floor %}
{% set floornum = floor.split(',') | count %}
{% for i in range(0, floornum) %}
{% set floors.floors = floors.floors + [floor.split(',')[i]|string|trim ] %}
{% endfor %}
{% elif floor[0]|count == 1 %}
{# if the first item in the list has only a single character, it can't be a valid entity #}
{% set floors.floors = floors.floors + [floor|string|trim] %}
{% else %}
{% set floors.floors = floor %}
{% endif %}
{# Detect switches #}
{% for floor in floors.floors %}
{% for area in floor_areas(floor) %}
{% for ent in area_entities(area) %}
{% for model in models %}
{% if model in device_attr(ent, 'model') | default('', true) and ent.split('.')[0] in domains %}
{% set switch.entities = switch.entities + [ent|string|trim] %}
{% endif %}
{% endfor %}
{% endfor %}
{% endfor %}
{% endfor %}
{% endif %}
{# Areas #}
{% set areas = namespace(areas=[]) %}
{% if area %}
{# Convert to a list #}
{% if ',' in area %}
{% set areanum = area.split(',') | count %}
{% for i in range(0, areanum) %}
{% set areas.areas = areas.areas + [area.split(',')[i]|string|trim ] %}
{% endfor %}
{% elif area[0]|count == 1 %}
{# if the first item in the list has only a single character, it can't be a valid entity #}
{% set areas.areas = areas.areas + [area|string|trim] %}
{% else %}
{% set areas.areas = area %}
{% endif %}
{# Detect switches #}
{% for area in areas.areas %}
{% for ent in area_entities(area) %}
{% for model in models %}
{% if model in device_attr(ent, 'model') | default('', true) and ent.split('.')[0] in domains %}
{% set switch.entities = switch.entities + [ent|string|trim] %}
{% endif %}
{% endfor %}
{% endfor %}
{% endfor %}
{% endif %}
{# Devices #}
{% set devices = namespace(devices=[]) %}
{% if device %}
{# Convert to a list #}
{% if ',' in device %}
{% set devicenum = device.split(',') | count %}
{% for i in range(0, devicenum) %}
{% set devices.devices = devices.devices + [device.split(',')[i]|string|trim ] %}
{% endfor %}
{% elif device[0]|count == 1 %} {# if the first item in the list has only a single character, it can't be a valid entity #}
{% set devices.devices = devices.devices + [device|string|trim] %}
{% else %}
{% set devices.devices = device %}
{% endif %}
{# Detect switches #}
{% for device in devices.devices %}
{% for ent in device_entities(device) %}
{% for model in models %}
{% if model in device_attr(ent, 'model') | default('', true) and ent.split('.')[0] in domains %}
{% set switch.entities = switch.entities + [ent|string|trim] %}
{% endif %}
{% endfor %}
{% endfor %}
{% endfor %}
{% endif %}
{# Entities #}
{% set entities = namespace(entities=[]) %}
{% if entity %}
{# Convert to a list #}
{% if ',' in entity %}
{% set entitynum = entity.split(',') | count %}
{% for i in range(0, entitynum) %}
{% set entities.entities = entities.entities + [entity.split(',')[i]|string|trim ] %}
{% endfor %}
{% elif entity[0]|count == 1 %} {# if the first item in the list has only a single character, it can't be a valid entity #}
{% set entities.entities = entities.entities + [entity|string|trim] %}
{% else %}
{% set entities.entities = entity %}
{% endif %}
{# Detect switches #}
{% for ent in entities.entities %}
{% for model in models %}
{% if model in device_attr(ent, 'model') | default('', true) and ent.split('.')[0] in domains %}
{% set switch.entities = switch.entities + [ent|string|trim] %}
{% endif %}
{% endfor %}
{% endfor %}
{% endif %}
{# Labels #}
{% set labels = namespace(labels=[]) %}
{% if label %}
{# Convert to a list #}
{% if ',' in label %}
{% set labelnum = label.split(',') | count %}
{% for i in range(0, labelnum) %}
{% set labels.labels = labels.labels + [label.split(',')[i]|string|trim ] %}
{% endfor %}
{% elif label[0]|count == 1 %}
{# if the first item in the list has only a single character, it can't be a valid entity #}
{% set labels.labels = labels.labels + [label|string|trim] %}
{% else %}
{% set labels.labels = label %}
{% endif %}
{# Detect switches #}
{% for label in labels.labels %}
{% for ent in label_entities(label) %}
{% for model in models %}
{% if model in device_attr(ent, 'model') | default('', true) and ent.split('.')[0] in domains %}
{% set switch.entities = switch.entities + [ent|string|trim] %}
{% endif %}
{% endfor %}
{% endfor %}
{% endfor %}
{% endif %}
{# Output #}
{{ switch.entities|unique|list|lower }}
# Convert LED number to value
leds:
'all': -1
'led 1': 0
'led 2': 1
'led 3': 2
'led 4': 3
'led 5': 4
'led 6': 5
'led 7': 6
led: '{{ my_led|default("all") }}'
led_value: >-
{% if led|int(default=-2) == -2 %}
{{ leds[led|lower]|int(default=-1) }}
{% else %}
{{ led|int(default=-1) }}
{% endif %}
level: '{{ my_level|default(100) }}'
# Convert Color to value
colors:
'off': 0
'red': 1
'orange': 21
'yellow': 42
'green': 85
'cyan': 127
'teal': 145
'blue': 170
'purple': 195
'light pink': 220
'lightpink': 220
'pink': 234
'white': 255
color: '{{ my_color|default("red") }}'
color_value: >-
{% if color|int(default=-1) == -1 %}
{{ colors[color|lower]|int(default=0) }}
{% else %}
{{ color|int(default=0) }}
{% endif %}
# Convert Effect to value
effects:
'off': 'off'
'clear': 'clear_effect'
'solid': 'solid'
'aurora': 'aurora'
'chase': 'chase'
'fast blink': 'fast_blink'
'fast chase': 'fast_chase'
'fast falling': 'fast_falling'
'fast rising': 'fast_rising'
'fast siren': 'fast_siren'
'medium blink': 'medium_blink'
'medium falling': 'medium_falling'
'medium rising': 'medium_rising'
'open/close': 'open_close'
'open close': 'open_close'
'pulse': 'pulse'
'slow blink': 'slow_blink'
'slow chase': 'slow_chase'
'slow falling': 'slow_falling'
'slow rising': 'slow_rising'
'slow siren': 'slow_siren'
'small to big': 'small_to_big'
effect: '{{ my_effect|default("clear") }}'
effect_value: >-
{% if effect|lower in effects %}
{{ effects[effect|lower] }}
{% else %}
{{ effect|lower }}
{% endif %}
# Convert Duration to value
durations:
'off': 0
'1 second': 1
'2 seconds': 2
'3 seconds': 3
'4 seconds': 4
'5 seconds': 5
'6 seconds': 6
'7 seconds': 7
'8 seconds': 8
'9 seconds': 9
'10 seconds': 10
'15 seconds': 15
'20 seconds': 20
'25 seconds': 25
'30 seconds': 30
'35 seconds': 35
'40 seconds': 40
'45 seconds': 45
'50 seconds': 50
'55 seconds': 55
'1 minute': 60
'2 minutes': 62
'3 minutes': 63
'4 minutes': 64
'5 minutes': 65
'6 minutes': 66
'7 minutes': 67
'8 minutes': 68
'9 minutes': 69
'10 minutes': 70
'15 minutes': 75
'20 minutes': 80
'25 minutes': 85
'30 minutes': 90
'35 minutes': 95
'40 minutes': 100
'45 minutes': 105
'50 minutes': 110
'55 minutes': 115
'1 hour': 120
'2 hours': 122
'3 hours': 123
'4 hours': 124
'5 hours': 125
'6 hours': 126
'7 hours': 127
'8 hours': 128
'9 hours': 129
'10 hours': 130
'15 hours': 135
'20 hours': 140
'1 day': 144
'2 days': 168
'3 days': 192
'4 days': 216
'5 days': 240
'indefinitely': 255
'forever': 255
duration: '{{ my_duration|default("indefinitely") }}'
duration_value: >-
{% if duration|int(default=-1) == -1 %}
{{ durations[duration|lower]|int(default=255) }}
{% else %}
{{ duration|int(default=255) }}
{% endif %}
payload: |-
{% if led_value == -1 %}
{% set payload_data = {
"led_effect": {
"effect": effect_value,
"color": color_value,
"level": my_level,
"duration": duration_value,
}
} %}
{% else %}
{% set payload_data = {
"individual_led_effect": {
"led": led_value,
"effect": effect_value,
"color": color_value,
"level": my_level,
"duration": duration_value,
}
} %}
{% endif %}
{{ payload_data | tojson }}
payload_clear: |-
{% if led_value == -1 %}
{% set payload_data = {
"led_effect": {
"effect": "clear_effect",
"color": color_value,
"level": my_level,
"duration": duration_value,
}
} %}
{% else %}
{% set payload_data = {
"individual_led_effect": {
"led": led_value,
"effect": "clear_effect",
"color": color_value,
"level": my_level,
"duration": duration_value,
}
} %}
{% endif %}
{{ payload_data | tojson }}
trigger:
- platform: state
id: 't0'
entity_id: !input start_trigger_state_entity
for: !input start_time_delay_state
- platform: state
id: 't1'
entity_id: !input start_trigger_state_entity
to: !input start_trigger_state
for: !input start_time_delay_state
- platform: numeric_state
id: 't2'
entity_id: !input start_trigger_numeric_entity
above: !input start_above_state
for: !input start_time_delay_state
- platform: numeric_state
id: 't3'
entity_id: !input start_trigger_numeric_entity
below: !input start_below_state
for: !input start_time_delay_state
- platform: state
id: 't4'
entity_id: !input end_trigger_state_entity
for: !input end_time_delay_state
- platform: state
id: 't5'
entity_id: !input end_trigger_state_entity
to: !input end_trigger_state
for: !input end_time_delay_state
- platform: numeric_state
id: 't6'
entity_id: !input end_trigger_numeric_entity
above: !input end_above_state
for: !input end_time_delay_state
- platform: numeric_state
id: 't7'
entity_id: !input end_trigger_numeric_entity
below: !input end_below_state
for: !input end_time_delay_state
# All Conditions
condition:
#Trigger conditions
- condition: or
conditions:
- condition: and # trigger for button or any state
conditions:
- condition: trigger
id: 't0'
- "{{ start_trigger_state == 'button_any_state' }}"
- condition: and # trigger not for button or any state
conditions:
- condition: trigger
id: 't1'
- "{{ (start_trigger_state != 'button_any_state') or (start_trigger_state != 'numeric_state_above') or (start_trigger_state != 'numeric_state_below') or (start_trigger_state != 'numeric_state_above_below') }}"
- condition: and # trigger for numeric above state
conditions:
- condition: trigger
id: 't2'
- "{{ (start_trigger_state == 'numeric_state_above') or (start_trigger_state == 'numeric_state_above_below') }}"
- condition: and # trigger for numeric below state
conditions:
- condition: trigger
id: 't3'
- "{{ (start_trigger_state == 'numeric_state_below') or (start_trigger_state == 'numeric_state_above_below') }}"
- condition: and # trigger for button or any state
conditions:
- condition: trigger
id: 't4'
- "{{ end_trigger_state == 'button_any_state' }}"
- condition: and # trigger not for button or any state
conditions:
- condition: trigger
id: 't5'
- "{{ (end_trigger_state != 'button_any_state') or (end_trigger_state != 'numeric_state_above') or (end_trigger_state != 'numeric_state_below') or (end_trigger_state != 'numeric_state_above_below') }}"
- condition: and # trigger for numeric above state
conditions:
- condition: trigger
id: 't6'
- "{{ (end_trigger_state == 'numeric_state_above') or (end_trigger_state == 'numeric_state_above_below') }}"
- condition: and # trigger for numeric below state
conditions:
- condition: trigger
id: 't7'
- "{{ (end_trigger_state == 'numeric_state_below') or (end_trigger_state == 'numeric_state_above_below') }}"
# Global Conditions
- condition: and
conditions: !input global_conditions
action:
- choose:
- alias: 'Start trigger'
conditions:
- condition: trigger
id:
- 't0'
- 't1'
- 't2'
- 't3'
sequence:
- repeat:
for_each: '{{ entity_list }}'
sequence:
- variables:
device_identifier: '{% set identifiers = device_attr(repeat.item, "identifiers")
| first %} {{ identifiers[1].split("_")[1] }}'
command_path: 'zigbee2mqtt/{{ device_identifier }}/set'
- service: mqtt.publish
data:
topic: '{{ command_path }}'
payload: '{{ payload }}'
default:
- choose:
- alias: 'End Trigger'
conditions:
- condition: trigger
id:
- 't4'
- 't5'
- 't6'
- 't7'
sequence:
- repeat:
for_each: '{{ entity_list }}'
sequence:
- variables:
device_identifier: '{% set identifiers = device_attr(repeat.item, "identifiers")
| first %} {{ identifiers[1].split("_")[1] }}'
command_path: 'zigbee2mqtt/{{ device_identifier }}/set'
- service: mqtt.publish
data:
topic: '{{ command_path }}'
payload: '{{ payload_clear }}'
mode: parallel
max_exceeded: silent
max: 100
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment