SLZB-OS

Operating system for SLZB series devices: SLZB-06x, SLZB-MRx, SLZB-06xU and SLZB-MRxU

About SLZB-OS

Dashboard

2. Dashboard

The Dashboard is the first screen you see when logging into SLZB-OS.
It provides an at-a-glance overview of your device’s current status, connectivity, and Zigbee network health.
From here, you can quickly access detailed sections via the top or side navigation menus.

image.png


2.1 Layout Overview

The dashboard typically consists of the following key blocks:

  1. Device Status Panel

    • Model – Displays the hardware model (e.g., SLZB-MR1U).

    • Firmware Version – Current SLZB-OS version installed.

    • Uptime – How long the device has been running since last restart.

    • CPU & Memory Usage – Real-time resource utilization.

  2. Network Status

    • IP Address – Current assigned IPv4 address.

    • Connection Type – Ethernet, PoE, USB, or Wi-Fi (depending on model).

    • MAC Address – Unique network identifier.

    • Link Status – Connection state and link speed.

  3. Zigbee Hub Summary

    • Coordinator State – Online/Offline status.

    • Connected Devices – Number of active Zigbee devices.

    • Last Message – Timestamp of the last received Zigbee event.

    • Zigbee2MQTT / ZHA Status – Shows which integration is currently active.

  4. Quick Actions

    • Restart Device – Reboots the SLZB device.

    • Restart Zigbee Hub – Restarts Zigbee coordinator service without rebooting the whole system.

    • Open Zigbee2MQTT Web UI – Shortcut to Z2M frontend (if enabled).

    • Check for Firmware Update – Quick link to update page.


2.2 Indicators & Colors


2.3 Typical Uses

Mode

3. Mode

The Mode page lets you choose how the coordinator is exposed to your smart‑home stack.

image.png

3.1 Radio SoC Modes

Your SLZB device’s primary radio SoC can operate in different roles depending on your smart home network design:

1. Zigbee Coordinator

2. Zigbee Router

3. OpenThread Border Router (OTBR)

4. Zigbee Hub (SLZB-OS managed)


3.2 Connection Modes

Once the radio role is selected, choose how the coordinator/router connects to your automation system:

A) Ethernet (Serial over TCP)

B) USB (Direct Serial)

C) Wi-Fi


3.3 Additional Features

These optional modes and functions can be enabled separately to expand device capabilities:

Wi-Fi Bridge (Ethernet ↔ Wi-Fi)

Bluetooth Proxy (ESPHome mode)


3.4 How to Apply Changes

  1. Go to Mode in the SLZB-OS menu.

  2. Select Radio SoC mode (Coordinator / Router / OTBR / Zigbee Hub).

  3. Choose Connection mode (Ethernet / USB / Wi-Fi).

  4. Enable any Additional Features (Wi-Fi Bridge, BLE Proxy) if needed.

  5. Click Save/Apply.

  6. Restart the service or device if prompted.

  7. Confirm status in Dashboard and, for Zigbee Hub, under Zigbee Hub → Dashboard.

Zigbee Hub

Build your local ZigBee network without Z2M/ZHA

Zigbee Hub

About Zigbee Hub mode

4. About Zigbee Hub mode

It is highly recommended to use U series coordinators for this mode (SLZB-06xU / MRxU / Ultima)

Limitations:
- no support for ZigBee devices that require a manufacturer code
- no support for ZGP
- no OTA updates for ZigBee devices
- limited support for ZigBee devices that use non-standard clusters (requires special converters)
- limited number of devices that can be paired:
   U series coordinators - up to 100 devices.
   non-U series - up to 20 devices.
It is not recommended to use more than this limit (although technically possible)

4.1 What is Zigbee Hub in SLZB-OS?

The Zigbee Hub feature allows the SLZB device to run its Zigbee network directly on the device — without needing an external computer, Raspberry Pi, or NAS to host the Zigbee stack.
In Zigbee Hub mode, SLZB-OS launches an integrated Zigbee stack service that can connect directly to your smart home platform over MQTT.

This mode is ideal for:

When Zigbee Hub is active, a dedicated Zigbee Hub menu appears in the SLZB-OS interface, containing the following pages:

  1. Dashboard – Live overview of Zigbee network status.

  2. Devices – List and manage all paired Zigbee devices.

  3. MQTT – Configure the MQTT broker connection.

  4. Settings – Advanced Zigbee network and coordinator options.


4.2 Zigbee Hub → Dashboard

The Dashboard is the central monitoring page for your Zigbee network.

image.png

The dashboard contains cards of your ZigBee devices with the data they provide and controls.
The dashboard is updated in real time via SSE.


4.3 Zigbee Hub → Devices

The Devices page lists every Zigbee device paired to your coordinator.

image.png

Pairing control: 

For each device, you’ll see:

Typical uses:

Device config

How to rename device

Select the pencil icon image.png

image.png

Enter new name and press "Save". Maximum length - 50 characters.

Device config

Click on the wrenchimage.png

Binding

image.png

This menu sends the device a bind request to the coordinator, the device must be active to accept this. If it is a battery-powered device you need to wake it up.

Configure reporting

image.png

Polling

image.png

Allows you to configure polling of the selected attribute after a certain time interval

Exposes

image.png

image.png

Provides information about expected data from the device and examples of using MQTT, HTTP, and Berry API to get or set device state.

IMPORTANT!
This section provides information about EXPECTED data from the device, based on information about the device clusters or converter (if it exists).
This information may not match the actual behavior of the device if it uses non-standard clusters!
If this is a Tuya DP device, then information will be displayed here only if a converter exists for the device!

Other tools

image.png

Here you can find the ZCN converter number (if used) and download device information


4.4 Zigbee Hub → MQTT

This page configures the MQTT connection that Zigbee2MQTT (running on SLZB-OS) uses to communicate with your smart home platform.

image.png

Configuration fields include:

Tips:


4.5 Zigbee Hub → Settings

The Settings page contains deeper configuration for the Zigbee coordinator and Zigbee2MQTT service.

image.png

Typical settings available:

Best practices:

4.6 Troubleshooting

Problems when starting a Zigbee network

OS v3.0.9 update is breaking. If you updated OS to v3.0.9 and started getting this error then follow the instructions below

Network commissioning timed out - most likely network with the same panId or extendedPanId already exists nearby.
Network formation refused there is too much RF interference or network with the same panId or extendedPanId already exists.
If you got this error after updating Zigbee chip:
- turn off coordinator
- turn off ALL Zigbee routers that were connected to Zigbee Hub. This is important, it will not work without this
- turn on coordinator. Zigbee Hub should start now but zigbee devices will be unavailable
- remove all devices (click on the red trash can)
- download and run berry script below, this script will keep permit join enabled as long as it is running
#META {"start":0}
#Insert your code below
import ZHB

ZHB.waitForStart(0xFF)

while 1
  ZHB.permitJoin(254)
  SLZB.delay(255 * 1000)
end
- turn back on previously disabled zigbee devices
- repair all devices
- after devices repaired you can stop and delete script

Other cases:
- move the coordinator away from the wifi router
- make sure there is no other coordinator nearby with the same zigbee network settings
Zigbee Hub

MQTT API

image.png

Zigbee Hub mode has the ability to connect to local or remote MQTT brokers. Currently only TCP connections are supported.
This document describes MQTT API for SLZB-OS 3.0.9 or higher

Topics are divided into IN and OUT.
IN - you can send messages to these topics.
OUT - Zigbee Hub sends messages to these topics.

zHub topics format

Data topic (OUT)

General data topic format below:
base topic / data / zigbee device ieee / zigbee endpoint / zigbee cluster / zigbee attribute

base topic - global prefix, so you can have few Zigbee Hubs connected to one broker, you just have to set different base topics.
data - static text (topic type)
zigbee device ieee - sender IEEE address in HEX format.
zigbee endpoint - zigbee endpoint from which this message is coming, DEC format.
zigbee cluster - zigbee cluster from which this message is coming, HEX format.
zigbee attribute - zigbee attribute from which this message is coming, HEX format.

Data topic example: zhub/data/a4c1383439bf5cc9/1/0000/0001

Read topic (IN) (available from v3.3.0)

This topic accepts requests to read attributes of ZigBee devices.
When you send a message to this topic, the coordinator generates and sends a request for the specified attribute to the target ZigBee device. The device must be online to accept the request, so this is usually used for AC-powered devices.

Topic format: base topic / read / zigbee device ieee / zigbee endpoint / zigbee cluster / zigbee attribute

base topic - global prefix, so you can have few Zigbee Hubs connected to one broker, you just have to set different base topics.
read - static text (topic type)
zigbee device ieee - sender IEEE address in HEX format.
zigbee endpoint - zigbee endpoint from which this message is coming, DEC format.
zigbee cluster - zigbee cluster from which this message is coming, HEX format.
zigbee attribute - zigbee attribute from which this message is coming, HEX format.

Read topic example: zhub/read/a4c1383439bf5cc9/1/0006/0000
payload: any text

Attribute update will be sent to data topic!

PLEASE NOTE!
You must add any text content to the payload!
Do not send an empty payload to this topic!
An empty payload will only delete this topic (if it exists). The coordinator will not respond to empty payloads.

Command topic (IN)

This topic is intended for sending ZCL commands to a Zigbee device.
General cmd topic format below:
base topic / cmd / zigbee device ieee / zigbee endpoint / zigbee cluster / zigbee command

base topic - global prefix, so you can have few Zigbee Hubs connected to one broker, you just have to set different base topics.
cmd - static text (topic type)
zigbee device ieee - target zigbee device IEEE address in HEX format.
zigbee endpoint - target zigbee device endpoint to which this message is coming, DEC format.
zigbee cluster - target zigbee device cluster to which this message is coming, HEX format.
zigbee command - zigbee command to send, HEX format.

Some clusters have special handlers for input commands, such as the ON/OFF or Light cluster. You can find their formats below:

ON/OFF cluster payload format for command topic

ON - send ON command
OFF - send OFF command

Example: zhub/cmd/a4c1383439bf5cc9/1/0006 payload: ON
Will send command to enable relay or light device.

Level control for Light cluster payload format

0000 command payload is a number in DEC from 1 to 254, the larger the number, the brighter the lamp will be.

Color control cluster payload format

0007 command payload is a color in HEX or RGB format. For example: 255,29,0 or #FFFFFF
000a command payload is a light temperature in mired. For example: 200

Other clusters

If no built-in clusters or ZCN converters has overridden the processing of this command, if the command contains a payload, it must be a HEX string of the following format:
- Bytes without spaces, uppercase, multiple of two. Example: 010203FF
- Bytes with spaces, uppercase, grouped by two. Example: 01 02 03 FF

Write topic (IN)

This topic is intended for writing ZigBee device ZCL attributes.
General write topic format below:
base topic / write / zigbee device ieee / zigbee endpoint / zigbee cluster / zigbee attribute

