ZigBee integration with Loxone and ConBee II USB stick

ZigBee integration with Loxone and ConBee II USB stick

You are here:
< Zpět

What it is?

This is full ZigBee gateway integration for Loxone over ConBee II USB stick, RPI and Node-Red using web sockets for Lights and UDP for sensors. Supported ZigBee vendors can be found here https://phoscon.de/en/conbee2/compatible

What it can do?

There will be more things coming when I add them to my home installation. Currently following ZigBee components are tested and fully working:

  • Xiaomi sensors over UDP
    • Multi (temperature and humidity)
    • Door (open/close)
    • Vibration
    • Water (flood)
    • Motion
    • Button
  • Philips HUE over web-sockets
    • White bulb LWB010
    • Color bulb LCT015

In general, any ConBee supported sensor can be integrated using UDP as well as any switch/stateful component can be integrated with web-sockets.

Why do it?

For me the biggest advantage was to move from complex and wifi unreliable underlying network design of Sensor <ZigBee> Xiaomi GW <wifi> Wemos D1 <wifi> Loxone <eth> which in combination of HUE on Zigbee -> Hue Bridge <wifi> Loxone <eth> sometimes results in missing UDP packet. Now there is only Ethernet connected RPI doing everything with significantly lower latency.

Get rid of Xiaomi GW, get rid of Wemos, get rid of HUE Bridge, never buy any other bridge and just integrate supported ZigBee devices directly to this setup.

On top motion sensors from Xiaomi are working 100% correctly while sending the moving payload every time without delay like in the case of Xiaomi GW.

And last but not least – it is fun 🙂


What HW will you need?

There is certain hardware you need to buy to be able to use this.


What SW will you need?

Let’s get to the implementation. I will not explain and go deep on how to do UDP virtual inputs in Loxone work, same as for standard Loxone principles or Node-Red because most of it can be easily found on this forum or elsewhere on the internet wikis, articles and community forums.

As I am an extreme rookie coder my Node-Red flows are sometimes stupid and too simple 🙂 Especially functions for sensors can be converted to sub-flows and automated using object variable of source node’s name to avoid manual variable input within the nodes themselves.

I was not able to combine Humi+Temp+Battery information into a single UDP message and send it to Loxone, because of multiple problems (most of them probably by my “not knowing” javascript). So please excuse so many “same” functions.

In the case of Philips HUE, I already got better and the integration is done via subflow which is nicer, but I have no time now to rewrite the sensor part as well. Also, there are people waiting for this manual 🙂


1. Setting up RPI

Plug-in the USB stick (using the extension cable to avoid interference especially when pairing bulbs)  to the RPI and go to http:\\ip_rpi, Phoscon APP should be already running and listening on TCP80 as a web server. Go through the initial configuration

Go to Settings and check you have latest FW

Right now the RPI and USB stick are ready to start pairing devices.


2. ZigBee device pairing in Phoscon web app

The pairing process is very different for difference ZigBee devices as well as their vendors. Good thing is that Phoscon runs as a web server so you can go with your HUE bulb to the USB stick and use your cell phone to start the pairing process 🙂

Let’s break down the Xiaomi devices and Philips HUE bulbs.


in general, you need to reset the device if it is already paired with other ZigBee gateway or Xiaomi MI Hub. This is done using 10s hold of the pairing button, after release the Xiaomi HUB says something like “blablabla” which means the device has been unpaired and is ready to pair with another gateway.

  1. Reset Zigbee device
  2. Go to Phoscon->Sensors->Add New Sensor->Other
  3. Press and hold the pairing button on the Zigbee device for approx. 3 sec, release (blue diode blinks) and change the state (motion, door sensor, change of temp/humi)
  4. Wait 1-3 sec and Phoscon app should go green with Pairing Done

Philips HUE

Unfortunately how Xiaomi is easy HUE is not that nice and honestly speaking after pair white and color bulb I am still not sure how it is done 🙂

  1. Reset the BULB. This is already a hard task because you need to have the HUE Dimmer otherwise it is not that easy 🙂 hold ON+OFF together on the remote as close as possible to bulb for 10 seconds. BULB blinks twice, keep holding and go back to the original light. Power cycle the bulb. Bulb SHOULD BE now reset
  2. Go to Phoscon->Lights->Add Light
  3. Now comes the magic
    1. Power Cycle the bulb
    2. Reset the bulb again
    3. 1. again
    4. 2.again
    5. repeat “somehow” until the bulb is detected, always wait for approx 5-10s
    6. sooner or later bulb appears in the Phoscon
  4. rename, done

