Sonoff Zigbee (SNZB) Sensors & Switches with Zigbee2MQTT

With the recent release of the affordable Sonoff Zigbee range, I decided to upgrade some sensors around the house from RF to Zigbee. Here is how I added them to my openHAB installation.

There are (at least) two ways to go about adding Zigbee things:

  1. The Zigbee Binding
  2. Using a Zigbee to MQTT bridge

I chose the second option.

Prerequisites:

This guide assumes that you already have a working MQTT Broker such as the embedded openHAB MQTT Broker Moquette or Mosquitto.

Note: This guide contains references to a Bridge to the embedded MQTT broker (mqtt:broker:bridge). Replace that with a reference to your own broker bridge, where necessary.

ZigBee Hardware

Note: * = Not covered yet as I don’t have one.

Software

Add-ons

Procedure:

  1. Prepare the CC2531

    Follow the guide in the Zigbee2MQTT documentation.

  2. Setup Zigbee2MQTT

    The software can be installed in various ways that are all well documented. I chose Docker.

  3. Add Map Transformations

    reachable.js:

    OPEN=ONLINE
    CLOSED=OFFLINE
    NULL=?
    

    zigbee2mqtt_log_level.js:

    0=DEBUG
    1=INFO
    2=WARNING
    3=ERROR
    0.0=DEBUG
    1.0=INFO
    2.0=WARNING
    3.0=ERROR
    debug=0
    info=1
    warn=2
    error=3
    

    zigbee2mqtt_log_type.js:

    pairing=PAIRING
    device_connected=DEVICE CONNECTED
    device_ban=DEVICE BAN
    device_ban_failed=DEVICE BAN FAILED
    device_announced=DEVICE ANNOUNCED
    device_removed=DEVICE REMOVE
    device_removed_failed=DEVICE REMOVE FAILED
    device_force_removed=DEVICE FORCE REMOVE
    device_force_removed_failed=DEVICE FORCE REMOVE FAILED
    device_banned=DEVICE BANNED
    device_whitelisted=DEVICE WHITELISTED
    device_renamed=DEVICE RENAMED
    group_renamed=GROUP RENAMED
    group_added=GROUP ADDED
    group_removed=GROUP REMOVED
    device_bind=DEVICE BOUND
    device_unbind=DEVICE UNBOUND
    device_group_add=DEVICE GROUP ADD
    device_group_add_failed=DEVICE GROUP ADD FAILED
    device_group_remove=DEVICE GROUP REMOVE
    device_group_remove_failed=DEVICE GROUP REMOVE FAILED
    device_group_remove_all=DEVICE GROUP REMOVE ALL
    device_group_remove_all_failed=DEVICE GROUP REMOVE ALL FAILED
    devices=LIST ALL DEVICES
    groups=LIST ALL GROUPS
    zigbee_publish_error=ZIGBEE PUBLISH ERROR
    ota_update=OTA UPDATE
    touchlink=TOUCHLINK
    

    zigbee2mqtt_supported.js:

    OPEN=YES
    CLOSED=NO
    NULL=UNKNOWN
    
  4. Add Zigbee2MQTT Thing

    Create a new Things file and add the following:

    Thing mqtt:topic:zigbee2mqtt "Zigbee 2 MQTT" (mqtt:broker:bridge) {
        Channels:
            Type contact : state       "State"              [ stateTopic="zigbee2mqtt/bridge/state", off="offline", on="online"]
            Type string : version      "Version"            [ stateTopic="zigbee2mqtt/bridge/config", transformationPattern="JSONPATH:$.version"]
            Type string : commit       "Commit"             [ stateTopic="zigbee2mqtt/bridge/config", transformationPattern="JSONPATH:$.commit"]
            Type string : type         "Type"               [ stateTopic="zigbee2mqtt/bridge/config", transformationPattern="REGEX:(.*type.*)∩JSONPATH:$.coordinator.type"]
            Type string : transportrev "Transport Revision" [ stateTopic="zigbee2mqtt/bridge/config", transformationPattern="REGEX:(.*meta.*)∩JSONPATH:$.coordinator.meta.transportrev"]
            Type string : product      "Product"            [ stateTopic="zigbee2mqtt/bridge/config", transformationPattern="REGEX:(.*meta.*)∩JSONPATH:$.coordinator.meta.product"]
            Type string : majorrel     "Major Release"      [ stateTopic="zigbee2mqtt/bridge/config", transformationPattern="REGEX:(.*meta.*)∩JSONPATH:$.coordinator.meta.majorrel"]
            Type string : minorrel     "Minor Release"      [ stateTopic="zigbee2mqtt/bridge/config", transformationPattern="REGEX:(.*meta.*)∩JSONPATH:$.coordinator.meta.minorrel"]
            Type string : maintrel     "Main Release"       [ stateTopic="zigbee2mqtt/bridge/config", transformationPattern="REGEX:(.*meta.*)∩JSONPATH:$.coordinator.meta.maintrel"]
            Type string : revision     "Revision"           [ stateTopic="zigbee2mqtt/bridge/config", transformationPattern="REGEX:(.*meta.*)∩JSONPATH:$.coordinator.meta.revision"]
            Type number : log          "Log Level"          [ stateTopic="zigbee2mqtt/bridge/config", commandTopic="zigbee2mqtt/bridge/config/log_level", transformationPattern="REGEX:(.*log_level.*)∩JSONPATH:$.log_level"]
            Type switch : permit       "Permit Join"        [ stateTopic="zigbee2mqtt/bridge/config", commandTopic="zigbee2mqtt/bridge/config/permit_join", transformationPattern="REGEX:(.*permit_join.*)∩JSONPATH:$.permit_join", off="false", on="true"]
            Type string : logtype      "Log type"           [ stateTopic="zigbee2mqtt/bridge/log", transformationPattern="JSONPATH:$.type"]
            Type string : message      "Message"            [ stateTopic="zigbee2mqtt/bridge/log", transformationPattern="JSONPATH:$.message"]
            Type string : friendlyname "Friendly name"      [ stateTopic="zigbee2mqtt/bridge/log", transformationPattern="REGEX:(.*friendly_name.*)∩JSONPATH:$.meta.friendly_name"]
            Type string : model        "Model"              [ stateTopic="zigbee2mqtt/bridge/log", transformationPattern="REGEX:(.*model.*)∩JSONPATH:$.meta.model"]
            Type string : vendor       "Vendor"             [ stateTopic="zigbee2mqtt/bridge/log", transformationPattern="REGEX:(.*vendor.*)∩JSONPATH:$.meta.vendor"]
            Type string : description  "Description"        [ stateTopic="zigbee2mqtt/bridge/log", transformationPattern="REGEX:(.*description.*)∩JSONPATH:$.meta.description"]
            Type contact : supported   "Supported"          [ stateTopic="zigbee2mqtt/bridge/log", transformationPattern="REGEX:(.*supported.*)∩JSONPATH:$.meta.supported", off="false", on="true"]
    }
    
  5. Add Zigbee2MQTT Item

    Put this in an Items file:

    Group  Zigbee_2_MQTT "Zigbee2MQTT"    <zigbee2mqtt>     (ZigbeeBridges)
    Contact Zigbee_2_MQTT_State       "State: [MAP(reachable.map):%s]" <contactable> (Zigbee_2_MQTT) { channel="mqtt:topic:zigbee2mqtt:state" }
    String  Zigbee_2_MQTT_Version     "Version: [%s]"                  <zigbee2mqtt> (Zigbee_2_MQTT) { channel="mqtt:topic:zigbee2mqtt:version" }
    String  Zigbee_2_MQTT_Commit      "Commit: [%s]"                   <zigbee2mqtt> (Zigbee_2_MQTT) { channel="mqtt:topic:zigbee2mqtt:commit" }
    String  Zigbee_2_MQTT_Type        "Type: [%s]"                     <zigbee2mqtt> (Zigbee_2_MQTT) { channel="mqtt:topic:zigbee2mqtt:type" }
    String  Zigbee_2_MQTT_Transport   "Transport rev: [%s]"            <zigbee2mqtt> (Zigbee_2_MQTT) { channel="mqtt:topic:zigbee2mqtt:transportrev" }
    String  Zigbee_2_MQTT_Product     "Product: [%s]"                  <zigbee2mqtt> (Zigbee_2_MQTT) { channel="mqtt:topic:zigbee2mqtt:product" }
    String  Zigbee_2_MQTT_Major_Rel   "Major rel: [%s]"                <zigbee2mqtt> (Zigbee_2_MQTT) { channel="mqtt:topic:zigbee2mqtt:majorrel" }
    String  Zigbee_2_MQTT_Minor_Rel   "Minor rel: [%s]"                <zigbee2mqtt> (Zigbee_2_MQTT) { channel="mqtt:topic:zigbee2mqtt:minorrel" }
    String  Zigbee_2_MQTT_Main_Rel    "Main rel: [%s]"                 <zigbee2mqtt> (Zigbee_2_MQTT) { channel="mqtt:topic:zigbee2mqtt:maintrel" }
    String  Zigbee_2_MQTT_Revision    "Revision: [%s]"                 <zigbee2mqtt> (Zigbee_2_MQTT) { channel="mqtt:topic:zigbee2mqtt:revision" }
    Switch  Zigbee_2_MQTT_Permit_Join "Permit Join: []"                <zigbee2mqtt> (Zigbee_2_MQTT) { channel="mqtt:topic:zigbee2mqtt:permit" } 
    
    Group  Zigbee_2_MQTT_Logs "Zigbee2MQTT Logs" <text> (Zigbee_2_MQTT)
    Number  Zigbee_2_MQTT_Log_Level   "Log level: [MAP(zigbee2mqtt_log_level.map):%s]" <text> (Zigbee_2_MQTT_Logs) { channel="mqtt:topic:zigbee2mqtt:log" } 
    String  Zigbee_2_MQTT_Log_Type    "Log type: [MAP(zigbee2mqtt_log_type.map):%s]"   <text> (Zigbee_2_MQTT_Logs) { channel="mqtt:topic:zigbee2mqtt:logtype" } 
    String  Zigbee_2_MQTT_Log_Message "Log message: [%s]"                              <text> (Zigbee_2_MQTT_Logs) { channel="mqtt:topic:zigbee2mqtt:message" } 
    String  Zigbee_2_MQTT_Friendly    "Friendly name: [%s]"                            <text> (Zigbee_2_MQTT_Logs) { channel="mqtt:topic:zigbee2mqtt:friendlyname" } 
    String  Zigbee_2_MQTT_Model       "Model: [%s]"                                    <text> (Zigbee_2_MQTT_Logs) { channel="mqtt:topic:zigbee2mqtt:model" } 
    String  Zigbee_2_MQTT_Vendor      "Vendor: [%s]"                                   <text> (Zigbee_2_MQTT_Logs) { channel="mqtt:topic:zigbee2mqtt:vendor" } 
    String  Zigbee_2_MQTT_Description "Description: [%s]"                              <text> (Zigbee_2_MQTT_Logs) { channel="mqtt:topic:zigbee2mqtt:description" } 
    Contact Zigbee_2_MQTT_Supported   "Supported: [MAP(zigbee2mqtt_supported.map)%s]"  <text> (Zigbee_2_MQTT_Logs) { channel="mqtt:topic:zigbee2mqtt:supported" } 
    
    
  6. Discover Zigbee Things and IDs

    I refer you to the Zigbee2MQTT documentation (last time, swear :crossed_fingers:)

  7. Add Zigbee Things

    Some of the Sonoff Zigbee things have payload values in common - such as battery_low and tamper between the Motion and Wireless Door/Window sensors.

    If you are adding either or both of those devices, create the following Map transformation:

    snzb_boolean.js

    OPEN=TRUE
    CLOSED=FALSE
    NULL=UNKNOWN
    
    1: Wireless Switches

             Reports actions. Can be one of the following three values: single, double and long.

    1. Add a new Thing to a file

      Thing mqtt:topic:snzb01a "My Awesome Button" (mqtt:broker:bridge) @ "Some Fancy Room" {
         Channels:
           Type string : action       "Action"       [ stateTopic="zigbee2mqtt/UNIQUE_ZIGBEE_ID", transformationPattern="REGEX:(.*action.*)∩JSONPATH:$.action"]
           Type number : linkquality  "Link Quality" [ stateTopic="zigbee2mqtt/UNIQUE_ZIGBEE_ID", transformationPattern="JSONPATH:$.linkquality"]
           Type number : battery      "Battery"      [ stateTopic="zigbee2mqtt/UNIQUE_ZIGBEE_ID", transformationPattern="JSONPATH:$.battery"]
           Type number : voltage      "Voltage"      [ stateTopic="zigbee2mqtt/UNIQUE_ZIGBEE_ID", transformationPattern="JSONPATH:$.voltage"]
      }
      
    2. Add a new Item to a file

      Group ZigbeeButtonActions "Zigbee Buttons" <button>
      
      Group  SNZB_01_1_Button "My Awesome Button" <sonoff_snzb01> (GF_SomeRoom, Sonoff_SNZB_01)
      String  SNZB_01_1_Button_Action  "Action: [%s]"      <none> (SNZB_01_1_Button, ZigbeeButtonActions) { channel="mqtt:topic:snzb01a:action" } 
      Number  SNZB_01_1_Button_Link    "Link quality [%d]" <none> (SNZB_01_1_Button)                      { channel="mqtt:topic:snzb01a:linkquality" }
      Number  SNZB_01_1_Button_Battery "Battery [%d]"      <none> (SNZB_01_1_Button)                      { channel="mqtt:topic:snzb01a:battery" }
      Number  SNZB_01_1_Button_Voltage "Voltage [%d]"      <none> (SNZB_01_1_Button)                      { channel="mqtt:topic:snzb01a:voltage" }
      
    3. Create a Rule

      val String filename = "my_super_cool_zigbee_rule_file.rules"
      
      rule "Zigbee button received update"
      when
         Member of ZigbeeButtonActions received update
      then
         logInfo(filename, "Zigbee button received update: {}", triggeringItem.name)
         switch (triggeringItem) {
            case SNZB_01_1_Button_Action: {
               switch (triggeringItem.state) {
                  case 'single': {
                     // Do stuff
                  }
                  case 'double': {
                     // Do other stuff
                  }
                  case 'long': {
                     // Do super secret stuff
                  }
               }
            }
         }
      end
      
    2: Temperature and Humidity Sensors

             Not covered yet.

    1. Add a new Thing to a file

      
      
    2. Add a new Item to a file

      
      
    3. Create a Rule

      
      
    3: Motion Sensors

             Reports occupancy.

    1. Create Map Transformations

      snzb03_occupancy.js
      OPEN=OCCUPIED
      CLOSED=IDLE
      NULL=UNKNOWN
      
    2. Add a new Thing to a file

      Thing mqtt:topic:snzb03a "Important Motion Sensor" (mqtt:broker:bridge) @ "Important Room" {
         Channels:
           Type contact : occupancy   "Occupancy"    [ stateTopic="zigbee2mqtt/UNIQUE_ZIGBEE_ID", transformationPattern="REGEX:(.*occupancy.*)∩JS:snzb03_occupancy.js"]
           Type contact : tamper      "Tamper"       [ stateTopic="zigbee2mqtt/UNIQUE_ZIGBEE_ID", transformationPattern="REGEX:(.*tamper.*)∩JS:tamper.js"]
           Type contact : battery_low "Battery Low"  [ stateTopic="zigbee2mqtt/UNIQUE_ZIGBEE_ID", transformationPattern="REGEX:(.*battery_low.*)∩JS:battery_low.js"]
           Type number : linkquality  "Link Quality" [ stateTopic="zigbee2mqtt/UNIQUE_ZIGBEE_ID", transformationPattern="JSONPATH:$.linkquality"]
           Type number : battery      "Battery"      [ stateTopic="zigbee2mqtt/UNIQUE_ZIGBEE_ID", transformationPattern="JSONPATH:$.battery"]
           Type number : voltage      "Voltage"      [ stateTopic="zigbee2mqtt/UNIQUE_ZIGBEE_ID", transformationPattern="JSONPATH:$.voltage"]
      }
      
    3. Add a new Item to a file:

      Group MotionSensors "Motion Sensors" <motion>
      
      Group  SNZB_03_1_Motion_Sensor "Important Room Motion Sensor" <sonoff_snzb03> (GF_ImportantRoom, Sonoff_SNZB_03)
      Contact SNZB_03_1_Motion_Sensor_Occupancy   "Important Room [MAP(snzb03_occupancy.map):%s]" <motion> (SNZB_03_1_Motion_Sensor, MotionSensors) { channel="mqtt:topic:snzb03a:occupancy" }
      Contact SNZB_03_1_Motion_Sensor_Tamper      "Tamper [MAP(snzb_boolean.map):%s]"              <none>   (SNZB_03_1_Motion_Sensor)                { channel="mqtt:topic:snzb03a:tamper" }
      Contact SNZB_03_1_Motion_Sensor_Battery_Low "Battery low [MAP(snzb_boolean.map):%s]"    <none>   (SNZB_03_1_Motion_Sensor)                { channel="mqtt:topic:snzb03a:battery_low" }
      Number  SNZB_03_1_Motion_Sensor_Link        "Link quality [%d]"                             <none>   (SNZB_03_1_Motion_Sensor)                { channel="mqtt:topic:snzb03a:linkquality" }
      Number  SNZB_03_1_Motion_Sensor_Battery     "Battery [%d]"                                  <none>   (SNZB_03_1_Motion_Sensor)                { channel="mqtt:topic:snzb03a:battery" }
      Number  SNZB_03_1_Motion_Sensor_Voltage     "Voltage [%d]"                                  <none>   (SNZB_03_1_Motion_Sensor)                { channel="mqtt:topic:snzb03a:voltage" }
      
    • Create a new Rule:
      val String filename = "best_rule_file_ever.rules"
      
      rule "Motion sensor status"
      when
         Member of MotionSensors changed
      then
         logInfo(filename, triggeringItem.name + ": " + triggeringItem.state)
      
         switch (triggeringItem.state) {
            case OPEN: {
               switch (triggeringItem) {
                  case SNZB_03_1_Motion_Sensor_Occupancy: {
                     // Motion detected, let the dogs loose!
                  }
               }
            }
            case CLOSED: {
               switch (triggeringItem) {
                  case SNZB_03_1_Motion_Sensor_Occupancy: {
                     // No more motion detected
                  }
               }
            }
         }
      end      
      
    4: Wireless Door/Window Sensors

             Reports contact.

    1. Add a new Thing to a file

      Thing mqtt:topic:snzb04a "Hidden Door Contact Sensor" (mqtt:broker:bridge) @ "Hidden Room" {
         Channels:
            Type contact : sensor      "Contact"      [ stateTopic="zigbee2mqtt/UNIQUE_ZIGBEE_ID", transformationPattern="REGEX:(.*contact.*)∩JSONPATH:$.contact", on="false", off="true"]
            Type contact : tamper      "Tamper"       [ stateTopic="zigbee2mqtt/UNIQUE_ZIGBEE_ID", transformationPattern="REGEX:(.*tamper.*)∩JSONPATH:$.tamper", on="true", off="false"]
            Type contact : battery_low "Battery Low"  [ stateTopic="zigbee2mqtt/UNIQUE_ZIGBEE_ID", transformationPattern="REGEX:(.*battery_low.*)∩JSONPATH:$.battery_low", on="true", off="false"]
            Type number : linkquality  "Link Quality" [ stateTopic="zigbee2mqtt/UNIQUE_ZIGBEE_ID", transformationPattern="JSONPATH:$.linkquality"]
            Type number : battery      "Battery"      [ stateTopic="zigbee2mqtt/UNIQUE_ZIGBEE_ID", transformationPattern="JSONPATH:$.battery"]
            Type number : voltage      "Voltage"      [ stateTopic="zigbee2mqtt/UNIQUE_ZIGBEE_ID", transformationPattern="JSONPATH:$.voltage"]
      }
      
    2. Add a new Item to a file

      Group DoorSensors   "Door Sensors"   <door>  
      
      Group  SNZB_04_1_Contact_Sensor "Hidden Door Contact Sensor" <sonoff_snzb04> (GF_HiddenRoom, Sonoff_SNZB_04)
      Contact SNZB_04_1_Contact_Sensor_Contact     "Contact: [%s]"                              <door> (SNZB_04_1_Contact_Sensor, DoorSensors) { channel="mqtt:topic:snzb04a:sensor" } 
      Contact SNZB_04_1_Contact_Sensor_Tamper      "Tamper [MAP(snzb_boolean.map):%s]"           <none> (SNZB_04_1_Contact_Sensor)              { channel="mqtt:topic:snzb04a:tamper" }
      Contact SNZB_04_1_Contact_Sensor_Battery_Low "Battery low [MAP(snzb_boolean.map):%s]" <none> (SNZB_04_1_Contact_Sensor)              { channel="mqtt:topic:snzb04a:battery_low" }
      Number  SNZB_04_1_Contact_Sensor_Link        "Link quality [%d]"                          <none> (SNZB_04_1_Contact_Sensor)              { channel="mqtt:topic:snzb04a:linkquality" }
      Number  SNZB_04_1_Contact_Sensor_Battery     "Battery [%d]"                               <none> (SNZB_04_1_Contact_Sensor)              { channel="mqtt:topic:snzb04a:battery" }
      Number  SNZB_04_1_Contact_Sensor_Voltage     "Voltage [%d]"                               <none> (SNZB_04_1_Contact_Sensor)              { channel="mqtt:topic:snzb04a:voltage" }
      
    3. Create a Rule

      val String filename = "doors_and_windows_and_tings.rules"
      
      rule "Door sensor status"
      when
          Member of DoorSensors changed
      then
          logInfo(filename, triggeringItem.name + ": " + triggeringItem.state)
      
          switch (triggeringItem.state) {
             case OPEN: {
                 switch (triggeringItem) {
                     case SNZB_04_1_Contact_Sensor_Contact: {
                        // The ***ting door is open!
                     }
                 }
             }
             case CLOSED: {
                 switch (triggeringItem) {
                     case SNZB_04_1_Contact_Sensor_Contact: {
                        // Closed now
                     }
                 }
             }
         }
      end 
      

