Create a temperature changing light from 2 lights and Shelly RGBW2 [SOLVED]

Hi,
here is my issue.
I have a temperature changing led strip that is actually made of one warm whiote channel and one cold white channel. The relative brightness of these two channels controls the resulting white temperature.
Now, this strip is controlled by a Shelly RGBW2, which sees the strip as 2 independent light, where the brightness of each can be independently controlled. So in HA I see 2 different lights and I have to manually control their brightness.
Is it possible to create a single light in HA that is changing white temperature by controlling the relative brightness?

I hope I explained the issue clearly enough,
Thanks

1 Like

You can use a template light for that.

1 Like

Oh, embarrassing how I missed that
Many thanks

I’m having the same problem as you are. I’ve got the Shelly setup in HA (using shelly integration, not MQTT) and can control the CW and WW channels individually, however I haven’t found a way to create a lovelace card that combines the two channels into a single light for which I can adjust the color temp & brightness.

If you’ve found a way to do this in lovelace via template lights as KTibow mentioned, could you share the yaml for your lovelace card?

Thanks

Yeah worked the math and still have to translate what I found into templates for all the configuration parameters.
In principle:

  • to read the status (on/off) it is sufficient to check that one of the values of the brightness of the two lights is grater than 0
  • to read the current brightness it must calculate the average of the two values of brightness.
  • to read the current temperature it must calculate the average weighted with the temperature of the two individual lights
  • to set the brightness and the temperature is a bit more complicated because you have to set the brightness according to two expressions that make the light match simultaneously both values.

Let me complete the translation of the equations in a configuration and I’ll share (after having tested!)

Cheers

1 Like

I had been thinking the sum of the two channels, but having max brightness be 200% and half brightness be 100% makes no sense. I agree the average is a better method.

Thanks for the pointers, I’ll give things a shot myself and share anything I come up with. Somewhat experienced with HA, but only recently have I started dabbling into the more advanced yaml writing things such as this.

Cheers

Here is the configuration I came up with:

light:
  - platform: template
    lights: 
      corrimano_u:
        friendly_name: "Corrimano"
        value_template: "{{ (state_attr('light.corrimano_caldo', 'brightness')|int + state_attr('light.corrimano_freddo', 'brightness')|int) > 0 }}"
        level_template: "{{ ((state_attr('light.corrimano_caldo', 'brightness')|float + state_attr('light.corrimano_freddo', 'brightness')|float)/2)|int }}"
        temperature_template: "{{ ((state_attr('light.corrimano_caldo', 'brightness')|float*6500 + state_attr('light.corrimano_freddo', 'brightness')|float*3000)/((state_attr('light.corrimano_caldo', 'brightness')|int + state_attr('light.corrimano_freddo', 'brightness')|int))) }}"
        set_level:
          - service: light.turn_on
            data:
              entity_id: light.corrimano_caldo
              brightness: "{{ (state_attr('light.corrimano_u', 'brightness')|int*2) * (6500-state_attr('light.corrimano_u', 'temperature')|int) / (6500-3000) }}"
          - service: light.turn_on
            data:
              entity_id: light.corrimano_freddo
              brightness: "{{ (state_attr('light.corrimano_u', 'brightness')|int*2) * (state_attr('light.corrimano_u', 'temperature')|int - 3000) / (6500-3000) }}"
        set_temperature:
          - service: light.turn_on
            data:
              entity_id: light.corrimano_caldo
              brightness: "{{ (state_attr('light.corrimano_u', 'brightness')|int*2) * (6500-state_attr('light.corrimano_u', 'temperature')|int) / (6500-3000) }}"
          - service: light.turn_on
            data:
              entity_id: light.corrimano_freddo
              brightness: "{{ (state_attr('light.corrimano_u', 'brightness')|int*2) * (state_attr('light.corrimano_u', 'temperature')|int - 3000) / (6500-3000) }}"
        turn_on:
          - service: light.turn_on
            data:
              entity_id: light.corrimano_caldo
          - service: light.turn_on
            data:
              entity_id: light.corrimano_freddo
        turn_off:
          - service: light.turn_off
            data:
              entity_id: light.corrimano_caldo
          - service: light.turn_off
            data:
              entity_id: light.corrimano_freddo

Where corrimano_caldo and corrimano_freddo are the warm and cold lights, respectively.
The temperatures 3000 and 6500 are hardcoded, replace to match yours. While I think the equations are right, the implementation is definitely not. As I can’t control correctly the template light.
I’ll continue experimenting, in the meantime if somebody notices what’s wrong with the above…

Do you mean that when you try nothing happens?

