diff --git a/tasmota/xdrv_23_zigbee_4_persistence.ino b/tasmota/xdrv_23_zigbee_4_persistence.ino index 062da3da4..d15a50ef9 100644 --- a/tasmota/xdrv_23_zigbee_4_persistence.ino +++ b/tasmota/xdrv_23_zigbee_4_persistence.ino @@ -204,7 +204,7 @@ const char * hydrateSingleString(const SBuffer & buf, uint32_t *d) { return ptr; } -void hydrateSingleDevice(const SBuffer & buf_d, uint32_t version) { +void hydrateSingleDevice(const SBuffer & buf_d, uint32_t version = 2) { uint32_t d = 1; // index in device buffer uint16_t shortaddr = buf_d.get16(d); d += 2; uint64_t longaddr = buf_d.get64(d); d += 8; @@ -424,4 +424,16 @@ void eraseZigbeeDevices(void) { #endif // ESP32 } +void restoreDumpAllDevices(void) { + for (const auto & device : zigbee_devices.getDevices()) { + const SBuffer buf = hibernateDevicev2(device); + if (buf.len() > 0) { + char hex_char[buf.len()*2+2]; + Response_P(PSTR("{\"" D_PRFX_ZB D_CMND_ZIGBEE_RESTORE "\":\"ZbRestore %s\"}"), + ToHex_P(buf.buf(0), buf.len(), hex_char, sizeof(hex_char))); + MqttPublishPrefixTopicRulesProcess_P(RESULT_OR_STAT, PSTR(D_PRFX_ZB D_CMND_ZIGBEE_DATA)); + } + } +} + #endif // USE_ZIGBEE diff --git a/tasmota/xdrv_23_zigbee_8_parsers.ino b/tasmota/xdrv_23_zigbee_8_parsers.ino index 48fff2a76..5d60d3ed3 100644 --- a/tasmota/xdrv_23_zigbee_8_parsers.ino +++ b/tasmota/xdrv_23_zigbee_8_parsers.ino @@ -1676,8 +1676,6 @@ int32_t EZ_IncomingMessage(int32_t res, const class SBuffer &buf) { case ZDO_Parent_annce_rsp: return EZ_ParentAnnceRsp(res, zdo_buf, true); default: - // TODO move later to LOG_LEVEL_DEBUG - AddLog_P(LOG_LEVEL_INFO, PSTR("ZIG: Internal ZDO message 0x%04X sent from 0x%04X %s"), clusterid, srcaddr, wasbroadcast ? PSTR("(broadcast)") : ""); break; } } else { diff --git a/tasmota/xdrv_23_zigbee_A_impl.ino b/tasmota/xdrv_23_zigbee_A_impl.ino index 58be4e01a..5b8fc1960 100644 --- a/tasmota/xdrv_23_zigbee_A_impl.ino +++ b/tasmota/xdrv_23_zigbee_A_impl.ino @@ -1282,40 +1282,57 @@ void CmndZbSave(void) { // ZbRestore {"Device":"0x5ADF","Name":"Petite_Lampe","IEEEAddr":"0x90FD9FFFFE03B051","ModelId":"TRADFRI bulb E27 WS opal 980lm","Manufacturer":"IKEA of Sweden","Endpoints":["0x01","0xF2"]} void CmndZbRestore(void) { if (zigbee.init_phase) { ResponseCmndChar_P(PSTR(D_ZIGBEE_NOT_STARTED)); return; } - JsonParser parser(XdrvMailbox.data); - JsonParserToken root = parser.getRoot(); + RemoveSpace(XdrvMailbox.data); - if (!parser || !(root.isObject() || root.isArray())) { ResponseCmndChar_P(PSTR(D_JSON_INVALID_JSON)); return; } + if (strlen(XdrvMailbox.data) == 0) { + // if empty, log values for all devices + restoreDumpAllDevices(); + } else if (XdrvMailbox.data[0] == '{') { // try JSON + JsonParser parser(XdrvMailbox.data); + JsonParserToken root = parser.getRoot(); - // Check is root contains `ZbStatus` key, if so change the root - JsonParserToken zbstatus = root.getObject().findStartsWith(PSTR("ZbStatus")); - if (zbstatus) { - root = zbstatus; - } + if (!parser || !(root.isObject() || root.isArray())) { ResponseCmndChar_P(PSTR(D_JSON_INVALID_JSON)); return; } - // check if the root is an array - if (root.isArray()) { - JsonParserArray arr = JsonParserArray(root); - for (const auto elt : arr) { - // call restore on each item - if (elt.isObject()) { - int32_t res = zigbee_devices.deviceRestore(JsonParserObject(elt)); - if (res < 0) { - ResponseCmndChar_P(PSTR("Restore failed")); - return; + // Check is root contains `ZbStatus` key, if so change the root + JsonParserToken zbstatus = root.getObject().findStartsWith(PSTR("ZbStatus")); + if (zbstatus) { + root = zbstatus; + } + + // check if the root is an array + if (root.isArray()) { + JsonParserArray arr = JsonParserArray(root); + for (const auto elt : arr) { + // call restore on each item + if (elt.isObject()) { + int32_t res = zigbee_devices.deviceRestore(JsonParserObject(elt)); + if (res < 0) { + ResponseCmndChar_P(PSTR("Restore failed")); + return; + } } } + } else if (root.isObject()) { + int32_t res = zigbee_devices.deviceRestore(JsonParserObject(root)); + if (res < 0) { + ResponseCmndChar_P(PSTR("Restore failed")); + return; + } + // call restore on a single object + } else { + ResponseCmndChar_P(PSTR("Missing parameters")); + return; } - } else if (root.isObject()) { - int32_t res = zigbee_devices.deviceRestore(JsonParserObject(root)); - if (res < 0) { + } else { // try hex + SBuffer buf = SBuffer::SBufferFromHex(XdrvMailbox.data, strlen(XdrvMailbox.data)); + // do a sanity check, the first byte must equal the length of the buffer + if (buf.get8(0) == buf.len()) { + // good, we can hydrate + hydrateSingleDevice(buf); + } else { ResponseCmndChar_P(PSTR("Restore failed")); return; } - // call restore on a single object - } else { - ResponseCmndChar_P(PSTR("Missing parameters")); - return; } ResponseCmndDone(); } @@ -1857,11 +1874,12 @@ bool Xdrv23(uint8_t function) case FUNC_COMMAND: result = DecodeCommand(kZbCommands, ZigbeeCommand); break; -#ifdef USE_ZIGBEE_EZSP case FUNC_SAVE_BEFORE_RESTART: +#ifdef USE_ZIGBEE_EZSP hibernateAllData(); - break; #endif // USE_ZIGBEE_EZSP + restoreDumpAllDevices(); + break; } } return result;