Done. :sunglasses:

5 Likes

Thanks for this, looks great!

You can do at least this one, and probably a few more directly in the channel without the JS transformation:

Cheers!

Will have to re-evaluate the JS transformations as they are probably not all necessary, I know the contact sensor one is useful though as it flips the OPEN = True mapping to the opposite of the rest. They helped me get through implementation without errors so I included them here.

Bring on the improvements though. Let’s trim-the-fat/shed-some-weight/less-is-more this approach!

I hear you - I went on the same journey recently with WLED stuff!

I think you can trim this down very easily already. For example, on your motion sensor, you could get rid of all the JS transforms by changing your things file as follows:

Type contact : occupancy   "Occupancy"    [ stateTopic="zigbee2mqtt/UNIQUE_ZIGBEE_ID", transformationPattern="JSONPATH:$.data.occupancy", on="true", off="false"]
Type contact : tamper      "Tamper"       [ stateTopic="zigbee2mqtt/UNIQUE_ZIGBEE_ID", transformationPattern="JSONPATH:$.data.tamper", on="true", off="false"]
Type contact : battery_low "Battery Low"  [ stateTopic="zigbee2mqtt/UNIQUE_ZIGBEE_ID", transformationPattern="JSONPATH:$.data.battery_low", on="true", off="false"]
     