Ikea, Osram, etc

Come later when I buy them/try them 🙂


3. Deconz contrib as a bridge between Phoscon and NodeRed

Node-Red integration with all the above mentioned contribs works as following:

DeconZ contrib has WebSocket connection towards Phoscon and listening for changes on ZigBee devices. this is done via the Deconz-IN NODE, selected device and selected payload to be sent to the next flow.

DeconZ connection towards the Phoscon is authenticated via the API key, which needs to be generated in Phoscon. There is a documented procedure on DeconZ github, however I had to do it manually using CURL POST command according to the documentation because the “Magic” button in Node-Red does not work. Please see https://dresden-elektronik.github.io/deconz-rest-doc/configuration/ and follow the manual

When you have the API key create new connection in your 1st NODE, I had to install another Node Red instance on same RPI as the Phoscon (that is why IP is the loopback), because running the DeconZ contrib on Loxberry located Node Red instance I was not able to put the web socket connection between NR<>Phoscon to work.

Correctly connected NODE results in a list of available devices, select payload based on what you want to monitor and you are all set


4. Loxone and Sensors over UDP

Set up a virtual UDP input in Loxone (follow any UDP related manual for Loxone). The principle is exactly the same as here https://www.vodnici.net/2019/02/zigbee2mqtt-nodered-a-loxone/ only the source of the UDP message will be different.

Every sensor and every payload type has to have its own Deconz-IN NODE which then passes the function and is send to Loxone over UDP.

In Loxone UDP virtual input is create on the same UDP port as the Node Red UDP OUT NODE and command detection is set according to msg.payload coming from the function for each and every NODE.

Here is the complete Node Red flow:

[{"id":"91feccf8.c1b43","type":"tab","label":"Wiki","disabled":false,"info":""},{"id":"79b42ace.b5d094","type":"deconz-input","z":"91feccf8.c1b43","name":"SKLEP-temp","server":"98ad42dd.bf8fa","device":"00:15:8d:00:01:f2:aa:ee-01-0402","device_name":"MS - SKLEP : ZHATemperature","state":"temperature","output":"always","outputAtStartup":true,"x":130,"y":80,"wires":[["4a5b4a0a.37e0c4"],[]]},{"id":"32f1f979.ee1426","type":"deconz-input","z":"91feccf8.c1b43","name":"SKLEP-humi","server":"98ad42dd.bf8fa","device":"00:15:8d:00:01:f2:aa:ee-01-0405","device_name":"Multi Sensor - SKLEP : ZHAHumidity","state":"humidity","output":"always","outputAtStartup":true,"x":130,"y":120,"wires":[["8a91e089.0b19e"],[]]},{"id":"41f30e16.2bfd","type":"deconz-battery","z":"91feccf8.c1b43","name":"SKLEP-bat","server":"98ad42dd.bf8fa","device":"00:15:8d:00:01:f2:aa:ee-01-0405","device_name":"Multi Sensor - SKLEP : ZHAHumidity","outputAtStartup":true,"x":120,"y":160,"wires":[[],["ca1a6b72.6730a8"]]},{"id":"ca1a6b72.6730a8","type":"function","z":"91feccf8.c1b43","name":"Bat2Lox","func":"var name=\"Sklep\"\nmsg.payload=name+\"-Batt \" + msg.payload.BatteryLevel;\nreturn msg;","outputs":1,"noerr":0,"x":260,"y":160,"wires":[["8480181f.4df158"]]},{"id":"8480181f.4df158","type":"udp out","z":"91feccf8.c1b43","name":"UDP2Loxone 55556 Conbee","addr":"loxone_IP","iface":"","port":"55556","ipv":"udp4","outport":"","base64":false,"multicast":"false","x":520,"y":120,"wires":[]},{"id":"4a5b4a0a.37e0c4","type":"function","z":"91feccf8.c1b43","name":"Temp2Lox","func":"var name = \"Sklep\"\nvar cat = \"Temp\"\n\nvar value = (msg.payload/100).toFixed(1);\nmsg.payload=name+cat+\" \" + value;\n\nreturn msg;","outputs":1,"noerr":0,"x":290,"y":80,"wires":[["8480181f.4df158"]]},{"id":"8a91e089.0b19e","type":"function","z":"91feccf8.c1b43","name":"Humi2Lox","func":"var name = \"Sklep\"\nvar cat = \"Humi\"\nvar value = (msg.payload/100).toFixed(1);\n\nmsg.payload=name+cat+\" \" + value;\n\nreturn msg;\n","outputs":1,"noerr":0,"x":280,"y":120,"wires":[["8480181f.4df158"]]},{"id":"3364467a.87f6ba","type":"deconz-input","z":"91feccf8.c1b43","name":"WS1-Sklep","server":"98ad42dd.bf8fa","device":"00:15:8d:00:02:11:b4:b2-01-0500","device_name":"WS1 - Sklep : ZHAWater","state":"water","output":"always","outputAtStartup":true,"x":120,"y":220,"wires":[["8b36df82.ddca6"],[]]},{"id":"cd4684f6.47e3c8","type":"deconz-battery","z":"91feccf8.c1b43","name":"WS1-Sklep-Batt","server":"98ad42dd.bf8fa","device":"00:15:8d:00:02:11:b4:b2-01-0500","device_name":"WS1 - Sklep : ZHAWater","outputAtStartup":true,"x":140,"y":260,"wires":[[],["8744fef3.4541b"]]},{"id":"8744fef3.4541b","type":"function","z":"91feccf8.c1b43","name":"Bat2Lox","func":"var name=\"WS1\"\nmsg.payload=name+\"-Batt \" + msg.payload.BatteryLevel;\nreturn msg;","outputs":1,"noerr":0,"x":320,"y":260,"wires":[["d20825bd.21fd78"]]},{"id":"8b36df82.ddca6","type":"function","z":"91feccf8.c1b43","name":"Water2Lox","func":"var name = \"WS1\";\n\nvar value = msg.payload;\n\nif ( value === false )\n{\nmsg.payload = name+\"-OK\";\nreturn msg;\n} \n\nelse if (value === true) \n{\nmsg.payload = name+\"-FLOOD\";\nreturn msg;\n}","outputs":1,"noerr":0,"x":310,"y":220,"wires":[["d20825bd.21fd78"]]},{"id":"d20825bd.21fd78","type":"udp out","z":"91feccf8.c1b43","name":"UDP2Loxone 55556 Conbee","addr":"loxone_IP","iface":"","port":"55556","ipv":"udp4","outport":"","base64":false,"multicast":"false","x":540,"y":240,"wires":[]},{"id":"a342e55f.2fa4a8","type":"deconz-input","z":"91feccf8.c1b43","name":"MO5","server":"98ad42dd.bf8fa","device":"00:15:8d:00:01:de:03:59-01-0406","device_name":"MO5 : ZHAPresence","state":"presence","output":"onupdate","outputAtStartup":false,"x":110,"y":320,"wires":[["cf724917.b98068"],[]]},{"id":"77bc9016.44412","type":"udp out","z":"91feccf8.c1b43","name":"UDP2Loxone 55556 Conbee","addr":"loxone_IP","iface":"","port":"55556","ipv":"udp4","outport":"","base64":false,"multicast":"false","x":520,"y":340,"wires":[]},{"id":"f9e1ca5a.45c918","type":"deconz-battery","z":"91feccf8.c1b43","name":"MO5-batt","server":"98ad42dd.bf8fa","device":"00:15:8d:00:01:de:03:59-01-0406","device_name":"MO5 : ZHAPresence","outputAtStartup":true,"x":120,"y":360,"wires":[[],["bd57d866.583298"]]},{"id":"bd57d866.583298","type":"function","z":"91feccf8.c1b43","name":"Bat2Lox","func":"var name=\"MO5\"\nmsg.payload=name+\"-Batt \" + msg.payload.BatteryLevel;\nreturn msg;","outputs":1,"noerr":0,"x":300,"y":360,"wires":[["77bc9016.44412"]]},{"id":"cf724917.b98068","type":"function","z":"91feccf8.c1b43","name":"MO2Lox","func":"var name = \"MO5\";\n\nvar value = msg.payload;\n\nif ( value === false )\n{\nmsg.payload = name+\"-OK\";\nreturn msg;\n} \n\nelse if (value === true) \n{\nmsg.payload = name+\"-MOVE\";\nreturn msg;\n}","outputs":1,"noerr":0,"x":310,"y":320,"wires":[["77bc9016.44412"]]},{"id":"f8c334a0.98b8f8","type":"deconz-battery","z":"91feccf8.c1b43","name":"DO1-batt","server":"98ad42dd.bf8fa","device":"00:15:8d:00:01:a2:1a:19-01-0006","device_name":"DO1-Mail : ZHAOpenClose","outputAtStartup":true,"x":120,"y":460,"wires":[[],["f347ade8.daa3d"]]},{"id":"5e5a7655.72f428","type":"deconz-input","z":"91feccf8.c1b43","name":"DO1","server":"98ad42dd.bf8fa","device":"00:15:8d:00:01:a2:1a:19-01-0006","device_name":"DO1-Mail : ZHAOpenClose","state":"open","output":"always","outputAtStartup":true,"x":110,"y":420,"wires":[["92ed2472.10f558"],[]]},{"id":"597b2e00.6afd74","type":"udp out","z":"91feccf8.c1b43","name":"UDP2Loxone 55556 Conbee","addr":"loxone_IP","iface":"","port":"55556","ipv":"udp4","outport":"","base64":false,"multicast":"false","x":500,"y":440,"wires":[]},{"id":"f347ade8.daa3d","type":"function","z":"91feccf8.c1b43","name":"Bat2Lox","func":"var name=\"DO1\"\nmsg.payload=name+\"-Batt \" + msg.payload.BatteryLevel;\nreturn msg;","outputs":1,"noerr":0,"x":280,"y":460,"wires":[["597b2e00.6afd74"]]},{"id":"92ed2472.10f558","type":"function","z":"91feccf8.c1b43","name":"DO2Lox","func":"var name = \"DO1\";\n\nvar value = msg.payload;\n\nif ( value === false )\n{\nmsg.payload = name+\"-close\";\nreturn msg;\n} \n\nelse if (value === true) \n{\nmsg.payload = name+\"-open\";\nreturn msg;\n}","outputs":1,"noerr":0,"x":280,"y":420,"wires":[["597b2e00.6afd74"]]},{"id":"e058f740.fcccf8","type":"deconz-input","z":"91feccf8.c1b43","name":"SW4","server":"98ad42dd.bf8fa","device":"00:15:8d:00:02:24:3c:d3-01-0006","device_name":"SW4 : ZHASwitch","state":"buttonevent","output":"onchange","outputAtStartup":false,"x":110,"y":520,"wires":[["13832d70.e82083"],[]]},{"id":"442659d9.d52588","type":"udp out","z":"91feccf8.c1b43","name":"UDP2Loxone 55556 Conbee","addr":"loxone_IP","iface":"","port":"55556","ipv":"udp4","outport":"","base64":false,"multicast":"false","x":540,"y":540,"wires":[]},{"id":"13832d70.e82083","type":"function","z":"91feccf8.c1b43","name":"Button2Lox","func":"var name = \"SW4\";\n\nvar value = msg.payload;\n\nif ( value == \"1002\" )\n{\nmsg.payload = name+\"-single\";\nreturn msg;\n} \n\nelse if (value == \"1004\") \n{\nmsg.payload = name+\"-double\";\nreturn msg;\n}\n\nelse if (value == \"1001\") \n{\nmsg.payload = name+\"-LP\";\nreturn msg;\n}\n\nelse if (value == \"1003\") \n{\nmsg.payload = name+\"-LR\";\nreturn msg;\n}","outputs":1,"noerr":0,"x":310,"y":520,"wires":[["442659d9.d52588"]]},{"id":"31ad16cc.dee63a","type":"function","z":"91feccf8.c1b43","name":"Bat2Lox","func":"var name=\"SW4\"\nmsg.payload=name+\"-Batt \" + msg.payload.BatteryLevel;\nreturn msg;\n","outputs":1,"noerr":0,"x":300,"y":560,"wires":[["442659d9.d52588"]]},{"id":"3a7a3e31.6daed2","type":"deconz-battery","z":"91feccf8.c1b43","name":"SW4-batt","server":"98ad42dd.bf8fa","device":"00:15:8d:00:02:24:3c:d3-01-0006","device_name":"SW4 : ZHASwitch","outputAtStartup":true,"x":120,"y":560,"wires":[[],["31ad16cc.dee63a"]]},{"id":"dc21844c.364c08","type":"deconz-input","z":"91feccf8.c1b43","name":"VS01","server":"98ad42dd.bf8fa","device":"00:15:8d:00:02:b0:99:85-01-0101","device_name":"Vibration Sensor : ZHAVibration","state":"0","output":"always","outputAtStartup":true,"x":110,"y":620,"wires":[["6cd0d254.aa93ec"],[]]},{"id":"274c1477.57932c","type":"udp out","z":"91feccf8.c1b43","name":"UDP2Loxone 55556 Conbee","addr":"loxone_IP","iface":"","port":"55556","ipv":"udp4","outport":"","base64":false,"multicast":"false","x":510,"y":640,"wires":[]},{"id":"61975736.93de08","type":"function","z":"91feccf8.c1b43","name":"Bat2Lox","func":"var name=\"VS01\"\nmsg.payload=name+\"-Batt \" + msg.payload.BatteryLevel;\nreturn msg;","outputs":1,"noerr":0,"x":280,"y":660,"wires":[["274c1477.57932c"]]},{"id":"6cd0d254.aa93ec","type":"function","z":"91feccf8.c1b43","name":"VS2Lox","func":"var name = \"VS01\";\n\nvar value = msg.payload.vibration;\n\nif ( value === false )\n{\nmsg.payload = name+\"-OK\";\nreturn msg;\n} \n\nelse if (value === true) \n{\nmsg.payload = name+\"-vibration\";\nreturn msg;\n}","outputs":1,"noerr":0,"x":290,"y":620,"wires":[["274c1477.57932c"]]},{"id":"8f0ea705.033b08","type":"deconz-battery","z":"91feccf8.c1b43","name":"VS01-Batt","server":"98ad42dd.bf8fa","device":"00:15:8d:00:02:b0:99:85-01-0101","device_name":"Vibration Sensor : ZHAVibration","outputAtStartup":true,"x":120,"y":660,"wires":[[],["61975736.93de08"]]},{"id":"98ad42dd.bf8fa","type":"deconz-server","z":"","name":"conbee","ip":"IP","port":"80","apikey":"APIKEY","ws_port":"443","secure":false,"polling":"5"}]

