Set colour of Shelly RGBW2 based on Power reading of Shelly1 PM

I’m VERY new to HA & am just learning the ropes with all this smart home stuff.

I would like to set the colour of by Shelly RGBW2 based on the power reading from a Shelly1 PM. i.e Green for low power use, changing to Red as power use increases.

Does anyone have any idea if this is possible & know how it would be achieved?

I’m probably pushing my luck here but could it also flash red once max power was reached ?

Hi and welcome :wave:

It is indeed possible to do that. To get started you should have a look at MQTT. You need some kind of broker (there is an add-on for that if you are using Home Assistant or if you are using Home Assistant Core on Docker there are also images available).

Your Home Assistant (i) and the Shelly Devices (i) must then have MQTT enabled so they are able to communicate with each other using said broker. If you’ve enabled that it is time to get yourself comfortable with the automation functionality. Either the one that is integrated in Home Assistant or by a using 3rd party solution like Node-RED (again available as an add-on and on docker hub).

If you feel comfortable enough in using the automation tool of your choice it is time to combine the loose ends.

Write an automation that listens to the information sent by Shelly1/1PM’s power topic and -based on the received value- send something to the Shelly RGBW2’s color or white set topic.

Since the color/<n>/set topic expects you to send a JSON payload I’d suggest you start simple and begin with sending a brightness value to the white/<n>/set topic that is based on the power value you’ve received beforehand. Once that works you could take a deep breath and deep dive into JSON payloads to color your bulbs :wink:

You will eventually learn that flashing the bulb red is also possible.

I hope that points you in the right direction. Have fun with your new tools!

Actually, @Florian, there is now an integration to control Shelly devices locally without MQTT should you want!

As for the automation, here is how I would tackle it.

First, create an input_number so you can define the min/max values and tweak them as you see fit. This will be useful in honing the red/green values without having to mess with the templates later on.

input_number:
  power_lights:
    name: Shelly Light color based on power
    min: 0
    max: 120
    step: 1

The min and max would be the values you want the power to be in green and red from whatever units you are using. In this example, I’ll assume power is in Watts. 0 Watts would be green, 120 W would be red. Actually, leave min at 0 unless you want to tweak the template math below. Max can be whatever you want.

Now, I’m going to create a template sensor because light rgb_color fields don’t work with templates and I’m going to go crazy trying to do math and stuff without them…

sensor:
  - platform: template
    sensors:
      shelly_light_sensor:
        friendly_name: "Power To Color"
        # The state of this sensor just follows the power monitor value we care about. (Watts)
        # If the power monitor value is an attribute, put it here instead 
        # with "{{ state_attr('sensor.shelly_pm', 'attribute_with_power_in_watts') }}"
        value_template: "{{ states('sensor.shelly_pm') }}"
        # Now create our special attributes for this sensor
        attribute_templates:
          # Scale these based on the state of this sensor. 
          # For a good gradient, green should remain full power until we get to half as red value increases.
          # At which point, red will remain full power as green value decreases. 
          red: >-
            {% set scale = (state('shelly_light_sensor') | int) / ((state_attr('input_number.power_lights', 'max') | int) / 2) %}
            {% set scale_red = scale * 255 %}
            {{ [scale_red, 255] | min | int }}
          green: >-
             {% set scale = (state('shelly_light_sensor') | int) / ((state_attr('input_number.power_lights', 'max') | int) / 2) %}
             {% set scale_green = (2 - scale) * 255 | int %}
             {{ [scale_green, 255] | min | int }}
          blue: 0
        

All I’m doing is scaling the current power relative to the max. So if it’s >= half power, the red value will be full power and green value will decrease. If it’s <= half power, green will be full value as red decreases. If you change the input_number minimum value, make sure you adjust the math here as it assumes a value of zero.

Now, create an automation that monitors the power change and updates the light value. If the shelly RGBW supports the light.turn_on, it would look like this…

automation:
  - alias: Update Light Color
    trigger: 
      platform: state
      # On all state changes....update the color
      entity_id: sensor.shelly_light_sensor
    action:
      - service: light.turn_on
        data_template:
          entity_id: light.shelly_rgbw
          # Because templates are hard with this, just input the attributes of our
          # special sensor straight into rgb
          rgb_color: ["{{ state_attr('shelly_light_sensor', 'red') | int }}",
                      "{{ state_attr('shelly_light_sensor', 'green') | int }}",
                      "{{ state_attr('shelly_light_sensor', 'blue') | int }}"]

If it doesn’t support that, do what @Florian suggests with json templates. The good thing is, your new sensor here will make it much easier as the Red/Green color math is all handled in this sensor and you’ll just have to use the attributes wherever needed.

I think in all cases, the template sensor and input_number will be useful to you in this case! I’m not actually using the value of the input_number anywhere, but you could later add that as well to do something else as you see fit. That would be cool.

Thanks for your help here. My Shellies are due for delivery next week so will let you know how I get on . . .

I got there in the end . . .

https://youtu.be/y_Z_mUzHte8