The above will use the JSONPATH transform to extract the required values, then map true and false to on and off (which for a contact channel actually means true and false will map to open and closed). If you want to switch it, you can map on="false" and off="true"

(I’ve made an assumption here on what the device actually returns on these topics, so you may need to tweak)

2 Likes

Good idea. Done! Replaced with a few simple maps. Much cleaner now.

Also improved my Zigbee2MQTT item by leaning on what I picked up from your post on the topic. Muchas gracias :+1:

1 Like

I have this setup in place, but the range is not that good. Sonoff also released a ZigBee bridge which can be flashed with Tasmota. I saw some tutorials to connect it directly with home assistant through their ZigBee binding. Is this also possible with the Openhab ZigBee binding?
Connecting everything via mqtt is possible, but it can be easier :smile:

Hey there,
I know you decided to go the MQTT way, but was wondering if anyone has any idea if it will just work with Zigbee Binding directly!
I’m thinking of buying some of those, but would be nice if someone had a positive experience already.

Yes, I was able to get SONOFF SNZB-03 motion sensor working with standard ZigBee binding directly. The key to discovering is to change the ZigBee USB stick channel to 15. See this thread. I believe it is a ZigBee 3.0 strangeness. (Zigbee 3.0 Installation Code )

1 Like

I’m not able to get the SNZB-02 temperature/humidity sensor to work. I was able to join the device, but the sensor doesn’t send any data.