Something happens but surely not the intended. There are two possible sources of error as I see it:

  1. the calcs above are intended to set the temperature in kelvin, but in the interface I see the temperature in mireds. Do I need to output mireds from the formula?
  2. setting the temperature of the light involves two service calls, one for each light. The first call changes the temperature, which is then used in the second call, therefore the relationship doesn’t work as intended. I believe I shouldn’t use state_attr('light.corrimano_u', 'temperature') when setting temperature. and shouldn’t use state_attr('light.corrimano_u', 'brightness') when setting brightness.

Could you be more specific? What does happen?
You should probably test using the template and services tabs of the developer tools.

After some experimentation myself, I came up with an alternative solution that I believe suits my needs better than a slider - which is primarily relying on a few presets.

Here is the lovelace card for the lighting strips:

type: vertical-stack
title: Under Cabinet Lighting
cards:
  - type: glance
    entities:
      - entity: scene.kucl_off
        name: 'Off'
        tap_action:
          action: call-service
          service: scene.turn_on
          service_data:
            entity_id: scene.kucl_off
      - entity: scene.kucl_on
        name: 'On'
        tap_action:
          action: call-service
          service: scene.turn_on
          service_data:
            entity_id: scene.kucl_on
      - entity: scene.kucl_dim
        name: Dim
        tap_action:
          action: call-service
          service: scene.turn_on
          service_data:
            entity_id: scene.kucl_dim
      - entity: scene.kucl_relax
        name: Relax
        tap_action:
          action: call-service
          service: scene.turn_on
          service_data:
            entity_id: scene.kucl_relax
      - entity: scene.kucl_superbright
        name: Bright
        tap_action:
          action: call-service
          service: scene.turn_on
          service_data:
            entity_id: scene.kucl_superbright
    show_state: false
    show_icon: true
  - type: horizontal-stack
    cards:
      - type: light
        entity: light.shellyrgbw2_b0ca61_channel_4
        name: Warm White
      - type: light
        entity: light.shellyrgbw2_b0ca61_channel_3
        name: Cool White
  - type: entities
    entities:
      - entity: binary_sensor.shellyrgbw2_b0ca61_overpowering
        name: Cabinet Lights
    title: Power Safety

The five preset scenes I have been using are quite simple:

  1. Off - as implied, both WW & CW set to off
  2. On - the standard choice for me - CW set to off and WW set to 100%
  3. Dim - CW set to off and WW set to 10%
  4. Relax - CW set to off and WW set to 50%
  5. Super Bright - CW set to 100% and WW set to 100% - we really only use this when cleaning and wanting max light.

Maybe this will be of some help to someone else. I’ve found that in practice I would not frequently use a slighter for brightness and a slider for color temp.

Here is a screenshot of the lovelace card:

Finally had time to play a bit more with this, and came up with something which is more or less working:

light:
  - platform: template
    lights: 
      corrimano_u:
        friendly_name: "Corrimano"
        value_template: "{{ (state_attr('light.corrimano_caldo', 'brightness')|int + state_attr('light.corrimano_freddo', 'brightness')|int) > 0 }}"
        level_template: "{{ ((state_attr('light.corrimano_caldo', 'brightness')|float + state_attr('light.corrimano_freddo', 'brightness')|float)/2)|int }}"
        temperature_template: "{{ ((state_attr('light.corrimano_caldo', 'brightness')|float*6500 + state_attr('light.corrimano_freddo', 'brightness')|float*3000)/((state_attr('light.corrimano_caldo', 'brightness')|int + state_attr('light.corrimano_freddo', 'brightness')|int))) }}"
        set_level:
          - service: light.turn_on
            data:
              entity_id: light.corrimano_caldo
              brightness: "{{ ((brightness*2) * (6500-state_attr('light.corrimano_u', 'temperature')|int) / (6500-3000)|int) }}"
          - service: light.turn_on
            data:
              entity_id: light.corrimano_freddo
              brightness: "{{ ((brightness*2) * (state_attr('light.corrimano_u', 'temperature')|int - 3000) / (6500-3000)|int) }}"
        set_temperature:
          - service: light.turn_on
            data:
              entity_id: light.corrimano_caldo
              brightness: "{{ ((state_attr('light.corrimano_u', 'brightness')|int*2) * (6500 - 1000000/color_temp) / (6500 - 3000)|int) }}"
          - service: light.turn_on
            data:
              entity_id: light.corrimano_freddo
              brightness: "{{ ((state_attr('light.corrimano_u', 'brightness')|int*2) * (1000000/color_temp - 3000) / (6500 - 3000)|int) }}"
        turn_on:
          - service: light.turn_on
            data:
              entity_id: light.corrimano_caldo
          - service: light.turn_on
            data:
              entity_id: light.corrimano_freddo
        turn_off:
          - service: light.turn_off
            data:
              entity_id: light.corrimano_caldo
          - service: light.turn_off
            data:
              entity_id: light.corrimano_freddo