You need to change the name in each function block variable which then changes the UDP message towards Loxone.

Messages to detect in Loxone are following for each type:

Battery: Sklep-Batt \v (default values 0,0,100,100), not digital input

Temperature: SklepTemp \v (default values 0,0,100,100), not digital input

Humidity: SklepHumi \v (default values 0,0,100,100), not digital input

Motion: MO3-move, digital input

etc etc etc

After Node Red “deploy button” all message are generated and sent to Loxone, so you can create the inputs as you wish, also with renaming.

The enhancement would be to have only 1 function/sub-flow for everything and do the detection based on the name of the DeconZ source node or even better based on the name of the sensor in Phoscon. However, I have found out this is part of the msg. too late 🙂 So it comes probably later.

Adding of a new sensor requires: pairing, copy/pasting of respective node red nodes, changing devices, changing names, changing functions variable, setting up loxone UDP inputs.

5. Loxone and Philips HUE over web-sockets

Integration of Philips HUE is possible over web-sockets and native LightController function block in Loxone.

  • Set up a new light controller function block v1 or v2 and set the output to RGB

Now we need to make the controller available in Node Red, this is done via https://flows.nodered.org/node/node-red-contrib-loxone and NODE called Controll-IN.

Similarly as in Phoscon you need to establish a new connection towards Loxone, only blocks with enabled visualization will be available and I highly recommend creating dedicated users and group for any external integrations for Loxone.