base topic - global prefix, so you can have few Zigbee Hubs connected to one broker, you just have to set different base topics.
write - static text (topic type)
zigbee device ieee - target zigbee device IEEE address in HEX format.
zigbee endpoint - target zigbee device endpoint to which this message is coming, DEC format.
zigbee cluster - target zigbee device cluster to which this message is coming, HEX format.
zigbee attribute - target zigbee device attribute to which this message is coming, HEX format.

Cluster 0006, attribute 4003 payload format
Last state - device will remember its state
ON - device will be on after power loss
OFF - device will be off after power loss

Cluster EF00 (Tuya DP) payload format

Please note that the write topic format for Tuya is different! base topic / write / zigbee device ieee / 1 / ef00 / data point / data type

data point - Tuya data point id. You can read more about it here: https://www.zigbee2mqtt.io/advanced/support-new-devices/03_find_tuya_data_points.html
data type - a number that represents the type of data being sent.
0 - RAW,  1 - BOOL,  2 - INT,  3 - STRING,  4 - ENUM,  5 - BITMAP

Examples:
topic: zhub/write/a4c138d089d1418c/1/ef00/0018/1
payload: 1

Any other clusters/attributes payload format

Payload should contain JSON: {"type": <zigbee data type>, "data":<data to be sent>}
type - a number that represents the type of data being sent.

Zigbee Data Types and Data Type IDs

Data Class

Data Type

Data Type ID

Null

No data
Reserved

0x00
0x01—0x07

General Data

8-bit data
16-bit data
24-bit data
32-bit data
40-bit data
48-bit data
56-bit data
64-bit data

0x08
0x09
0x0a
0x0b
0x0c
0x0d
0x0e
0x0f

Logical

Boolean
Reserved

0x10
0x11—0x17

Bitmap

8-bit data
16-bit data
24-bit data
32-bit data
40-bit data
48-bit data
56-bit data
64-bit data

0x18
0x19
0x1a
0x1b
0x1c
0x1d
0x1e
0x1f

Unsigned integer

Unsigned 8-bit integer
Unsigned 16-bit integer
Unsigned 24-bit integer
Unsigned 32-bit integer
Unsigned 40-bit integer
Unsigned 48-bit integer
Unsigned 56-bit integer
Unsigned 64-bit integer

0x20
0x21
0x22
0x23
0x24
0x25
0x26
0x27

Signed integer

Signed 8-bit integer
Signed 16-bit integer
Signed 24-bit integer
Signed 32-bit integer
Signed 40-bit integer
Signed 48-bit integer
Signed 56-bit integer
Signed 64-bit integer

0x28
0x29
0x2a
0x2b
0x2c
0x2d
0x2e
0x2f

Enumeration

8-bit enumeration
16-bit enumeration
Reserved

0x30
0x31
0x32—0x37

Floating point

Semi-precision
Single precision
Double precision
Reserved

0x38
0x39
0x3a
0x3b—0x3f

String

Reserved
Octet string
Character string
Long octet string
Long character string
Reserved

0x40
0x41
0x42
0x43
0x44
0x45—0x47

Ordered sequence

Array
Reserved
Structure
Reserved

0x48
0x49—0x4b
0x4c
0x4d—0x4f

Collection

Set
Bag
Reserved

0x50
0x51
0x52—0x57

Reserved

-

0x58—0xdf

Time

Time of day
Date
UTC Time
Reserved

0xe0
0xe1
0xe2
0xe3—0xe7

Identifier

Cluster ID
Attribute ID
BACnet ID
Reserved

0xe8
0xe9
0xea
0xeb—0xef

Miscellaneous

IEEE Address
128-bit security key
Reserved

0xf0
0xf1
0xf2—0xfe

Unknown

Unknown

0xff

data - a HEX string of the following format:
- Bytes without spaces, uppercase, multiple of two. Example: 010203FF
- Bytes with spaces, uppercase, grouped by two. Example: 01 02 03 FF

Please note that the number of bytes in the payload strictly depends on the data type!
For example, if you send data with type 16-bit integer, the number of bytes in the payload should be 2.
Example: {"type": 33, "data":"0000"}
33 - is 0x21 converted to DEC

System control topic (IN) (available from v3.3.0)

This topic allows you to control main functions of the Zigbee Hub.

Topic format: base topic / system_control

Payload format: {"action": "<system control actions>", <additional parameters>}

Permit join action

Allows you to open a ZigBee network to add new devices.

Payload format: {"action": "permit_join", "time": <time to open the network in seconds, from 1 to 254>, "addr": <network address of the device on which to open the network. Can be omitted if the network needs to be opened on all devices>}

Examples:
{"action": "permit_join", "time": 60} - open the entire network for 60 seconds
{"action": "permit_join", "time": 0} - close network
{"action": "permit_join", "time": 60, "addr": 64580} - open the network for 60 seconds only on device with network address 64580 (DEC number, not HEX)

Configure reporting action

Configures reporting for the selected device. If the device is battery-powered, it must be woken up to accept this command.

Payload format: {"action": "configure_reporting", "ieee": <IEEE address of the target device, HEX string>, "ep": <target endpoint, DEC>, "cl": <target cluster, DEC>, "attr": <target attribute, DEC>, "minRep": <minimum time for reporting in seconds, DEC>, "maxRep": <max time for reporting in seconds, DEC>, "dType": <zigbee reporting data type for this attribute, DEC>, "change": <how much the attribute value must change for reporting to occur. Should be omitted for discrete attributes>}

Examples:
{"action": "configure_reporting", "ieee": "3425b4fffe12e9e9", "ep": 1, "cl": 6, "attr": 0, "minRep": 1, "maxRep": 3600, "dType": 0} - configure ON/OFF attribute repotring to minimum 1s and max 3600s report time. "change" field is omitted because it is a discrete attribute.
{"action": "configure_reporting", "ieee": "3425b4fffe12e9e9", "ep": 1, "cl": 2820, "attr": 1285, "minRep": 30, "maxRep": 3600, "dType": 33, "change": 200} - configure RMS Voltage attribute repotring to minimum 1s and max 3600s report time. Reporting will occur no earlier than 30s if the value has changed by 200 or more (2v) or after a 3600s timeout if value does not changed.

Binding action

Binds the target device to the coordinator or to another device.

If one device bound to another, the coordinator will stop receiving reports from the bound device cluster.

