diff --git a/tasmota/CHANGELOG.md b/tasmota/CHANGELOG.md index 0977c85c7..665186b0d 100644 --- a/tasmota/CHANGELOG.md +++ b/tasmota/CHANGELOG.md @@ -7,6 +7,7 @@ - Fix Zigbee sending wrong Sat value with Hue emulation - Add command ``ZbRestore`` to restore device configuration dumped with ``ZbStatus 2`` - Add support for unreachable (unplugged) Zigbee devices in Philips Hue emulation and Alexa +- Add Zigbee ``ZbUnbind``command ## Released diff --git a/tasmota/i18n.h b/tasmota/i18n.h index 47afc7307..04433788f 100644 --- a/tasmota/i18n.h +++ b/tasmota/i18n.h @@ -505,6 +505,8 @@ #define D_JSON_ZIGBEE_RECEIVED "ZbReceived" #define D_CMND_ZIGBEE_BIND "Bind" #define D_JSON_ZIGBEE_BIND "ZbBind" +#define D_CMND_ZIGBEE_UNBIND "Unbind" + #define D_JSON_ZIGBEE_UNBIND "ZbUnbind" #define D_CMND_ZIGBEE_PING "Ping" #define D_JSON_ZIGBEE_PING "ZbPing" #define D_JSON_ZIGBEE_IEEE "IEEEAddr" diff --git a/tasmota/xdrv_23_zigbee_8_parsers.ino b/tasmota/xdrv_23_zigbee_8_parsers.ino index 5e05d6c82..cc95d4ed0 100644 --- a/tasmota/xdrv_23_zigbee_8_parsers.ino +++ b/tasmota/xdrv_23_zigbee_8_parsers.ino @@ -388,6 +388,31 @@ int32_t Z_BindRsp(int32_t res, const class SBuffer &buf) { return -1; } +// +// Handle Unbind Rsp incoming message +// +int32_t Z_UnbindRsp(int32_t res, const class SBuffer &buf) { + Z_ShortAddress nwkAddr = buf.get16(2); + uint8_t status = buf.get8(4); + + const char * friendlyName = zigbee_devices.getFriendlyName(nwkAddr); + if (friendlyName) { + Response_P(PSTR("{\"" D_JSON_ZIGBEE_UNBIND "\":{\"" D_JSON_ZIGBEE_DEVICE "\":\"0x%04X\"" + ",\"" D_JSON_ZIGBEE_NAME "\":\"%s\"" + ",\"" D_JSON_ZIGBEE_STATUS "\":%d" + ",\"" D_JSON_ZIGBEE_STATUS_MSG "\":\"%s\"" + "}}"), nwkAddr, friendlyName, status, getZigbeeStatusMessage(status).c_str()); + } else { + Response_P(PSTR("{\"" D_JSON_ZIGBEE_UNBIND "\":{\"" D_JSON_ZIGBEE_DEVICE "\":\"0x%04X\"" + ",\"" D_JSON_ZIGBEE_STATUS "\":%d" + ",\"" D_JSON_ZIGBEE_STATUS_MSG "\":\"%s\"" + "}}"), nwkAddr, status, getZigbeeStatusMessage(status).c_str()); + } + MqttPublishPrefixTopic_P(RESULT_OR_TELE, PSTR(D_JSON_ZIGBEEZCL_RECEIVED)); + XdrvRulesProcess(); + + return -1; +} /*********************************************************************************************\ * Send specific ZNP messages @@ -553,6 +578,7 @@ ZBM(AREQ_ZDO_ACTIVEEPRSP, Z_AREQ | Z_ZDO, ZDO_ACTIVE_EP_RSP) // 4 ZBM(AREQ_ZDO_SIMPLEDESCRSP, Z_AREQ | Z_ZDO, ZDO_SIMPLE_DESC_RSP) // 4584 ZBM(AREQ_ZDO_IEEE_ADDR_RSP, Z_AREQ | Z_ZDO, ZDO_IEEE_ADDR_RSP) // 4581 ZBM(AREQ_ZDO_BIND_RSP, Z_AREQ | Z_ZDO, ZDO_BIND_RSP) // 45A1 +ZBM(AREQ_ZDO_UNBIND_RSP, Z_AREQ | Z_ZDO, ZDO_UNBIND_RSP) // 45A2 // Dispatcher callbacks table const Z_Dispatcher Z_DispatchTable[] PROGMEM = { @@ -565,6 +591,7 @@ const Z_Dispatcher Z_DispatchTable[] PROGMEM = { { AREQ_ZDO_ACTIVEEPRSP, &Z_ReceiveActiveEp }, { AREQ_ZDO_IEEE_ADDR_RSP, &Z_ReceiveIEEEAddr }, { AREQ_ZDO_BIND_RSP, &Z_BindRsp }, + { AREQ_ZDO_UNBIND_RSP, &Z_UnbindRsp }, }; /*********************************************************************************************\ diff --git a/tasmota/xdrv_23_zigbee_9_impl.ino b/tasmota/xdrv_23_zigbee_9_impl.ino index 49f89c9c7..423ac43f1 100644 --- a/tasmota/xdrv_23_zigbee_9_impl.ino +++ b/tasmota/xdrv_23_zigbee_9_impl.ino @@ -34,7 +34,7 @@ const char kZbCommands[] PROGMEM = D_PRFX_ZB "|" // prefix D_CMND_ZIGBEE_STATUS "|" D_CMND_ZIGBEE_RESET "|" D_CMND_ZIGBEE_SEND "|" D_CMND_ZIGBEE_PROBE "|" D_CMND_ZIGBEE_READ "|" D_CMND_ZIGBEEZNPRECEIVE "|" D_CMND_ZIGBEE_FORGET "|" D_CMND_ZIGBEE_SAVE "|" D_CMND_ZIGBEE_NAME "|" - D_CMND_ZIGBEE_BIND "|" D_CMND_ZIGBEE_PING "|" D_CMND_ZIGBEE_MODELID "|" + D_CMND_ZIGBEE_BIND "|" D_CMND_ZIGBEE_UNBIND "|" D_CMND_ZIGBEE_PING "|" D_CMND_ZIGBEE_MODELID "|" D_CMND_ZIGBEE_LIGHT "|" D_CMND_ZIGBEE_RESTORE ; @@ -43,7 +43,7 @@ void (* const ZigbeeCommand[])(void) PROGMEM = { &CmndZbStatus, &CmndZbReset, &CmndZbSend, &CmndZbProbe, &CmndZbRead, &CmndZbZNPReceive, &CmndZbForget, &CmndZbSave, &CmndZbName, - &CmndZbBind, &CmndZbPing, &CmndZbModelId, + &CmndZbBind, &CmndZbUnbind, &CmndZbPing, &CmndZbModelId, &CmndZbLight, CmndZbRestore, }; @@ -534,8 +534,9 @@ void CmndZbSend(void) { // // Command `ZbBind` // -void CmndZbBind(void) { +void ZbBindUnbind(bool unbind) { // false = bind, true = unbind // ZbBind {"Device":"", "Endpoint":, "Cluster":, "ToDevice":"", "ToEndpoint":, "ToGroup": } + // ZbUnbind {"Device":"", "Endpoint":, "Cluster":, "ToDevice":"", "ToEndpoint":, "ToGroup": } // local endpoint is always 1, IEEE addresses are calculated if (zigbee.init_phase) { ResponseCmndChar_P(PSTR(D_ZIGBEE_NOT_STARTED)); return; } @@ -601,7 +602,11 @@ void CmndZbBind(void) { SBuffer buf(34); buf.add8(Z_SREQ | Z_ZDO); - buf.add8(ZDO_BIND_REQ); + if (unbind) { + buf.add8(ZDO_UNBIND_REQ); + } else { + buf.add8(ZDO_BIND_REQ); + } buf.add16(srcDevice); buf.add64(srcLongAddr); buf.add8(endpoint); @@ -620,6 +625,20 @@ void CmndZbBind(void) { ResponseCmndDone(); } +// +// Command ZbBind +// +void CmndZbBind(void) { + ZbBindUnbind(false); +} + +// +// Command ZbBind +// +void CmndZbUnbind(void) { + ZbBindUnbind(true); +} + // Probe a specific device to get its endpoints and supported clusters void CmndZbProbe(void) { CmndZbProbeOrPing(true);