When you get “got miniserver structure” green message all is OK and continue selecting the function block you created by name and selecting State based on white/color bulb

Configure the DeconZ-OUT NODE with selecting the paired bulb, setting command to object:json and payload in default

Now we have coming HSV string (1st payload) from LoxoneLightController and we have a bulb which requires JSON object in the following format (2nd payload). If you are interested in what it is in deep feel free to follow wiki article – https://en.wikipedia.org/wiki/HSL_and_HSV 🙂

White Bulb is easier as there is only a single integer coming from Loxone which needs to be translated to Brightness within the JSON.

The integration is done using my simple sub-flow located and described here https://flows.nodered.org/flow/e8ccc3a40cde8e169ed528d9bf51de33 this sub-flow detect if data are for white or colored lamp and transforms to HSV into 0-255 Brightness, 0-255 Saturation, 0-65535 Color.

[{"id":"7be55345.48bebc","type":"subflow","name":"Loxone2HUE","info":"","category":"","in":[{"x":380,"y":280,"wires":[{"id":"525c492b.7ab478"}]}],"out":[{"x":900,"y":280,"wires":[{"id":"ebbc239d.76c84","port":0},{"id":"467ba87f.00d8e8","port":0}]}],"env":[],"color":"#DDAA99"},{"id":"ebbc239d.76c84","type":"function","z":"7be55345.48bebc","name":"COLOR","func":"msg.payload = msg.payload.replace(\"hsv(\", \"\").replace(\")\", \"\").split(\",\");\n\nvar hue = Number(msg.payload[0]) * 65500 / 360;\nvar sat = Number(msg.payload[1]) * 255 /100;\nvar bri = Number(msg.payload[2]) * 255 /100 ;\nvar time = 5; \n\nif (bri == '0') {\n  return { payload: { on: false } };\n}\n\nmsg.payload = {\"on\":true,\"bri\":bri,\"hue\":hue,\"sat\":sat,\"transitiontime\":time};\nreturn msg;","outputs":1,"noerr":0,"x":740,"y":220,"wires":[[]]},{"id":"525c492b.7ab478","type":"switch","z":"7be55345.48bebc","name":"White or Color","property":"payload","propertyType":"msg","rules":[{"t":"cont","v":"hsv(","vt":"str"},{"t":"else"}],"checkall":"true","repair":false,"outputs":2,"x":560,"y":280,"wires":[["ebbc239d.76c84"],["467ba87f.00d8e8"]]},{"id":"467ba87f.00d8e8","type":"function","z":"7be55345.48bebc","name":"WHITE","func":"var bri = msg.payload * 255 /100 ;\nvar time = 5;\n\nif (bri == '0') {\n  return { payload: { on: false } };\n}\n\nmsg.payload = {\"on\":true,\"bri\":bri,\"transitiontime\":time};\nreturn msg;","outputs":1,"noerr":0,"x":740,"y":340,"wires":[[]]}]

