Blog
Setting color temperature and brightness of IKEA Tradfri lights simultaneously with Home Assistant

Setting color temperature and brightness of IKEA Tradfri lights simultaneously with Home Assistant

In my smart home I use multiple IKEA Tradfri lights in combination with a Conbee Zigbee hub and Home Assistant. Recently I encountered a problem when trying to set both the brightness and the color temperature in a Home Assistant service call (light.turn_on). Apparently, the Tradfri bulbs only respond to one of these values at a time. This is unfortunate as changing the temperature and brightness is usually linked. For example, setting the lights to a dimmed warm setting at night or bright white in the morning. Luckily, there is a workaround to be able to set both simultaneously (sort of at least).

The solution to setting brightness and color temp on Tradfri lights is to split the single service call in to two and let those blend. In my setup, I first set the brightness of the lights with a small transition and use a second call to change the color temperature with a longer transition. I have tested multiple setups and this method results in the smoothest transition. In essence my workaround performs three steps:

  1. Turn on the light with the target brightness.
  2. Delay for a second to make sure that the previous call has finished.
  3. Set the color temperature of the light with a short transition (5 seconds).

By putting these steps in to a script it can act as a drop-in replacement of a normal light call. If one of the settings was already set earlier, for example the brightness did not change, the transition is even smoother.

I have created two versions of this workaround, one for Home Assistant (YAML) and one for Node-RED, to help others that encounter this problem. It is not the most elegant solution but in practice it works pretty good!

Home Assistant script

To use the workaround in Home Assistant (yaml) add the following snippet to scripts.yaml:

turn_on_ikea_light:
  sequence:
    # Check whether the light is off (optional)
    - condition: template
      value_template: "{{ is_state(entity, 'off') }}"
    - delay: '00:00:01'
    # Set the brightness of the lights.
    - service: light.turn_on
      data_template:
        entity_id: "{{ entity }}"
        brightness_pct: "{{ brightness_pct }}"
        transition: 1
    - delay: '00:00:01'
    # Set the color temperature.
    - service: light.turn_on
      data_template:
        entity_id: "{{ entity }}"
        color_temp: "{{ color_temp }}"
        transition: 5

This block of code adds a new script turn_on_ikea_light that can be called inside automations. entity, brightness_pct and color_temp are variables that can be set when calling the script. An example is the following automation where a light is turned on when a motion sensor registers movement:

# Example automation using the script
automation:
  - alias: Turn on lights on movement
    trigger:
      - platform: state
        entity_id: sensor.motion_sensor
        to: 'on'
    action:
      service: script.turn_on_ikea_light
      data_template:
        # Variables that are passed on to the script:
        entity: light.some_light_entity
        brightness_pct: 80
        color_temp: 350

Node-RED script

I’ve recently switched most of my automations to Node-RED so also rewrote my workaround. In Node-RED we need two service calls to HA (one for brightness and one for color temp). In the most simple case this can be done with two “call service” nodes and a delay node. To be able to reuse the flow this can be created as a subflow:

Subflow to set brightness and color temperature on Ikea lights.
Subflow to set brightness and color temperature on Ikea lights.

The subflow shown above expects a JSON message as the msg.payload. The payload is then split in to the two service calls. For example, to set the temperature of a light to 150 and the brightness to 100%, one could send the following payload:

{
    "entity_id": "light.some_light_entity",
    "color_temp": 150,
    "brightness_pct":100
}

The values can be hard coded in a change-node or can be dynamically set (for example based on the time of day).

Complete flow in Node-RED. Replace the inject node with something useful, e.g. a motion event.
Complete flow in Node-RED. Replace the inject node with something useful, e.g. a motion event.

The nodes of the subflow can be imported using the following snippet:

