Scripts execute argument list out of order

Hi everyone–

In trying to investigate an issue I documented in the thread Light Groups control order, I made a pair of simple scripts to turn on and off a set of lights and a light template to run it:

  hall_lights_on:
    sequence:
    - service: light.turn_on
      data_template:
        entity_id: "{{ entity_id }}"
    - service: light.turn_on
      data_template:
        entity_id: "{{ entity_id }}"
    - service: light.turn_on
      data_template:
        entity_id: "{{ entity_id }}"
    mode: single
    alias: Hall Lights On

  hall_lights_off:
    sequence:
    - service: light.turn_off
      data_template:
        entity_id: "{{ entity_id1 }}"
    - service: light.turn_off
      data_template:
        entity_id: "{{ entity_id2 }}"
    - service: light.turn_off
      data_template:
        entity_id: "{{ entity_id3 }}"
    mode: single
    alias: Hall Lights Off

  - platform: template
    lights:
      hall_lights:
        friendly_name: "Hall Lights"
        value_template: "{{ is_state('light.hall_lights_1_load', 'on') }}"
        level_template: "{{ state_attr('light.hall_lights_1_load', 'brightness') | int }}"
int}})"
        turn_on:
          service: script.hall_lights_on
          data:
            entity_id: "light.hall_lights_1_load, light.hall_lights_2_remote, light.hall_lights_3_remote"
        turn_off:
          service: script.hall_lights_off
          data:
            entity_id1: "light.hall_lights_1_load"
            entity_id2: "light.hall_lights_2_remote"
            entity_id3: "light.hall_lights_3_remote"

Notice I use two different approaches for ‘on’ and ‘off’. ‘On’ uses a single variable defined as a list of entities whereas ‘Off’ uses multiple variables, one for each entity. There is a difference in behavior too.

Turning ‘On’ the switch template results in the underlying entities being turned on in a random order. Additionally, the script takes an extra second or two at the end during which I have no clue what it’s doing. If I attempt to turn off the switch before the script has completed, it results in all of the entities turning off, followed by at least one turning back on, resulting in a mixed state.

Turn ‘Off’ the switch template however results in predictable order execution, always entity_id1, then 2 and then 3. There is no delay at the end.

Does anyone have any ideas that can explain the ‘on’ behavior? This is the syntax I’d prefer to use for reusability among multiple device groups. This behavior is remarkably similar to the behavior of entities in a switch group as I explain in the thread linked above. Hoping to track down the root cause of this.

Otherwise, any suggestions on better ways to pass a variable length list of arguments to a script without explicitly naming each one?

Thanks.

Your on sequence turns all three lights on three times.

  hall_lights_on:
    sequence:
    - service: light.turn_on
      data_template:
        entity_id: "{{ entity_id }}"  # light.hall_lights_1_load, light.hall_lights_2_remote, light.hall_lights_3_remote
    - service: light.turn_on
      data_template:
        entity_id: "{{ entity_id }}" # same id, same three lights
    - service: light.turn_on
      data_template:
        entity_id: "{{ entity_id }}" # same id, same three lights.

Your off sequence uses three different ids:

  hall_lights_off:
    sequence:
    - service: light.turn_off
      data_template:
        entity_id: "{{ entity_id1 }}" # light.hall_lights_1_load
    - service: light.turn_off
      data_template:
        entity_id: "{{ entity_id2 }}" # light.hall_lights_2_remote
    - service: light.turn_off
      data_template:
        entity_id: "{{ entity_id3 }}" # light.hall_lights_3_remote

So they will turn on in order.

What a mess!

Your version tidied up…

 hall_lights_on:
    alias: Hall Lights On 
    sequence:
    - service: light.turn_on
      data:
        entity_id:
          - "{{ entity_id1 }}"
          - "{{ entity_id2 }}"
          - "{{ entity_id3 }}"

  hall_lights_off:
    alias: Hall Lights Off
    sequence:
    - service: light.turn_off
      data:
        entity_id:
          - "{{ entity_id1 }}"
          - "{{ entity_id2 }}"
          - "{{ entity_id3 }}"

  - platform: template
    lights:
      hall_lights:
        friendly_name: "Hall Lights"
        value_template: "{{ is_state('light.hall_lights_1_load', 'on') }}"
        level_template: "{{ state_attr('light.hall_lights_1_load', 'brightness') | int }}"
        turn_on:
          service: script.hall_lights_on
          data: &lights
            entity_id1: light.hall_lights_1_load
            entity_id2: light.hall_lights_2_remote
            entity_id3: light.hall_lights_3_remote
        turn_off:
          service: script.hall_lights_off
          data: *lights

But - All of that can be deleted and replaced with

light:
  - platform: group
    name: Hall Lights
    entities:
      - light.hall_lights_1_load
      - light.hall_lights_2_remote
      - light.hall_lights_3_remote

Nah, he needs them turned on in a particular order. The group can’t guarantee that.

The script had no delays in it, so it should all be instantaneous either way. If its not, then there’s some other problems going on there and he’s just hoping to mask the problem with ‘oh yeah, it’s intentional they come on like that’.