“date_code” : “20201026”,
“definition” : {
“description” : “Temperature and humidity sensor”,
“exposes” : [ {
“access” : 1,
“description” : “Remaining battery in %”,
“name” : “battery”,
“property” : “battery”,
“type” : “numeric”,
“unit” : “%”,
“value_max” : 100,
“value_min” : 0
}, {
“access” : 1,
“description” : “Measured temperature value”,
“name” : “temperature”,
“property” : “temperature”,
“type” : “numeric”,
“unit” : “°C”
}, {
“access” : 1,
“description” : “Measured relative humidity”,
“name” : “humidity”,
“property” : “humidity”,
“type” : “numeric”,
“unit” : “%”
}, {
“access” : 1,
“description” : “Link quality (signal strength)”,
“name” : “linkquality”,
“property” : “linkquality”,
“type” : “numeric”,
“unit” : “lqi”,
“value_max” : 255,
“value_min” : 0
} ],
“model” : “SNZB-02”,
“vendor” : “SONOFF”
},
“endpoints” : {
“1” : {
“bindings” : [ {
“cluster” : “msTemperatureMeasurement”,
“target” : {
“endpoint” : 1,
“ieee_address” : “0x00124b0018e1aba5”,
“type” : “endpoint”
}
}, {
“cluster” : “msRelativeHumidity”,
“target” : {
“endpoint” : 1,
“ieee_address” : “0x00124b0018e1aba5”,
“type” : “endpoint”
}
}, {
“cluster” : “genPowerCfg”,
“target” : {
“endpoint” : 1,
“ieee_address” : “0x00124b0018e1aba5”,
“type” : “endpoint”
}
} ],
“clusters” : {
“input” : [ “genBasic”, “genIdentify”, “msTemperatureMeasurement”, “msRelativeHumidity”, “genPowerCfg” ],
“output” : [ “genIdentify” ]
},
“configured_reportings” : [ {
“attribute” : “measuredValue”,
“cluster” : “msTemperatureMeasurement”,
“maximum_report_interval” : 1800,
“minimum_report_interval” : 5,
“reportable_change” : 50
}, {
“attribute” : “measuredValue”,
“cluster” : “msRelativeHumidity”,
“maximum_report_interval” : 3600,
“minimum_report_interval” : 10,
“reportable_change” : 100
}, {
“attribute” : “batteryVoltage”,
“cluster” : “genPowerCfg”,
“maximum_report_interval” : 62000,
“minimum_report_interval” : 3600,
“reportable_change” : 0
} ]
}
},
“friendly_name” : “TH01_SENSOR1”,
“ieee_address” : “0x00124b002268578f”,
“interview_completed” : true,
“interviewing” : false,
“model_id” : “TH01”,
“network_address” : 32103,
“power_source” : “Battery”,
“supported” : true,
“type” : “EndDevice”