[{"id":"13593ff8.a6556","type":"api-call-service","z":"2dc416a2.d3b6fa","name":"Turn on lights","server":"161bb087.35566f","service_domain":"light","service":"turn_on","data":"{\"entity_id\":\"light.some_entity\",\"transition\":1}","render_data":false,"mergecontext":"","output_location":"payload","output_location_type":"msg","x":700,"y":480,"wires":[[]]},{"id":"7167f74f.dd6528","type":"api-call-service","z":"2dc416a2.d3b6fa","name":"Set color temp","server":"161bb087.35566f","service_domain":"light","service":"turn_on","data":"{\"transition\":5}","render_data":false,"mergecontext":"","output_location":"payload","output_location_type":"msg","x":840,"y":420,"wires":[[]]},{"id":"96a91d65.7a1a4","type":"delay","z":"2dc416a2.d3b6fa","name":"","pauseType":"delay","timeout":"1","timeoutUnits":"seconds","rate":"1","nbRateUnits":"1","rateUnits":"second","randomFirst":"1","randomLast":"5","randomUnits":"seconds","drop":false,"x":680,"y":420,"wires":[["7167f74f.dd6528"]]},{"id":"b76ccf31.5d0c","type":"function","z":"2dc416a2.d3b6fa","name":"Split payload","func":"br = {\n    payload: {\n        data: {\n            entity_id: msg.payload.entity_id,\n            brightness_pct: msg.payload.brightness_pct\n        }\n    }\n}\n\nwarmth = {\n    payload: {\n        data: {\n            entity_id: msg.payload.entity_id,\n            color_temp: msg.payload.color_temp\n        }\n    }\n}\n\nreturn [warmth, br]\n","outputs":2,"noerr":0,"x":490,"y":440,"wires":[["96a91d65.7a1a4"],["13593ff8.a6556"]]},{"id":"161bb087.35566f","type":"server","z":"","name":"Home Assistant"}]

Comments (24)

F F3rn4nd0 g3s3

Hi,

and how set for a ikea color bulg (004.086.12) ?

:-)

Thanks for your time and share!

Best regards

Fernando.

W Wouter Bulten

Hi Fernando, you can use the same approach. Just replace color_temp with the color you want (for example rgb_color).

J Johannes Fornander

Thanks for sharing. I copied your Node-RED script with split payload. Where do insert the code for temp and brightness? Under each "call service" or under the "split payload"?

W Wouter Bulten

Hi! The json message needs to be sent as the msg.payload. If you want it dynamic as in the example above (so that the splitting works), you will need to set it before you send the message to the subflow. It wil then be split inside the subflow and forwarded to the two service calls.

N nicolas ganz

Thanks for this post - I am in the process of switching my 15 Tradfri bulbs to Hassio/Node red and was going crazy about the fact that i can only change one variable at a time! However i am completely new to node red an jso: I have imported you snipplet and set up an inject to with the given msg.payload. Upon importing it updatet the call service nodes to a new version that apparently handles entity_id differently. Now I dont get where i should specify the entity_id? Whatever i do the "call service" nodes in the subflow will just say "no connection".

N nicolas ganz

[SOLVED]: Actually this workes out of the box. The entity_id needs to be specified just in the msg.payload (replacing the "light.some_light_entity"). What had the sub-flow failing was that when importing the snipplet it also created a new Home Assistant server with Woulters settings and was trying to send the call_service to that server instead of mine! I had to switch back to my own server in the two call_service nodes and now this is working like a charm! (No idea how to get rid of the "new server" however - since i desperately imported the snipplet about 10 times I now have the according number of servers in the list, all called "Home Assistant")

W Wouter Bulten

Hi Nicolas, good to hear that you solved it! Good to know that this happend to you, maybe I can change the snippet to prevent this. You can remove old connection in the Node RED settings.

