I’ve written the following automation that generally works well for using a remote control with four buttons to control the hue and saturation of my Ikea Tradfiri color LED bulb. However, there seems to be some issue with round-trip conversion because when I repeatedly press the right/left buttons to change the hue, the saturation slowly decreases (e.g., it should remain at 100, but it slowly drops from 100 to 98.8 to 97.6 and so on each time the hue changes until the saturation gets close to 0). After doing some research, I believe this has to do with some rounding errors. Home Assistant maps hue and saturation to a narrower range of values than Zigbee’s color cluster. While this is not a show-stopper, it’s a bit annoying as I would like to be able to cycle through all the colors using the remote without the saturation dropping. Any thoughts on how I can fix this?
automation:
- id: "light_color_cycle"
alias: "Reading light color"
trigger:
- platform: device
device_id: 1f5b19e8dcb1889edffcadd2ab8b558c
domain: zha
type: remote_button_short_press
subtype: left
id: hue_down
- platform: device
device_id: 1f5b19e8dcb1889edffcadd2ab8b558c
domain: zha
type: remote_button_short_press
subtype: right
id: hue_up
- platform: device
device_id: 1f5b19e8dcb1889edffcadd2ab8b558c
domain: zha
type: remote_button_short_press
subtype: turn_on
id: sat_up
- platform: device
device_id: 1f5b19e8dcb1889edffcadd2ab8b558c
domain: zha
type: remote_button_short_press
subtype: turn_off
id: sat_down
- platform: device
device_id: 1f5b19e8dcb1889edffcadd2ab8b558c
domain: zha
type: remote_button_long_press
subtype: dim_up
id: sat_max
- platform: device
device_id: 1f5b19e8dcb1889edffcadd2ab8b558c
domain: zha
type: remote_button_long_press
subtype: dim_down
id: sat_min
action:
service: light.turn_on
entity_id: light.reading_nook
data:
hs_color: >-
{% set hue = int(state_attr('light.reading_nook', 'hs_color')[0]) %}
{% set sat = int(state_attr('light.reading_nook', 'hs_color')[1]) %}
{% if trigger.id == 'hue_down' %}
{% set hue = (hue - 9) % 360 %}
{% elif trigger.id == 'hue_up' %}
{% set hue = (hue + 9) % 360 %}
{% elif trigger.id == 'sat_up' %}
{% set sat = min(sat + 5, 100) %}
{% elif trigger.id == 'sat_down' %}
{% set sat = max(sat - 5, 0) %}
{% elif trigger.id == 'sat_max' %}
{% set sat = 100 %}
{% elif trigger.id == 'sat_min' %}
{% set sat = 0 %}
{% endif %}
[{{ hue|int }}, {{ sat|int }}]
How about when a button is pressed for the hue, first before changing the hue, just put the saturation into a variable that you then use to adjust the saturation after the hue gets changed?
What is the native color space of the bulb? I don’t have any Trådfri color bulbs (only bulbs which can only do temperature and/or brightness), but all my Philips Hue bulbs use XY color for their native space.
Either do as above, store your expected saturation in a number helper, and always base your changes on that rather than the actual value on the bulb. Or do your own rounding, to the nearest multiple of 5. If the saturation is 98.8, round it back up to 100 when changing the hue.
this would be supported on an Ikea light
min_color_temp_kelvin=2000, max_color_temp_kelvin=6535, min_mireds=153, max_mireds=500, supported_color_modes=[<ColorMode.COLOR_TEMP: 'color_temp'>, <ColorMode.HS: 'hs'>], color_mode=hs, brightness=73.95, color_temp_kelvin=None, color_temp=None, hs_color=(8, 65), rgb_color=(255, 111, 89), xy_color=(0.583, 0.326)
so yeah do as @KruseLuds suggests, copy the relevant value from the Hue light and sync it to the Ikea lights upon change
Thanks everyone! I created two variables to save the current hue/saturation of the Ikea light. I manipulate those variables directly and then, at the end of the automation, set the light color to the variables. Here’s my updated code. It’s a little complicated because I want to manipulate two different Ikea Tradfiri bulbs – they are controlled by a regular on/off switch, so only one of them may be actually on at any given time (hence the parallel execution).
input_number:
ikea_light_hue:
name: Ikea light hue
min: 0
max: 360
ikea_light_saturation:
name: Ikea light saturation
min: 0
max: 100
automation:
- id: "light_color_cycle"
alias: "Reading light color"
mode: restart
trigger:
- platform: device
device_id: 1f5b19e8dcb1889edffcadd2ab8b558c
domain: zha
type: remote_button_short_press
subtype: left
id: hue_down
- platform: device
device_id: 1f5b19e8dcb1889edffcadd2ab8b558c
domain: zha
type: remote_button_short_press
subtype: right
id: hue_up
- platform: device
device_id: 1f5b19e8dcb1889edffcadd2ab8b558c
domain: zha
type: remote_button_short_press
subtype: turn_on
id: sat_up
- platform: device
device_id: 1f5b19e8dcb1889edffcadd2ab8b558c
domain: zha
type: remote_button_short_press
subtype: turn_off
id: sat_down
- platform: device
device_id: 1f5b19e8dcb1889edffcadd2ab8b558c
domain: zha
type: remote_button_long_press
subtype: dim_up
id: sat_max
- platform: device
device_id: 1f5b19e8dcb1889edffcadd2ab8b558c
domain: zha
type: remote_button_long_press
subtype: dim_down
id: sat_min
- platform: device
device_id: 1f5b19e8dcb1889edffcadd2ab8b558c
domain: zha
type: remote_button_long_press
subtype: left
id: colorloop
- platform: device
device_id: 1f5b19e8dcb1889edffcadd2ab8b558c
domain: zha
type: remote_button_long_press
subtype: right
id: colorloop
action:
- choose:
- conditions:
- condition: template
value_template: "{{ trigger.id == 'hue_down' }}"
sequence:
- service: input_number.set_value
target:
entity_id: input_number.ikea_light_hue
data:
value: "{{ (states('input_number.ikea_light_hue')|int - 9) % 360 }}"
- conditions:
- condition: template
value_template: "{{ trigger.id == 'hue_up' }}"
sequence:
- service: input_number.set_value
target:
entity_id: input_number.ikea_light_hue
data:
value: "{{ (states('input_number.ikea_light_hue')|int + 9) % 360 }}"
- conditions:
- condition: template
value_template: "{{ trigger.id == 'hue_down' }}"
sequence:
- service: input_number.set_value
target:
entity_id: input_number.ikea_light_hue
data:
value: "{{ (states('input_number.ikea_light_hue')|int - 9) % 360 }}"
- conditions:
- condition: template
value_template: "{{ trigger.id == 'hue_up' }}"
sequence:
- service: input_number.set_value
target:
entity_id: input_number.ikea_light_hue
data:
value: "{{ (states('input_number.ikea_light_hue')|int + 9) % 360 }}"
- conditions:
- condition: template
value_template: "{{ trigger.id == 'sat_down' }}"
sequence:
- service: input_number.set_value
target:
entity_id: input_number.ikea_light_saturation
data:
value: "{{ max(states('input_number.ikea_light_saturation')|int - 5, 0) }}"
- conditions:
- condition: template
value_template: "{{ trigger.id == 'sat_up' }}"
sequence:
- service: input_number.set_value
target:
entity_id: input_number.ikea_light_saturation
data:
value: "{{ min(states('input_number.ikea_light_saturation')|int + 5, 100) }}"
- conditions:
- condition: template
value_template: "{{ trigger.id == 'sat_min' }}"
sequence:
- service: input_number.set_value
target:
entity_id: input_number.ikea_light_saturation
data:
value: 0
- conditions:
- condition: template
value_template: "{{ trigger.id == 'sat_max' }}"
sequence:
- service: input_number.set_value
target:
entity_id: input_number.ikea_light_saturation
data:
value: 100
- conditions:
- condition: template
value_template: "{{ trigger.id == 'colorloop' }}"
sequence:
- parallel:
- service: light.turn_on
target:
entity_id: light.reading_nook
data:
effect: colorloop
- service: light.turn_on
target:
entity_id: light.attic_floor
data:
effect: colorloop
- if:
- condition: template
value_template: "{{ trigger.id != 'colorloop' }}"
then:
- parallel:
- service: light.turn_on
target:
entity_id: light.reading_nook
data:
hs_color: >-
[ {{ states('input_number.ikea_light_hue') }}, {{ states('input_number.ikea_light_saturation') }} ]
you are aware you have the first 2 conditions in the chosen listed twice?
also, why are you using the final condition in an if structure? and the use of the parallel seems moot, as there is nothing else you are doing at that time?
I wonder why/how you came to your main automation setup