With the SONOFF SNZB-03 Motion Sensor there was no problems it instantly begin to publish its data to my ZigBee2Mqtt bridge.

info 2021-02-12 11:12:41: MQTT publish: topic ‘zigbee2mqtt/MS01-MOTION1/occupancy’, payload ‘true’
info 2021-02-12 11:12:41: MQTT publish: topic ‘zigbee2mqtt/MS01-MOTION1/tamper’, payload ‘false’
info 2021-02-12 11:12:41: MQTT publish: topic ‘zigbee2mqtt/MS01-MOTION1/battery_low’, payload ‘false’
info 2021-02-12 11:12:41: MQTT publish: topic ‘zigbee2mqtt/MS01-MOTION1/linkquality’, payload ‘47’
info 2021-02-12 11:13:41: MQTT publish: topic ‘zigbee2mqtt/MS01-MOTION1/occupancy’, payload ‘false’
info 2021-02-12 11:13:41: MQTT publish: topic ‘zigbee2mqtt/MS01-MOTION1/tamper’, payload ‘false’
info 2021-02-12 11:13:41: MQTT publish: topic ‘zigbee2mqtt/MS01-MOTION1/battery_low’, payload ‘false’
info 2021-02-12 11:13:41: MQTT publish: topic ‘zigbee2mqtt/MS01-MOTION1/linkquality’, payload ‘47’