B Bram
Thanks for the script Wouter. I'm trying to turn on two lights with the script when there is motion detect but only one turns on. Any idea what could be causing this. This is how i defined the action of my automation: action: - service: script.turn_on_ikea_light data: brightness_pct: 50 color_temp: 365 entity: light.color_temperature_light_5 - service: script.turn_on_ikea_light data: brightness_pct: 50 color_temp: 365 entity: light.color_temperature_light_6
W Wouter Bulten
Hi Bram, I'm not sure why you have this problem. Does the script work for both lights separately? You could try calling the script with a group instead of separate entities. Regards, Wouter
B Bram
Calling the script using a deCONZ light group made it work. Thanks!
M mitswan
I know this is old but FWIW I managed to solve this issue by updating the Scene config (via the Deconz API) every 5 mins. This works because the 'Zigbee Scene' is stored inside the globes. The following adjusts the white balance into sunset with a special late night mode to help preserve your night vision: ``` from requests import post, get, put from datetime import datetime, timedelta import json deconzkey = '' hassauth = { "Authorization": "Bearer ", "content-type": "application/json", } sceneid = '2' mins_transition = 60 noon_xyb = [0.324, 0.329, 254] dusk_xyb = [0.501, 0.39 , 254] late_xyb = [0.461, 0.306, 35 ] response = get('http://deconz/api/{}/groups/5/scenes/{}'.format(deconzkey,sceneid)) scene = json.loads(response.text) response = get('http://homeassistant:8123/api/states',headers=hassauth) states = json.loads(response.text) sun = [x for x in states if x['entity_id'] == 'sun.sun'][0] tzoffset = datetime.now() - datetime.utcnow() now = datetime.now() sunset = datetime.fromisoformat(sun['attributes']['next_dusk']) + tzoffset sunset = sunset.replace(day=now.day,month=now.month,year=now.year,tzinfo=None) blend = min(max((sunset - now).total_seconds() / 60,0),mins_transition) / mins_transition if now.hour <= 5: xyb = late_xyb else: xyb = [noon_xyb[i]*blend + dusk_xyb[i]*(1-blend) for i in range(3)] for light in scene['lights']: url = 'http://deconz/api/{}/groups/5/scenes/{}/lights/{}/state'.format(deconzkey,sceneid,light['id']) response = put(url, data=json.dumps({"xy":[xyb[0],xyb[1]],"bri":xyb[2]})) ``` This could be adapted to accept color and brightness - create a quick scene and immediately switch to it.
W Wouter Bulten
Hi Mitswan, Thanks for the elaborate comment! Interesting approach :) If I understand your code, you request the scene to get the lights and then update the scene for the individual lights? Do you need to do the PUT request for every light? Couldn't you update the scene itself? Regards, Wouter
T Timo Reiß
Hello everyone, i am new to home assistant. I would like to know if it is possible to change the color temp stepless?
W Wouter Bulten
Hi Timo, You mean you want to transition the color temp? That should already happen due to the 'transition.' If not, let me know what you mean with 'stepless' and I'll see if I can help.
T Timo Reiß
Thanks für you answer, As far as i know, in the app its only possible to set 3 different color temps. -cold -mid -warm Is it possible to set costum colot temps? for example something between Cold and mid?
W Wouter Bulten
You can set the `color_temp` any value you want, see the [light](https://www.home-assistant.io/integrations/light/) page on the HA website. It's in mireds. If I recall correctly, valid values are between 153 and 500. You can also set it using the `kelvin` parameter if you prefer to define the color temperature in Kelvins.
M Martin Bergman
Hi Wouter, Thank you for your script! However I couldn't get it to set temperature of my IKEA trådfri groups (i.e. "rooms"in the trådfri app). It will just adjust brightness in sync, but never color. entity: light.living_room #group/room created in trådfri app - only contains bulbs that can do color-temp and brightness color_temp: 333 # swap between 333 and 454 - nothing happens brightness_pct: 100 #swap between 1 and 100 - always updates in sync Do you have a suggestion of what to look at?
W Wouter Bulten
Hi! Unfortunately, I don't use the Ikea app/hub but instead use Deconz with a Conbee Zigbee router. So I'm not sure if the room thing from the Tradfri app works differently. Technically, this script does nothing more than sending two calls shortly after one another. Are you able to update the color temp using a service call in HA? If not, then it's not related to the script, but something related to the grouping/lights.
E Ernst-Jan Kromhout
Hi Wouter, Wanneer ik dit invul in de automation, en hem wil saven krijg ik op color_temp een fout melding. type: turn_on device_id: f5c3559faa9eecfe4c975bcf70fbf914 entity_id: light.0xbc33acfffea07865 domain: light brightness_pct: 80 color_temp: 350 Enig idee waar dat ik zou kunnen zitten
W Wouter Bulten
Hi Ernst, kun je misschien de foutmelding delen? Dat is wat makkelijker debuggen.
D Dpbe
The strange thing is: it used to work in the past. Sending a brightness and and temperature call at the same time wasn't a problem until a specific firmware update of the bulbs. I am using the same solution as yours.
W Wouter Bulten
Hi Dpbe, Thanks for the comment! Do you have an error message to share? or was it more of an observation? Regards, Wouter
S Shane
Hey there, "white": does nothing, does anyone know how to trun off the white in NR to use only colour? I can see that using the colour temp brings back white. But cant turn white off?
W Wouter Bulten
Do you mean that you want to disable the purely white LEDs in the bulb? I think the only way to achieve that is by using setting it to a very warm color.

Adding new comments is no longer possible. If you have a question or remark, please reach out via the contact page.

Copyright © 2026 Wouter Bulten

I may not have gone where I intended to go, but I think I have ended up where I needed to be.

— Douglas Adams, The Long Dark Tea-Time of the Soul

Colophon & disclaimer