Background
Zigbee2mqtt is an opensource zigbee-mqtt-bridge solution which utilizes cheap hardware in order to bypass commercial gateways to communicate using the Zigbee protocol. It operates using mqtt (a message broker) making it suitable for IOT platforms.
I have recently bought some cheap and simple IKEA Trådfri bulbs as well as some Philips Hue white bulbs and I have not seen any complete solutions for the new Openhab2 mqtt binding. I’ll share some info about it here. Mostly I have take bits and pieces from other topics.
Pre-requisits
- zigbee2mqtt up and running with working Zigbee sniffer (ie CC2531 or similar)
- Trådfri bulbs which are included in the zigbee network (they can be a pain to include, for me 6 very short ons and longer offs made it possible to reset them)
- Philips HUE white bulbs (I’ve used the regular cheap HUE White which you should be able to get for 6-7$ a piece.)
To set zigbee2mqtt up see: https://www.zigbee2mqtt.io/
For Openhab you will need to have the following addons installed:
action: mqtt-action
bindings: mqtt (the version 2), expire (optional)
transformation: jsonpath, javascript
I’m running on Openhab 2.5.0-M1, the 2.4 version has some bugs when it comes to MQTT, so I recommend the 2.5.0-M1.
You need to create an mqtt broker using Paper UI. You can run the mqtt “server” on either your openhab instance or as in my case I run it on a different server.
Things:
Add a file called zigbee2mqtt.things
Bridge mqtt:broker:mymqttbroker [ host="mymqttbrokeripaddr", secure=false ]
{
Thing topic zigbeebridge "Zigbee2mqtt Bridge" {
Channels:
Type switch : permitJoin [ commandTopic="zigbee2mqtt/bridge/config/permit_join", on="true", off="false" ]
Type string : state [ stateTopic="zigbee2mqtt/bridge/state" ]
Type string : logType [ stateTopic="zigbee2mqtt/bridge/log", transformationPattern="JSONPATH:$.type" ]
Type string : logMessage [ stateTopic="zigbee2mqtt/bridge/log", transformationPattern="JSONPATH:$.message" ]
}
Thing topic ikeabulb01 "IKEA Bulb 01" {
Channels:
Type switch : switch "Ikea Bulb 01 Switch" [ stateTopic="zigbee2mqtt/ikeabulb01", commandTopic="zigbee2mqtt/ikeabulb01/set", transformationPattern="JSONPATH:$.state", transformationPatternOut="JS:switch2Zigbee2mqtt.js"]
Type dimmer : dimmer "Ikea Bulb 01 Dimmer" [ stateTopic="zigbee2mqtt/ikeabulb01", commandTopic="zigbee2mqtt/ikeabulb01/set", min=0, max=100, step=1, transformationPatternOut="JS:openhabdimmer2zigbeebridge.js", transformationPattern="JS:tradfri2openhab.js" ]
Type number : linkquality "Ikea Bulb 01 LinkQuality" [ stateTopic="zigbee2mqtt/ikeabulb01", transformationPattern="JSONPATH:$.linkquality" ]
}
Thing topic huewhite02 "Philips HUE White 02" {
Channels:
Type switch : switch "Hue White 02 Switch" [ stateTopic="zigbee2mqtt/huewhite02", commandTopic="zigbee2mqtt/huewhite02/set", transformationPattern="JSONPATH:$.state", transformationPatternOut="JS:switch2Zigbee2mqtt.js"]
Type dimmer : dimmer "Hue White 02 Dimmer" [ stateTopic="zigbee2mqtt/huewhite02", commandTopic="zigbee2mqtt/huewhite02/set", min=0, max=100, step=1, transformationPatternOut="JS:openhabdimmer2zigbeebridge.js", transformationPattern="JS:huewhite2openhab.js" ]
Type number : linkquality "Hue White 02 LinkQuality" [ stateTopic="zigbee2mqtt/huewhite02", transformationPattern="JSONPATH:$.linkquality" ]
}
}
Under transformation add a file called switch2zigbee2mqtt
(function(x) {
var result = "";
if (x == '1' || x == 'ON') {
result="{ \"state\": \"ON\" }";
} else {
result="{ \"state\": \"OFF\" }";
}
return result;
})(input)
A file called: huewhite2openhab.js
(function(x) {
var result;
var json = JSON.parse(x);
if (json.state == 'OFF') {
return 0;
}
if (json.brightness >= 254) {
return 100;
}
// If brightnes is 0 or 1 it is off from my experiments
if (json.brightness <= 1) {
return 0;
}
result = Math.round(((json.brightness / 255) * 100));
return result;
})(input)
A file called: tradfri2openhab.js
(function(x) {
var result;
var json = JSON.parse(x);
if (json.state == 'OFF') {
return 0;
}
if (json.brightness == 254) {
return 100;
}
result = Math.round(((json.brightness / 255) * 100));
return result;
})(input)
A file called: openhabdimmer2zigbeebridge.js
(function(i) {
return input == 0
? "{ \"state\":\"OFF\" }"
: "{ \"state\":\"ON\" , \"brightness_percent\": " + input + " }";
})(input)
An items file called zigbee2mqtt.items (this is just an example)
Group Zigbee
Group ZigbeeBridge "Zigbee2mqtt Bridge" (Zigbee)
String ZigbeeBridgeState "Zigbee2mqtt Bridge State" (ZigbeeBridge) { channel="mqtt:topic:mymqttbroker:zigbeebridge:state" }
Switch ZigbeeBridgePermitJoin "Zigbee2mqtt Bridge Permit join" (ZigbeeBridge) { channel="mqtt:topic:mymqttbroker:zigbeebridge:permitJoin" , expire="10m,command=OFF" }
String ZigbeeBridgeLogType "Zigbee2mqtt Bridge LogType" (ZigbeeBridge) { channel="mqtt:topic:mymqttbroker:zigbeebridge:logType" }
String ZigbeeBridgeLogMessage "Zigbee2mqtt Bridge LogMessage" (ZigbeeBridge) { channel="mqtt:topic:mymqttbroker:zigbeebridge:logMessage" }
Group ZigbeeKitchenBulb (Zigbee)
Switch ZigbeeKitchenBulbSwitch "Kitchen [%s]" (ZigbeeKitchenBulb) { channel="mqtt:topic:mymqttbrokername:ikeabulb01:switch" }
Dimmer ZigbeeKitchenBulbDim "Kitchen [%s]" (ZigbeeKitchenBulb) { channel="mqtt:topic:mymqttbrokername:ikeabulb01:dimmer" }
Number ZigbeeKitchenBulbQuality "Kitchen LinkQuality [%d]" <qualityofservice> (ZigbeeKitchenBulb) { channel="mqtt:topic:mymqttbrokername:ikeabulb01:linkquality" }
The name ikeabulb01 has to be set as a friendly name inside the configuration on zigbee2mqtt (configuration.yaml)
Notice that I’m using the expire binding to set the permit join off after 10 mins.
Using this example you will need to enable permit join in openhab before you can add zigbee components.
You can test by adding the Zigbee group item to your sitemap, to enable access to all members of the Zigbee group:
sitemap mysitemap label="My Cool Sitemap with Zigbee" {
Frame {
Group item=Zigbee
}
}
The reason why I use these transformations is because when dimmer get a 0 value, we want to turn off.
The valid value range for the bulbs are 1-254 which are passed onto openhab, hence 0 equals off and max is 254.
Also for HUE White the value 1 is also off (at least from my experiment, thus if we get 1 we should display that as 0 in openhab)
See comments in scripts.
Some random things to note:
- We need to send both state and brightness_percent in order to change the dimvalue
- It’s a good idea to run mosquitto_sub to see all topics for zigbee2mqtt when debuggig, i do this by running:
mosquitto_sub -h brokerIpaddress -v -t 'zigbee2mqtt/#'
-
LinkQuality is a value for how good connection it is. The higher value the better, value can range from 0 to 255
-
It can also be helpful to manually send mqtt messages, i.e
mosquitto_pub -h brokeripaddress -t 'zigbee2mqtt/ikeabulb01/set' -m '{"state":"ON","brightness":254}'
In zigbee2mqtt configuration (configuration.yaml) you should set the parameter persistent to true.
When doing so the status of the bulbs will be updated /refreshed when you restart openhab.
Mine looks something like this:
homeassistant: false
permit_join: true
mqtt:
base_topic: zigbee2mqtt
server: 'mqtt://ipnumber'
serial:
port: /dev/ttyACM0
devices:
'0xd0cf5efffecb1654':
friendly_name: ikeabulb01
retain: true
Thansk to @AndreasBrett for input and suggestions
Regards, S