1.) Is it paired corretly with the Zigbee bridge?

2.) Have you checked with a mqtt Client

3.) is your openhab Configuration right

4.) Did you read that

The solution was for me to switch to the DEV branch of Zigbee2Mqtt, after that sensors immediately begun to publish their data. Thanks, anyway Dibbler42.

I switched only because of the SNZB-02 sensor. All other Zigbee2Mqtt devices that I’m using were working without issues (e.g. IKEA bulbs, IKEA motion sensors and even SNZB-03 motion sensor).

Sonoff SNZB-02 issue

How to Switch to DEV branch of Zigbee2Mqtt

1 Like

Have you thought about using the Sonoff Zigbee Bridge itself flashed with tasmota2mqqt?
That is how im currently receiving data from all my sensors. It takes out the need for any other binding as openhab just pick up the mqqt that the bridge outputs. Worth having a look anyway :grinning:

1 Like

A tip. Don’t use Contact as the Type use Switch. If you don’t put anything in the Command parameters the device becomes a read only switch (which is what it is really). Dealing with the state then becomes easier.
I think the original idea of the Contact was for an alarm sensor which in untriggered state is Closed and Open is actuated.

Does anyone know how to publish a message from true and false to 1 & 0? my door contact has values of true and false but my security system only recognises 1 & 0.

