Fix exception if number of devices increases after allocating memory (#23724)

WIP
This commit is contained in:
Theo Arends 2025-07-28 12:39:37 +02:00
parent b22f7c8f10
commit 127fc2432c

View File

@ -92,6 +92,7 @@ typedef struct Domoticz_t {
uint32_t fan_debounce; // iFan02 state debounce timer uint32_t fan_debounce; // iFan02 state debounce timer
#endif // USE_SONOFF_IFAN #endif // USE_SONOFF_IFAN
int update_timer; int update_timer;
uint8_t devices;
uint8_t keys; uint8_t keys;
uint8_t switches; uint8_t switches;
bool subscribe; bool subscribe;
@ -122,7 +123,7 @@ bool DomoticzLoadData(void) {
Domoticz->Settings.update_timer = root.getUInt(PSTR("Update"), Domoticz->Settings.update_timer); Domoticz->Settings.update_timer = root.getUInt(PSTR("Update"), Domoticz->Settings.update_timer);
JsonParserArray arr = root[PSTR("Relay")]; JsonParserArray arr = root[PSTR("Relay")];
if (arr) { if (arr) {
for (uint32_t i = 0; i < TasmotaGlobal.devices_present; i++) { for (uint32_t i = 0; i < Domoticz->devices; i++) {
if (arr[i]) { Domoticz->Settings.relay_idx[i] = arr[i].getUInt(); } if (arr[i]) { Domoticz->Settings.relay_idx[i] = arr[i].getUInt(); }
} }
} }
@ -153,9 +154,9 @@ bool DomoticzSaveData(void) {
"\"Update\":%u"), "\"Update\":%u"),
Domoticz->Settings.crc32, Domoticz->Settings.crc32,
Domoticz->Settings.update_timer); Domoticz->Settings.update_timer);
if (TasmotaGlobal.devices_present) { if (Domoticz->devices) {
ResponseAppend_P(PSTR(",\"Relay\":")); ResponseAppend_P(PSTR(",\"Relay\":"));
for (uint32_t i = 0; i < TasmotaGlobal.devices_present; i++) { for (uint32_t i = 0; i < Domoticz->devices; i++) {
ResponseAppend_P(PSTR("%c%d"), (0==i)?'[':',', Domoticz->Settings.relay_idx[i]); ResponseAppend_P(PSTR("%c%d"), (0==i)?'[':',', Domoticz->Settings.relay_idx[i]);
} }
ResponseAppend_P(PSTR("]")); ResponseAppend_P(PSTR("]"));
@ -199,7 +200,7 @@ void DomoticzSettingsLoad(bool erase) {
// memset(&Domoticz->Settings, 0x00, sizeof(DzSettings_t)); // Won't work as we need to keep our pointers // memset(&Domoticz->Settings, 0x00, sizeof(DzSettings_t)); // Won't work as we need to keep our pointers
Domoticz->Settings.update_timer = 0; Domoticz->Settings.update_timer = 0;
for (uint32_t i = 0; i < TasmotaGlobal.devices_present; i++) { for (uint32_t i = 0; i < Domoticz->devices; i++) {
Domoticz->Settings.relay_idx[i] = 0; Domoticz->Settings.relay_idx[i] = 0;
if (i < Domoticz->keys) { if (i < Domoticz->keys) {
Domoticz->Settings.key_idx[i] = 0; Domoticz->Settings.key_idx[i] = 0;
@ -216,7 +217,7 @@ void DomoticzSettingsLoad(bool erase) {
// Init any other parameter in struct DzSettings // Init any other parameter in struct DzSettings
Domoticz->Settings.update_timer = Settings->domoticz_update_timer; Domoticz->Settings.update_timer = Settings->domoticz_update_timer;
for (uint32_t i = 0; i < MAX_DOMOTICZ_IDX; i++) { for (uint32_t i = 0; i < MAX_DOMOTICZ_IDX; i++) {
if (i < TasmotaGlobal.devices_present) { if (i < Domoticz->devices) {
Domoticz->Settings.relay_idx[i] = Settings->domoticz_relay_idx[i]; Domoticz->Settings.relay_idx[i] = Settings->domoticz_relay_idx[i];
} }
if (i < Domoticz->keys) { if (i < Domoticz->keys) {
@ -250,8 +251,8 @@ void DomoticzSettingsLoad(bool erase) {
void DomoticzSettingsSave(void) { void DomoticzSettingsSave(void) {
// Called from FUNC_SAVE_SETTINGS every SaveData second and at restart // Called from FUNC_SAVE_SETTINGS every SaveData second and at restart
uint32_t crc32 = GetCfgCrc32((uint8_t*)&Domoticz->Settings +4, sizeof(DzSettings_t) -4); // Skip crc32 uint32_t crc32 = GetCfgCrc32((uint8_t*)&Domoticz->Settings +4, sizeof(DzSettings_t) -4); // Skip crc32
if (TasmotaGlobal.devices_present) { if (Domoticz->devices) {
crc32 += GetCfgCrc32((uint8_t*)Domoticz->Settings.relay_idx, TasmotaGlobal.devices_present * sizeof(uintdz_t)); crc32 += GetCfgCrc32((uint8_t*)Domoticz->Settings.relay_idx, Domoticz->devices * sizeof(uintdz_t));
} }
if (Domoticz->keys) { if (Domoticz->keys) {
crc32 += GetCfgCrc32((uint8_t*)Domoticz->Settings.key_idx, Domoticz->keys * sizeof(uintdz_t)); crc32 += GetCfgCrc32((uint8_t*)Domoticz->Settings.key_idx, Domoticz->keys * sizeof(uintdz_t));
@ -301,12 +302,12 @@ int DomoticzRssiQuality(void) {
} }
uint32_t DomoticzRelayIdx(uint32_t relay) { uint32_t DomoticzRelayIdx(uint32_t relay) {
if (relay >= TasmotaGlobal.devices_present) { return 0; } if (relay >= Domoticz->devices) { return 0; }
return Domoticz->Settings.relay_idx[relay]; return Domoticz->Settings.relay_idx[relay];
} }
void DomoticzSetRelayIdx(uint32_t relay, uint32_t idx) { void DomoticzSetRelayIdx(uint32_t relay, uint32_t idx) {
if (relay >= TasmotaGlobal.devices_present) { return; } if (relay >= Domoticz->devices) { return; }
Domoticz->Settings.relay_idx[relay] = idx; Domoticz->Settings.relay_idx[relay] = idx;
} }
@ -342,7 +343,7 @@ void DomoticzUpdateFanState(void) {
void MqttPublishDomoticzPowerState(uint8_t device) { void MqttPublishDomoticzPowerState(uint8_t device) {
if (Settings->flag.mqtt_enabled) { // SetOption3 - Enable MQTT if (Settings->flag.mqtt_enabled) { // SetOption3 - Enable MQTT
if (device < 1) { device = 1; } if (device < 1) { device = 1; }
if (device > TasmotaGlobal.devices_present) { return; } if (device > Domoticz->devices) { return; }
if (DomoticzRelayIdx(device -1)) { if (DomoticzRelayIdx(device -1)) {
#ifdef USE_SHUTTER #ifdef USE_SHUTTER
if (Domoticz->is_shutter) { if (Domoticz->is_shutter) {
@ -388,7 +389,7 @@ void DomoticzMqttUpdate(void) {
Domoticz->update_timer--; Domoticz->update_timer--;
if (Domoticz->update_timer <= 0) { if (Domoticz->update_timer <= 0) {
Domoticz->update_timer = Domoticz->Settings.update_timer; Domoticz->update_timer = Domoticz->Settings.update_timer;
for (uint32_t i = 1; i <= TasmotaGlobal.devices_present; i++) { for (uint32_t i = 1; i <= Domoticz->devices; i++) {
#ifdef USE_SHUTTER #ifdef USE_SHUTTER
if (Domoticz->is_shutter) { if (Domoticz->is_shutter) {
// no power state updates for shutters // no power state updates for shutters
@ -412,7 +413,7 @@ void DomoticzMqttUpdate(void) {
void DomoticzMqttSubscribe(void) { void DomoticzMqttSubscribe(void) {
bool any_relay = false; bool any_relay = false;
for (uint32_t i = 0; i < TasmotaGlobal.devices_present; i++) { for (uint32_t i = 0; i < Domoticz->devices; i++) {
if (DomoticzRelayIdx(i)) { if (DomoticzRelayIdx(i)) {
any_relay = true; any_relay = true;
break; break;
@ -433,7 +434,7 @@ void DomoticzMqttSubscribe(void) {
int DomoticzIdx2Relay(uint32_t idx) { int DomoticzIdx2Relay(uint32_t idx) {
if (idx > 0) { if (idx > 0) {
for (uint32_t i = 0; i < TasmotaGlobal.devices_present; i++) { for (uint32_t i = 0; i < Domoticz->devices; i++) {
if (idx == DomoticzRelayIdx(i)) { if (idx == DomoticzRelayIdx(i)) {
return i; return i;
} }
@ -571,7 +572,7 @@ bool DomoticzMqttData(void) {
return true; // Stop loop return true; // Stop loop
} }
char stemp1[10]; char stemp1[10];
snprintf_P(XdrvMailbox.topic, XdrvMailbox.index, PSTR("/" D_CMND_POWER "%s"), (TasmotaGlobal.devices_present > 1) ? itoa(relay_index +1, stemp1, 10) : ""); snprintf_P(XdrvMailbox.topic, XdrvMailbox.index, PSTR("/" D_CMND_POWER "%s"), (Domoticz->devices > 1) ? itoa(relay_index +1, stemp1, 10) : "");
snprintf_P(XdrvMailbox.data, XdrvMailbox.data_len, PSTR("%d"), nvalue); snprintf_P(XdrvMailbox.data, XdrvMailbox.data_len, PSTR("%d"), nvalue);
} else { } else {
return true; // No command received return true; // No command received
@ -745,10 +746,11 @@ void DomoticzInit(void) {
Domoticz = (Domoticz_t*)calloc(1, sizeof(Domoticz_t)); // Need calloc to reset registers to 0/false Domoticz = (Domoticz_t*)calloc(1, sizeof(Domoticz_t)); // Need calloc to reset registers to 0/false
if (nullptr == Domoticz) { return; } if (nullptr == Domoticz) { return; }
if (TasmotaGlobal.devices_present) { Domoticz->devices = TasmotaGlobal.devices_present;
Domoticz->Settings.relay_idx = (uintdz_t*)calloc(TasmotaGlobal.devices_present, sizeof(uintdz_t)); if (Domoticz->devices) {
Domoticz->Settings.relay_idx = (uintdz_t*)calloc(Domoticz->devices, sizeof(uintdz_t));
if (nullptr == Domoticz->Settings.relay_idx) { return; } if (nullptr == Domoticz->Settings.relay_idx) { return; }
for (uint32_t i = 0; i < TasmotaGlobal.devices_present; i++) { for (uint32_t i = 0; i < Domoticz->devices; i++) {
if (ButtonUsed(i)) { Domoticz->keys++; } if (ButtonUsed(i)) { Domoticz->keys++; }
if (SwitchUsed(i)) { Domoticz->switches++; } if (SwitchUsed(i)) { Domoticz->switches++; }
} }
@ -763,7 +765,7 @@ void DomoticzInit(void) {
} }
AddLog(LOG_LEVEL_DEBUG, PSTR(D_LOG_DOMOTICZ "Support %d Device(s), %d Button(s), %d Switch(es) and %d Sensors"), AddLog(LOG_LEVEL_DEBUG, PSTR(D_LOG_DOMOTICZ "Support %d Device(s), %d Button(s), %d Switch(es) and %d Sensors"),
TasmotaGlobal.devices_present, Domoticz->keys, Domoticz->switches, DZ_MAX_SENSORS); Domoticz->devices, Domoticz->keys, Domoticz->switches, DZ_MAX_SENSORS);
DomoticzSettingsLoad(0); DomoticzSettingsLoad(0);
Domoticz->update_flag = true; Domoticz->update_flag = true;
@ -778,10 +780,10 @@ void CmndDomoticzIdx(void) {
// DzIdx0 0 - Reset all disabling subscription too // DzIdx0 0 - Reset all disabling subscription too
// DzIdx1 403 - Relate relay1 (=Power1) to Domoticz Idx 403 persistent // DzIdx1 403 - Relate relay1 (=Power1) to Domoticz Idx 403 persistent
// DzIdx5 403 - Relate relay5 (=Power5) to Domoticz Idx 403 non-persistent (need a rule at boot to become persistent) // DzIdx5 403 - Relate relay5 (=Power5) to Domoticz Idx 403 non-persistent (need a rule at boot to become persistent)
if ((XdrvMailbox.index >= 0) && (XdrvMailbox.index <= TasmotaGlobal.devices_present)) { if ((XdrvMailbox.index >= 0) && (XdrvMailbox.index <= Domoticz->devices)) {
if (XdrvMailbox.payload >= 0) { if (XdrvMailbox.payload >= 0) {
if (0 == XdrvMailbox.index) { if (0 == XdrvMailbox.index) {
for (uint32_t i = 0; i < TasmotaGlobal.devices_present; i++) { for (uint32_t i = 0; i < Domoticz->devices; i++) {
DomoticzSetRelayIdx(i, 0); DomoticzSetRelayIdx(i, 0);
} }
} else { } else {
@ -900,7 +902,7 @@ void HandleDomoticzConfiguration(void) {
WSContentStart_P(PSTR(D_CONFIGURE_DOMOTICZ)); WSContentStart_P(PSTR(D_CONFIGURE_DOMOTICZ));
WSContentSendStyle(); WSContentSendStyle();
WSContentSend_P(HTTP_FORM_DOMOTICZ, (Domoticz->switches)? D_DOMOTICZ_SWITCH :"", (Domoticz->keys)? D_DOMOTICZ_KEY :""); WSContentSend_P(HTTP_FORM_DOMOTICZ, (Domoticz->switches)? D_DOMOTICZ_SWITCH :"", (Domoticz->keys)? D_DOMOTICZ_KEY :"");
for (uint32_t i = 0; i < TasmotaGlobal.devices_present; i++) { for (uint32_t i = 0; i < Domoticz->devices; i++) {
WSContentSend_P(HTTP_FORM_DOMOTICZ_INDEX, i +1); WSContentSend_P(HTTP_FORM_DOMOTICZ_INDEX, i +1);
if (i < Domoticz->switches) { if (i < Domoticz->switches) {
WSContentSend_P(HTTP_FORM_DOMOTICZ_INPUT, 's', i, Domoticz->Settings.switch_idx[i]); WSContentSend_P(HTTP_FORM_DOMOTICZ_INPUT, 's', i, Domoticz->Settings.switch_idx[i]);
@ -942,7 +944,7 @@ void DomoticzSaveSettings(void) {
cmnd += AddWebCommand(PSTR(D_PRFX_DOMOTICZ D_CMND_UPDATETIMER), PSTR("ut"), STR(DOMOTICZ_UPDATE_TIMER)); cmnd += AddWebCommand(PSTR(D_PRFX_DOMOTICZ D_CMND_UPDATETIMER), PSTR("ut"), STR(DOMOTICZ_UPDATE_TIMER));
char arg_idx[5]; char arg_idx[5];
char cmnd2[24]; char cmnd2[24];
for (uint32_t i = 0; i < TasmotaGlobal.devices_present; i++) { for (uint32_t i = 0; i < Domoticz->devices; i++) {
snprintf_P(cmnd2, sizeof(cmnd2), PSTR(D_PRFX_DOMOTICZ D_CMND_IDX "%d"), i +1); snprintf_P(cmnd2, sizeof(cmnd2), PSTR(D_PRFX_DOMOTICZ D_CMND_IDX "%d"), i +1);
snprintf_P(arg_idx, sizeof(arg_idx), PSTR("r%d"), i); snprintf_P(arg_idx, sizeof(arg_idx), PSTR("r%d"), i);
cmnd += DomoticzAddWebCommand(cmnd2, arg_idx, Domoticz->Settings.relay_idx[i]); cmnd += DomoticzAddWebCommand(cmnd2, arg_idx, Domoticz->Settings.relay_idx[i]);