Help me implement a template light for non-linear groups

I just discovered templates, and I’m having such a hard time with HA syntax in general. I found this example that I was able to implement to a light that had most of it’s “travel” in the first 20% of the slider, what a game changer that was!

Now I have a light with 16 individually addressable bulbs, in a 4x4 group configuration. This is in the bedroom, and all on at lowest brightness is too bright, so I want to create a template that creates a virtual light on top of those 4 groups. The slider should map to the 4 groups in such a way that, say, the first 20% should only bring the first group up to about 10%, and then gradually bring the next group in, and so on…

I don’t even know where to start, other than doing it wrong, by creating a template like the linked one for each group with a different non-linear mapping, and then again using groups to group them into one entity.

Surely there’s a less convoluted way?

remember that in the template, you are not restricted to one service call. look here at the first example for set_hs.

so you can create 1 template light that controls all 4 and brings brightness to each at their own curve if you want… so you don’t need to create 4 separate ones plus a group unless you really want independent lights with those different curves

Thanks for the pointer, I was able to use it to create this, which does in fact work, even though it isn’t pretty. I’m quite obviously no mathologist. The 1-4 is just to visualize how the groups come in while working on it.

Screen Recording 2024-06-23 at 01.00.02(1)

There’s one issue. If I pull the slider too fast in succession, I get an ‘already running’ error on light.turn_on. Any ideas how I can fix that?

  - platform: template
    lights:
      svefnherbergi_platform:
        friendly_name: Svefnherbergi Non-Linear
        turn_on:
          service: light.turn_on
          entity_id: light.svefnherbergi_loftljos
        turn_off:
          service: light.turn_off
          entity_id: light.svefnherbergi_loftljos
        set_level:
          - service: light.turn_on
            data_template:
              brightness: "{{ ((0.55 + brightness/200) **2 * 55 ) -18 | int }}"
              entity_id: light.wiz_svefn_1
          - service: light.turn_on
            data_template:
              brightness: "{{ ((0.45 + brightness/200) **2 * 55 ) -22 | int }}"
              entity_id: light.wiz_svefn_2
          - service: light.turn_on
            data_template:
              brightness: "{{ ((0.45 + brightness/200) **2 * 45 ) -32 | int }}"
              entity_id: light.wiz_svefn_3
          - service: light.turn_on
            data_template:
              brightness: "{{ ((0.45 + brightness/200) **2 * 40 ) -38 | int }}"
              entity_id: light.wiz_svefn_4

i’m not sure it’s “fixable” or even what the fix might be. however the below and see if it reduces the occurance…

what i think is happening is that the calls are implemented in essentially mode:single. which means that if you scrub (move the slider back and forth) quickly and you get another call while one’s not finished, the question is what should it do? should it queue up the requests? that seems wrong… then you could scrub quickly and 10 seconds after scrubbing, it’s still going up and down.
it could try to cancel the existing call, but that may not always happen immediately. so the closest to “right” is to blow off the subsequent calls… which is what it’s doing. ideally it remembers the very very last one… but not sure about that.

in my below, i’m running all 4 set_levels in parallel… so if the slowness in the calls are due to things other than homeassistant itself being slow, then this should reduce the amount of times you see that error, but it doesn’t eliminate it…

all hypothesis… mind you…

- platform: template
    lights:
      svefnherbergi_platform:
        friendly_name: Svefnherbergi Non-Linear
        turn_on:
          service: light.turn_on
          entity_id: light.svefnherbergi_loftljos
        turn_off:
          service: light.turn_off
          entity_id: light.svefnherbergi_loftljos
        set_level:
          - parallel:
              - service: light.turn_on
                data_template:
                  brightness: "{{ ((0.55 + brightness/200) **2 * 55 ) -18 | int }}"
                  entity_id: light.wiz_svefn_1
              - service: light.turn_on
                data_template:
                  brightness: "{{ ((0.45 + brightness/200) **2 * 55 ) -22 | int }}"
                  entity_id: light.wiz_svefn_2
              - service: light.turn_on
                data_template:
                  brightness: "{{ ((0.45 + brightness/200) **2 * 45 ) -32 | int }}"
                  entity_id: light.wiz_svefn_3
              - service: light.turn_on
                data_template:
                  brightness: "{{ ((0.45 + brightness/200) **2 * 40 ) -38 | int }}"
                  entity_id: light.wiz_svefn_4

I implemented the virtual light based off the link you highlighted. I am not seeing the same errors you are seeing, but I stuck close to the original equation and simply adjusted this value

light:
  - platform: template
    lights:
      sleep1_synth1:
        friendly_name: sleeping room synth
        turn_on: 
          service: light.turn_on
          entity_id: light.pc_lights
        turn_off: 
          service: light.turn_off
          entity_id: light.pc_lights
        set_level:        
          - service: light.turn_on
            data_template:
             brightness: "{{ ( (0.58 + brightness/255) **5 * 0.1017 *255) | int }}"             
             entity_id: light.pc_lights
          - service: light.turn_on
            data_template:         
             brightness: "{{ ( (0.48 + brightness/255) **5 * 0.1017 *255) | int }}"             
             entity_id: light.bed_lights 
          - service: light.turn_on
            data_template:        
             brightness: "{{ ( (0.38 + brightness/255) **5 * 0.1017 *255) | int }}"             
             entity_id: light.night_stand 
          - service: light.turn_on
            data_template:
             brightness: "{{ ( (0.28 + brightness/255) **5 * 0.1017 *255) | int }}"             
             entity_id: light.corner_stand
            
        value_template: >-
          {{ is_state('light.pc_lights', 'on') }}
        level_template: >-
          {% if state_attr("light.pc_lights","brightness") != None %}
              {{  ( ((  (states.light.pc_lights.attributes.brightness+0.5) /255/0.1017)**0.2 * 255 ) - 147.9 ) | int  }} 
          {% else %}
            0
          {% endif %}      

Your equation is not generating a whole number. That may be causing delays in you system, but I’m not positive without testing. In addition, I’m getting a startup error that needs addressed.

EDIT: I’m’ not getting the same 'already running error`, but I am seeing odd behavior with your template questions. The slider as to adjust itself either up or down to lock in the brightness. I would suggest rounding your values or test the template I shared.

EDIT2: Startup issue has been resolved. The template is updated with the corrected code.

1 Like

Thanks for the pointers again!

Will you let us know the outcome? This one was interesting.