Payload format: {"action": "binding", "mode": "<binding mode>", "scrIeee": "<IEEE of the device to which the binding request will be sent, HEX string>", ""scrEp": <endpoint number that needs to be bound, DEC number>, "scrCl": <cluster number that needs to be bound, DEC number>, <additional parameters>}

To device mode

Binds one device to another.

Payload format: {"action": "binding", "mode": "to_device", "scrIeee": "<IEEE of the device to which the binding request will be sent, HEX string>", ""scrEp": <endpoint number that needs to be bound, DEC number>, "scrCl": <cluster number that needs to be bound, DEC number>, "dstEp": <endpoint number to which the binding will be done, DEC number>, "dstIeee": "<IEEE device to which binding will be performed, HEX string>"}

Example: {"action": "binding", "mode": "to_device", "scrIeee": "3425b4fffe12e9e9", ""scrEp": 1, "scrCl": 6, "dstEp": 1, "dstIeee": "a4c1389ffb198304"} - binding a Zigbee button (ON/OFF cluster) to a Zigbee relay.

To coordinator mode

Binds to the coordinator so that it can receive reports from this cluster.

Zigbee Hub will attempt to bind automatically when interviewing a device, but this does not always work perfectly.

Payload format: {"action": "binding", "mode": "to_device", "scrIeee": "<IEEE of the device to which the binding request will be sent, HEX string>", ""scrEp": <endpoint number that needs to be bound, DEC number>, "scrCl": <cluster number that needs to be bound, DEC number>}

Example: {"action": "binding", "mode": "to_coordinator", "scrIeee": "3425b4fffe12e9e9", ""scrEp": 1, "scrCl": 6} - binding a Zigbee button (ON/OFF cluster) to the coordinator.

Zigbee Hub

Berry ZCN system manual

Everything here requires the device to run in Zigbee Hub mode and SLZB-OS v3.3.8.dev0 or higher.

This document describes the Berry side of the ZCN converter system: writing device-specific Zigbee Hub converters as Berry scripts, without rebuilding the firmware.

The concept of ZCN primarily refers to native C++ converters, but we decided to keep this name for Berry converters for simplicity. Actually Berry converters are not native, they are a scripting interface.


1. What Berry ZCN is and when to use it

A Berry ZCN converter is the runtime-scriptable twin of a native zcn_converter_t: a description of how a specific Zigbee device deviates from standard ZCL handling — extra/proprietary attributes, remapped clusters, custom value normalization, custom MQTT/Home Assistant discovery — plus Berry callback functions that the hub invokes at the same points where native converters invoke C function pointers.

Use Berry ZCN when you want to:


2. Architecture and lifecycle

2.1 Slots

There are  (currently 2) slots for Berry converters. Each registered converter occupies one slot. Registration fails with "no free slots for ZCN" when all slots are taken.

2.2 VM binding and garbage collection

2.3 Attachment is NOT persisted — attach on every boot

This is the most important lifecycle difference from native ZCN:

Since interviews only run at pairing, a converter script must call ZCN.attach() for its devices every time it starts. The standard pattern:

var slot = ZCN.register(my_converter)
ZCN.attach(slot, "0x3425b4fffe12e9e9") # repeat for each device

Optional, run the script with autostart (#META {"start":1}) so the converter is registered and attached right after boot.

2.4 Priority over native converters

Berry converters take priority everywhere:

2.5 Matching logic


3. Quick start

The easiest way to produce a converter is the ZCN Builder page in the web UI (Zigbee Hub → ZCN Builder): assemble the structure in the form, pick callback presets, and copy the generated Berry code. 

ZCN.register() validates the map, finds a free slot, and feeds the structure into the native slot. It returns the slot number (needed for ZCN.attach) and raises a descriptive error on failure (the partially built slot is deleted automatically).


4. Converter map reference

The converter is a plain Berry map. Missing keys get defaults: int → 0, string → "", bool → false, function → nil (exceptions noted below). Extra/unknown keys are ignored.

4.1 Top level

Key Type Required Meaning
signature map yes (raises otherwise) Device matching, see below
on_annonce function no Called when the device announces itself (power-on / rejoin)
on_intw_stage function no Called before interview stages; see §5.2
overrides_count int yes, if overrides present Must equal overrides.size() — it is not derived automatically
overrides list of maps no Endpoint overrides

4.2 signature

The signature tells SLZB-OS whether this converter is suitable for the device for which the interview is currently being performed.

Key Type Meaning
matcher function If present, used instead of model/manuf. Must be a function
model string Zigbee model identifier (exact match via strcmp())
manuf string Manufacturer name (exact match)

4.3 Endpoint override (element of overrides)

Key Type Meaning
endpoint int Zigbee endpoint number this override applies to
clusterCount int Number of clusters in clusters
clusters list of maps Cluster object array

4.4 Cluster override (element of clusters)

Key Type Default Meaning
id int 0 ZCL cluster id (e.g. 0x0402)
addMode int 0 0 = ADD (merge with the standard cluster: your attrs are used where ids collide, standard attrs fill the rest),
1 = OVERRIDE (standard cluster fully ignored; only your definition used)
bind bool false Bind this cluster to the hub during interview
attrCount int 0 Number of attributes in attrs
attrs list of maps Attribute objects array
cmd_config map Cluster command handling (buttons/actions), see below
on_mqtt_cmd function nil Used for cmd_config.
Handles MQTT messages on the {base}/cmd/... topic for this cluster. Return true = handled (standard handling skipped)

4.5 cmd_config

Tells SLZB-OS what actions(triggers) this cluster provides. Typically used for Zigbee buttons and scene remotes.

Key Type Meaning
on_cmd function

Converts the received command record into an action string (e.g. "btn_single").

Must return a string to publish it as an action.

exposes string "|"-separated list of all possible action strings — used to generate device-trigger discovery
exposesOverride function Dynamic alternative to exposes: return the "|"-separated list at discovery time; empty-string return skips triggers for this cluster

Note: the command path is only taken when the cluster has on_cmd and at least one of exposes / exposesOverride.

4.6 Attribute override (element of attrs)

Key Type Default Meaning
id int 0 ZCL attribute id
name string "" Human-readable name (shown in web UI)
mqttClass int 0 MQTT entity type, see table below
mqttSubClass string "" MQTT entity device_class (e.g. "temperature""moisture")
unit string "" Unit of measurement (e.g. "°C")
dataType int 0

ZCL data type.

Required for configuring reporting and if this attribute is writable.

Can be omitted if the attribute is not writable and not reported.

ram bool false If True, ZHB will create a special container (record) for this attribute in RAM at startup. The received value will be cached in this container, only the last value is stored.
rp bool false Configure attribute reporting during interview. Also adds this attribute to web UI "configure reporting" dialog.
minReport int 1 Reporting: minimum interval, s.
Can be omitted if rp is false
maxReport int 3600 Reporting: maximum interval, s.
Can be omitted if rp is false
change int 1 Reporting: reportable change threshold.
Can be omitted if rp is false
rpChangeMult real 0

Multiplier for the web UI "configure reporting" dialog:

raw ZCL reportable change = human value × rpChangeMult (e.g. 100 for 0.01-unit temperature).
Can be omitted if rp is false

query bool false If True, the coordinator will send a request to read this attribute when the hub starts.
on_normalize function nil Tells ZHB how to convert raw Zigbee data into usable data, see §5.4
on_serialization function nil Tells ZHB how to convert data in a container (record) into a text representation, see §5.5
on_discovery function nil Allow you to customize/veto discovery for this attribute, see §5.6
on_mqtt_write function nil Tells ZHB how to handle {base}/write/... MQTT messages, see §5.7

mqttClass values:

Value Class
0 NONE (not exposed to WEB/MQTT)
1 BINARY_SENSOR
2 BUTTON
3 TRIGGER
4 EVENT (Not supported by ZHB dashboard)
5 FAN (Not supported by ZHB dashboard)
6 LIGHT
7 NUMBER
8 SELECT
9 SENSOR
10 SWITCH
11 TEXT (Not supported by ZHB dashboard)
12 COVER (Not supported by ZHB dashboard)

5. Callback reference

All callbacks run inside your script's VM, scheduled through the Berry event system. The hub task waits up to ~20 ms for the VM to become available; if the VM is busy longer (e.g. a blocked loop in your script), the event is dropped — keep both the callbacks and the rest of the script non-blocking.

dev arguments are ZigbeeDevice instances, record arguments are ZclAttrRecord instances (§6). doc/data are JSON proxy objects supporting obj["key"] = value style access.

5.1 on_annonce

Called when an attached device sends a device announce (typically power-on or rejoin). Return value ignored.

5.2 on_intw_stage

Called before interview stages, identified by string tag. Return one of:

Return Meaning
0 (DONE) Stage handled by the converter — hub skips its standard logic and go to next stage
1 (WAIT) Converter started something async — hub waits, stage will be re-entered
2 (ERR) Fail interview on this stage
3 (ZCN_UNUSED) Converter does not care — hub runs standard logic (default choice)

Stage tags: req_epdiscover_epget_power_sourceautobindconf_reportingias_enrollget_ias_typesend_tuya_magic.

Caveat (same as native): on the first interview the converter is matched at the intw_zcn stage, so tags for stages ordered before it (req_epdiscover_ep) only fire on re-interview — unless the device was pre-attached with ZCN.attach().

5.3 cmd_config.on_cmd

Called when a ZCL command arrives on the cluster (record.isCmd() is true; record.getAttr() holds the command id). Return the action string to publish (must be one of the exposes values for HA to recognize it). Non-string return = not handled.
Important for Tuya commands: record.asInt() contains the ID of the Tuya command and record.getAttr() its data.

5.4 on_normalize

Called right after the raw ZCL value is parsed into the record, before it is stored and serialized.
Mutate the record in place:

"on_normalize": def (record, dev)
  record.setFloat(record.asInt() / 100.0)
end

You can also redirect a record to another cluster/attr (record.setCl()record.setAttr()record.setEp()) — e.g. unpacking a proprietary struct into standard records. The redirect target attr must exist (declare it with ram: true).

5.5 on_serialization

Called when the stored record is converted to JSON for MQTT / web dashboard.
Write into data:

"on_serialization": def (record, dev, data)
  data["type_sm"] = "report"
  data["val"] = record.asFloat()
end

Keys follow the native zcl_json convention: "type_sm" (usually "report") and "val". If absent, standard serialization for the data type applies.

5.6 on_discovery

Called when generating discovery payload for this attribute. doc is the discovery JSON (base payload already filled from mqttClass/mqttSubClass/name/unit); zhbBase is the MQTT base topic. Add or override keys, e.g. doc["state_class"] = "measurement". In most cases, you only use doc if you need to add something (like minmax and step for a slider).

Return true to publish, false to veto discovery of this attribute. Note: with no callback set the attribute is still discovered when mqttClass != 0; but if you do set a callback, you must return true for it to be published.

5.7 on_mqtt_write

Called for MQTT messages on the {base}/write/... topic targeting this attribute. data is the raw payload string. Convert and send to the device (dev.sendCmddev.sendTuyaData, etc.). Return true = handled (standard ZCL write skipped).

5.8 on_mqtt_cmd (cluster level)

Same idea for the {base}/cmd/... topic — cluster commands sent from MQTT (e.g. switch toggles). Return true = handled.


6. Objects available in callbacks

6.1 ZigbeeDevice - Berry Zigbee device proxy

Method Description
matcher(manuf, model) -> bool Exact manuf+model compare
getName() / getIeee() / getModel() / getManuf() / getNwk() Identity
hasName() / setName(s) / setModel(s) / setManuf(s) Identity write access (e.g. normalizing Tuya _TZE200_... model strings in a matcher)
getPS() / setPS(v) Power source (CONST_ZCL_PS.*)
getBattery() / getLqi() / getLastSeen() Telemetry
getIAS() / setIAS(v) IAS zone type (CONST_ZCL_IAS.*)
isBattery() / isAc() / isTuya() / haveTuyaDP() / isInterviewing() / isZcnUsed() State predicates (isZcnUsed = a native converter is attached)
haveEndpoint(ep) / addEp(ep) / removeEp(ep) Endpoint list management (addEp creates an empty endpoint — populate it with addInCluster/addOutCluster)
hasInCluster(cl) / addInCluster(cl [, ep]) Input cluster list (ep 0 / omitted = first endpoint); duplicate-safe
hasOutCluster(cl) / addOutCluster(cl [, ep]) Output cluster list, same semantics
removeCluster(ep, cl) Remove a single input cluster from an endpoint ("ignore cluster X" quirks)
getVal(ep, cl, attr) / setVal(ep, cl, attr, value) Read / update a stored record value (setVal accepts bool/int/real/string/bytes and only updates an existing record)
addRecord(ep, cl, attr) / haveRecord(ep, cl, attr) / removeRecord(ep, cl, attr) / removeAllRecords() RAM record management
queryAllRecords([pauseMs]) / queryMissingRecords([pauseMs]) Actively read all / value-less records from the device (warning: a non-zero pause blocks the script and the hub for pause × records ms — prefer 0)
startPooling(intervalSec, ep, cl, attr) / stopPooling(ep, cl, attr) Periodic attribute polling driven by the hub task
sendOnOff / sendBri / sendColor / sendColorTemp High-level actuator commands
sendCmd(ep, cl, cmd [, bytes]) Raw ZCL cluster command
sendTuyaData(dp, ztype, val) Tuya 0xEF00 datapoint write
sendTuyaQuery() / sendTuyaMagic() Tuya: query all datapoints / send the "magic" init packet (typical in on_annonce)
readAttr(ep, cl, attr...) ZCL Read Attributes request
writeAttr(ep, cl, attr, dType, bytes) ZCL Write Attribute with a raw payload (for custom on_mqtt_write handlers)
confReporting(ep, cl, attr, dType, minReport, maxReport, change) ZCL Configure Reporting (for custom on_intw_stage("conf_reporting") handling)
nodeDescReq() / simpleDescReq(ep) / reqEndpoints() Low-level ZDO requests; responses are processed by the interview state machine, so these are mainly useful inside on_intw_stage
bindToHub / bindToDevice / bindToGroup Binding operations
(module-level) ZHB.await(seq [, timeoutMs]) -> bool / ZHB.lastStatus() / ZHB.on_response(seq, cb(ok, status) [, timeoutMs]) -> bool Wait for the device's response to a previous send (sync / async); the device is resolved from seqZHB.await() raises inside ZCN callbacks — they run on the ZHB task; use ZHB.on_response() there. See docs/slzb-os-scripts/docs/modules/zhb.md

6.2 ZclAttrRecord - Zigbee data container

Getters: getEp()getCl()getAttr()getStatus()getZtype() (raw ZCL type), getSMtype() (internal storage type, compare against ZclAttrRecord.TYPE_* constants: TYPE_NONE/U32/I32/FLOAT/BUF/STR/BOOL/CMD/CMD_PAYLOAD).

Predicates: isCmd()isCmdPayload()isTuya() (cluster == 0xEF00), hasPayload() (type is not TYPE_NONE), matcher(cl, attr [, ep]) -> bool.

Value access: asInt()asFloat()asStr()asBytes()asLumiStruct([start]) — parses the Lumi/Aqara proprietary struct (Basic 0xFF01/0xFF02 buffer) into a {tag_id: int} map; getMSB16() / getLSB16() — high/low 16-bit halves of the raw 32-bit value (e.g. packed color X/Y).

Mutation: setInt(v)setUInt(v)setFloat(v)setBool(v)setStr(v)setBuf(bytes) (replaces the payload with a copy of a Berry bytes() buffer, 1–255 bytes), setCmd(cmdId [, tuyaCluster])setMSB16(v) / setLSB16(v)setEp(v)setCl(v)setAttr(v).


7. ZCNP — native callback presets

The ZCNP module exposes ready-made preset functions used by built-in converters, so a Berry converter can reference them directly instead of re-implementing the logic:

import ZCNP
...
"on_normalize": ZCNP.zcn_norm_i16_divide_100, # the received zigbee value has data type int16 and needs to be divided by 100 to convert it to float
"on_serialization": ZCNP.zcn_ser_float, # the received value is converted to float, so we convert float to string
"on_discovery": ZCNP.zcn_dis_gen_basic_measurement, # add "measurement" class on discovery
Kind Functions
normalize zcn_norm_i16_divide_10/100/1000zcn_norm_u16_divide_10/100/1000zcn_norm_lumi_basic
serialization zcn_ser_floatzcn_ser_raw_uintzcn_ser_xyzcn_tuya_ser_switchzcn_ser_tuya_batt_enumzcn_ser_lumi_basic
discovery zcn_dis_gen_basiczcn_dis_gen_basic_measurementzcn_dis_tuya_batt_enum
mqtt write zcn_write_tuya_intzcn_write_tuya_float_int100zcn_write_int16tuya_switch_handler
cmd zcn_cmd_onoff_actiontuya_ias_wd_cmd_action
zcn_norm_i16_divide_10/100/1000

divides received two-byte signed int by 10/100/1000 and converts result to float.

Typically used for temperature sensors, etc.

zcn_norm_u16_divide_10/100/1000

divides received two-byte unsigned int by 10/100/1000 and converts result to float.

Typically used for humidity or voltage sensors, etc

zcn_norm_lumi_basic parses the battery value from the proprietary LUMI structure and sends it to the basic cluster
zcn_dis_gen_basic generates the minimum possible discovery payload
zcn_dis_gen_basic_measurement

generates the minimum possible discovery payload and add:

{"state_class": "measurement"}
zcn_dis_tuya_batt_enum battery enumeration: high, med, low
zcn_cmd_onoff_action handles standard ZCL ON/OFF commands for cluster 0x0006
tuya_ias_wd_cmd_action
zcn_write_tuya_int sends the received value as tuya int type
zcn_write_tuya_float_int100 converts the received float value to int by multiplying by 100 and sends it as tuya int type
zcn_write_int16 writes a ZCL attribute with int16 data type
tuya_switch_handler converts the received text "ON"/"OFF" text to bool (1/0) and sends it as tuya bool type

8. ZCN module API

Public functions:

Function Description
ZCN.register(converter_map) -> int

Register a converter from a Berry map (see §4). 

returns used slot number, raises a error on failure

ZCN.attach(slot, ieee_str) -> bool

Attach converter to a paired device (IEEE as hex string, e.g. "0x00124b00..."). Clears the device's saved-message cache and (re)creates the converter's RAM records.

Raises on: hub not started, bad slot, unknown IEEE.

ZCN.delete(slot) Free the slot: unpins all callbacks, frees all allocations. Automatic when the VM stops

9. Example — SNZB-01P custom button actions(triggers)

#META {"start":0}
#ZCN_BUILDER {"scriptVariableName":"snzb01p_zcn","autostartOnBoot":false,"signatureMode":"model","signatureModel":"SNZB-01P","signatureManufacturer":"eWeLink","matcherCallback":{"enabled":false,"presetReference":"","bodyText":""},"onAnnonce":{"enabled":false,"presetReference":"","bodyText":""},"onIntwStage":{"enabled":true,"presetReference":"","bodyText":"if (tag == \"intw_get_power_source\")\n  dev.setPS(3)  # battery\n  return 0\nend\nreturn 3  # ZCN unused - standard handling"},"attachEnabled":false,"attachIeeeAddress":"","endpointOverrides":[{"endpointNumber":1,"clusters":[{"clusterIdText":"0x0006","addMode":0,"bindCluster":false,"onMqttCmd":{"enabled":false,"presetReference":"","bodyText":""},"commandConfig":{"enabled":true,"exposesList":"btn_single|btn_double|btn_long","onCmd":{"enabled":true,"presetReference":"","bodyText":"# attr: 0 = long, 1 = double, 2 = single\nvar names = ['btn_long', 'btn_double', 'btn_single']\nvar id = record.getAttr()\nif (id < 3) return names[id] end\nreturn \"\""},"exposesOverride":{"enabled":false,"presetReference":"","bodyText":""}},"attributes":[]}]}]}
import ZCN

var snzb01p_zcn = {
  "signature": {
    "model": "SNZB-01P",
    "manuf": "eWeLink",
  },
  "on_intw_stage": def(dev, tag)
    if (tag == "intw_get_power_source")
      dev.setPS(3)  # battery
      return 0
    end
    return 3  # ZCN unused - standard handling
  end,
  "overrides_count": 1,
  "overrides": [
    {
      "endpoint": 1,
      "clusterCount": 1,
      "clusters": [
        {
          "id": 0x0006,
          "cmd_config": {
            "exposes": "btn_single|btn_double|btn_long",
            "on_cmd": def(dev, record)
              # attr: 0 = long, 1 = double, 2 = single
              var names = ['btn_long', 'btn_double', 'btn_single']
              var cmd_id = record.getAttr()
              if (cmd_id < 3)
                return names[id]
              end

              return ""
            end,
          },
        },
      ],
    },
  ],
}

var zcn_slot = ZCN.register(snzb01p_zcn)
ZCN.attach(zcn_slot, "0x00124b0012345678")  # attach to a device manually

10. Gotchas

  1. Counts are explicit. overrides_countclusterCountattrCount are read from the map, not derived from list sizes. A count smaller than the list silently drops entries; a count larger than the list reads will crash device.
  2. Attach every boot. zcn_be is not saved to the device DB. No ZCN.attach() after reboot (and no fresh interview) = converter silently inactive.
  3. signature is mandatory — registration raises without it. matcher must be a function if present.
  4. Callbacks must be fast.
  5. on_cmd needs exposes. Without exposes or exposesOverride on the same cluster, the command path is never taken.
  6. on_discovery must return true for the attribute to be discovered — a forgotten return (nil) vetoes it.
  7. ram: true for redirect targets and dashboard-only values — otherwise the record does not exist until the device first reports it (or ever, for synthetic attrs).
  8. Slot exhaustion. Only 2 Berry converters can exist at once, across all scripts. A crashed-then-restarted script frees and re-takes its slots automatically, but a script that registers in a loop will run out.
  9. ZCN.attach requires a running hub and a paired device — it raises "enable zHub first" / "wrong device ieee" otherwise. If your script autostarts before the hub is up, wait via ZHB.waitForStart() first.
  10. Multiple matching converters: Not recommended. Converters are meant to be unique.
  11. Berry converters are much slower than native ones! Berry ZCN intended for rapid prototyping, not for continuous use as it will slow down the system.

Network

5. Network Settings

The Network page in SLZB-OS manages how your device connects to your local network and, if required, to the internet.
The available sections may vary depending on the selected Mode and hardware capabilities (Ethernet, Wi-Fi).

image.png


5.1 Information Block

At the top of the page you may see an info notice if certain network interfaces are inactive.
Example:

“Wi-Fi page is inactive because Wi-Fi mode is not activated.”
To enable it, change the device’s mode to one that supports Wi-Fi (see Mode page).


5.2 Connection Overview

A visual diagram shows the main connections:


5.3 LAN / Ethernet Settings

Ethernet is the primary connection method for most SLZB devices.

5.3.1 DHCP (Dynamic Host Configuration Protocol)

5.3.2 Static IP Configuration

If DHCP is disabled, manually configure:

  1. IP Address – The fixed address the device will use. Must be unique on your network.

  2. Subnet Mask – Defines which IP addresses are considered local (e.g., 255.255.255.0).

  3. Gateway – The IP address of your router or gateway to access external networks.

  4. DNS Server(s) – Optional; used to resolve domain names. Defaults to your gateway if not set.

Tip: Use a static IP if you run integrations that need a consistent address (e.g., Home Assistant with static MQTT host).


5.4 Wi-Fi Settings

(Visible only when Wi-Fi mode is active)

5.4.1 Scan for Wi-Fi Networks

5.4.2 Connect to Network

5.4.3 IP Configuration


5.5 Applying Changes

  1. Adjust the settings for the interface you are using (Ethernet/Wi-Fi).

  2. Click Save or Apply.

  3. The device may briefly lose connectivity while settings are applied.

  4. Verify new settings on the Dashboard or via your router.


5.6 Troubleshooting

Zigbee2MQTT / ZHA Settings

6. Zigbee2MQTT and ZHA Configuration

The Z2M and ZHA page in SLZB-OS provides configuration tools for connecting your device’s Zigbee coordinator to an external server running either Zigbee2MQTT (Z2M) or Zigbee Home Automation (ZHA).
It also contains advanced options for connection methods and device identity.

Note:

image.png


7.1 Configuration Generator – Purpose and Output

This section provides ready-to-use parameters for integrating your coordinator with an external Zigbee2MQTT or ZHA setup via Ethernet.

What it does:

What it provides:

You simply copy these values into your external Z2M configuration.yaml or ZHA connection string.


7.2 Serial Options

If you use USB or direct serial mode, the Serial Settings section appears.

Available fields:


7.3 Advanced Socket Connection Options

The ADVANCED: Socket options – helper section controls how the coordinator’s serial data is forwarded over TCP.

Available options:

  1. Enable Zigbee Socket packet processing

    • Instead of forwarding raw bytes, SLZB-OS assembles complete EZSP/ZNP frames before sending them.

    • Only valid Zigbee frames are forwarded — other traffic is ignored.

  2. Allow multi-threaded socket connection

    • Up to 5 clients can connect to the socket at once.

    • Important: Only one client can actively communicate with the Zigbee chip at a time. If multiple clients send data simultaneously, the connection will not function correctly.

  3. Multi-Radio Queue Control (only shown on dual-radio devices)

    • Balances socket traffic between radios.


7.4 IEEE Address Change

The ADVANCED: Adapter IEEE address change section allows you to read or modify the coordinator’s IEEE (extended) address.

image.png

Important notes from the UI:

Migration tip from SLZB-OS:
If migrating from another CC26xx adapter, you may avoid re-pairing devices if you:

  1. Shut down Zigbee2MQTT/ZHA and power off your old coordinator.

  2. Power off all Zigbee routers for ≥15 seconds (e.g., cut building power briefly).

  3. Power on the new coordinator.

  4. Power on routers.

  5. Start Zigbee2MQTT/ZHA.
    Devices may take 5–10 minutes to reconnect.

  6. If they do not, set the IEEE address of your new coordinator to match the old one, and repeat steps 1–5.

IEEE tools in UI:

Security

8. Security

This page controls access to the SLZB‑OS web interface and the TCP “socket” that exposes the Zigbee coordinator to Z2M/ZHA. The options below are listed exactly as they appear.


image.png

8.1 Web‑server when socket is connected

What it does: Controls whether the SLZB‑OS web UI remains available while the coordinator’s TCP socket is actively in use by Zigbee2MQTT or ZHA.

Recommendation:
For maximum security on production systems, choose Disable. Use Enable while commissioning or troubleshooting.


8.2 Web server authentication

What it does: Enables login protection for the SLZB‑OS web interface.

Recommendation:
Keep this enabled and use a strong password.


8.3 IP whitelist for socket

What it does: Restricts which client can connect to the Zigbee TCP socket (the bridge used by Z2M/ZHA).

Recommendation:
Enable this and set Allowed IP to the host that runs Z2M/ZHA (e.g., your Home Assistant server).


8.4 Fallback Wi‑Fi AP password

What it does: Protects the fallback Wi‑Fi access point (brought up by the device in recovery/initial setup scenarios).

Recommendation:
Enable this to prevent unauthorized local access during recovery.


8.5 Save & Operational Notes

 

VPN

9. VPN (WireGuard)

The VPN page in SLZB-OS contains a WireGuard settings helper, allowing the Zigbee coordinator to securely connect to your Home Assistant server or other remote endpoint.


image.png

9.1 WireGuard Overview

WireGuard is a modern, highly secure VPN protocol. In SLZB-OS, it:

Note: You must have the WireGuard add-on installed and configured on your Home Assistant or other VPN server.


9.2 How WireGuard Works for Home Assistant

When configured:

  1. Your coordinator connects to the WireGuard server.

  2. All Zigbee and management traffic is securely tunneled through this encrypted channel.

  3. The remote server sees the coordinator as if it were on the same local network.

This is useful when:


9.3 WireGuard Settings

The page provides the following editable fields:

  1. Local IP Address
    IP address of the coordinator inside the VPN network.

  2. Private Key
    Secret key unique to the coordinator. Keep it confidential.

  3. Public Key
    Coordinator’s public key (share with the WireGuard server so it can authenticate your device).

  4. Peer Public Key
    The public key of the VPN server or peer you will connect to.

  5. Endpoint
    IP address or domain name of the VPN server, plus port (e.g., vpn.example.com:51820).

  6. Allowed IPs
    Specifies which IP ranges are routed through the VPN tunnel (e.g., 0.0.0.0/0 to route all traffic).

  7. Persistent Keepalive
    Interval in seconds to send keepalive packets and maintain connection (useful behind NAT).


9.4 Save & Connect


9.5 Security Recommendations

DDNS

10. DDNS (Dynamic DNS)

The DDNS page in SLZB-OS provides a helper to keep a public hostname updated with your device’s current public IP address. This is especially useful if your ISP changes your IP periodically and you want to access the coordinator remotely without manually tracking IP changes.


image.png

10.1 How It Works

When enabled, SLZB-OS:

  1. Detects your current public IP.

  2. Sends an update request to your chosen DDNS provider.

  3. Repeats this at the set interval to ensure your hostname always points to the correct IP.


10.2 Available Settings

  1. Enable DDNS client
    Turns the DDNS updater on or off.

  2. Public IP provider request URL

    • A URL to query your current public IP address.

    • The result of this GET request is placed into the variable {{ip}}.

    • If you are not using a third-party service to get your IP, you can leave this blank.

    • If blank, the variable {{ip}} will not be available.

  3. DDNS provider request URL

    • The URL used to update your DDNS provider with the current IP.

    • You can use {{ip}} in this field to insert the IP address from the previous step at the required point in the query.

    • Some providers can detect your IP automatically from the request — in that case, you may not need to insert it manually.

  4. Check interval

    • How often the IP address is checked/updated, in seconds.

    • Minimum: 10 seconds

    • Maximum: 65535 seconds


10.3 Example Workflow

  1. Set Public IP provider request URL to something like:
    https://api.ipify.org

  2. Set DDNS provider request URL according to your DDNS service’s API. For example:
    https://myddns.example/update?hostname=myhome&myip={{ip}}

  3. Set Check interval to a reasonable value, such as 300 seconds (5 minutes).

  4. Save settings.


10.4 Security Note

Scripts and Automations

11. Scripts and Automations

The Scripts and Automations feature in SLZB-OS lets you create and run your own automation logic directly on the coordinator, without needing an external controller to send every command. Scripts can respond to events, toggle GPIOs, interact with the Zigbee hub, or perform other custom actions.


image.png

11.1 Overview

For examples and full API documentation, refer to the official repository:
???? https://github.com/smlight-tech/slzb-os-scripts


11.2 Script Manager

The Script Manager section contains the list of available scripts and their control options:

Field / Button Description
Status Shows whether the script is enabled/disabled.
Filename The name of the script file stored in the coordinator.
Run on boot Toggle to run the script automatically after the device boots.
Actions Buttons to edit, run, stop, or delete the script.

11.3 Adding a Script

  1. Click the “+” button in Script Manager to create a new script.

  2. Enter your code in the built-in script editor.

  3. Save the script — it will appear in the list with its filename.

  4. Optionally enable Run on boot.


11.4 Running a Script


11.5 Editing / Updating a Script


11.6 Removing a Script


11.7 Notes & Best Practices

Settings

12. Settings & Tools

The Settings & Tools section in SLZB-OS contains core configuration and maintenance options that apply to the entire coordinator, regardless of the selected Zigbee mode or network configuration.


image.png

12.1 General Settings

12.1.1 Device Name

12.1.2 Update Check Interval

12.1.3 Enable Remote Support Mode


12.2 Firmware Update

The Firmware Update page allows upgrading SLZB-OS to the latest release or a specific version.

image.png

12.2.1 Update Methods

  1. Online Update

    • Fetches and installs the latest stable firmware from SMLIGHT servers.

  2. Manual Upload

    • Lets you upload a .bin firmware file from your computer.

12.2.2 Update Process

  1. Select update method (online or manual).

  2. Confirm and start update.

  3. Device will reboot automatically after installation.

Note: Updating SLZB-OS does not affect your Zigbee network data — Zigbee pairing and configuration are stored in Zigbee2MQTT/ZHA, not in the core firmware.


12.2.3 Automatic Zigbee Firmware Updates

12.3 LED Settings

This page configures the behavior of the onboard status LEDs.

image.png

12.3.1 LED Modes

12.3.2 Brightness


12.4 Time Settings

image.png

12.4.1 Time Zone

12.4.2 NTP Server

12.4.3 Manual Time Set


12.5 Log and Debug

This section helps in troubleshooting and monitoring.

image.png

12.5.1 Clear Logs

Additional features

13. Report a Bug / Feedback

The Report a Bug / Feedback page in SLZB-OS is dedicated to collecting your input to improve your experience with the smart home Zigbee coordinator.


image.png

13.1 Purpose

From this page, you can:

  1. Report a Bug – If you encounter issues or unexpected behavior.

  2. Suggest an Idea – Share innovative thoughts or feature requests.

  3. Report Incorrect Translation – Notify the team about any translation errors in the interface.

  4. Provide General Feedback – Offer comments or suggestions about the product.

  5. Leave Positive Feedback – Share what you enjoy about the device or firmware.


13.2 How to Submit

  1. Select Request Type:

    • Report a Bug

    • Suggest an Idea

    • Report Translation

    • Positive Feedback

  2. Write Your Text – Enter details about the bug, idea, translation correction, or general thoughts.

  3. Optional Contact Details:

    • Email address – if you want the SMLIGHT team to follow up.

    • Name – optional identifier.

  4. Click Submit.


13.3 Tips for Useful Reports


13.4 Quick Translation Reporting

If you spot a translation issue anywhere in the interface:


13.5 Privacy

The information you submit is used solely for troubleshooting and product improvement. Technical data from logs will not include Zigbee/Thread/Z-Wave network keys or passwords!

SLZB-OS API endpoints

General information

The SLZB-OS operating system has several API channels: HTTP, SSE and MQTT.

When using any of these channels, it is not recommended to send more than one request per second.
A large number of requests per second can slow down the coordinator and negatively affect stability.

HTTP API

Web-interface API endpoints

Not documented and may change without notice. The primary purpose is for internal use by the web interface system!

You can find all the queries in the developer tools in your browser:

image.png

Prometheus metrics

Endpoint: /metrics

image.png

SSE

https://en.wikipedia.org/wiki/Server-sent_events

image.png

Endpoint: /events

Home Assistant endpoints

General device information: /ha_info

image.png

Real time sensors: /ha_sensors

image.png

MQTT API

This API is available from firmware v3.2.4

zHub MQTT API can be found here: https://smlight.tech/support/manuals/books/slzb-os/page/mqtt-api

ATTENTION! Some topics are reserved by the system!
/api2/# topic is reserved for MQTT API usage.
/cmd/#, /write/#, /read/# and /data/# topics are used by HA discovery for Zigbee Hub.
Please avoid using these topics.

SLZB-Ultima specific

Ultima has a special API for interacting with IR, Ambilight, Buzzer, etc. Other models don't have this!

Buzzer Control

Buzzer control topic: <Base topic>/api2/write/buzzer

Payload: RTTTL sound pattern

Example: Arkanoid:d=4,o=5,b=140:8g6,16p,16g.6,2a#6,32p,8a6,8g6,8f6,8a6,2g6

IR Learn & Replay

IR Learn

Topic: <Base topic>/api2/status/ir

The OS will send information about all received IR messages to this topic.
Example message below:

{
  "raw": "472209080a190909090809080a08090809090908090909080a070a08091a090809080a0809080a080908090909080a0809190a0809080909090809080a0809080a08091a0908091a0a19091a09190a080908091a0a0809190a190a19091a09080a190a",
  "proto": 11,
  "addr": "0x0008",
  "cmd": "0x003d"
}

"proto" field values:

UNKNOWN = 0,
PULSE_WIDTH = 1,
PULSE_DISTANCE = 2,
APPLE = 3,
DENON = 4,
JVC = 5,
LG = 6,
LG2 = 7,
NEC = 8,
NEC2 = 9,
ONKYO = 10,
PANASONIC = 11,
KASEIKYO = 12,
KASEIKYO_DENON = 13,
KASEIKYO_SHARP = 14,
KASEIKYO_JVC = 15,
KASEIKYO_MITSUBISHI = 16,
RC5 = 17,
RC6 = 18,
RC6A = 19,
SAMSUNG = 20,
SAMSUNGLG = 21,
SAMSUNG48 = 22,
SHARP = 23,
SONY = 24,
BANG_OLUFSEN = 25,
BOSEWAVE = 26,
LEGO_PF = 27,
MAGIQUEST = 28,
WHYNTER = 29,
FAST = 30,
OTHER = 31,
Replay

Topic: <Base topic>/api2/write/ir

Raw payload example:

472209080a190909090809080a08090809090908090909080a070a08091a090809080a0809080a080908090909080a0809190a0809080909090809080a0809080a08091a0908091a0a19091a09190a080908091a0a0809190a190a19091a09080a190a

Starting from SLZB-OS v3.3.0 you can use JSON payload below:

Json payload examples:

{
  "proto": 11,
  "addr": "0x0008",
  "cmd": "0x003d",
  "repeats": 5
}
{
  "proto": 11,
  "addr": 8,
  "cmd": 61,
  "repeats": 5
}
{"raw":"472209080a190909090809080a08090809090908090909080a070a08091a090809080a0809080a080908090909080a0809190a0809080909090809080a0809080a08091a0908091a0a19091a09190a080908091a0a0809190a190a19091a09080a190a"}

Ambilight

Topic: <Base topic>/api2/write/ambilight

Payload example:

{"color":"#00ff00","bri":128,"effect":2,"speed":10}

If you only need to change one ambilight parameter then you can send only that one:

{"color":"#ffff00"}

color - LEDs color in #RRGGBB hex format.
bri - Brightness from 1 to 255
effect - effect to be installed. You can choose between: 0 - Solid, 1 - LEDs disabled, 2 - Blur, 3 - Rainbow.
speed - speed for this effect. Range: 1 - 50

USB to Ethernet passthrough mode

General information

This feature is supported only by "U" series devices and SLZB-Ultima
(CPU model: ESP32S3)

USB to Ethernet passthrough mode allows connecting a USB device to your coordinator USB port (directly or via a USB hub) and using such USB devices remotely over IP.
For example, a USB Z-Wave adapter can be connected and used remotely, similarly to an Ethernet-based Z-Wave coordinator.

What devices can be connected?

  1. Devices on CP210x chipset
  2. Devices on PL2303 chipset
  3. Devices on CH340 chipset
  4. Devices on CH341 chipset
  5. Devices on CH9102 chipset
  6. Other CDC-ACM devices

We cannot guarantee support for all third-party CDC-ACM devices.

How many USB devices can be connected?

If the "Use new USB driver" option is disabled - one USB device.
With the "Use new USB driver" option active, 2 USB devices can be connected, but ONLY ON THE CONDITION THAT THEY ARE BOTH ON THE CP2102x CHIPSET!

How much power can the coordinator provide via USB?

The coordinator can provide up to 1A.
The optimal current is 500mA.

If you are using a powered USB hub, please make sure that PoE is disabled!
It is forbidden to use PoE and a powered USB hub at the same time!

USB to Ethernet passthrough setup

1. Mode select

Open the "USB" page and activate "Enable USB to Ethernet passthrough mode" and "Use new USB driver"

image.png

We recommend using the "Use new USB driver" option as the new driver provides greater stability and a wider list of supported USB devices.
The old driver will be removed in future updates!

2. Connect your USB device and reboot your coordinator

3. Select your USB device

Select your USB device from the list.

image.png

"Empty" -  passthrough server disabled.
"Any serial device" - the system will select the first device found and try to open interface 0.

4. Set the serial speed

The most common setting is 115200.

The serial speed depends on the firmware of your dongle. If you don't know what to choose, please contact the support service of the dongle manufacturer.

5. Choose an interface

image.png

Most USB devices will only have one interface - interface 0.
But some devices may have several: for example one for firmware update/debug and another for communication.

If your device has multiple interfaces then you will have to try them all until you find correct one.

For ZWA-2 you need to select interface 1

6. About autoboot

Some dongles have an autoboot circuit that puts the radio module into bootloader mode using the DTR/RTS lines, for example SLZB-07p7/p10.
For such a dongle to work you need to select the option "My dongle has autoboot".

Most dongles that have autoboot use the CH340 or CP2102x chipsets.
If you don't know if your dongle has autoboot, please contact the support service of the dongle manufacturer.

7. After setup

After you have selected all the settings, please click the "Save" button and restart the coordinator for the changes to take effect.

8. Host application settings

Most programs use the format tcp://ip:port or socket://ip:port, less often just ip:port

Examples:
tcp://192.168.50.196:8638
socket://192.168.50.196:8638
192.168.50.196:8638

If your host program has "RTS/CTS" or "Hardware flow control" settings, you should select "disabled"

Wire Guard VPN setup

WHAT IS VPN WIREGUARD

This is a feature of SLZB-OS that allow them to connect to remote Home Assistant / Zigbee2MQTT server through secure VPN tunnel without any additional hardware. WireGuard is an extremely simple yet fast and modern VPN that utilizes state-of-the-art cryptography. It aims to be faster, simpler, leaner, and more useful than IPsec while avoiding the massive headache. It intends to be considerably more performant than OpenVPN.

Current VPN limits

Via VPN, the following is currently available:

  • Webserver
  • Radiomodules (sockets)

What doesn't work through a VPN:

  • Ethernet to WiFi bridge
  • MQTT

1. Prerequisites

1.1. Hardware and Software used

  • A server with Home Assistant is installed and running. In this manual, we are using Raspberry Pi 3B+ with a clean fresh install of HAOSS.
  • An SLZB-06 family coordinator (firmware version 2.2.6 or later).
  • WireGuad add-on, Zigbee2MQTT add-on and ZHA integration.
  • The Zigbee device you want to connect remotelly.

1.2. IP Address reservation

It is reccomended to reserve a static IP addresses on the router for Home Assistant server and the SLZB-06 family coordinator. In our case, on a TP-Link router, static IP address reservations can be configured under the Network >> DHCP Server >> Address Reservation section.

2. Establishing access to your Home Assistant / Zigbee2MQTT

In order to let remote SLZB-06 coordinator to establish secure connection with your Home Assistant / Zigbee2MQTT, coordinator should know how to reach your Home Assistant. There are two options here:

  • if you do not have a white IP address - you can use intermediary services like DuckDNS, that will let SLZB-06 coordinator know how to find your Home Assistant (so coordinator will knock to the doors and ask "Hey, may I connect to your Wireguard Add-on and establish a secure tunnel?").
  • if you have a white IP address - you can open a port to access your Home Assistant directly without intermediary services like DuckDNS (although you can use DuckDNS togather with white IP address).

TIP

You need to use only one option - if you do not have white/static IP address from your provider - use DuckDNS, if you have - either open port or use service like DuckDNS as well.

Lets looks through both options.

2.1. Port forwarding

The location of this function may vary depending on your router. On a TP-Link router, it can be found under Advanced >> NAT Forwarding >> Port Forwarding. Add a port forwarding rule in which you specify:

Service Name: wireguard
Device IP Address: IP address of Home Assistant (in our case 192.168.0.103)
External Port: 51820
Internal Port: 51820
Protocol: UDP

2.2. DuckDNS set-up

2.2.1. Duck DNS domain registration

  1. Visit the duckdns.org website and log in using your preferred method.
  2. Create a unique domain name, such as slzb-06, enter it in the domains section and click add domain. This will add the new domain to your list of domains.

WARNING
DuckDNS is not compatible with CGNAT!

2.2.2. Install Duck DNS add-on

  1. We'll need to install the DuckDNS add-on in Home Assistant. Head over to the Left panel within Home Assistant click Settings and choose Add-ons.
  2. Navigate to the Add-on Store and search for Duck DNS add-on. Click Install and wait for the installation to complete.
  3. Once installed, click Configure tab on the top side of the add-on.

2.2.3. Duck DNS add-on configuration

TIP:
Keep your DuckDNS token private!

  1. In the Domains field, enter the domain you created in Duck DNS. In UI mode, delete the empty domain.
  2. In the Token field, enter your Duck DNS token.
  3. In the Lets Encrypt section, set accept_terms to true.
  4. Save settings and run add-on.
domains:
  - slzb-06.duckdns.org
token: 490d69be-u835-984a-a9aa-8430bcbd02bd
aliases: []
lets_encrypt:
  accept_terms: true
  algo: secp384r1
  certfile: fullchain.pem
  keyfile: privkey.pem
seconds: 300

duckdns-addon-config

Once these steps are completed, you can use the Duck DNS address as the host in Wireguard and as the Endpoint hostname in the coordinator's web interface.

3. WireGuard add-on setting-up and configuration

3.1. Wireguard add-on installation

  1. We'll need to install the WireGuad add-on in Home Assistant. Head over to the Left panel within Home Assistant click Settings and choose Add-ons.
  2. Navigate to the Add-on Store and search for WireGuard Add-on. Click Install and wait for the installation to complete.
  3. Once installed, click the Configure tab on the top side of the add-on.

3.2. WireGuard add-on configuration in Home Assistant

The configuration is divided into two parts: the server side and the client side.

3.2.1. Server side:

host: The public IP address that clients can use to access WireGuard. This guide uses a static public IP address. However, you can also use DuckDNS.
address: The IP address assigned to the WireGuard add-on interface. For a WireGuard network, it is recommended to use a different network than the main one to avoid routing problems. Home routers typically use the 192.168.0.0/24 or 192.168.1.0/24 network.

Network Selection: The /24 subnet mask is the most common. It determines how many devices can be on the network. A /24 subnet mask allows for 256 IP addresses or 254 connected devices. Two IP addresses are reserved for the network address and the gateway address. The /24 subnet mask is popular because of its simplicity. Every /24 network address always ends with 0. For example, 192.168.0.0/24, 192.168.1.0/24, 192.168.2.0/24, ..., 192.168.255.0/24. For WireGuard, you can choose any arbitrary network. For example, I chose 192.168.10.0/24. You can choose this one or another.

Host Selection: Once the network address is selected, you need to choose the host addresses. This includes the WireGuard interface address and the peer addresses. You can use an IP calculator to see the range of available addresses on the network. In my case, this is the range from 192.168.10.1 to 192.168.10.254. For the WireGuard add-on interface address, I chose 192.168.10.1.
dns: For DNS, you can use the router's address, or 1.1.1.1, 1.0.0.1.

3.2.2. Client side:

name: Arbitrary client name, e.g., myphone, mylaptop, SLZB-06
addresses: Address from the Wireguard network issued to the client. You can take the next address after the Wireguard interface.
client_allowed_ips: This is a list of networks that the WireGuard peer is allowed to access. In this guide, this is the main network and the WireGuard network.

server:
  host: 176.37.187.207 #Avoid publicly sharing your public IP address
  addresses:
    - 192.168.10.1
  dns:
    - 192.168.0.1
  log_level: debug
peers:
  - name: slzb-06
    addresses:
      - 192.168.10.2
    allowed_ips: []
    client_allowed_ips:
      - 192.168.0.0/24 #Change this address if your main network is different
      - 192.168.10.0/24

You can add more clients. For example, your phone or another coordinator. To do this, copy the client part, change the name, and increase the IP address by one.

- name: slzb-06-2
  addresses:
    - 192.168.10.3
  allowed_ips: []
  client_allowed_ips:
    - 192.168.0.0/24 #Change this address if your main network is different
    - 192.168.10.0/24

3.3. Getting Wireguard configuration for use at SLZB-06

3.3.1. Using File Editor

  1. Install the File Editor add-on.
  2. Go to the Configuration tab and turn off the Enforce Basepath switch. This will allow full access to the Home Assistant file system.
  1. Open the File editor add-on. In the top left corner, click the directory icon. Click the back arrow to go up one level. Select the directory ssl >> wireguard >> SLZB-06 >> client.conf.

3.3.2. Using Studio Code Server

If you prefer Studio Code Server. Open the add-on, on the left Exproler panel in a space, right-click >> Add Folder to Workspace >> select the ssl directory >> wireguard >> click ok. Select the slzb-06 directory >> client.conf.

TIP:
You can run Wireguard in a separate container instead of an HA addon

3a. WireGuard container setting-up and configuration

3a.1. Install wireguard container

docker pull linuxserver/wireguard

3a.2. Run container example

docker run -d \
  --name=wireguard \
  --cap-add=NET_ADMIN \
  --cap-add=SYS_MODULE `#optional` \
  -e PUID=1000 \
  -e PGID=1000 \
  -e TZ=Etc/UTC \
  -e SERVERURL=wireguard.domain.com `#optional` \
  -e SERVERPORT=51820 `#optional` \
  -e PEERS=1 `#optional` \
  -e PEERDNS=auto `#optional` \
  -e INTERNAL_SUBNET=10.13.13.0 `#optional` \
  -e ALLOWEDIPS=0.0.0.0/0 `#optional` \
  -e PERSISTENTKEEPALIVE_PEERS= `#optional` \
  -e LOG_CONFS=true `#optional` \
  -p 51820:51820/udp \
  -v /path/to/wireguard/config:/config \
  -v /lib/modules:/lib/modules `#optional` \
  --sysctl="net.ipv4.conf.all.src_valid_mark=1" \
  --restart unless-stopped \
  lscr.io/linuxserver/wireguard:latest

TIP:
Change SERVERURL to your URL wireguard (using some like dudckns if this ip changes )
/path/to/wireguard/config in order to use your config wireguard folder.

3a.3. Add route to access client vpn ip's from host and others containers (like zigbee2mqtt)

wireguard_internal_subnet=$(docker exec wireguard printenv INTERNAL_SUBNET)
wireguard_ip=$(docker inspect -f '{{range.NetworkSettings.Networks}}{{.IPAddress}}{{end}}' wireguard)
ip route replace $wireguard_internal_subnet/24 via $wireguard_ip

3a.4. Get wireguard connection data

  • Go to wireguard config folder and enter into peer1 or peer2 and read peer1.conf or peer2.conf
  • Enter this info into SLZB-06

3a.5. zigbee2mqtt configuration.yaml for WG container

  • Modify line port: tcp://IP:6638 and replace IP with the IP Address of wireguard container (The $wireguard_ip value obtaneid previously)
  • Restart Z2M container/addon

4. Wireguard configuration on SLZB-06

WARNING
You should never share your private key and public IP address with anyone.

TIP:
Newer versions of Wireguard require a Preshared Key. SLZB-06 supports Preshared Key starting from firmware version v2.5.3

A VPN tunnel allows you to be on one network and connect to another. To add a VPN configuration to the SLZB-06 coordinator, go to the device address, in the left-hand side menu, click VPN, and activate the Enable VPN Wireguard switch. Transfer local and endpoint IP addresses, and private and public keys from the client.conf file. Click Save

5. Configuring IP routing on Home Assistant server

  1. Install the Advanced SSH & Web Terminal add-on on your Home Assistant.
  2. Go to the Configuration tab and in the password row set a strong password. The password can be generated. Click Save
  3. In the Info tab, disable the Protection mode switch and start the add-on.
  4. Click Open Web UI and paste the following command:

host_result=$(host a0d7b954-wireguard); addon_ip=${host_result##* }; ip route replace 192.168.10.0/24 via $addon_ip; echo $addon_ip

where 192.168.10.0/24 is the network that we have allocated for the Wireguard interface and peers. This command tells Home Assistant that to reach the 192.168.10.0/24 network, it needs to go through the IP address of the Wireguard add-on.

To check if the command works, you can view the routing table by running the command route -n. If the desired network is in the list, then the command worked. Additionally, you can ping the coordinator.

The routing command only works temporarily and then gets erased. To make it permanent, you need to create a sensor in the configuration.yaml file and restart Home Assistant. After that, the sensor name will appear in Devices & Services >> Entities.

command_line:
  - sensor:
      name: wireguard_route
      command: "host_result=$(host a0d7b954-wireguard); addon_ip=${host_result##* }; ip route replace 192.168.10.0/24 via $addon_ip; echo $addon_ip"

6. Running ZHA / Zigbee2MQTT with remote SLZB-06

6.1. ZHA launch with remote SLZB-06

  1. Head over to the Left panel within Home Assistant click Settings and choose Devices & Services.
  2. In the bottom right corner, click the Add Integration button, find and select the Zigbee Home Automationintegration.
  3. In the Radio Type window, select the line
  • ZNP - for SLZB-06/06p7 and 06p10 (based on Texas Instruments chips) Submit.
  • EZSP - for SLZB-06M and SLZB-06Mg24 (based on SiliconLabs chips) and click Submit.
  1. In the Serial Port Settings window, enter socket://192.168.10.2:6638. Where 192.168.10.2 is the IP address assigned to the coordinator in Wireguard. Leave the Port speed and Data flow control unchanged and click Submit.
  2. In the Network Formation window, select the option to create a new network. After following these steps, you should receive a success message.

6.2. Running local and Remote SLZB-06 with Zigbee2MQTT via Wireguard

6.2.1. Zigbee2MQTT running with local SLZB-06

MQTT Settings

  1. in Home Assistant go to Settings >> Add-ons >> Add-on store and install the Mosquitto broker addon >> enable Watchdog switch, then start it. As of the writing of this manual, the version of the add-on is 6.4.0.
  2. Click on the Home Assistant user icon >> User settings section >> and enable the Advanced mode switch.
  3. Go to Settings >> People >> Users tab >> click the add user button:
    Display name: mqtt_user
    Username: mqtt_user
    Password: mqtt_password
    You can choose your username and password.
  4. Go to Settings >> Devices & Services >> press the Add Integration button >> MQTT >> MQTT
    Broker: core-mosquitto
    Port: 1883
    Username: mqtt_user
    Password: mqtt_password

Press Submit and Finish

Zigbee2MQTT Settings

  1. Go back to the Add-on store, click  >> Repositories, fill in https://github.com/zigbee2mqtt/hassio-zigbee2mqtt and click Add
  2. Install Zigbee2MQTT add-on and enable the Watchdog switch. As of the writing of this manual, the version of the add-on is 1.37.1-1.
  3. Click on Configuration and paste in the following configuration. You need to change the mqtt login and password in it if they differ and the coordinator IP address. Click Save. Switch to the info tab and click Start. The add-on takes some time to start, so if you get a 502: Bad Gateway error try again in a minute.

data_path: /config/zigbee2mqtt
socat:
  enabled: false
  master: pty,raw,echo=0,link=/tmp/ttyZ2M,mode=777
  slave: tcp-listen:8485,keepalive,nodelay,reuseaddr,keepidle=1,keepintvl=1,keepcnt=5
  options: "-d -d"
  log: false
mqtt:
  server: mqtt://core-mosquitto
  user: mqtt_user
  password: mqtt_password #Change password if it is different for you
serial:
  port: tcp://192.168.0.109:6638 #Change the IP address to the address of your coordinator
  adapter: zstack

6.2.2. Zigbee2MQTT running with remote SLZB-06 connected via Wireguard

To set up a second Zigbee2MQTT instance, you need to add another slightly modified repository URL to Home Assistant. Each such URL is perceived as new and unique. Here are some examples of modified URLs:

https://github.com/zigbee2mqtt/hassio-zigbee2mqtt/
http://github.com/zigbee2mqtt/hassio-zigbee2mqtt
http://github.com/zigbee2mqtt/hassio-zigbee2mqtt/
http://www.github.com/zigbee2mqtt/hassio-zigbee2mqtt/

  1. Navigate to the Add-on store, click on the three dots  icon, and then select Repositories. Paste any of the provided links into the URL field.
  2. Refresh the page and install the new Zigbee2MQTT instance. Activate the Watchdog switch.
  3. Click on the Configuration tab and paste in the following configuration, change the network port and save it.

data_path: /config/zigbee2mqtt_lan2
socat:
  enabled: false
  master: pty,raw,echo=0,link=/tmp/ttyZ2M,mode=777
  slave: tcp-listen:8485,keepalive,nodelay,reuseaddr,keepidle=1,keepintvl=1,keepcnt=5
  options: "-d -d"
  log: false
mqtt:
  server: mqtt://core-mosquitto
  base_topic: zigbee2mqtt_lan2
  user: mqtt_user
  password: mqtt_password
serial:
  port: tcp://192.168.10.3:6638
  adapter: zstack

data_path: The directory where the Zigbee2MQTT configuration file is located. By default, this is the /config/zigbee2mqtt directory (the same as homeassistant/zigbee2mqtt/ in File Editor"). For the second network, I created a new directory by changing its name in the add-on settings to /config/zigbee2mqtt_lan2

base_topic: The MQTT topic for publishing messages to and from the Zigbee network. By default, the base topic is called zigbee2mqtt and is used by the first instance. For the second network, I created a different topic by changing its name to zigbee2mqtt_lan2 in the add-on settings.

Network port: By default, port 8485 is used. This port is occupied by the first add-on. For the second instance, I used port 8486 and saved the port settings.

As a result, we will have two instances of Zigbee2MQTT with two different Zigbee networks running independently of each other. Following the example of the second instance, more Zigbee2mqtt instances can be set up.

Advanced Config

For advanced Zigbee network configuration, including pan ID, coordinator transmit power, device last seen time, and Z2M logging level, you can utilize a separate Zigbee2MQTT configuration file named configuration.yaml.

If the addon has not been started after changing the configuration, the folder and file must be created manually.

For example, if your data path in the addon configuration is called config/zigbee2mqtt_lan2, then the directory that needs to be created will be named zigbee2mqtt_lan2 in the homeassistant folder This is the same thing. Then you need to create a new file called configuration.yaml and paste the configuration below.

If the addon is running, stop it and completely delete its directory with all subfolders. Create a folder with the same name again, and create a configuration.yaml file inside it. After that, you can start the Zigbee2MQTT addon.

mqtt:
  server: mqtt://core-mosquitto:1883
  user: mqtt_user
  password: mqtt_password
  base_topic: zigbee2mqtt_lan2
  version: 5
serial:
  port: tcp://192.168.10.3:6638
  adapter: zstack
  baudrate: 115200
  disable_led: false
advanced:
  transmit_power: 20
  channel: 15
  pan_id: GENERATE
  network_key: GENERATE
  availability_blocklist: []
  availability_passlist: []
  last_seen: ISO_8601

7. Pairing Zigbee devices on a remote coordinator

Adding Zigbee devices to a remote WireGuard coordinator is the same as adding them to a local network coordinator.

8. Conclusion

As a result of following this guide, we established a secure connection to a remote Zigbee LAN coordinator using a custom Wireguard VPN client.

9. Troubleshooting

z2m: MQTT error: Connection refused: Not authorized
Check the correctness of the mqtt_user data. Wrap mqtt_user and mqtt_password in quotes like this "

Zigbee2MQTT not adding to MQTT Bridge
Delete the MQTT integration settings and reconfigure it

502: Bad Gateway
Zigbee2MQTT is still starting up, or failed to start. Zigbee2MQTT takes about 1 minute to start. The error also occurs with various addon startup errors. See the logs for Zigbee2MQTT add-on errors.

Changelog SLZB-OS

📦 v3.3.8.dev5 - Release Notes

New features

Fixes


 

📦 v3.3.8.dev3 - Release Notes

New features

Improvements

Fixes


📦 v3.3.8.dev2 - Release Notes

New features

Improvements

Fixes


📦 v3.3.8.dev1 - Release Notes

New features

Improvements

Fixes

Zigbee Hub

💙💛 Special congratulations to our Ukrainian team on Independence Day and to everyone who supports Ukraine during this difficult time 💙💛


📦 v3.3.5.dev1 - Release Notes

Breaking changes in this update!

Please read breaking changes note before this update: documentation

Improvements

Fixes

Zigbee Hub


📦 v3.3.3.dev7 - Release Notes

Improvements

Fixes

Zigbee Hub


📦 v3.3.3.dev4 - Release Notes

Improvements

Fixes

Zigbee Hub


📦 v3.3.3.dev1 - Release Notes

Improvements

Fixes

Zigbee Hub


📦 v3.3.1 - Release Notes

Improvements

Fixes

Zigbee Hub


📦 SLZB-OS 3.2.9 - Release Notes

Fixes

Zigbee Hub


📦 SLZB-OS 3.2.8 - Release Notes

Highlights

Improvements

Fixes

Zigbee Hub


📦 SLZB-OS 3.2.7 - Release Notes

Highlights

Improvements

Fixes

Zigbee Hub


📦 SLZB-OS 3.2.6.dev3 - Release Notes (dev)

🛠️ Improvements

🐛 Fixes


📦 SLZB-OS 3.2.6.dev2 - Release Notes (dev)

✨ Thread + OTBR running on the device - update

Many users have asked for the ability to set TLVs for this mode via SLZB-OS and now you can do this on /otbr page!

🛠️ Improvements

🐛 Fixes


📦 SLZB-OS 3.2.6.dev0 - Release Notes (dev)

✨ New: Thread + OTBR running on the device (SLZB-xU only) - evaluation/beta mode.

You can now run OpenThread Border Router (OTBR) directly on the SLZB device, instead of running the OTBR add-on/app in Home Assistant.

✅ Why this could be a no-brainer:

🏠 Home Assistant setup:

⚠️ Important notes / limitations:

🛠️ Improvements

🐛 Fixes


🚀 SLZB-OS v3.2.5.dev1 - Release Notes


✨ New Features & Enhancements


🐞 Fixes & Improvements


🚀 SLZB-OS v3.2.4 - Release Notes

The latest version of SLZB-OS (v3.2.4) brings improvements to MQTT integration, internal scripting (automations), Zigbee diagnostics, and overall system stability.


✨ New Features & Enhancements


🐞 Fixes & Improvements


🚀 SLZB-OS v3.2.0 - Release Notes

We’re happy to announce the release of SLZB-OS v3.2.0 - a stability-focused update with new device support, major improvements for U-series USB functionality, and multiple Zigbee Hub reliability enhancements.


✨ Highlights


🆕 New Features


📡 Zigbee Hub Improvements


🔌 USB & Passthrough


🌐 Wi‑Fi & Network


⚙️ OTA & System Stability


🛠️ Other Fixes and Improvements


SLZB-OS v3.0.9

We’re excited to release SLZB-OS v3.0.9, bringing major improvements to Zigbee HubThread, and network stability, along with performance boosts, script engine fixes, and a few critical updates.


⚠️ BREAKING CHANGES - ONLY FOR ZIGBEE HUB MODE USERS - NO EFFECT ON ZIGBEE2MQTT OR ZHA USERS!!!

If you use device as Zigbee coordinator (with Zigbee2MQTT or ZHA) / Thread router - it does not affect you. Again, this change is only for those who use device in a Zigbee Hub Mode.


📡 Zigbee Hub Improvements

🌐 MQTT & DDNS Enhancements

⚡ Performance & System Stability

🧩 Berry Script Engine (zHub)

🌍 Localization

💡 How to Update SLZB‑OS

You can update your coordinator using one of the following methods:

Bluetooth Low Energy

Please note!
To use this functionality, you need to update your Home Assistant to 2026.8 or higher and update SLZB-OS to v3.3.3.dev7 or higher.

General information

SLZB-OS supports receiving BLE advertisements for U series and Ultima devices (ESP32-S3 devices).
Active BLE connections are not supported.
Only support passive/active scanning.

The system consists of two parts:
- SLZB-OS with "Proxy advertisements" enabled. Responsible for physically receiving BLE packets and sending them to HA.
- SMLIGHT SLZB Home Assistant integration. Manages scanning on the SLZB-OS side, receives raw BLE and forwards them to the HA core.

BLE proxy

BLE proxy uses port 5050 so please make sure it is not blocked on your network!

SLZB-OS supports proxying BLE packets to Home Assistant using optimized UDP protocol.

To use BLE proxy you need:

  1. Have SLZB-OS v3.3.3.dev7 or later
  2. Have Home Assistant 2026.8 or later
  3. Have active SMLIGHT SLZB integration
  4. Have "BLE" and "Proxy advertisements" enabled in SLZB-OS

image.png

Breaking changes

Breaking changes

v3.3.5.dev1

Where did the changes take place?

Zigbee Hub mode users (Does not apply to you if you are using ZHA or Zigbee2MQTT)

USB to Ethernet passthrough mode

Berry: HTTP and ZB modules

Zigbee Hub mode breaking changes

Applies only to those using Zigbee Hub mode

What happened?

In some cases, the ZigBee network key was written to the radio module incorrectly. We fixed this and now it will always written correctly.

Impact

There is a possibility that after the update your zigbee network will break because the network key will now be written correctly (not shifted) and it will not match what is your zigbee network already use. 

Migration

All Zigbee Hub backups made before this update will become incompatible!
Please delete old backups and create a new one after update to prevent conflicts!

In most cases, the migration should go smoothly.

If you see the message:

image.png

Click on "Delete network backup" and restart your device. You will probably have to re-pair your devices after this.

USB to Ethernet passthrough mode

What happened?

We are completely switching to a new USB host driver.

Why are we doing this?
The old driver does not provide enough stability for our users, the device can often crash or not start at all when a USB device is connected. There is also a degradation in performance over time.
Therefore, we are switching to a new improved driver that solves all these problems!

Impact

The old driver looked for the first available serial interface and used it automatically.
The new driver allows you to choose which interface to use (some USB devices provide more than one interface) so you will now need to choose which interface you want to use.

Migration

image.png

Make sure your USB device is selected

image.png

From the drop-down list under Port, select the interface you want to use.

Save the settings and restart the device.

If there are several interfaces and you don't know which one you need, try them all in turn or ask the manufacturer of this USB device which interface to choose.

For ZWA-2 and ZBT-2 you need to select interface 1

Berry: HTTP

What happened?

Stream mode APIs has been changed because the old one did not allow stream POST requests.

Impact

If you don't use HTTP stream mode, nothing impact for you.

HTTP.open() now requires explicit specification of whether stream mode is used (last parameter, optional). If not specified, stream mode is disabled.

For stream mode:
HTTP.setHeader() should be called after HTTP.open() but before HTTP.completeStreamConfig() The buffer size in HTTP.open() for stream mode now means how much data you are going to send in a POST.
Required HTTP.completeStreamConfig() call to complete configuration.

Migration

Update your script according to this example https://github.com/smlight-tech/slzb-os-scripts/blob/v3.3.5.dev0/docs/modules/http.md#quick-example-1

Berry: ZB

What happened?

The ZB module had a significant limitation from the very beginning - it could only work with Radio1 while MR coordinators had 2 radio and Ultima3 can have 3.
Therefore, the ZB module was updated to support work with any number of radio modules.

Impact

Now each ZB function requires specifying the number of the radio module to which it will be applied!

Migration

Update your script according to this example: https://github.com/smlight-tech/slzb-os-scripts/blob/v3.3.5.dev0/examples/basic/zb_reboot_on_drop.be

New API description: https://github.com/smlight-tech/slzb-os-scripts/blob/v3.3.5.dev0/docs/modules/zb.md

Known issues

We know this exists and are working on a fix

Known issues

v3.3.8.dev1 (non-U devices)

OTA updates not working

What happened?

Starting with v3.3.8.dev1, OTA updates do not work on non-U devices.

Due to a bug, native OTBR support was enabled for non-U devices, which resulted in low available RAM values. Due to the low amount of available RAM, the device can no longer perform HTTPS requests, so OTA updates via our update server no longer work.

Solution

You need to update your device locally.

  1. Download the update file from this link https://updates.smlight.tech/firmware/slzb06x/core/slzb-os-v3.3.8.dev5-ota.bin
  2. Go to the menu "Settings and Tools" -> "Firmware update"
  3. Select "Flash the custom firmware" for "SLZB-OS Update"
  4. Select downloaded update file and press "Update firmware"
  5. Wait for the update to finish
Known issues

All OS versions

CC26XX radio modules (Texas instruments) freeze / hang / crash

Known problem for a long time

What happened?

CC2652P, CC2652P7, and CC2674P10 have a critical bug in the SDK and may hang, especially under high load.

Main symptom: "Error: SRSP - SYS - ping after 6000ms" error, i.e. the radio module is no longer sending any traffic.
In this state, the radio module may also not respond to RST pin, so sometimes this requires a physical power cycle.

Solution

Partial solution: limit traffic in the ZigBee network, remove spamming ZigBee devices. This will postpone the problem but will not solve it completely.

Complete solution: no complete solutions have been found yet.

Spontaneous device reboots: TASK_WDT

What happened?

The device reboots from time to time with the reboot reason TASK_WDT.

Solution

Usually the cause is spam mDNS traffic on your network.
The device can handle traffic of up to about 1000 multicast packets per second, if the flow is higher the device will reboot after a while.
To resolve this you need to do one of the following:

Disabling mDNS

Completely disable mDNS traffic at the router level or on the "Network" page in the coordinator settings.
Will work if you are not using mDNS and are not using Thread.

Finding the source of multicast traffic

Yes, you need to analyze and find the device that is spamming the network. What to do with this device is up to you. Usually, the device that generates such traffic have a bug in its firmware.

Additional router settings

IGMP Snooping in combination with the settings in the card below can help

image.png