mirror of
https://github.com/arendst/Tasmota.git
synced 2025-07-24 11:16:34 +00:00
Zigbee loads device data early before MCU startup (#21917)
This commit is contained in:
parent
4f035d18f6
commit
f88a635d5d
@ -30,6 +30,7 @@ All notable changes to this project will be documented in this file.
|
||||
- ESP32 platform update from 2024.07.11 to 2024.08.10 (#21893)
|
||||
- ESP32 Framework (Arduino Core) from v3.0.2 to v3.0.4 (#21893)
|
||||
- Refactored Analog driver to better support multiple channels
|
||||
- Zigbee loads device data early before MCU startup
|
||||
|
||||
### Fixed
|
||||
- Berry `light.get` for separate RGB/CT (#21818)
|
||||
|
@ -69,7 +69,7 @@ public:
|
||||
#endif // USE_ZIGBEE_EEPROM
|
||||
{}
|
||||
|
||||
bool active = true; // is Zigbee active for this device, i.e. GPIOs configured
|
||||
bool active = false; // is Zigbee active for this device, i.e. GPIOs configured
|
||||
bool state_machine = false; // the state machine is running
|
||||
bool state_waiting = false; // the state machine is waiting for external event or timeout
|
||||
bool state_no_timeout = false; // the current wait loop does not generate a timeout but only continues running
|
||||
|
@ -425,7 +425,27 @@ static const Zigbee_Instruction zb_prog[] PROGMEM = {
|
||||
ZI_ON_ERROR_GOTO(ZIGBEE_LABEL_ABORT)
|
||||
ZI_ON_TIMEOUT_GOTO(ZIGBEE_LABEL_ABORT)
|
||||
ZI_ON_RECV_UNEXPECTED(&ZNP_Recv_Default)
|
||||
|
||||
ZI_LOG(LOG_LEVEL_INFO, D_LOG_ZIGBEE "Loading Zigbee data")
|
||||
ZI_CALL(&Z_Prepare_Storage, 0)
|
||||
ZI_CALL(&Z_Load_Devices, 0)
|
||||
ZI_CALL(&Z_Load_Data, 0)
|
||||
ZI_CALL(&Z_Set_Save_Data_Timer, 0)
|
||||
ZI_CALL(&Z_ZbAutoload, 0)
|
||||
#ifndef USE_ZIGBEE_DEBUG
|
||||
ZI_WAIT(15500) // wait for 15 seconds for Tasmota to stabilize
|
||||
#else
|
||||
ZI_WAIT(30000) // wait for cumulated 5 minutes
|
||||
ZI_WAIT(30000)
|
||||
ZI_WAIT(30000)
|
||||
ZI_WAIT(30000)
|
||||
ZI_WAIT(30000)
|
||||
ZI_WAIT(30000)
|
||||
ZI_WAIT(30000)
|
||||
ZI_WAIT(30000)
|
||||
ZI_WAIT(30000)
|
||||
ZI_WAIT(30000)
|
||||
#endif
|
||||
|
||||
//ZI_MQTT_STATE(ZIGBEE_STATUS_BOOT, "Booting")
|
||||
ZI_LOG(LOG_LEVEL_INFO, D_LOG_ZIGBEE "rebooting ZNP device")
|
||||
@ -532,11 +552,6 @@ static const Zigbee_Instruction zb_prog[] PROGMEM = {
|
||||
// Correctly configured and running, enable all Tasmota features
|
||||
// ======================================================================
|
||||
ZI_LABEL(ZIGBEE_LABEL_READY)
|
||||
ZI_CALL(&Z_Prepare_Storage, 0)
|
||||
ZI_CALL(&Z_Load_Devices, 0)
|
||||
ZI_CALL(&Z_Load_Data, 0)
|
||||
ZI_CALL(&Z_Set_Save_Data_Timer, 0)
|
||||
ZI_CALL(&Z_ZbAutoload, 0)
|
||||
ZI_MQTT_STATE(ZIGBEE_STATUS_OK, kStarted)
|
||||
ZI_LOG(LOG_LEVEL_INFO, kZigbeeStarted)
|
||||
ZI_CALL(&Z_State_Ready, 1) // Now accept incoming messages
|
||||
@ -881,7 +896,27 @@ static const Zigbee_Instruction zb_prog[] PROGMEM = {
|
||||
ZI_ON_ERROR_GOTO(ZIGBEE_LABEL_ABORT)
|
||||
ZI_ON_TIMEOUT_GOTO(ZIGBEE_LABEL_ABORT)
|
||||
ZI_ON_RECV_UNEXPECTED(&EZ_Recv_Default)
|
||||
|
||||
ZI_LOG(LOG_LEVEL_INFO, D_LOG_ZIGBEE "Loading Zigbee data")
|
||||
ZI_CALL(&Z_Prepare_Storage, 0)
|
||||
ZI_CALL(&Z_Load_Devices, 0)
|
||||
ZI_CALL(&Z_Load_Data, 0)
|
||||
ZI_CALL(&Z_Set_Save_Data_Timer, 0)
|
||||
ZI_CALL(&Z_ZbAutoload, 0)
|
||||
#ifndef USE_ZIGBEE_DEBUG
|
||||
ZI_WAIT(15500) // wait for 15 seconds for Tasmota to stabilize
|
||||
#else
|
||||
ZI_WAIT(30000) // wait for cumulated 5 minutes
|
||||
ZI_WAIT(30000)
|
||||
ZI_WAIT(30000)
|
||||
ZI_WAIT(30000)
|
||||
ZI_WAIT(30000)
|
||||
ZI_WAIT(30000)
|
||||
ZI_WAIT(30000)
|
||||
ZI_WAIT(30000)
|
||||
ZI_WAIT(30000)
|
||||
ZI_WAIT(30000)
|
||||
#endif
|
||||
|
||||
// Hardware reset
|
||||
ZI_LOG(LOG_LEVEL_INFO, kResettingDevice) // Log Debug: resetting EZSP device
|
||||
@ -978,12 +1013,7 @@ static const Zigbee_Instruction zb_prog[] PROGMEM = {
|
||||
ZI_LOG(LOG_LEVEL_INFO, kZigbeeGroup0)
|
||||
ZI_SEND(ZBS_SET_MCAST_ENTRY) ZI_WAIT_RECV(2500, ZBR_SET_MCAST_ENTRY)
|
||||
|
||||
// ZI_LABEL(ZIGBEE_LABEL_READY)
|
||||
ZI_CALL(&Z_Prepare_Storage, 0)
|
||||
ZI_CALL(&Z_Load_Devices, 0)
|
||||
ZI_CALL(&Z_Load_Data, 0)
|
||||
ZI_CALL(&Z_Set_Save_Data_Timer, 0)
|
||||
ZI_CALL(&Z_ZbAutoload, 0)
|
||||
ZI_LABEL(ZIGBEE_LABEL_READY)
|
||||
ZI_MQTT_STATE(ZIGBEE_STATUS_OK, kStarted)
|
||||
ZI_LOG(LOG_LEVEL_INFO, kZigbeeStarted)
|
||||
ZI_CALL(&Z_State_Ready, 1) // Now accept incoming messages
|
||||
@ -1088,6 +1118,7 @@ void ZigbeeStateMachine_Run(void) {
|
||||
}
|
||||
if (zigbee.pc < 0) {
|
||||
zigbee.state_machine = false;
|
||||
zigbee.active = false;
|
||||
return;
|
||||
}
|
||||
|
||||
@ -1133,6 +1164,7 @@ void ZigbeeStateMachine_Run(void) {
|
||||
zigbee.state_machine = false;
|
||||
if (cur_d8) {
|
||||
AddLog(LOG_LEVEL_ERROR, PSTR(D_LOG_ZIGBEE "Stopping (%d)"), cur_d8);
|
||||
zigbee.active = false;
|
||||
}
|
||||
break;
|
||||
case ZGB_INSTR_CALL:
|
||||
|
@ -1172,8 +1172,6 @@ void CmndZbName(void) {
|
||||
//
|
||||
// Where <device_id> can be: short_addr, long_addr, device_index, friendly_name
|
||||
|
||||
if (zigbee.init_phase) { ResponseCmndChar_P(PSTR(D_ZIGBEE_NOT_STARTED)); return; }
|
||||
|
||||
// check if parameters contain a comma ','
|
||||
char *p = XdrvMailbox.data;
|
||||
char *device_id = strsep(&p, ","); // zigbee identifier
|
||||
@ -1214,8 +1212,6 @@ void CmndZbModelId(void) {
|
||||
//
|
||||
// Where <device_id> can be: short_addr, long_addr, device_index, friendly_name
|
||||
|
||||
if (zigbee.init_phase) { ResponseCmndChar_P(PSTR(D_ZIGBEE_NOT_STARTED)); return; }
|
||||
|
||||
// check if parameters contain a comma ','
|
||||
char *p;
|
||||
strtok_r(XdrvMailbox.data, ",", &p);
|
||||
@ -1241,8 +1237,6 @@ void CmndZbLight(void) {
|
||||
//
|
||||
// Where <device_id> can be: short_addr, long_addr, device_index, friendly_name
|
||||
|
||||
if (zigbee.init_phase) { ResponseCmndChar_P(PSTR(D_ZIGBEE_NOT_STARTED)); return; }
|
||||
|
||||
// check if parameters contain a comma ','
|
||||
char *p = XdrvMailbox.data;
|
||||
char *device_id = strsep(&p, ","); // zigbee identifier
|
||||
@ -1287,8 +1281,6 @@ void CmndZbOccupancy(void) {
|
||||
// 0x8 = 120 s
|
||||
// Where <device_id> can be: short_addr, long_addr, device_index, friendly_name
|
||||
|
||||
if (zigbee.init_phase) { ResponseCmndChar_P(PSTR(D_ZIGBEE_NOT_STARTED)); return; }
|
||||
|
||||
// check if parameters contain a comma ','
|
||||
char *p;
|
||||
strtok_r(XdrvMailbox.data, ",", &p);
|
||||
@ -1320,7 +1312,6 @@ void CmndZbOccupancy(void) {
|
||||
// Remove an old Zigbee device from the list of known devices, use ZigbeeStatus to know all registered devices
|
||||
//
|
||||
void CmndZbForget(void) {
|
||||
if (zigbee.init_phase) { ResponseCmndChar_P(PSTR(D_ZIGBEE_NOT_STARTED)); return; }
|
||||
Z_Device & device = zigbee_devices.parseDeviceFromName(XdrvMailbox.data, nullptr, nullptr, XdrvMailbox.payload); // in case of short_addr, it must be already registered
|
||||
if (!device.valid()) { ResponseCmndChar_P(PSTR(D_ZIGBEE_UNKNOWN_DEVICE)); return; }
|
||||
|
||||
@ -1342,7 +1333,6 @@ void CmndZbInfo_inner(const Z_Device & device) {
|
||||
device.jsonPublishAttrList(PSTR(D_JSON_ZIGBEE_INFO), attr_list); // publish as ZbReceived
|
||||
}
|
||||
void CmndZbInfo(void) {
|
||||
if (zigbee.init_phase) { ResponseCmndChar_P(PSTR(D_ZIGBEE_NOT_STARTED)); return; }
|
||||
TrimSpace(XdrvMailbox.data);
|
||||
|
||||
if (strlen(XdrvMailbox.data) == 0) {
|
||||
@ -1369,7 +1359,6 @@ void CmndZbInfo(void) {
|
||||
// Save Zigbee information to flash
|
||||
//
|
||||
void CmndZbSave(void) {
|
||||
if (zigbee.init_phase) { ResponseCmndChar_P(PSTR(D_ZIGBEE_NOT_STARTED)); return; }
|
||||
switch (XdrvMailbox.payload) {
|
||||
case 2: // save only data
|
||||
hibernateAllData();
|
||||
@ -1578,7 +1567,6 @@ void CmndZbEmulation(void) {
|
||||
// ZbRestore [{"Device":"0x5ADF","Name":"Petite_Lampe","IEEEAddr":"0x90FD9FFFFE03B051","ModelId":"TRADFRI bulb E27 WS opal 980lm","Manufacturer":"IKEA of Sweden","Endpoints":["0x01","0xF2"]}]
|
||||
// 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; }
|
||||
TrimSpace(XdrvMailbox.data);
|
||||
|
||||
if (strlen(XdrvMailbox.data) == 0) {
|
||||
@ -1795,34 +1783,31 @@ void ZigbeePermitJoinUpdate(void) {
|
||||
// 1.b. `ZbStatus Room` - Show single device shortaddr and name `{"ZbStatus1":[{"Device":"0x868E","Name":"Room"}]}`
|
||||
// 2. `ZbStatus2 Room` - Show detailed information of device `{"ZbStatus2":[{"Device":"0x868E","Name":"Room","IEEEAddr":"0x90FD9FFFFE03B051","ModelId":"TRADFRI bulb E27 WS opal 980lm","Manufacturer":"IKEA of Sweden","Endpoints":[1,242],"Config":["L01.2","O01"]}]}`
|
||||
void CmndZbStatus(void) {
|
||||
if (ZigbeeSerial) {
|
||||
if (zigbee.init_phase) { ResponseCmndChar_P(PSTR(D_ZIGBEE_NOT_STARTED)); return; }
|
||||
String dump;
|
||||
TrimSpace(XdrvMailbox.data);
|
||||
String dump;
|
||||
|
||||
if (0 == XdrvMailbox.index) { // Case 0
|
||||
dump = zigbee_devices.dumpCoordinator();
|
||||
if (0 == XdrvMailbox.index) { // Case 0
|
||||
dump = zigbee_devices.dumpCoordinator();
|
||||
} else {
|
||||
Z_Device & device = zigbee_devices.parseDeviceFromName(XdrvMailbox.data, nullptr, nullptr, XdrvMailbox.payload);
|
||||
if (XdrvMailbox.data_len > 0) {
|
||||
if (!device.valid()) { ResponseCmndChar_P(PSTR(D_ZIGBEE_UNKNOWN_DEVICE)); return; }
|
||||
// case 1.b and 2.
|
||||
dump = zigbee_devices.dumpDevice(XdrvMailbox.index, device);
|
||||
} else {
|
||||
Z_Device & device = zigbee_devices.parseDeviceFromName(XdrvMailbox.data, nullptr, nullptr, XdrvMailbox.payload);
|
||||
if (XdrvMailbox.data_len > 0) {
|
||||
if (!device.valid()) { ResponseCmndChar_P(PSTR(D_ZIGBEE_UNKNOWN_DEVICE)); return; }
|
||||
// case 1.b and 2.
|
||||
dump = zigbee_devices.dumpDevice(XdrvMailbox.index, device);
|
||||
} else {
|
||||
if (XdrvMailbox.index >= 2) { ResponseCmndChar_P(PSTR(D_ZIGBEE_UNKNOWN_DEVICE)); return; }
|
||||
// case 1.a
|
||||
dump = zigbee_devices.dumpDevice(XdrvMailbox.index, device_unk);
|
||||
}
|
||||
if (XdrvMailbox.index >= 2) { ResponseCmndChar_P(PSTR(D_ZIGBEE_UNKNOWN_DEVICE)); return; }
|
||||
// case 1.a
|
||||
dump = zigbee_devices.dumpDevice(XdrvMailbox.index, device_unk);
|
||||
}
|
||||
|
||||
Response_P(PSTR("{\"%s%d\":%s}"), XdrvMailbox.command, XdrvMailbox.index, dump.c_str());
|
||||
}
|
||||
|
||||
Response_P(PSTR("{\"%s%d\":%s}"), XdrvMailbox.command, XdrvMailbox.index, dump.c_str());
|
||||
}
|
||||
|
||||
//
|
||||
// Command `ZbData`
|
||||
//
|
||||
void CmndZbData(void) {
|
||||
if (zigbee.init_phase) { ResponseCmndChar_P(PSTR(D_ZIGBEE_NOT_STARTED)); return; }
|
||||
TrimSpace(XdrvMailbox.data);
|
||||
|
||||
if (strlen(XdrvMailbox.data) == 0) {
|
||||
@ -1867,7 +1852,6 @@ void CmndZbConfig(void) {
|
||||
uint64_t zb_precfgkey_h = Settings->zb_precfgkey_h;
|
||||
int8_t zb_txradio_dbm = Settings->zb_txradio_dbm;
|
||||
|
||||
// if (zigbee.init_phase) { ResponseCmndChar_P(PSTR(D_ZIGBEE_NOT_STARTED)); return; }
|
||||
TrimSpace(XdrvMailbox.data);
|
||||
if (strlen(XdrvMailbox.data) > 0) {
|
||||
JsonParser parser(XdrvMailbox.data);
|
||||
@ -2224,10 +2208,10 @@ void ZigbeeShow(bool json)
|
||||
if (json) {
|
||||
return;
|
||||
#ifdef USE_WEBSERVER
|
||||
} else {
|
||||
} else {
|
||||
UnishoxStrings msg(ZB_WEB);
|
||||
uint32_t zigbee_num = zigbee_devices.devicesSize();
|
||||
if (zigbee_num > 0) {
|
||||
if ((zigbee_num > 0) && (!zigbee.init_phase)) { // don't displays devices on UI if still in initialization phase
|
||||
if (zigbee_num > 255) { zigbee_num = 255; }
|
||||
|
||||
WSContentSend_P(msg[ZB_WEB_CSS], WebColor(COL_TEXT));
|
||||
@ -2426,7 +2410,7 @@ void ZigbeeShow(bool json)
|
||||
zigbee.major_rel, zigbee.minor_rel,
|
||||
zigbee.maint_rel, zigbee.revision);
|
||||
WSContentSend_P(HTTP_BTN_ZB_BUTTONS);
|
||||
} else if (zigbee.state_machine) { // show buttons only if the state machine is still running. If not running anymore, it means aborted
|
||||
} else {
|
||||
uint32_t grey = WebColor(COL_FORM);
|
||||
WSContentSend_P(HTTP_BTN_ZB_BUTTONS_DISABLED, grey, grey);
|
||||
}
|
||||
@ -2485,6 +2469,9 @@ bool Xdrv23(uint32_t function) {
|
||||
if (TasmotaGlobal.gpio_optiona.enable_ccloader) { return false; }
|
||||
|
||||
bool result = false;
|
||||
if (!zigbee.active && (FUNC_PRE_INIT == function)) {
|
||||
ZigbeeInit();
|
||||
}
|
||||
|
||||
if (zigbee.active) {
|
||||
switch (function) {
|
||||
@ -2521,9 +2508,6 @@ bool Xdrv23(uint32_t function) {
|
||||
WebServer_on(PSTR("/zbr"), ZigbeeMapRefresh, HTTP_GET); // add web handler for Zigbee map refresh
|
||||
break;
|
||||
#endif // USE_WEBSERVER
|
||||
case FUNC_PRE_INIT:
|
||||
ZigbeeInit();
|
||||
break;
|
||||
case FUNC_COMMAND:
|
||||
result = DecodeCommand(kZbCommands, ZigbeeCommand, kZbSynonyms);
|
||||
break;
|
||||
|
@ -83,7 +83,7 @@ extern "C" {
|
||||
int zc_started(struct bvm *vm) {
|
||||
// return `nil` if `zigbee.active` is false (i.e. no GPIO configured)
|
||||
// or aborted, `zigbee.init_phase` is `true` but `zigbee.state_machine` is `false`
|
||||
if (!zigbee.active || (!zigbee.state_machine && zigbee.init_phase)) {
|
||||
if (!zigbee.active) {
|
||||
be_return_nil(vm);
|
||||
}
|
||||
be_pushbool(vm, !zigbee.init_phase);
|
||||
@ -117,7 +117,7 @@ extern "C" {
|
||||
// implement item() and find()
|
||||
int zc_item_or_find(struct bvm *vm, bbool raise_if_unknown) {
|
||||
int32_t top = be_top(vm); // Get the number of arguments
|
||||
if (zigbee.init_phase) {
|
||||
if (!zigbee.active) {
|
||||
be_raise(vm, "internal_error", "zigbee not started");
|
||||
}
|
||||
if (top >= 2 && (be_isint(vm, 2) || be_isstring(vm, 2))) {
|
||||
@ -189,7 +189,7 @@ extern "C" {
|
||||
|
||||
int zc_iter(bvm *vm);
|
||||
int zc_iter(bvm *vm) {
|
||||
if (zigbee.init_phase) {
|
||||
if (!zigbee.active) {
|
||||
be_raise(vm, "internal_error", "zigbee not started");
|
||||
}
|
||||
be_pushntvclosure(vm, zc_iter_closure, 1);
|
||||
|
Loading…
x
Reference in New Issue
Block a user