clear your cache. Compare the script to what’s included here, i’ve been making changes. Lastly, reload the script.
I cleared the caches and restarted HA host. I copied the whole script to scripts.yaml and added my configs from above.
Still the same. Script now visible in frontend, no traces.
If I add another light to that group it also works to switch on if all are off…
wohnzimmer:
entities:
- light.led_sofa
- light.led_esstisch
- light.led_test
Could this config disable the variable traces?
config:
counter:
frontend:
history:
image:
input_boolean:
input_button:
input_datetime:
input_number:
input_select:
input_text:
logbook:
person:
stream:
sun:
timer:
zone:
cloud:
my:
recorder:
purge_keep_days: 365
auto_purge: false
include:
domains:
- automation
- sensor
- light
- fan
- cover
- binary_sensor
- input_boolean
- climate
- person
- vacuum
exclude:
entity_globs:
- sensor.*timestamp*
entities:
- sensor.uptime
Also, just to be sure:
It is okay to have the lights in more than one group, right?
Update:
I can’t switch on a group where the two lights are on and the third one is off.
I can only switch off all of them if all of them are on.
and that doesn’t make sense. I can’t help if you can’t provide the trace. I designed this to specifically work in that case and it works like that for me. Just tested it. I have no idea what you’re doing. Post exactly all the yaml you have, or ensure you copy exactly what I wrote and you didn’t edit it.
thanks @petro! this is working for me now for dimmers and switches (I don’t have any covers).
I made a change to brightness_pct variable. My zooz dimmers show brightness range of 0-99 (not 255) in Z2M. I left out the conversion in brightness_pct and dimming is working as expected now
variables:
brightness_pct: >
{%- set brightness_pct = (level | int(0)) | int %}
{%- set brightness_pct = [ 0, brightness_pct ] | max %}
{%- set brightness_pct = [ 99, brightness_pct] | min %}
{{- brightness_pct }}
I just realized that the new devices are connected using S2.
So it shouldn’t work at all, right?
Situation for switching off is like that:
- fails when both are on
- works when only one is on
Multicast does not work at all with S2, I believe it’s in the ZwaveJS roadmap.
Good to know, well it works a little bit. Might be a good sign.
Apologies for reviving this old thread, but I just discovered your fantastic script. I previously created separate scripts for each of my zwave cover groups, hardcoding device ids into each script, with separate scripts for open, close, stop, and set position.
I’m trying to replace those numerous scripts with your single script, and to create template covers to interact with them. I’ve had luck editing the template light generated by your shortcut above, replacing values from the light domain with values from the cover domain–open, close, and reported state all work-- but am stuck on what to pass to the script for the set_cover_position (the very last line of the YAML below):
shades_master_bedroom:
unique_id: shades_master_bedroom
friendly_name: Shades Master Bedroom
value_template: >
{{ is_state('group.shades_master_bedroom', 'open') }}
position_template: >
{%- set entities = expand('group.shades_master_bedroom') %}
{%- set covers = entities | selectattr('domain', 'eq', 'cover') | selectattr('state', 'eq', 'open') %}
{%- set levels = covers | map(attribute='attributes.current_position') | map('int') | list %}
{{- levels | average if levels else 0 }}
availability_template: >
{{- expand('group.shades_master_bedroom') | selectattr('state','in',['unavailable','unknown']) | list | length == 0 }}
open_cover:
- service: script.zwave_multicast_group
data:
group: group.shades_master_bedroom
level: 255
close_cover:
- service: script.zwave_multicast_group
data:
group: group.shades_master_bedroom
level: 0
set_cover_position:
- service: script.zwave_multicast_group
data:
group: group.shades_master_bedroom
level: >
{{- brightness_pct }}
I’ve tried brightness_pct, value, level, and everything I can think of after evaluating your script, but nothing works (any value I pass when interacting with the template cover just results in the shades closing all the way). This service call, however, works fine:
service: script.zwave_multicast_group
data:
group: group.shades_master_bedroom
level: 10
with levels from 0 to 255
Any guidance on what I should put in the last line of the template to get it to accept a position value?
Also, for reference, here are my four scripts to accomplish for a single group what yours does in one. The only functionality I would lose moving to your script is the “stop” function. Any way to integrate that function into your script?
multicast_shades_master_close:
alias: Multicast Shades - Master Close
sequence:
- service: zwave_js.multicast_set_value
data:
command_class: '38'
property: targetValue
value: 0
target:
device_id:
- 3a9b47282ac5b1a82b01dc4af7032a48
- b3e769c15948158541755297d1f258bb
- 0266da4a6eb09bc94f94ee77f2a0871f
- 672be298a3d3870612f891cefa6bb744
- 2decb1288aeec569e7c955c86ebf6667
mode: single
icon: mdi:window-shutter
multicast_shades_master_open:
alias: Multicast Shades - Master Open
sequence:
- service: zwave_js.multicast_set_value
data:
command_class: '38'
property: targetValue
value: 99
target:
device_id:
- 3a9b47282ac5b1a82b01dc4af7032a48
- b3e769c15948158541755297d1f258bb
- 0266da4a6eb09bc94f94ee77f2a0871f
- 672be298a3d3870612f891cefa6bb744
- 2decb1288aeec569e7c955c86ebf6667
mode: single
icon: mdi:window-shutter-open
multicast_shades_master_stop:
alias: Multicast Shades - Master Stop
sequence:
- service: zwave_js.multicast_set_value
data:
command_class: '38'
property: Up
value: false
target:
device_id:
- 3a9b47282ac5b1a82b01dc4af7032a48
- b3e769c15948158541755297d1f258bb
- 0266da4a6eb09bc94f94ee77f2a0871f
- 672be298a3d3870612f891cefa6bb744
- 2decb1288aeec569e7c955c86ebf6667
mode: single
icon: mdi:window-shutter-alert
multicast_shades_master_set:
alias: Multicast Shades - Master Set
fields:
position:
description: Target position
sequence:
- service: zwave_js.multicast_set_value
data:
command_class: '38'
property: targetValue
value: '{{ position }}'
target:
device_id:
- 3a9b47282ac5b1a82b01dc4af7032a48
- b3e769c15948158541755297d1f258bb
- 0266da4a6eb09bc94f94ee77f2a0871f
- 672be298a3d3870612f891cefa6bb744
- 2decb1288aeec569e7c955c86ebf6667
mode: single
icon: mdi:window-shutter-cog
the variable for cover templates is position
and you’d have to convert that from 0 to 100 to 0 to 255.
I’m not really sure if this will work with covers as I don’t own any zwave ones myself. So the rest of the script will be very hard for me to debug for you.
Thank you! position
worked, just have to figure out the conversion now, and see if I can’t tinker up a “stop” action.
Should just be {{ position * 255/100 }}
or {{ position * 2.55 }}
whatever floats your boat
Actually, I had success changing the script setting to use level
instead of brightness_pct
for the cover
class:
cover:
command_class: 38
property: targetValue
endpoint: 0
value: "{{ level }}"
Doing so changes the behavior of the service call to accept values only from 0 to 99:
service: script.zwave_multicast_group
data:
group: group.shades_master_bedroom
level: 99
Would it be better to do it the way you post (in the template device) rather than with a change to the script?
Doesn’t really matter to be honest. If you’re just using it for a group of covers, then have it as a separate script.
I do plan to update/fix this at some point. Waiting for S2 multicast. I also think there’s probably room for improvement in the script.
Well it’s working great with just changing your script to specify level
for the settings of cover
When you get around to updating the script for S2, I’ll be happy to debug for covers – although I don’t have any that support the tilt
commands. FYI, the stop_cover
configuration variable for a template cover works well for the zwave commands if you pass a value
of false
and a property
of Up
in the data
of command_class: '38'
rather than a number value … just in case there’s a way to work that into the update.
- service: zwave_js.multicast_set_value
data:
command_class: '38'
property: Up
value: false
Because I can’t leave well enough alone, I updated the script for template covers with a new position variable:
zwave_multicast_group:
mode: parallel
alias: Multicast to Zwave Group
fields:
group:
description: (Required) The group of lights & switches
example: group.bonus_room_area
level:
description: (Optional) The brightness level, switches will be on if the level is greater than 0.
example: 99
variables:
brightness_pct: >
{%- set brightness_pct = (level | int(0) / 255 * 100) | int %}
{%- set brightness_pct = [ 0, brightness_pct ] | max %}
{%- set brightness_pct = [ 99, brightness_pct] | min %}
{{- brightness_pct }}
position: >
{%- set position = (level) | int %}
{%- set position = [ 0, position ] | max %}
{%- set position = [ 99, position] | min %}
{{- position }}
value: >
{%- set value = brightness_pct > 0 %}
{{- value }}
settings:
light:
command_class: 38
property: targetValue
endpoint: 0
value: "{{ brightness_pct }}"
switch:
command_class: 37
property: targetValue
endpoint: 0
value: "{{ value }}"
cover:
command_class: 38
property: targetValue
endpoint: 0
value: "{{ position }}"
lights: >
{% if value %}
{% set off_lights = expand(group)
| selectattr('domain', 'eq', 'light')
| selectattr('state', 'eq', 'off')
| map(attribute='entity_id') | list %}
{% set on_lights = expand(group)
| selectattr('domain', 'eq', 'light')
| selectattr('state', 'eq', 'on')
| selectattr('attributes.brightness', 'defined')
| rejectattr('attributes.brightness','eq', level)
| map(attribute='entity_id') | list %}
{{ (off_lights + on_lights) or none }}
{% else %}
{{ expand(group)
| selectattr('domain', 'eq', 'light')
| selectattr('state', 'eq', 'on')
| map(attribute='entity_id') | list or none }}
{% endif %}
covers: >
{% if value %}
{% set off_lights = expand(group)
| selectattr('domain', 'eq', 'cover')
| selectattr('state', 'eq', 'closed')
| map(attribute='entity_id') | list %}
{% set on_lights = expand(group)
| selectattr('domain', 'eq', 'cover')
| selectattr('state', 'eq', 'open')
| selectattr('attributes.current_position', 'defined')
| rejectattr('attributes.current_position','eq', position)
| map(attribute='entity_id') | list %}
{{ (off_lights + on_lights) or none }}
{% else %}
{{ expand(group)
| selectattr('domain', 'eq', 'cover')
| selectattr('state', 'eq', 'open')
| map(attribute='entity_id') | list or none }}
{% endif %}
switches: >
{%- set switches = expand(group) | selectattr('domain', 'eq', 'switch') %}
{%- set switches = switches | selectattr('state','eq', 'off' if value else 'on') %}
{%- set switches = switches | map(attribute='entity_id') | list %}
{{- switches or none }}
items: >
{%- set ns = namespace(items={}, spool={}) %}
{%- set fmat = "('{0}': {1})" %}
{%- set items = (switches or []) + (lights or []) + (covers or []) %}
{%- for item in items %}
{%- set state_obj = expand(item) | first | default(none) %}
{%- if state_obj and state_obj.domain in ['light','switch','cover'] %}
{%- set domain = state_obj.domain %}
{%- set entity_id = state_obj.entity_id %}
{%- set entity_ids = lights if domain == 'light' else switches %}
{%- set entity_ids = covers if domain == 'cover' else entity_ids %}
{%- set current = settings[domain] %}
{%- set current = dict(current, **settings[entity_id]) if entity_id in settings else current %}
{%- set key = domain ~ '_' ~ current.items() | list | string | lower | regex_findall('[a-z0-9_]+') | join('_') %}
{%- if key in ns.spool %}
{%- set ns.spool = dict(ns.spool, **{key:ns.spool[key] + [entity_id]}) %}
{%- else %}
{%- set ns.spool = dict(ns.spool, **{key:[entity_id]}) %}
{%- endif %}
{%- set entity_ids = ns.spool[key] %}
{%- set current = dict(domain=domain, **current) %}
{%- set current = dict(current, entity_id=entity_ids) %}
{%- set ns.items = dict(ns.items, **{key:current | string}) %}
{%- endif %}
{%- endfor %}
[{{ ns.items.values() | unique | sort | list | join(', ') }}]
execute: >
{{ items is not none or items != [] }}
total: >
{{ items | length if execute else 0 }}
sequence:
- condition: template
value_template: "{{ execute }}"
- repeat:
count: "{{ total }}"
sequence:
- service: zwave_js.multicast_set_value
target:
entity_id: "{{ items[repeat.index - 1].entity_id }}"
data:
command_class: "{{ items[repeat.index - 1].command_class }}"
property: "{{ items[repeat.index - 1].property }}"
endpoint: "{{ items[repeat.index - 1].endpoint }}"
value: "{{ items[repeat.index - 1].value }}"
Everything seems to work as expected with a template cover that outputs “position” for its variable:
shades_master_bedroom:
unique_id: shades_master_bedroom
friendly_name: Shades Master Bedroom
value_template: >
{{ is_state('group.shades_master_bedroom', 'open') }}
position_template: >
{%- set entities = expand('group.shades_master_bedroom') %}
{%- set covers = entities | selectattr('domain', 'eq', 'cover') | selectattr('state', 'eq', 'open') %}
{%- set levels = covers | map(attribute='attributes.current_position') | map('int') | list %}
{{- levels | average if levels else 0 }}
availability_template: >
{{- expand('group.shades_master_bedroom') | selectattr('state','in',['unavailable','unknown']) | list | length == 0 }}
open_cover:
- service: script.zwave_multicast_group
data:
group: group.shades_master_bedroom
level: 255
close_cover:
- service: script.zwave_multicast_group
data:
group: group.shades_master_bedroom
level: 0
set_cover_position:
- service: script.zwave_multicast_group
data:
group: group.shades_master_bedroom
level: >
{{- position }}
I’ll take a crack at updating your shortcut template generator to do this for cover groups and post if I can get it working.
EDITED to update error in script (position
doesn’t need to scale to 255, max targetValue
sent by zwave for covers is 99)
Here’s the shortcut to paste into the template area of the developer tools for a group consisting of cover entities:
{% set entities = 'group.shades_master_bedroom' %}
{% set groups = states.group | selectattr('entity_id', 'in', entities) | list %}
{% set fmat = """
#################################
### {1:^25} ###
#################################
{0}:
unique_id: {0}
friendly_name: {1}
value_template: >
{{{{ is_state('group.{0}', 'open') }}}}
position_template: >
{{%- set entities = expand('group.{0}') %}}
{{%- set covers = entities | selectattr('domain', 'eq', 'cover') | selectattr('state', 'eq', 'open') %}}
{{%- set levels = covers | map(attribute='attributes.current_position') | map('int') | list %}}
{{{{- levels | average if levels else 0 }}}}
availability_template: >
{{{{- expand('group.{0}') | selectattr('state','in',['unavailable','unknown']) | list | length == 0 }}}}
open_cover:
- service: script.zwave_multicast_group
data:
group: group.{0}
level: 99
close_cover:
- service: script.zwave_multicast_group
data:
group: group.{0}
level: 0
set_cover_position:
- service: script.zwave_multicast_group
data:
group: group.{0}
level: >
{{{{- position }}}}
""" %}
- platform: template
covers:
{%- for group in groups %}
{{ fmat.format(group.object_id, group.name.replace('_',' ').title()) }}
{%- endfor %}
It generates the template code that’s working for me with the updated script. Hope it helps others!
[[EDITED to change max value to 99 from 100]]
Does something need to change with the script now? I can’t seem to save it.
Here is the error:
Message malformed: extra keys not allowed @ data['zwave_multicast_group']
Script
zwave_multicast_group:
mode: parallel
alias: Multicast to Zwave Group
fields:
group:
description: (Required) The group of lights & switches
example: group.all_inside_zwave
level:
description: >-
(Optional) The brightness level, switches will be on if the level is
greater than 0.
example: 99
variables:
brightness_pct: >
{%- set brightness_pct = (level | int(0) / 255 * 100) | int %} {%- set
brightness_pct = [ 0, brightness_pct ] | max %} {%- set brightness_pct = [
99, brightness_pct] | min %} {{- brightness_pct }}
value: |
{%- set value = brightness_pct > 0 %} {{- value }}
settings:
light:
command_class: 38
property: targetValue
endpoint: 0
value: "{{ brightness_pct }}"
switch:
command_class: 37
property: targetValue
endpoint: 0
value: "{{ value }}"
cover:
command_class: 38
property: targetValue
endpoint: 0
value: "{{ brightness_pct }}"
lights: |
{% if value %}
{% set off_lights = expand(group)
| selectattr('domain', 'eq', 'light')
| selectattr('state', 'eq', 'off')
| map(attribute='entity_id') | list %}
{% set on_lights = expand(group)
| selectattr('domain', 'eq', 'light')
| selectattr('state', 'eq', 'on')
| selectattr('attributes.brightness', 'defined')
| rejectattr('attributes.brightness','eq', level)
| map(attribute='entity_id') | list %}
{{ (off_lights + on_lights) or none }}
{% else %}
{{ expand(group)
| selectattr('domain', 'eq', 'light')
| selectattr('state', 'eq', 'on')
| map(attribute='entity_id') | list or none }}
{% endif %}
covers: |
{% if value %}
{% set off_lights = expand(group)
| selectattr('domain', 'eq', 'cover')
| selectattr('state', 'eq', 'closed')
| map(attribute='entity_id') | list %}
{% set on_lights = expand(group)
| selectattr('domain', 'eq', 'cover')
| selectattr('state', 'eq', 'open')
| selectattr('attributes.current_position', 'defined')
| rejectattr('attributes.current_position','eq', brightness_pct)
| map(attribute='entity_id') | list %}
{{ (off_lights + on_lights) or none }}
{% else %}
{{ expand(group)
| selectattr('domain', 'eq', 'cover')
| selectattr('state', 'eq', 'open')
| map(attribute='entity_id') | list or none }}
{% endif %}
switches: >
{%- set switches = expand(group) | selectattr('domain', 'eq', 'switch') %}
{%- set switches = switches | selectattr('state','eq', 'off' if value else
'on') %} {%- set switches = switches | map(attribute='entity_id') | list
%} {{- switches or none }}
items: >
{%- set ns = namespace(items={}, spool={}) %} {%- set fmat = "('{0}':
{1})" %} {%- set items = (switches or []) + (lights or []) + (covers or
[]) %} {%- for item in items %}
{%- set state_obj = expand(item) | first | default(none) %}
{%- if state_obj and state_obj.domain in ['light','switch','cover'] %}
{%- set domain = state_obj.domain %}
{%- set entity_id = state_obj.entity_id %}
{%- set entity_ids = lights if domain == 'light' else switches %}
{%- set entity_ids = covers if domain == 'cover' else entity_ids %}
{%- set current = settings[domain] %}
{%- set current = dict(current, **settings[entity_id]) if entity_id in settings else current %}
{%- set key = domain ~ '_' ~ current.items() | list | string | lower | regex_findall('[a-z0-9_]+') | join('_') %}
{%- if key in ns.spool %}
{%- set ns.spool = dict(ns.spool, **{key:ns.spool[key] + [entity_id]}) %}
{%- else %}
{%- set ns.spool = dict(ns.spool, **{key:[entity_id]}) %}
{%- endif %}
{%- set entity_ids = ns.spool[key] %}
{%- set current = dict(domain=domain, **current) %}
{%- set current = dict(current, entity_id=entity_ids) %}
{%- set ns.items = dict(ns.items, **{key:current | string}) %}
{%- endif %}
{%- endfor %} [{{ ns.items.values() | unique | sort | list | join(', ')
}}]
execute: |
{{ items is not none or items != [] }}
total: |
{{ items | length if execute else 0 }}
sequence:
- condition: template
value_template: "{{ execute }}"
- repeat:
count: "{{ total }}"
sequence:
- service: zwave_js.multicast_set_value
target:
entity_id: "{{ items[repeat.index - 1].entity_id }}"
data:
command_class: "{{ items[repeat.index - 1].command_class }}"
property: "{{ items[repeat.index - 1].property }}"
endpoint: "{{ items[repeat.index - 1].endpoint }}"
value: "{{ items[repeat.index - 1].value }}"
The indentation in your script is wrong. Use this:
- repeat:
count: "{{ total }}"
sequence:
- service: zwave_js.multicast_set_value
target:
entity_id: "{{ items[repeat.index - 1].entity_id }}"
data:
command_class: "{{ items[repeat.index - 1].command_class }}"
property: "{{ items[repeat.index - 1].property }}"
endpoint: "{{ items[repeat.index - 1].endpoint }}"
value: "{{ items[repeat.index - 1].value }}"