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.