Success with Sonoff zigbee bridge and zigbee binding

Hi,
I wanted to start using zigbee at home, and I wanted it simple.
First, I bought Itead Sonoff Zigbee Bridge (SNZB or zbbridge) and flashed it with tasmota.
See https://notenoughtech.com/home-automation/flashing-tasmota-on-sonoff-zigbee-bridge or https://www.digiblur.com/2020/07/how-to-use-sonoff-zigbee-bridge-with.html (without soldering, but more HomeAssistant oriented).
It works fine, but I like items auto-discovery and don’t want to bother with magic-voodoo-json data extraction and formatting.
The article from digiblur shows native integration with HomeAssistant binding, and I’ve managed to achieve it with OpenHAB.

So here is a litlle howto:

  • Read Digiblur’s article and strictly apply all steps, except the HA ones. The related video is also helpful.
    I uploaded the latest UART firmware (6.7.6), it seems you don’t have to stick to older 6.5.5 with OH
    A the end, you should be able to telnet to port 8888

  • Install socat, and bind your serial port to the zbbridge radio:
    socat -dd pty,link=/dev/ttyzbbridge,raw tcp:192.168.x.y:8888
    Of course, adjust the IP address to point the zbbridge one.

  • Install serial binding in OH
    You must also configure OH startup script to include /dev/ttyzbbridge as stated in the documentation

  • Install Zigbee binding in OH

  • Add a new Zigbee “Ember EM35x Coordinator” thing
    Just set the serial port to /dev/ttyzbbridge. I didn’t touch other settings since I was not sure of what they really do

  • Pair zigbee devices as stated on the zigbee binding documentation:
    Search for Zigbee things
    Put your device in pairing mode, it should appear.
    Wait for the discovery to finish (a name should appear, not “unknow zigbee device”

  • Enjoy :slight_smile:

I did this minutes ago, this is a basic procedure. I was able to pair Xiaomi plug, Aqara temp/hum and door sensors, and a Ikea Tradfri dimmer. Some of the devices don’t report battery status as zigbee2tasmota does.

There is room for a lot of enhancements, for example:

  • Make socat a service with auto-reconnect
  • Fine-tune the zigbee coordinator settings

Finally, it would be great the the serial binding allows Serial-over-TCP connections as HA does with socket://<your bridge IP>:8888 as serial port path.

2 Likes

That is a serial binding issue and hopefully it can make it into OH3.

Apparently zbbridge also works with MQTT, have you tried it ?

https://tasmota.github.io/docs/Zigbee/

Good news, I’ll try it (in a few weeks :slight_smile:)

If you are lucky, OH3 will be released shortly before the end of the year.

Yes, that’s where I started.
It works very well, but I was dispapointed by some aspects : No real detection of device downlink (LWT does not works), all sensors are send in JSON format throught the same MQTT topic that is parsed by ALL channel of ALL MQTT things, no discovery (like Homie) …
I know a lot of people are happy with this way of doing, but I wanted to test if remote-zigbee-binding was doable and, indeed, it is !
Things are not perfect however : socat is needed, and some channels are not managed (battery status, …) on some devices.

In fact, I’ll keep using the MQTT way for some weeks at least.

This post simply aimed to report that it’s perfectly doable with the integrated ZigBee binding.

1 Like

You should have a look at the following Tasmota options:

SetOption89 1
SetOption83 1
SetOption112 1

I’m still working on the JSON transformation, because i’m getting a warning if the payload doesn’t include an information. These are my Things for now:

Type switch : KinderzimmerHeizstrahlerState             "Status"                        	[ stateTopic = "tele/Kinderzimmer_Heizstrahler/SENSOR" , transformationPattern = "REGEX:(.*\"Power\".*)∩JSONPATH:$.ZbReceived.Kinderzimmer_Heizstrahler.Power", commandTopic = "cmnd/ZigBee2Tasmota/ZbSend", formatBeforePublish = "{ \"device\":\"Kinderzimmer_Heizstrahler\", \"send\":{\"Power\":\"%s\"} }", on = "1", off = "0" ]
		Type number : KinderzimmerHeizstrahlerLinkquality       "Verbindungsqualität"           	[ stateTopic = "tele/Kinderzimmer_Heizstrahler/SENSOR" , transformationPattern = "REGEX:(.*\"LinkQuality\".*)∩JSONPATH:$.ZbReceived.Kinderzimmer_Heizstrahler.LinkQuality" ]

Thanks for the tip !
I now have a MQTT topic per device.
I just adapted my things:

Bridge mqtt:broker:mosquitto-nas [ host="localhost", secure=false, clientID="openhab-aqara.things" ]
{   Thing topic Zbbridge1 "Zbbridge1 Sonoff" @ "Garage" {
      Channels:
        Type datetime : LastUpdate "LastUpdate" [stateTopic="tele/zbbridge1/STATE" , transformationPattern="JSONPATH:$.Time"]      
        Type number : LoadAvg "LoadAvg" [stateTopic="tele/zbbridge1/STATE" , transformationPattern="JSONPATH:$.LoadAvg"]
        Type number : Vcc "Vcc" [stateTopic="tele/zbbridge1/STATE" , transformationPattern="JSONPATH:$.Vcc"]
        Type string : Version [stateTopic="stat/zbbridge1/INFO1", transformationPattern="JSONPATH:$.Version"]
      }

    Thing topic AqaraTemp02 "AqaraTemp02" @ "Cave" {
    Channels:
        Type string : Name "Name" [stateTopic="tele/AqaraTemp02/SENSOR" , transformationPattern="JSONPATH:$.ZbReceived.AqaraTemp02.Name"]
        Type datetime : LastUpdate "LastUpdate" [stateTopic="tele/AqaraTemp02/SENSOR" , transformationPattern="JSONPATH:$.ZbReceived.AqaraTemp02.Temperature"]      
        Type number : Temperature "Temperature" [stateTopic="tele/AqaraTemp02/SENSOR" , transformationPattern="JSONPATH:$.ZbReceived.AqaraTemp02.Temperature", unit="°C"]
        Type number : Pressure "Pressure" [stateTopic="tele/AqaraTemp02/SENSOR" , transformationPattern="JSONPATH:$.ZbReceived.AqaraTemp02.Pressure" , unit="hPa"]
        Type number : Humidity "Humidity" [stateTopic="tele/AqaraTemp02/SENSOR" , transformationPattern="JSONPATH:$.ZbReceived.AqaraTemp02.Humidity" , unit="%"]
        Type number : BatteryVoltage "BatteryVoltage" [stateTopic="tele/AqaraTemp02/SENSOR" , transformationPattern="JSONPATH:$.ZbReceived.AqaraTemp02.BatteryVoltage" , unit="V"]
        Type number : BatteryPercentage "BatteryPercentage" [stateTopic="tele/AqaraTemp02/SENSOR" , transformationPattern="JSONPATH:$.ZbReceived.AqaraTemp02.BatteryPercentage" , unit="%"]
        Type number : LinkQuality "LinkQuality" [ stateTopic="tele/AqaraTemp02/SENSOR" , transformationPattern="JSONPATH:$.ZbReceived.AqaraTemp02.LinkQuality"]
      }

    Thing topic TuyaTemp01 "TuyaTemp01" @ "Cuisine" {
    Channels:
        Type string : Name "Name" [stateTopic="tele/TuyaTemp01/SENSOR" , transformationPattern="JSONPATH:$.ZbReceived.TuyaTemp01.Name"]
        Type datetime : LastUpdate "LastUpdate" [stateTopic="tele/TuyaTemp01/SENSOR" , transformationPattern="JSONPATH:$.ZbReceived.TuyaTemp01.Temperature"]
        Type number : Temperature "Temperature" [stateTopic="tele/TuyaTemp01/SENSOR" , transformationPattern="JSONPATH:$.ZbReceived.TuyaTemp01.Temperature", unit="°C"]
        Type number : Pressure "Pressure" [stateTopic="tele/TuyaTemp01/SENSOR" , transformationPattern="JSONPATH:$.ZbReceived.TuyaTemp01.Pressure" , unit="hPa"]
        Type number : Humidity "Humidity" [stateTopic="tele/TuyaTemp01/SENSOR" , transformationPattern="JSONPATH:$.ZbReceived.TuyaTemp01.Humidity" , unit="%"]
        Type number : BatteryVoltage "BatteryVoltage" [stateTopic="tele/TuyaTemp01/SENSOR" , transformationPattern="JSONPATH:$.ZbReceived.TuyaTemp01.BatteryVoltage" , unit="V"]
        Type number : BatteryPercentage "BatteryPercentage" [stateTopic="tele/TuyaTemp01/SENSOR" , transformationPattern="JSONPATH:$.ZbReceived.TuyaTemp01.BatteryPercentage" , unit="%"]
        Type number : LinkQuality "LinkQuality" [ stateTopic="tele/TuyaTemp01/SENSOR" , transformationPattern="JSONPATH:$.ZbReceived.TuyaTemp01.LinkQuality"]
      }

    Thing topic AqaraPlug01 "AqaraPlug01" @ "Garage" {
    Channels:
        Type string : Name "Name" [stateTopic="tele/AqaraPlug01/SENSOR" , transformationPattern="JSONPATH:$.ZbReceived.AqaraPlug01.Name"]
        Type datetime : LastUpdate "LastUpdate" [stateTopic="tele/AqaraPlug01/SENSOR" , transformationPattern="JSONPATH:$.ZbReceived.AqaraPlug01.Temperature"]
        Type switch : Power "Power" [stateTopic="tele/AqaraPlug01/SENSOR" , transformationPattern="JSONPATH:$.ZbReceived.AqaraPlug01.Power", commandTopic = "cmnd/zbbridge1/zbSend", formatBeforePublish="{ \"device\":\"AqaraPlug01\", \"send\":{\"Power\":%s} }" ]
        Type number : LinkQuality "LinkQuality" [ stateTopic="tele/AqaraPlug01/SENSOR" , transformationPattern="JSONPATH:$.ZbReceived.AqaraPlug01.LinkQuality"]
      }

    Thing topic HueSensor1 "HueSensor1" @ "Extérieur" {
    Channels:
        Type string : Name "Name" [stateTopic="tele/HueSensor1/SENSOR" , transformationPattern="JSONPATH:$.ZbReceived.HueSensor1.Name"]
        Type datetime : LastUpdate "LastUpdate" [stateTopic="tele/HueSensor1/SENSOR" , transformationPattern="JSONPATH:$.ZbReceived.HueSensor1.LinkQuality"]
        Type number : LinkQuality "LinkQuality" [ stateTopic="tele/HueSensor1/SENSOR" , transformationPattern="JSONPATH:$.ZbReceived.HueSensor1.LinkQuality"]
		Type number : BatteryPercentage "BatteryPercentage" [stateTopic="tele/HueSensor1/SENSOR" , transformationPattern="JSONPATH:$.ZbReceived.HueSensor1.BatteryPercentage" , unit="%"]
        Type number : Temperature "Temperature" [stateTopic="tele/HueSensor1/SENSOR" , transformationPattern="JSONPATH:$.ZbReceived.HueSensor1.Temperature", unit="°C"]
        Type switch : Occupancy "Occupancy" [stateTopic="tele/HueSensor1/SENSOR" , transformationPattern="JSONPATH:$.ZbReceived.HueSensor1.Occupancy"]
        Type number : Illuminance "Illuminance" [stateTopic="tele/HueSensor1/SENSOR" , transformationPattern="JSONPATH:$.ZbReceived.HueSensor1.Illuminance"]
	}

    Thing topic SonoffMotion1 "SonoffMotion1" @ "Cave" {
    Channels:
        Type string : Name "Name" [stateTopic="tele/SonoffMotion1/SENSOR" , transformationPattern="JSONPATH:$.ZbReceived.SonoffMotion1.Name"]
        Type datetime : LastUpdate "LastUpdate" [stateTopic="tele/SonoffMotion1/SENSOR" , transformationPattern="JSONPATH:$.ZbReceived.SonoffMotion1.LinkQuality"]
        Type number : LinkQuality "LinkQuality" [ stateTopic="tele/SonoffMotion1/SENSOR" , transformationPattern="JSONPATH:$.ZbReceived.SonoffMotion1.LinkQuality"]
		Type number : BatteryPercentage "BatteryPercentage" [stateTopic="tele/SonoffMotion1/SENSOR" , transformationPattern="JSONPATH:$.ZbReceived.SonoffMotion1.BatteryPercentage" , unit="%"]
        Type switch : Occupancy "Occupancy" [stateTopic="tele/SonoffMotion1/SENSOR" , transformationPattern="JSONPATH:$.ZbReceived.SonoffMotion1.Occupancy"]
	}

    Thing topic SonoffRelay1 "SonoffRelay1" @ "Extérieur" {
    Channels:
        Type string   : Name "Name" [stateTopic="tele/SonoffRelay1/SENSOR" , transformationPattern="JSONPATH:$.ZbReceived.SonoffRelay1.Name"]
        Type datetime : LastUpdate "LastUpdate" [stateTopic="tele/SonoffRelay1/SENSOR" , transformationPattern="JSONPATH:$.ZbReceived.SonoffRelay1.LinkQuality"]
        Type number   : LinkQuality "LinkQuality" [ stateTopic="tele/SonoffRelay1/SENSOR" , transformationPattern="JSONPATH:$.ZbReceived.SonoffRelay1.LinkQuality"]
        Type switch   : Power "Power" [stateTopic="tele/SonoffRelay1/SENSOR" , transformationPattern="JSONPATH:$.ZbReceived.SonoffRelay1.Power", commandTopic = "cmnd/zbbridge1/zbSend", formatBeforePublish="{ \"device\":\"SonoffRelay1\", \"send\":{\"Power\":%s} }" ]
	}

Edit : My previous command transformation pattern was wrong.

1 Like

I just came across this device. How reliable has your setup been? I did couple experiments with a CC2531 but couldn’t get any as reliable as the hue hub. This looks like a potential great solution. How has this been working for you?

Since it’s my first Zigbee setup, I have no real point of comparison.
The setup is easy, the device quality is good.

Although it’s still considered as exprimental, it works rather well.
Since the few weeks it’s “in production”, it is relatively stable. I just had to reboot once, the zigbee stack seemed to crash.
https://zigbee.blakadder.com/ lists more devices recognized by zigbee2mqtt than by zigbee2tasmota, but I had no important issues with the devices I’ve used so far (aqara, xiaomi, sonoff, hue).
There is no zigbee map as zigbee2mqtt offers.

Finally, the coverage seems corrects, but no excellent, due to the lack of an external antenna.

So, I’m really happy with my setup, and will keep it for a while.

PS : Itead says there is a limitation to 16 devices, I don’t know if it also applies to tasmota.

Just started configuring my senors and get same problem with these warnings… More worse - MQTT binding reports NULL value on items like “battery percentage”, when value is not included in the payload.
Any idea how to resolve this? At least remove NULL value…

Oh…yes. I’ve got everything working.

First you should make the following settings in Tasmota:
MQTT Topics for every Zigbee Client
SetOption89 1

Friendlyname as group
SetOption83 1

Friendlyname in the Zigbee Topic
SetOption112 1

The MQTT message should look like this afterwards:
tele/FlurOG_Motion/SENSOR = {"ZbReceived":{"FlurOG_Motion":{"Device":"0x88D7","Name":"FlurOG_Motion","Illuminance":0,"Occupancy":1,"Endpoint":1,"LinkQuality":58}}}

And then comes the important part. The combination of jsonpath and regex. The things should look like this:

//Flur OG Temperatur
			Type number : FlurOGBattery                             "Batterie"                      	[ stateTopic = "tele/FlurOG_Temperature/SENSOR" , transformationPattern = "REGEX:(.*\"BatteryPercentage\".*)∩JSONPATH:$.ZbReceived.FlurOG_Temperature.BatteryPercentage" ]
			Type number : FlurOGTemperature                         "Temperatur"                    	[ stateTopic = "tele/FlurOG_Temperature/SENSOR" , transformationPattern = "REGEX:(.*\"Temperature\".*)∩JSONPATH:$.ZbReceived.FlurOG_Temperature.Temperature" ]
			Type number : FlurOGHumidity                            "Luftfeuchtigkeit"              	[ stateTopic = "tele/FlurOG_Temperature/SENSOR" , transformationPattern = "REGEX:(.*\"Humidity\".*)∩JSONPATH:$.ZbReceived.FlurOG_Temperature.Humidity" ]
			Type number : FlurOGLinkquality                         "Verbindungsqualität"           	[ stateTopic = "tele/FlurOG_Temperature/SENSOR" , transformationPattern = "REGEX:(.*\"LinkQuality\".*)∩JSONPATH:$.ZbReceived.FlurOG_Temperature.LinkQuality" ]
			Type number : FlurOGVoltage                             "Spannung"                      	[ stateTopic = "tele/FlurOG_Temperature/SENSOR" , transformationPattern = "REGEX:(.*\"BatteryVoltage\".*)∩JSONPATH:$.ZbReceived.FlurOG_Temperature.BatteryVoltage" ]

If it’s not just reading information and you have to set something, then it should look like this switch:

Type switch : KinderzimmerHeizstrahlerState "Status" [ stateTopic = "tele/Kinderzimmer_Heizstrahler/SENSOR" , transformationPattern = "REGEX:(.*\"Power\".*)∩JSONPATH:$.ZbReceived.Kinderzimmer_Heizstrahler.Power", commandTopic = "cmnd/ZigBee2Tasmota/ZbSend", formatBeforePublish = "{ \"device\":\"Kinderzimmer_Heizstrahler\", \"send\":{\"Power\":\"%s\"} }", on = "1", off = "0" ]

And the Items for these things:

Number:Temperature 	FlurOG_Temperatur 	                                "Flur OG Temperatur [%.2f °C]"		                        	<temperature> 		(gOG_Flur)		                                                            { channel="mqtt:topic:mosquitto:Zigbee2Tasmota:FlurOGTemperature" }
		Number 		        FlurOG_Luftfeuchtigkeit 											                                                <humidity> 			(gOG_Flur,gChartFeuchtigkeit,gHumidityAvg) 			                        { channel="mqtt:topic:mosquitto:Zigbee2Tasmota:FlurOGHumidity" }
		Number		        FlurOG_Verbindungsqualitaet		                    "Flur OG Temperatur"  						                	<qualityofservice>  (gZigbeeLink)								                                { channel="mqtt:topic:mosquitto:Zigbee2Tasmota:FlurOGLinkquality"}
		Number 		        FlurOG_Batterie 								    "Flur OG Temperatur [%.1f %%]"      	                  		<battery> 			(gZigbeeBattery)												            { channel="mqtt:topic:mosquitto:Zigbee2Tasmota:FlurOGBattery" }
		Number 		        FlurOG_Spannung 													                                                <energy> 															                            { channel="mqtt:topic:mosquitto:Zigbee2Tasmota:FlurOGVoltage" }

I hope it helps you and everyone else. Took me hours to find the right regex expression.

4 Likes

Thanks! You saved my day!

1 Like

Hello

I have followed your instruction but I’m stuck with this


it’s state between UNKNOWN and OFFLINE - COM ERROR
I did change only port into ttyzbbridge as below:

How to solve that?

Hello,

Openhab must have permissions to access the serial device /dev/ttyzbbridge
You can try cat /dev/ttyzbbridge as openhab user.
You also have to adjust your startup command line to include this device -Dgnu.io.rxtx.SerialPorts=/dev/ttyzbbridge

More details on this page:

Could you try this ?

  1. I added EXTRA_JAVA_OPTS="-Dgnu.io.rxtx.SerialPorts=/dev/ttyzbbridge" under JAVA in /etc/default/openhab2 already is that the right way to do?

  2. I also try with sudo usermod -a -G dialout openhab. but when I run cat /dev/ttyzbbridge without sudo. it is still permission denied

I use openhabian to install OpenHAB in my rasberrypi

I’m very beginner here so if I ask something stupid I apologize.

1 - Yes, that’s correct
2 - So your permissions are not correct
a/ Check the permissions : ls -l /dev/ttyzbbridge
You could try to add owner or group to socat command (I have not tested):
socat -dd pty,link=/dev/ttyzbbridge,raw,user-late=openhab,group-late=dialout tcp:192.168.x.y:8888
b/ You have to logoff/logon again for new group membership to apply

1 Like

It’s work!!! Like a magic.
Thanks to you! Now I can search zigbee device via Zigbee binding and link channel to item easily!

Good news :slight_smile:

Finally, what did exactly solve your issue ?
Is this the modified socat commande ?