Turning on a light group containing

 - light.1
 - light.2
 - light.3

Is the same as

service: light.turn_on
entity_id:
  - light.1
  - light.2
  - light.3

Homeassistant will just loop through the entities in a fraction of a second, and they should all come on at the same time as the microsecond delay between each one is imperceptible.

If there is some kind of network congestion that is causing that delay to be perceptible, then there is no way to guarantee that that congestion will be predictable and always work in a certain order.

The only way to guarantee light 1 > wait > light 2 > wait > light 3 would be to add delays to the script that were definitely longer than the expected delay from network congestion, but tbh I think that would look like you had power problems anyway. A far neater/cooler option for that case (once the fault was fixed) would be a slow transition on light 1, a slightly longer one on light 2, and slightly longer again on light 3, or better yet independent control of each light when it’s actually needed.

1 Like

Thank you all for your help, but the entire point of this post and my previous post is that it’s not instantaneous.

Light groups can’t guarantee the order, and it seems that whichever device gets in first blocks the others for at least a second. I thought I’ve managed to replicate this behavior with my original ‘on’ example since it exhibits the same behavior. I fixed my ‘on’ example as follows, but it still exhibits the out of order execution:

  hall_lights_on:
    sequence:
    - service: light.turn_on
      data_template:
        entity_id: "{{ entity_id }}"
    mode: single
    alias: Hall Lights On

I’m next going to try splitting the entity_id string in here and assigning it to multiple services in the sequence. This should give me execution similar to the ‘off’ example.

As I explain in my original post Light Groups control order, I’m trying to guarantee that the switch with the actual light attached (the load) turns on first. Something funky is going on with the delay of the second and third devices; I’m 100% sure it’s not due to network congestion and suspect it could be due to HA or the ISY integration; although it could be the ISY hardware queueing up commands too, in which case this workaround is the best I’ll do. That’s another issue I’m trying to track down.

Either way, however HA should absolutely be able to control the order of the devices as I demonstrated in the ‘off’ experiment. I just want to use a list syntax similar to ‘on’ so I can reuse the script for multiple device groups.

And yes, that’s exactly what I’m trying to do. If the load comes on first, it will seem instantaneous even if the remotes lag a little bit behind. Ideally everything would come on instantaneously and I wouldn’t care. But it seems like I’m dealing with two problems that together cause an issue for me, and I’m trying to solve at least one of them.

That is not fixed, see my reply above.

Yes that will work.

For anyone who experiences similar issues, this is what I ended up with so far. With the YAML repeated node syntax @anon43302295 shared, the template isn’t too bad to duplicate for each light group:

light:
  - platform: template
    lights:
      hall_lights:
        friendly_name: "Hall Lights"
        value_template: "{{ is_state('light.hall_lights_1_load', 'on') }}"
        level_template: "{{ state_attr('light.hall_lights_1_load', 'brightness') | int }}"
        turn_on:
          service: script.light_group_on
          data: &lights
            entity_id1: "light.hall_lights_1_load"
            entity_id2: "light.hall_lights_2_remote"
            entity_id3: "light.hall_lights_3_remote"
        turn_off:
          service: script.light_group_off
          data:
            <<: *lights
        set_level:
          service: script.light_group_level
          data:
            <<: *lights
            brightness: "{{ brightness }}"

script:
  light_group_on:
    sequence:
    - service: light.turn_on
      data_template:
        entity_id: "{{ entity_id1 }}"
    - service: light.turn_on
      data_template:
        entity_id: "{{ entity_id2 }}"
    - service: light.turn_on
      data_template:
        entity_id: "{{ entity_id3 | default('NONE') }}"
    mode: single
    alias: Light Group On

  light_group_off:
    sequence:
    - service: light.turn_off
      data_template:
        entity_id: "{{ entity_id1 }}"
    - service: light.turn_off
      data_template:
        entity_id: "{{ entity_id2 }}"
    - service: light.turn_off
      data_template:
        entity_id: "{{ entity_id3 | default('NONE') }}"
    mode: single
    alias: Light Group Off
    
  light_group_level:
    sequence:
    - service: light.turn_on
      data_template:
        entity_id: "{{ entity_id1 }}"
        brightness: "{{ brightness }}"
    - service: light.turn_on
      data_template:
        entity_id: "{{ entity_id2 }}"
        brightness: "{{ brightness }}"
    - service: light.turn_on
      data_template:
        entity_id: "{{ entity_id3 | default('NONE') }}"
        brightness: "{{ brightness }}"
    mode: single
    alias: Light Group Level

Note the scripts will work for two or three entity arguments. It can easily be expanded to support other light functions (color, etc.) or handle a larger group. I may fiddle around with the script ‘mode’ if I find preemption to be an issue. A variable length argument would have been ideal, but I guess this will have to do. I’ll likely open another thread about the blocking issue.

Also, if you have any thoughts/tips how the template could be optimized further to reduce duplication or otherwise, please share. HA is still new to me and I’m only beginning to scratch the surface. Can this be put into a blueprint? I have a lot of lights :slight_smile: .
Thanks.