Node-RED subflow for IKEA Tradfri dimmer using Zigbee2MQTT

image image image

Consider using Zigbee2MQTT binding before using this Node-Red flow (and probably only use this if your devices doesn’t support binding)

This is mostly about re-sharing the great work of NotEnoughTech (IKEA TRADFRI Wireless dimmer in NodeRED - NotEnoughTech), and also about some minor tweaks I did to:

  • Make it work with the latest versions of software and/or hardware.
    • Payload and button events did not work
  • Be able to use it as a subflow with multiple lamps and remotes.
    • Replaced hardcoded light and remote with subflow environment variables.

Here is how to use it:

And here is how the subflow looks:


And the code:

[{"id":"e5817ab55eab8ab8","type":"subflow","name":"Subflow: IKEA Light Dimmer","info":"","category":"","in":[],"out":[],"env":[{"name":"lightEntity","type":"str","value":""},{"name":"remoteEntity","type":"env","value":"NR_NODE_NAME"},{"name":"dimmerStep","type":"num","value":"15"},{"name":"lightTopic","type":"env","value":"zigbee2mqtt/${lightEntity}","ui":{"type":"hide"}},{"name":"remoteTopic","type":"env","value":"zigbee2mqtt/${remoteEntity}","ui":{"type":"hide"}},{"name":"lightTopicGet","type":"env","value":"${lightTopic}/get","ui":{"type":"hide"}},{"name":"lightTopicSet","type":"env","value":"${lightTopic}/set","ui":{"type":"hide"}}],"meta":{},"color":"#DDAA99"},{"id":"c786b38d.959c2","type":"switch","z":"e5817ab55eab8ab8","name":"Messages","property":"payload.action","propertyType":"msg","rules":[{"t":"eq","v":"on","vt":"str"},{"t":"eq","v":"off","vt":"str"},{"t":"eq","v":"brightness_stop","vt":"str"},{"t":"eq","v":"brightness_move_up","vt":"str"},{"t":"eq","v":"brightness_move_down","vt":"str"}],"checkall":"true","repair":false,"outputs":5,"x":410,"y":340,"wires":[["e6af827.9be108"],["d39b4454.a0cc78"],["d9fd37b3.5511c8"],["dc0cf8a0.604028","359b8cf5.78b704"],["cebc76c0.d58538","359b8cf5.78b704"]]},{"id":"dc0cf8a0.604028","type":"function","z":"e5817ab55eab8ab8","name":"Brightness up","func":"var step = Number.parseInt(env.get('dimmerStep'));\nvar brightness =  flow.get(\"IKEA_bulb1_brightness\");\n\nif(brightness > 0){\n    brightness = brightness + step;\n    flow.set(\"IKEA_bulb1_brightness\", brightness);\n\t}\n\t\nif(brightness >= 255){\n    brightness = 254;\n    flow.set('press', false);\n    flow.set(\"IKEA_bulb1_brightness\", brightness);\n    }\n\nmsg.payload = {\"state\":\"ON\",\n               \"brightness\":brightness};\nreturn msg;","outputs":1,"noerr":0,"initialize":"","finalize":"","libs":[],"x":600,"y":580,"wires":[["aab4e92d.c91e28","51644345.67539c"]]},{"id":"cebc76c0.d58538","type":"function","z":"e5817ab55eab8ab8","name":"Brightness down","func":"var step = Number.parseInt(env.get('dimmerStep'));\nvar brightness =  flow.get(\"IKEA_bulb1_brightness\");\n\nif(brightness <= 255){\n    brightness = brightness - step; \n    flow.set(\"IKEA_bulb1_brightness\", brightness);\n\t}\n\t\nif(brightness <= 0){\n    brightness = 1;\n    flow.set('press', false);\n    flow.set(\"IKEA_bulb1_brightness\", brightness);\n    }\n\nmsg.payload = {\"state\":\"ON\",\n               \"brightness\":brightness};\nreturn msg;","outputs":1,"noerr":0,"initialize":"","finalize":"","libs":[],"x":600,"y":620,"wires":[["aab4e92d.c91e28","bf17a32.3347d6"]]},{"id":"b132cd47.5361c","type":"switch","z":"e5817ab55eab8ab8","name":"Control loop","property":"press","propertyType":"flow","rules":[{"t":"true"}],"checkall":"true","repair":false,"outputs":1,"x":970,"y":760,"wires":[["cebc76c0.d58538"]]},{"id":"420aac7b.c64574","type":"switch","z":"e5817ab55eab8ab8","name":"Control loop","property":"press","propertyType":"flow","rules":[{"t":"true"}],"checkall":"true","repair":false,"outputs":1,"x":970,"y":800,"wires":[["dc0cf8a0.604028"]]},{"id":"51644345.67539c","type":"delay","z":"e5817ab55eab8ab8","name":"","pauseType":"delay","timeout":"1000","timeoutUnits":"milliseconds","rate":"1","nbRateUnits":"1","rateUnits":"second","randomFirst":"1","randomLast":"5","randomUnits":"seconds","drop":false,"allowrate":false,"outputs":1,"x":680,"y":800,"wires":[["420aac7b.c64574"]]},{"id":"bf17a32.3347d6","type":"delay","z":"e5817ab55eab8ab8","name":"","pauseType":"delay","timeout":"1000","timeoutUnits":"milliseconds","rate":"1","nbRateUnits":"1","rateUnits":"second","randomFirst":"1","randomLast":"5","randomUnits":"seconds","drop":false,"allowrate":false,"outputs":1,"x":680,"y":760,"wires":[["b132cd47.5361c"]]},{"id":"359b8cf5.78b704","type":"change","z":"e5817ab55eab8ab8","name":"start","rules":[{"t":"set","p":"payload","pt":"msg","to":"true","tot":"bool"}],"action":"","property":"","from":"","to":"","reg":false,"x":650,"y":380,"wires":[["30695df.bdaa9a2"]]},{"id":"d9fd37b3.5511c8","type":"change","z":"e5817ab55eab8ab8","name":"stop","rules":[{"t":"set","p":"payload","pt":"msg","to":"false","tot":"bool"}],"action":"","property":"","from":"","to":"","reg":false,"x":650,"y":420,"wires":[["30695df.bdaa9a2"]]},{"id":"30695df.bdaa9a2","type":"change","z":"e5817ab55eab8ab8","name":"Control the loop","rules":[{"t":"set","p":"press","pt":"flow","to":"payload","tot":"msg"}],"action":"","property":"","from":"","to":"","reg":false,"x":830,"y":395,"wires":[[]]},{"id":"da10d307.eded8","type":"mqtt in","z":"e5817ab55eab8ab8","name":"IKEA Light","topic":"${lightTopic}","qos":"2","datatype":"json","broker":"eca6af44.5297b","nl":false,"rap":false,"inputs":0,"x":220,"y":200,"wires":[["8a13f8be.ca9058"]]},{"id":"aab4e92d.c91e28","type":"mqtt out","z":"e5817ab55eab8ab8","name":"IKEA Light Control","topic":"${lightTopicSet}","qos":"","retain":"","respTopic":"","contentType":"","userProps":"","correl":"","expiry":"","broker":"eca6af44.5297b","x":1050,"y":280,"wires":[]},{"id":"394c130c.943f4c","type":"mqtt out","z":"e5817ab55eab8ab8","name":"IKEA Light Status","topic":"${lightTopicGet}","qos":"","retain":"","respTopic":"","contentType":"","userProps":"","correl":"","expiry":"","broker":"eca6af44.5297b","x":570,"y":140,"wires":[]},{"id":"e79a3c52.ae408","type":"inject","z":"e5817ab55eab8ab8","name":"","repeat":"","crontab":"","once":false,"onceDelay":0.1,"topic":"","payload":"{\"state\":\"\"}","payloadType":"json","x":240,"y":140,"wires":[["394c130c.943f4c"]]},{"id":"e6af827.9be108","type":"function","z":"e5817ab55eab8ab8","name":"ON","func":"msg.payload = { \"state\":\"ON\"};\nreturn msg;","outputs":1,"noerr":0,"initialize":"","finalize":"","libs":[],"x":650,"y":280,"wires":[["aab4e92d.c91e28"]]},{"id":"d39b4454.a0cc78","type":"function","z":"e5817ab55eab8ab8","name":"OFF","func":"msg.payload = { \"state\":\"OFF\"};\nreturn msg;","outputs":1,"noerr":0,"initialize":"","finalize":"","libs":[],"x":650,"y":320,"wires":[["aab4e92d.c91e28"]]},{"id":"8a13f8be.ca9058","type":"delay","z":"e5817ab55eab8ab8","name":"","pauseType":"rate","timeout":"5","timeoutUnits":"seconds","rate":"1","nbRateUnits":"1","rateUnits":"second","randomFirst":"1","randomLast":"5","randomUnits":"seconds","drop":true,"outputs":1,"x":490,"y":200,"wires":[["523a3a9a.7d63f4"]]},{"id":"523a3a9a.7d63f4","type":"function","z":"e5817ab55eab8ab8","name":"Update","func":"\nflow.set(\"IKEA_bulb1_brightness\", msg.payload.brightness);\n\nreturn msg;","outputs":1,"noerr":0,"initialize":"","finalize":"","libs":[],"x":660,"y":200,"wires":[[]]},{"id":"c10f24b5.2fcc78","type":"mqtt in","z":"e5817ab55eab8ab8","name":"IKEA Button","topic":"${remoteTopic}","qos":"1","datatype":"json","broker":"eca6af44.5297b","nl":false,"rap":false,"inputs":0,"x":190,"y":340,"wires":[["c786b38d.959c2"]]},{"id":"1da55aa957bc76db","type":"delay","z":"e5817ab55eab8ab8","name":"","pauseType":"rate","timeout":"5","timeoutUnits":"seconds","rate":"1","nbRateUnits":"1","rateUnits":"second","randomFirst":"1","randomLast":"5","randomUnits":"seconds","drop":true,"outputs":1,"x":890,"y":160,"wires":[[]]},{"id":"eca6af44.5297b","type":"mqtt-broker","name":"MQTT","broker":"192.168.50.94","port":"1883","clientid":"","autoConnect":true,"usetls":false,"protocolVersion":"4","keepalive":"60","cleansession":true,"birthTopic":"","birthQos":"0","birthPayload":"","birthMsg":{},"closeTopic":"","closeQos":"0","closePayload":"","closeMsg":{},"willTopic":"","willQos":"0","willPayload":"","willMsg":{},"userProps":"","sessionExpiry":""}]

Praise (and coffee)? Go to the link above!

If you like my tweaks?
BMC

I use the previous version and I added a function that toggles the light between highest and lowest setting when pressing ON while the light is already ON.

Just add a “current state” before the ON and redirect to this script if it is already ON:

var brightness =  flow.get("IKEA_bulb1_brightness");

if(brightness < 254){
    brightness = 254;
	}
	
else{
    brightness = 2;
    //flow.set('press', false);
    }

    flow.set("IKEA_bulb1_brightness", brightness);
msg.payload = {"state":"ON",
               "brightness":brightness};
return msg;

Nice! This I will use :slightly_smiling_face: I’ll update the first post later

I just learned yesterday that you can bind the remote directly to the lamp with Zigbee2MQTT.
So you should consider that instead, and only go this route if your devices doesn’t support binding.