cheers

Continuing the discussion from Sonoff Zigbee (SNZB) Sensors & Switches with Zigbee2MQTT:

First of all, thanks for the great tips. Without you I would never have been able to set up my Sonoff devices.

With your tips I was able to integrate the temperature sensor.

Here is my version of the working SNZB-02 setup.
I only had to adjust the motion detector setup a little bit.

temperatursensor.items

Group TemperatureSensoren "Temperatursensoren" <motion>

Group  SNZB_02_1_Temperatur_Humidity_Sensor "Important Room Motion Sensor" <sonoff_snzb02> (GF_ImportantRoom, Sonoff_SNZB_02)
Number SNZB_02_1_Temperatur_Humidity_Sensor_temperature   "Temperatur [%s]" <motion> (SNZB_02_1_Temperatur_Humidity_Sensor, TemperatureSensoren) { channel="mqtt:topic:snzb02a:temperature" }
Number SNZB_02_1_Temperatur_Humidity_Sensor_humidity      "humidity [%s]"              <none>   (SNZB_02_1_Temperatur_Humidity_Sensor)                { channel="mqtt:topic:snzb02a:humidity" }
Contact SNZB_02_1_Temperatur_Humidity_Sensor_Battery_Low "Battery low [%s]"         <none>   (SNZB_02_1_Temperatur_Humidity_Sensor)                { channel="mqtt:topic:snzb02a:battery_low" }
Number  SNZB_02_1_Temperatur_Humidity_Sensor_Link        "Link quality [%d]"                             <none>   (SNZB_02_1_Temperatur_Humidity_Sensor)                { channel="mqtt:topic:snzb02a:linkquality" }
Number  SNZB_02_1_Temperatur_Humidity_Sensor_Battery     "Battery [%d]"                                  <none>   (SNZB_02_1_Temperatur_Humidity_Sensor)                { channel="mqtt:topic:snzb02a:battery" }
Number  SNZB_02_1_Temperatur_Humidity_Sensor_Voltage     "Voltage [%d]"                                  <none>   (SNZB_02_1_Temperatur_Humidity_Sensor)                { channel="mqtt:topic:snzb02a:voltage" }

temperatursensor.things

Thing mqtt:topic:snzb02a "Temperatur Sensor" (mqtt:broker:MQTT-Broker) @ "Important Room" {
   Channels:
     Type number : temperature   "Temperature"    [ stateTopic="zigbee2mqtt/Temperatursensor_02", transformationPattern="JSONPATH:$.temperature"]
     Type number : humidity      "Humidity"       [ stateTopic="zigbee2mqtt/Temperatursensor_02", transformationPattern="JSONPATH:$.humidity"]
     Type contact : battery_low "Battery Low"  [ stateTopic="zigbee2mqtt/Temperatursensor_02", transformationPattern="JSONPATH:$.battery_low", on="true", off="false"]
     Type number : linkquality  "Link Quality" [ stateTopic="zigbee2mqtt/Temperatursensor_02", transformationPattern="JSONPATH:$.linkquality"]
     Type number : battery      "Battery"      [ stateTopic="zigbee2mqtt/Temperatursensor_02", transformationPattern="JSONPATH:$.battery"]
     Type number : voltage      "Voltage"      [ stateTopic="zigbee2mqtt/Temperatursensor_02", transformationPattern="JSONPATH:$.voltage"]
}