Complete flow is not needed I believe as the only part for the function is available on GIT, rest is anyway case-specific and cant is used, as configuration NODEs for both Loxone and DeconZ will need to have your own configurations (IP, API, TOKEN, USER, PASSWORD,…).

I will try to add more as I integrate more

Have fun and let me know! Here in Czech/English!


Pomohl Vám náš blog? Chcete nás podpořit? I málo udělá radost 😉
Table of Contents

11 thoughts on “ZigBee integration with Loxone and ConBee II USB stick

  1. Hi question, how does it work in loxone with a window open close sensor?

    I see both the messages for open and close in udp log, but i don’t now what to do with them.

    1. Hi,
      1st options is to take functional block Windows/Door sensor and point Virtual IN to its O/R for Open/Close -> I am using this for all of my current sensor based on historical reason.

      Maybe if I do it now from scratch I would think about using loxone websockets and do the mapping directly in nodered to avoid the UDP traffic – this was not possible in case of xiaomy GW from which I moved to this solution while not having enough time for improving the concept/design.


    1. yes, if I understood your question correctly 🙂 with this integeration all zigbee lights are working as native light in Loxone

  2. Hey Jakub
    Thank you very much for the great recipe to connect the Xiaomi equipment, it works perfect! I to have one question with the magic cube. Did you implement any of these as well? I do get connection but I don’t get it operational when i turn the cube.
    Kind regards

    1. Hi,
      by magic cube you mean the standard Xiaomi cube?
      I had it implemented with xiaomi GWloxone bridge. Not over NoreRed, but it should be just the same -> just a different payload.


Leave a Reply

Your email address will not be published. Required fields are marked *