The following works as expected if done from the UI, see examples:

  • if I switch on and set 50% brightness, then 153 mireds (6500K) only the cold one switches on, at 100% brightness, which is correct
  • if I switch on and set 50% brightness, then 333 mireds (3000K) only the warm one switches on, at 100% brightness, which is correct
  • if I switch on and set 50% brightness, then 210 mireds (4750K) both the warm and cold ones switch on, at 50% brightness, which is correct

Now, there is still something I don’t understand. If I change brightness only form UI, the behaviour is not logic. For example, if I’m in any state, then I change brightness, whatever is the temperature, the warm light get switched on at full brightness, the cold one gets switched off. If I then change the temperature, the brightness of each of the two lights goes back to correct relative values, but with overall brightness at 50%.

I think this is due to the template not having the temperature attribute, in fact if I try the following in template on the developers tools, I get None:

{{state_attr('light.corrimano_u', 'temperature')}}

It’s getting complicated

what do you see in the states section?

no temperature state, only min and max

thanks

What do you get when you evaluate

in the template section of devtools?

When off it gives an error “Division by zero” (which is something that should probably be managed later), otherwise it gives the temperature in kelvin. I modified to convert in mireds and now the template light has the color_temp attribute and current state of the light. When changing the temperature on the UI the behavior is still not correct, but I think this can be related to the same issue (kelvin vs. mireds).
Will let you know, thanks for the good hints so far!

I’m happy to report that the template light works as intended now.
The key was to use color_temp everywhere and use mireds in every formula.
Now setting brightness and temperature work, included the fact that due to the nature of how this light is made, the extremely warm or extremely cold can’t be set at more than 50% brightness. Also, since the warm white is at 3000K or 333 mireds, warmer whites cannot be achieved, but the max_mireds attribute is equal to 500. I did not find a way to correct this
Here is the config:

light:
  - platform: template
    lights: 
      corrimano:
        friendly_name: "Corrimano"
        value_template: "{{ (state_attr('light.corrimano_caldo', 'brightness')|int + state_attr('light.corrimano_freddo', 'brightness')|int) > 0 }}"
        level_template: "{{ ((state_attr('light.corrimano_caldo', 'brightness')|float + state_attr('light.corrimano_freddo', 'brightness')|float)/2)|int }}"
        temperature_template: "{{ 1000000/(((state_attr('light.corrimano_caldo', 'brightness')|float*3000 + state_attr('light.corrimano_freddo', 'brightness')|float*6500)/((state_attr('light.corrimano_caldo', 'brightness')|int + state_attr('light.corrimano_freddo', 'brightness')|int)))) }}"
        set_level:
          - service: light.turn_on
            data:
              entity_id: light.corrimano_caldo
              brightness: "{{ ((brightness*2) * (6500-1000000/state_attr('light.corrimano', 'color_temp')|int) / (6500-3000)|int) }}"
          - service: light.turn_on
            data:
              entity_id: light.corrimano_freddo
              brightness: "{{ ((brightness*2) * (1000000/state_attr('light.corrimano', 'color_temp')|int - 3000) / (6500-3000)|int) }}"
        set_temperature:
          - service: light.turn_on
            data:
              entity_id: light.corrimano_caldo
              brightness: "{{ ((state_attr('light.corrimano', 'brightness')|int*2) * (6500 - 1000000/color_temp) / (6500 - 3000)|int) }}"
          - service: light.turn_on
            data:
              entity_id: light.corrimano_freddo
              brightness: "{{ ((state_attr('light.corrimano', 'brightness')|int*2) * (1000000/color_temp - 3000) / (6500 - 3000)|int) }}"
        turn_on:
          - service: light.turn_on
            data:
              entity_id: light.corrimano_caldo
          - service: light.turn_on
            data:
              entity_id: light.corrimano_freddo
        turn_off:
          - service: light.turn_off
            data:
              entity_id: light.corrimano_caldo
          - service: light.turn_off
            data:
              entity_id: light.corrimano_freddo

Thanks for the hints that made this possible

2 Likes

Hi I try your template and is working, but still look little buggy when I am usin it.

Do you have same situation like on this video when you using it?

001

Errors in ha core regarding this light template:

2022-03-04 17:41:53 WARNING (MainThread) [homeassistant.helpers.template] Template warning: 'float' got invalid input 'None' when rendering template '{{ 1000000/(((state_attr('light.livingroom_light_01_white_warm', 'brightness')|float*3000 + state_attr('light.livingroom_light_01_white_cool', 'brightness')|float*6500)/((state_attr('light.livingroom_light_01_white_warm', 'brightness')|int + state_attr('light.livingroom_light_01_white_cool', 'brightness')|int)))) }}' but no default was specified. Currently 'float' will return '0', however this template will fail to render in Home Assistant core 2022.1
2022-03-04 17:41:53 WARNING (MainThread) [homeassistant.helpers.template] Template warning: 'float' got invalid input 'None' when rendering template '{{ 1000000/(((state_attr('light.livingroom_light_01_white_warm', 'brightness')|float*3000 + state_attr('light.livingroom_light_01_white_cool', 'brightness')|float*6500)/((state_attr('light.livingroom_light_01_white_warm', 'brightness')|int + state_attr('light.livingroom_light_01_white_cool', 'brightness')|int)))) }}' but no default was specified. Currently 'float' will return '0', however this template will fail to render in Home Assistant core 2022.1
2022-03-04 17:41:53 WARNING (MainThread) [homeassistant.helpers.template] Template warning: 'int' got invalid input 'None' when rendering template '{{ 1000000/(((state_attr('light.livingroom_light_01_white_warm', 'brightness')|float*3000 + state_attr('light.livingroom_light_01_white_cool', 'brightness')|float*6500)/((state_attr('light.livingroom_light_01_white_warm', 'brightness')|int + state_attr('light.livingroom_light_01_white_cool', 'brightness')|int)))) }}' but no default was specified. Currently 'int' will return '0', however this template will fail to render in Home Assistant core 2022.1
2022-03-04 17:41:53 WARNING (MainThread) [homeassistant.helpers.template] Template warning: 'int' got invalid input 'None' when rendering template '{{ 1000000/(((state_attr('light.livingroom_light_01_white_warm', 'brightness')|float*3000 + state_attr('light.livingroom_light_01_white_cool', 'brightness')|float*6500)/((state_attr('light.livingroom_light_01_white_warm', 'brightness')|int + state_attr('light.livingroom_light_01_white_cool', 'brightness')|int)))) }}' but no default was specified. Currently 'int' will return '0', however this template will fail to render in Home Assistant core 2022.1

Another possible solution is to create two helper variables that control the color and temperature.
The input of the sliders update the helpers variables first. Then the values for the warm and cold white is calculated from the helpers.

- platform: template
  lights:
    keuken_werkblad:
      friendly_name: "Keuken werkblad"
      unique_id: lampen_keukenwerkblad
      value_template: "{{ (state_attr('light.keukenwerkblad_channel_3', 'brightness')|int(0) + state_attr('light.keukenwerkblad_channel_4', 'brightness')|int(0)) > 0 }}"
      level_template: "{{ states('input_number.keukenwerkblad_brightness')|int }}"
      temperature_template: "{{ states('input_number.keukenwerkblad_color_temp')|int }}"
      set_level:
        - service: input_number.set_value
          data:
            value: "{{ brightness|int }}"
          target:
            entity_id: input_number.keukenwerkblad_brightness
        - service: light.turn_on
          data:
            entity_id: light.keukenwerkblad_channel_3
            brightness: "{{ ((states('input_number.keukenwerkblad_color_temp')|int-153)/347*states('input_number.keukenwerkblad_brightness')|int)|int }}"
        - service: light.turn_on
          data:
            entity_id: light.keukenwerkblad_channel_4
            brightness: "{{ ((500-states('input_number.keukenwerkblad_color_temp')|int)/347*states('input_number.keukenwerkblad_brightness')|int)|int }}"
      set_temperature:
        - service: input_number.set_value
          data:
            value: "{{ color_temp|int }}"
          target:
            entity_id: input_number.keukenwerkblad_color_temp
        - service: light.turn_on
          data:
            entity_id: light.keukenwerkblad_channel_3
            brightness: "{{((states('input_number.keukenwerkblad_color_temp')|int-153)/347*states('input_number.keukenwerkblad_brightness')|int)|int}}"
        - service: light.turn_on
          data:
            entity_id: light.keukenwerkblad_channel_4
            brightness: "{{((500-states('input_number.keukenwerkblad_color_temp')|int)/347*states('input_number.keukenwerkblad_brightness')|int)|int}}"
      turn_on:
        - service: light.turn_on
          data:
            entity_id: light.keukenwerkblad_channel_3
            brightness: "{{((states('input_number.keukenwerkblad_color_temp')|int-153)/347*states('input_number.keukenwerkblad_brightness')|int)|int}}"
        - service: light.turn_on
          data:
            entity_id: light.keukenwerkblad_channel_4
            brightness: "{{((500-states('input_number.keukenwerkblad_color_temp')|int)/347*states('input_number.keukenwerkblad_brightness')|int)|int}}"
      turn_off:
        - service: light.turn_off
          data:
            entity_id: light.keukenwerkblad_channel_3
        - service: light.turn_off
          data:
            entity_id: light.keukenwerkblad_channel_4
2 Likes