Zigbee Through-RPC
The Zigbee Through-RPC Command Protocol exposes three RPC methods that allow external clients (HTTP, WebSocket, MQTT) to directly issue ZCL (Zigbee Cluster Library) commands to any Zigbee device on the network.
The following methods are available:
Zigbee.SendCommand— send a raw ZCL cluster commandZigbee.ReadAttr— read a ZCL attribute valueZigbee.WriteAttr— write a ZCL attribute value
Common Concepts
Addressing
Every method requires identifying the target Zigbee device by its network address and endpoint:
| Property | Type | Description |
|---|---|---|
| uint16 | 16-bit Zigbee short network address of the target device |
| uint8 | Endpoint number on the target device |
| uint16 | ZCL Cluster ID (e.g. |
dst_addr is the 16-bit short address assigned to the device during Zigbee network joining. It is not the 64-bit IEEE/MAC address.
Payload Encoding
All binary payloads and attribute values are passed as lowercase hex strings (e.g. "0100" = bytes 0x01 0x00). Multi-byte values follow little-endian byte order per the ZCL specification. Omit the field or pass "" for an empty payload.
Timeout
All methods accept an optional timeout_ms parameter (default 10000 ms) that controls how long to wait for a response from the end device.
Methods
Zigbee.SendCommand
Send a raw ZCL cluster command to a Zigbee device.
Request
| Property | Type | Description |
|---|---|---|
| uint16 | Short Zigbee network address of the target device |
| uint8 | Target endpoint number |
| uint16 | ZCL Cluster ID |
| uint8 | ZCL Command ID within the cluster |
| string | Command payload as a hex string. Optional, default |
| uint32 | Response timeout in milliseconds. Optional, default |
Response
| Property | Type | Description |
|---|---|---|
| bool |
|
| string | ZCL status code name (e.g. |
Zigbee.ReadAttr
Read a single ZCL attribute from a Zigbee device.
Request
| Property | Type | Description |
|---|---|---|
| uint16 | Short Zigbee network address of the target device |
| uint8 | Target endpoint number |
| uint16 | ZCL Cluster ID |
| uint16 | Attribute ID to read |
| uint32 | Response timeout in milliseconds. Optional, default |
Response
| Property | Type | Description |
|---|---|---|
| bool |
|
| uint8 | ZCL attribute data type code (present on success) |
| string | Raw attribute value as a hex string (present on success) |
| uint8 | Length of the value in bytes (present on success) |
ZCL Data Types
Common ZCL data type codes returned in the type field:
| Value | Description |
|---|---|
| Boolean — 1 byte |
| uint8 — 1 byte |
| uint16 — 2 bytes |
| uint32 — 4 bytes |
| int16 — 2 bytes |
| character string — variable length |
Zigbee.WriteAttr
Write a value to a single ZCL attribute on a Zigbee device.
Request
| Property | Type | Description |
|---|---|---|
| uint16 | Short Zigbee network address of the target device |
| uint8 | Target endpoint number |
| uint16 | ZCL Cluster ID |
| uint16 | Attribute ID to write |
| uint8 | ZCL attribute data type code — must match the ZCL-defined type of the target attribute |
| string | Value to write as a hex string |
| uint32 | Response timeout in milliseconds. Optional, default |
Response
| Property | Type | Description |
|---|---|---|
| bool |
|
| string | ZCL status code name (e.g. |
When a device times out or returns a ZCL-level error, the response body will be {"success": false, "status": "..."} with the relevant ZCL status code name.
Examples
Zigbee.SendCommand — On/Off/Toggle
The On/Off cluster (cluster: 6) uses cmd to select the operation: 0 = off, 1 = on, 2 = toggle.
- Turn On (cmd: 1)
- Turn Off (cmd: 0)
- Toggle (cmd: 2)
- Zigbee.SendCommand HTTP GET Request
- Zigbee.SendCommand Curl Request
- Zigbee.SendCommand Mos Request
http://192.168.33.1/rpc/Zigbee.SendCommand?dst_addr=12345&dst_ep=1&cluster=6&cmd=1
curl -X POST -d '{"id":1,"method":"Zigbee.SendCommand","params":{"dst_addr":12345,"dst_ep":1,"cluster":6,"cmd":1}}' http://${SHELLY}/rpc
mos --port ${PORT} call Zigbee.SendCommand '{"dst_addr":12345,"dst_ep":1,"cluster":6,"cmd":1}'
Response
- Zigbee.SendCommand HTTP GET Response
- Zigbee.SendCommand Curl Response
- Zigbee.SendCommand Mos Response
{
"success": true,
"status": "ZB_ZCL_STATUS_SUCCESS"
}
{
"id": 1,
"params": {
"success": true,
"status": "ZB_ZCL_STATUS_SUCCESS"
}
}
{
"success": true,
"status": "ZB_ZCL_STATUS_SUCCESS"
}
- Zigbee.SendCommand HTTP GET Request
- Zigbee.SendCommand Curl Request
- Zigbee.SendCommand Mos Request
http://192.168.33.1/rpc/Zigbee.SendCommand?dst_addr=12345&dst_ep=1&cluster=6&cmd=0
curl -X POST -d '{"id":1,"method":"Zigbee.SendCommand","params":{"dst_addr":12345,"dst_ep":1,"cluster":6,"cmd":0}}' http://${SHELLY}/rpc
mos --port ${PORT} call Zigbee.SendCommand '{"dst_addr":12345,"dst_ep":1,"cluster":6,"cmd":0}'
Response
- Zigbee.SendCommand HTTP GET Response
- Zigbee.SendCommand Curl Response
- Zigbee.SendCommand Mos Response
{
"success": true,
"status": "ZB_ZCL_STATUS_SUCCESS"
}
{
"id": 1,
"params": {
"success": true,
"status": "ZB_ZCL_STATUS_SUCCESS"
}
}
{
"success": true,
"status": "ZB_ZCL_STATUS_SUCCESS"
}
- Zigbee.SendCommand HTTP GET Request
- Zigbee.SendCommand Curl Request
- Zigbee.SendCommand Mos Request
http://192.168.33.1/rpc/Zigbee.SendCommand?dst_addr=12345&dst_ep=1&cluster=6&cmd=2
curl -X POST -d '{"id":1,"method":"Zigbee.SendCommand","params":{"dst_addr":12345,"dst_ep":1,"cluster":6,"cmd":2}}' http://${SHELLY}/rpc
mos --port ${PORT} call Zigbee.SendCommand '{"dst_addr":12345,"dst_ep":1,"cluster":6,"cmd":2}'
Response
- Zigbee.SendCommand HTTP GET Response
- Zigbee.SendCommand Curl Response
- Zigbee.SendCommand Mos Response
{
"success": true,
"status": "ZB_ZCL_STATUS_SUCCESS"
}
{
"id": 1,
"params": {
"success": true,
"status": "ZB_ZCL_STATUS_SUCCESS"
}
}
{
"success": true,
"status": "ZB_ZCL_STATUS_SUCCESS"
}
Zigbee.SendCommand — Move to Level (50%, 1s transition)
The payload "800a00" encodes level 0x80 (128 = 50%) followed by transition time 0x000a (10 × 100ms = 1 second) in little-endian byte order.
- Zigbee.SendCommand HTTP GET Request
- Zigbee.SendCommand Curl Request
- Zigbee.SendCommand Mos Request
http://192.168.33.1/rpc/Zigbee.SendCommand?dst_addr=12345&dst_ep=1&cluster=8&cmd=4&payload="800a00"
curl -X POST -d '{"id":1,"method":"Zigbee.SendCommand","params":{"dst_addr":12345,"dst_ep":1,"cluster":8,"cmd":4,"payload":"800a00"}}' http://${SHELLY}/rpc
mos --port ${PORT} call Zigbee.SendCommand '{"dst_addr":12345,"dst_ep":1,"cluster":8,"cmd":4,"payload":"800a00"}'
Response
- Zigbee.SendCommand HTTP GET Response
- Zigbee.SendCommand Curl Response
- Zigbee.SendCommand Mos Response
{
"success": true,
"status": "ZB_ZCL_STATUS_SUCCESS"
}
{
"id": 1,
"params": {
"success": true,
"status": "ZB_ZCL_STATUS_SUCCESS"
}
}
{
"success": true,
"status": "ZB_ZCL_STATUS_SUCCESS"
}
Zigbee.SendCommand — Custom Timeout
- Zigbee.SendCommand HTTP GET Request
- Zigbee.SendCommand Curl Request
- Zigbee.SendCommand Mos Request
http://192.168.33.1/rpc/Zigbee.SendCommand?dst_addr=12345&dst_ep=1&cluster=6&cmd=1&timeout_ms=5000
curl -X POST -d '{"id":1,"method":"Zigbee.SendCommand","params":{"dst_addr":12345,"dst_ep":1,"cluster":6,"cmd":1,"timeout_ms":5000}}' http://${SHELLY}/rpc
mos --port ${PORT} call Zigbee.SendCommand '{"dst_addr":12345,"dst_ep":1,"cluster":6,"cmd":1,"timeout_ms":5000}'
Response
- Zigbee.SendCommand HTTP GET Response
- Zigbee.SendCommand Curl Response
- Zigbee.SendCommand Mos Response
{
"success": true,
"status": "ZB_ZCL_STATUS_SUCCESS"
}
{
"id": 1,
"params": {
"success": true,
"status": "ZB_ZCL_STATUS_SUCCESS"
}
}
{
"success": true,
"status": "ZB_ZCL_STATUS_SUCCESS"
}
Zigbee.ReadAttr — On/Off State (cluster 6, attr 0)
A response value of "01" means the light is currently on.
- Zigbee.ReadAttr HTTP GET Request
- Zigbee.ReadAttr Curl Request
- Zigbee.ReadAttr Mos Request
http://192.168.33.1/rpc/Zigbee.ReadAttr?dst_addr=12345&dst_ep=1&cluster=6&attr=0
curl -X POST -d '{"id":1,"method":"Zigbee.ReadAttr","params":{"dst_addr":12345,"dst_ep":1,"cluster":6,"attr":0}}' http://${SHELLY}/rpc
mos --port ${PORT} call Zigbee.ReadAttr '{"dst_addr":12345,"dst_ep":1,"cluster":6,"attr":0}'
Response
- Zigbee.ReadAttr HTTP GET Response
- Zigbee.ReadAttr Curl Response
- Zigbee.ReadAttr Mos Response
{
"success": true,
"type": 16,
"value": "01",
"len": 1
}
{
"id": 1,
"params": {
"success": true,
"type": 16,
"value": "01",
"len": 1
}
}
{
"success": true,
"type": 16,
"value": "01",
"len": 1
}
Zigbee.WriteAttr — Identify Time = 10s (cluster 3, attr 0)
The value "0a00" encodes 10 seconds as a uint16 in little-endian byte order.
- Zigbee.WriteAttr HTTP GET Request
- Zigbee.WriteAttr Curl Request
- Zigbee.WriteAttr Mos Request
http://192.168.33.1/rpc/Zigbee.WriteAttr?dst_addr=12345&dst_ep=1&cluster=3&attr=0&type=33&value="0a00"
curl -X POST -d '{"id":1,"method":"Zigbee.WriteAttr","params":{"dst_addr":12345,"dst_ep":1,"cluster":3,"attr":0,"type":33,"value":"0a00"}}' http://${SHELLY}/rpc
mos --port ${PORT} call Zigbee.WriteAttr '{"dst_addr":12345,"dst_ep":1,"cluster":3,"attr":0,"type":33,"value":"0a00"}'
Response
- Zigbee.WriteAttr HTTP GET Response
- Zigbee.WriteAttr Curl Response
- Zigbee.WriteAttr Mos Response
{
"success": true,
"status_str": "ZB_ZCL_STATUS_SUCCESS"
}
{
"id": 1,
"params": {
"success": true,
"status_str": "ZB_ZCL_STATUS_SUCCESS"
}
}
{
"success": true,
"status_str": "ZB_ZCL_STATUS_SUCCESS"
}