From 048bd474e4ec8fd6667f163b559f56d5ebe5a8b2 Mon Sep 17 00:00:00 2001 From: Gunnar Skjold Date: Thu, 26 Mar 2026 15:14:59 +0100 Subject: [PATCH] Heap memory improvements --- .../include/AmsConfiguration.h | 2 +- lib/AmsData/include/AmsData.h | 4 +- lib/AmsData/src/AmsData.cpp | 14 ++--- lib/AmsMqttHandler/include/AmsMqttHandler.h | 15 +++-- lib/AmsMqttHandler/src/AmsMqttHandler.cpp | 11 ++-- .../src/HomeAssistantMqttHandler.cpp | 39 +++++++----- lib/JsonMqttHandler/src/JsonMqttHandler.cpp | 2 +- lib/MeterCommunicators/src/IEC6205621.cpp | 61 +++++++++--------- lib/MeterCommunicators/src/IEC6205675.cpp | 63 ++++++++++--------- lib/MeterCommunicators/src/LNG.cpp | 4 +- lib/MeterCommunicators/src/LNG2.cpp | 4 +- lib/RawMqttHandler/src/RawMqttHandler.cpp | 2 +- lib/RealtimePlot/include/RealtimePlot.h | 4 +- lib/RealtimePlot/src/RealtimePlot.cpp | 3 - lib/SvelteUi/include/AmsWebServer.h | 8 +-- lib/SvelteUi/src/AmsWebServer.cpp | 12 ++-- 16 files changed, 135 insertions(+), 113 deletions(-) diff --git a/lib/AmsConfiguration/include/AmsConfiguration.h b/lib/AmsConfiguration/include/AmsConfiguration.h index 3b8e4df7..c41e6f22 100644 --- a/lib/AmsConfiguration/include/AmsConfiguration.h +++ b/lib/AmsConfiguration/include/AmsConfiguration.h @@ -10,7 +10,7 @@ #include "Arduino.h" #if defined(ESP8266) -#define BUF_SIZE_COMMON 1024 +#define BUF_SIZE_COMMON 2048 #else #define BUF_SIZE_COMMON 4096 #endif diff --git a/lib/AmsData/include/AmsData.h b/lib/AmsData/include/AmsData.h index b6d73bb7..35be98c6 100644 --- a/lib/AmsData/include/AmsData.h +++ b/lib/AmsData/include/AmsData.h @@ -95,7 +95,9 @@ protected: uint64_t lastList2 = 0; uint8_t listType = 0, meterType = AmsTypeUnknown; time_t packageTimestamp = 0; - String listId = "", meterId = "", meterModel = ""; + char listId[32] = {}; + char meterId[32] = {}; + char meterModel[65] = {}; time_t meterTimestamp = 0; uint32_t activeImportPower = 0, reactiveImportPower = 0, activeExportPower = 0, reactiveExportPower = 0; float l1voltage = 0, l2voltage = 0, l3voltage = 0, l1current = 0, l2current = 0, l3current = 0; diff --git a/lib/AmsData/src/AmsData.cpp b/lib/AmsData/src/AmsData.cpp index 139d3a51..5f63dc7c 100644 --- a/lib/AmsData/src/AmsData.cpp +++ b/lib/AmsData/src/AmsData.cpp @@ -88,10 +88,10 @@ void AmsData::apply(AmsData& other) { } this->counterEstimated = false; case 2: - this->listId = other.getListId(); - this->meterId = other.getMeterId(); + strncpy(this->listId, other.listId, sizeof(this->listId) - 1); + strncpy(this->meterId, other.meterId, sizeof(this->meterId) - 1); this->meterType = other.getMeterType(); - this->meterModel = other.getMeterModel(); + strncpy(this->meterModel, other.meterModel, sizeof(this->meterModel) - 1); this->reactiveImportPower = other.getReactiveImportPower(); this->reactiveExportPower = other.getReactiveExportPower(); this->l1current = other.getL1Current(); @@ -119,7 +119,7 @@ void AmsData::apply(OBIS_code_t obis, double value) { if(obis.gr == 1) { if(obis.sensor == 96) { if(obis.tariff == 0) { - meterId = String((long) value, 10); + snprintf(meterId, sizeof(meterId), "%ld", (long) value); return; } else if(obis.tariff == 1) { return; @@ -278,11 +278,11 @@ uint8_t AmsData::getListType() { } String AmsData::getListId() { - return this->listId; + return String(this->listId); } String AmsData::getMeterId() { - return this->meterId; + return String(this->meterId); } uint8_t AmsData::getMeterType() { @@ -290,7 +290,7 @@ uint8_t AmsData::getMeterType() { } String AmsData::getMeterModel() { - return this->meterModel; + return String(this->meterModel); } time_t AmsData::getMeterTimestamp() { diff --git a/lib/AmsMqttHandler/include/AmsMqttHandler.h b/lib/AmsMqttHandler/include/AmsMqttHandler.h index 0520b98b..19087831 100644 --- a/lib/AmsMqttHandler/include/AmsMqttHandler.h +++ b/lib/AmsMqttHandler/include/AmsMqttHandler.h @@ -98,8 +98,8 @@ protected: uint64_t lastStateUpdate = 0; uint64_t lastSuccessfulLoop = 0; - String pubTopic; - String subTopic; + char pubTopic[64]; + char subTopic[64]; AmsFirmwareUpdater* updater = NULL; bool rebootSuggested = false; @@ -115,9 +115,14 @@ private: this->updater = updater; mqtt.dropOverflow(true); - pubTopic = String(mqttConfig.publishTopic); - subTopic = String(mqttConfig.subscribeTopic); - if(subTopic.isEmpty()) subTopic = pubTopic+"/command"; + strncpy(pubTopic, mqttConfig.publishTopic, sizeof(pubTopic) - 1); + pubTopic[sizeof(pubTopic) - 1] = '\0'; + if(strlen(mqttConfig.subscribeTopic) > 0) { + strncpy(subTopic, mqttConfig.subscribeTopic, sizeof(subTopic) - 1); + subTopic[sizeof(subTopic) - 1] = '\0'; + } else { + snprintf(subTopic, sizeof(subTopic), "%s/command", mqttConfig.publishTopic); + } } }; diff --git a/lib/AmsMqttHandler/src/AmsMqttHandler.cpp b/lib/AmsMqttHandler/src/AmsMqttHandler.cpp index 26e935a2..f04f74db 100644 --- a/lib/AmsMqttHandler/src/AmsMqttHandler.cpp +++ b/lib/AmsMqttHandler/src/AmsMqttHandler.cpp @@ -118,8 +118,9 @@ bool AmsMqttHandler::connect() { mqtt.setTimeout(mqttConfig.timeout); mqtt.setKeepAlive(mqttConfig.keepalive); mqtt.begin(mqttConfig.host, mqttConfig.port, *actualClient); - String statusTopic = String(mqttConfig.publishTopic) + "/status"; - mqtt.setWill(statusTopic.c_str(), "offline", true, 0); + char statusTopic[72]; + snprintf(statusTopic, sizeof(statusTopic), "%s/status", mqttConfig.publishTopic); + mqtt.setWill(statusTopic, "offline", true, 0); #if defined(ESP8266) if(mqttSecureClient) { @@ -160,17 +161,17 @@ bool AmsMqttHandler::connect() { bool AmsMqttHandler::defaultSubscribe() { bool ret = true; - if(!subTopic.isEmpty()) { + if(subTopic[0] != '\0') { if(mqtt.subscribe(subTopic)) { #if defined(AMS_REMOTE_DEBUG) if (debugger->isActive(RemoteDebug::ERROR)) #endif - debugger->printf_P(PSTR(" Subscribed to [%s]\n"), subTopic.c_str()); + debugger->printf_P(PSTR(" Subscribed to [%s]\n"), subTopic); } else { #if defined(AMS_REMOTE_DEBUG) if (debugger->isActive(RemoteDebug::ERROR)) #endif - debugger->printf_P(PSTR(" Unable to subscribe to [%s]\n"), subTopic.c_str()); + debugger->printf_P(PSTR(" Unable to subscribe to [%s]\n"), subTopic); ret = false; } } diff --git a/lib/HomeAssistantMqttHandler/src/HomeAssistantMqttHandler.cpp b/lib/HomeAssistantMqttHandler/src/HomeAssistantMqttHandler.cpp index ac174c6b..081100a2 100644 --- a/lib/HomeAssistantMqttHandler/src/HomeAssistantMqttHandler.cpp +++ b/lib/HomeAssistantMqttHandler/src/HomeAssistantMqttHandler.cpp @@ -88,7 +88,7 @@ bool HomeAssistantMqttHandler::postConnect() { } bool HomeAssistantMqttHandler::publish(AmsData* update, AmsData* previousState, EnergyAccounting* ea, PriceService* ps) { - if(pubTopic.isEmpty() || !connected()) + if(pubTopic[0] == 'pubTopic.isEmpty()' || !connected()) return false; if(time(nullptr) < FirmwareVersion::BuildEpoch) @@ -136,7 +136,8 @@ bool HomeAssistantMqttHandler::publishList1(AmsData* data, EnergyAccounting* ea) toJsonIsoTimestamp(data->getPackageTimestamp(), pt, sizeof(pt)); snprintf_P(json, BUF_SIZE_COMMON, HA1_JSON, data->getActiveImportPower(), pt); - return mqtt.publish(pubTopic + "/power", json); + { char _t[72]; snprintf(_t, sizeof(_t), "%s/power", pubTopic); + return mqtt.publish(_t, json); } } bool HomeAssistantMqttHandler::publishList2(AmsData* data, EnergyAccounting* ea) { @@ -162,7 +163,8 @@ bool HomeAssistantMqttHandler::publishList2(AmsData* data, EnergyAccounting* ea) data->getL3Voltage(), pt ); - return mqtt.publish(pubTopic + "/power", json); + { char _t[72]; snprintf(_t, sizeof(_t), "%s/power", pubTopic); + return mqtt.publish(_t, json); } } bool HomeAssistantMqttHandler::publishList3(AmsData* data, EnergyAccounting* ea) { @@ -184,7 +186,8 @@ bool HomeAssistantMqttHandler::publishList3(AmsData* data, EnergyAccounting* ea) mt, pt ); - return mqtt.publish(pubTopic + "/energy", json); + { char _t[72]; snprintf(_t, sizeof(_t), "%s/energy", pubTopic); + return mqtt.publish(_t, json); } } bool HomeAssistantMqttHandler::publishList4(AmsData* data, EnergyAccounting* ea) { @@ -226,7 +229,8 @@ bool HomeAssistantMqttHandler::publishList4(AmsData* data, EnergyAccounting* ea) data->getL3ActiveExportCounter(), pt ); - return mqtt.publish(pubTopic + "/power", json); + { char _t[72]; snprintf(_t, sizeof(_t), "%s/power", pubTopic); + return mqtt.publish(_t, json); } } String HomeAssistantMqttHandler::getMeterModel(AmsData* data) { @@ -288,7 +292,8 @@ bool HomeAssistantMqttHandler::publishRealtime(AmsData* data, EnergyAccounting* json[pos++] = '}'; json[pos] = '\0'; - return mqtt.publish(pubTopic + "/realtime", json); + { char _t[72]; snprintf(_t, sizeof(_t), "%s/realtime", pubTopic); + return mqtt.publish(_t, json); } } bool HomeAssistantMqttHandler::publishTemperatures(AmsConfiguration* config, HwTools* hw) { @@ -317,13 +322,14 @@ bool HomeAssistantMqttHandler::publishTemperatures(AmsConfiguration* config, HwT pos += snprintf_P(json+pos, BUF_SIZE_COMMON-pos, PSTR(",\"t\":%s"), pt); pos += snprintf_P(json+pos, BUF_SIZE_COMMON-pos, PSTR("}")); - bool ret = mqtt.publish(pubTopic + "/temperatures", json); + char _t[72]; snprintf(_t, sizeof(_t), "%s/temperatures", pubTopic); + bool ret = mqtt.publish(_t, json); loop(); return ret; } bool HomeAssistantMqttHandler::publishPrices(PriceService* ps) { - if(pubTopic.isEmpty() || !connected()) + if(pubTopic[0] == 'pubTopic.isEmpty()' || !connected()) return false; if(!ps->hasPrice()) return false; @@ -457,13 +463,14 @@ bool HomeAssistantMqttHandler::publishPrices(PriceService* ps) { json[pos++] = '}'; json[pos] = '\0'; - bool ret = mqtt.publish(pubTopic + "/prices", json, true, 0); + char _t[72]; snprintf(_t, sizeof(_t), "%s/prices", pubTopic); + bool ret = mqtt.publish(_t, json, true, 0); loop(); return ret; } bool HomeAssistantMqttHandler::publishSystem(HwTools* hw, PriceService* ps, EnergyAccounting* ea) { - if(pubTopic.isEmpty() || !connected()) + if(pubTopic[0] == 'pubTopic.isEmpty()' || !connected()) return false; publishSystemSensors(); @@ -483,7 +490,8 @@ bool HomeAssistantMqttHandler::publishSystem(HwTools* hw, PriceService* ps, Ener FirmwareVersion::VersionString, pt ); - bool ret = mqtt.publish(pubTopic + "/state", json); + char _t[72]; snprintf(_t, sizeof(_t), "%s/state", pubTopic); + bool ret = mqtt.publish(_t, json); loop(); return ret; } @@ -827,9 +835,9 @@ bool HomeAssistantMqttHandler::publishFirmware() { if(!fInit) { snprintf_P(json, BUF_SIZE_COMMON, PSTR("{\"name\":\"%sFirmware\",\"stat_t\":\"%s/firmware\",\"uniq_id\":\"%s_fwupgrade\",\"dev_cla\":\"firmware\",\"cmd_t\":\"%s\",\"pl_inst\":\"fwupgrade\"}"), sensorNamePrefix.c_str(), - pubTopic.c_str(), + pubTopic, deviceUid.c_str(), - subTopic.c_str() + subTopic ); fInit = mqtt.publish(updateTopic + "/" + deviceUid + "/config", json, true, 0); loop(); @@ -841,7 +849,8 @@ bool HomeAssistantMqttHandler::publishFirmware() { strlen(updater->getNextVersion()) == 0 ? FirmwareVersion::VersionString : updater->getNextVersion(), updater->getProgress() < 0 ? "null" : String(updater->getProgress(), 0) ); - bool ret = mqtt.publish(pubTopic + "/firmware", json); + char _t[72]; snprintf(_t, sizeof(_t), "%s/firmware", pubTopic); + bool ret = mqtt.publish(_t, json); loop(); return ret; } @@ -858,7 +867,7 @@ void HomeAssistantMqttHandler::onMessage(String &topic, String &payload) { priceImportInit = 0; priceExportInit = 0; } - } else if(topic.equals(subTopic)) { + } else if(topic == subTopic) { if(payload.equals("fwupgrade")) { if(strcmp(updater->getNextVersion(), FirmwareVersion::VersionString) != 0) { updater->setTargetVersion(updater->getNextVersion()); diff --git a/lib/JsonMqttHandler/src/JsonMqttHandler.cpp b/lib/JsonMqttHandler/src/JsonMqttHandler.cpp index 145be3f7..701c03f5 100644 --- a/lib/JsonMqttHandler/src/JsonMqttHandler.cpp +++ b/lib/JsonMqttHandler/src/JsonMqttHandler.cpp @@ -520,7 +520,7 @@ void JsonMqttHandler::onMessage(String &topic, String &payload) { #endif debugger->printf_P(PSTR("Received command [%s] to [%s]\n"), payload.c_str(), topic.c_str()); - if(topic.equals(subTopic)) { + if(topic == subTopic) { #if defined(AMS_REMOTE_DEBUG) if (debugger->isActive(RemoteDebug::DEBUG)) #endif diff --git a/lib/MeterCommunicators/src/IEC6205621.cpp b/lib/MeterCommunicators/src/IEC6205621.cpp index 8b6b0ad9..fda3a7a5 100644 --- a/lib/MeterCommunicators/src/IEC6205621.cpp +++ b/lib/MeterCommunicators/src/IEC6205621.cpp @@ -16,50 +16,53 @@ IEC6205621::IEC6205621(const char* p, Timezone* tz, MeterConfig* meterConfig) { String payload(p+1); lastUpdateMillis = millis64(); - listId = payload.substring(payload.startsWith("/") ? 1 : 0, payload.indexOf("\n")); + String listIdStr = payload.substring(payload.startsWith("/") ? 1 : 0, payload.indexOf("\n")); - if(listId.startsWith(F("ADN"))) { + if(listIdStr.startsWith(F("ADN"))) { meterType = AmsTypeAidon; - listId = listId.substring(0,4); - } else if(listId.startsWith(F("KFM"))) { + listIdStr = listIdStr.substring(0,4); + } else if(listIdStr.startsWith(F("KFM"))) { meterType = AmsTypeKaifa; - listId = listId.substring(0,4); - } else if(listId.startsWith(F("KMP"))) { + listIdStr = listIdStr.substring(0,4); + } else if(listIdStr.startsWith(F("KMP"))) { meterType = AmsTypeKamstrup; - listId = listId.substring(0,4); - } else if(listId.startsWith(F("KAM"))) { + listIdStr = listIdStr.substring(0,4); + } else if(listIdStr.startsWith(F("KAM"))) { meterType = AmsTypeKamstrup; - listId = listId.substring(0,4); - } else if(listId.startsWith(F("ISk"))) { + listIdStr = listIdStr.substring(0,4); + } else if(listIdStr.startsWith(F("ISk"))) { meterType = AmsTypeIskra; - listId = listId.substring(0,5); - } else if(listId.startsWith(F("XMX"))) { + listIdStr = listIdStr.substring(0,5); + } else if(listIdStr.startsWith(F("XMX"))) { meterType = AmsTypeLandisGyr; - listId = listId.substring(0,6); - } else if(listId.startsWith(F("Ene")) || listId.startsWith(F("EST"))) { + listIdStr = listIdStr.substring(0,6); + } else if(listIdStr.startsWith(F("Ene")) || listIdStr.startsWith(F("EST"))) { meterType = AmsTypeSagemcom; - listId = listId.substring(0,4); - } else if(listId.startsWith(F("LGF"))) { + listIdStr = listIdStr.substring(0,4); + } else if(listIdStr.startsWith(F("LGF"))) { meterType = AmsTypeLandisGyr; - listId = listId.substring(0,4); + listIdStr = listIdStr.substring(0,4); } else { meterType = AmsTypeUnknown; - listId = listId.substring(0,4); - } - - meterId = extract(payload, F("96.1.0")); - if(meterId.isEmpty()) { - meterId = extract(payload, F("0.0.5")); + listIdStr = listIdStr.substring(0,4); } + strncpy(listId, listIdStr.c_str(), sizeof(listId) - 1); - meterModel = extract(payload, F("96.1.1")); - if(meterModel.isEmpty()) { - meterModel = extract(payload, F("96.1.7")); - if(meterModel.isEmpty()) { - meterModel = payload.substring(payload.indexOf(listId) + listId.length(), payload.indexOf(F("\n"))); - meterModel.trim(); + String meterIdStr = extract(payload, F("96.1.0")); + if(meterIdStr.isEmpty()) { + meterIdStr = extract(payload, F("0.0.5")); + } + strncpy(meterId, meterIdStr.c_str(), sizeof(meterId) - 1); + + String meterModelStr = extract(payload, F("96.1.1")); + if(meterModelStr.isEmpty()) { + meterModelStr = extract(payload, F("96.1.7")); + if(meterModelStr.isEmpty()) { + meterModelStr = payload.substring(payload.indexOf(listIdStr) + listIdStr.length(), payload.indexOf(F("\n"))); + meterModelStr.trim(); } } + strncpy(meterModel, meterModelStr.c_str(), sizeof(meterModel) - 1); tmElements_t tm { 0, 0, 0, 0, 0, 0, 0 }; String timestamp = extract(payload, F("1.0.0")); diff --git a/lib/MeterCommunicators/src/IEC6205675.cpp b/lib/MeterCommunicators/src/IEC6205675.cpp index 6e919f43..a4df2660 100644 --- a/lib/MeterCommunicators/src/IEC6205675.cpp +++ b/lib/MeterCommunicators/src/IEC6205675.cpp @@ -213,7 +213,7 @@ IEC6205675::IEC6205675(const char* d, Timezone* tz, uint8_t useMeterType, MeterC uint8_t str_len = 0; str_len = getString(AMS_OBIS_UNKNOWN_1, sizeof(AMS_OBIS_UNKNOWN_1), ((char *) (d)), str); if(str_len > 0) { - meterId = String(str); + strncpy(meterId, str, sizeof(meterId) - 1); } listType = 4; @@ -227,9 +227,8 @@ IEC6205675::IEC6205675(const char* d, Timezone* tz, uint8_t useMeterType, MeterC } else if(data->base.type == CosemTypeOctetString) { // Assuming first string is a list identifier memcpy(str, data->oct.data, data->oct.length); str[data->oct.length] = 0x00; - String listId = String(str); - if(listId.startsWith(F("KFM_001"))) { - this->listId = listId; + if(strncmp(str, "KFM_001", 7) == 0) { + strncpy(this->listId, str, sizeof(this->listId) - 1); meterType = AmsTypeKaifa; uint8_t idx = 0; @@ -241,12 +240,12 @@ IEC6205675::IEC6205675(const char* d, Timezone* tz, uint8_t useMeterType, MeterC data = getCosemDataAt(idx++, ((char *) (d))); memcpy(str, data->oct.data, data->oct.length); str[data->oct.length] = 0x00; - meterId = String(str); + strncpy(meterId, str, sizeof(meterId) - 1); data = getCosemDataAt(idx++, ((char *) (d))); memcpy(str, data->oct.data, data->oct.length); str[data->oct.length] = 0x00; - meterModel = String(str); + strncpy(meterModel, str, sizeof(meterModel) - 1); data = getCosemDataAt(idx++, ((char *) (d))); activeImportPower = ntohl(data->dlu.data); @@ -277,12 +276,12 @@ IEC6205675::IEC6205675(const char* d, Timezone* tz, uint8_t useMeterType, MeterC data = getCosemDataAt(idx++, ((char *) (d))); memcpy(str, data->oct.data, data->oct.length); str[data->oct.length] = 0x00; - meterId = String(str); + strncpy(meterId, str, sizeof(meterId) - 1); data = getCosemDataAt(idx++, ((char *) (d))); memcpy(str, data->oct.data, data->oct.length); str[data->oct.length] = 0x00; - meterModel = String(str); + strncpy(meterModel, str, sizeof(meterModel) - 1); data = getCosemDataAt(idx++, ((char *) (d))); activeImportPower = ntohl(data->dlu.data); @@ -301,7 +300,7 @@ IEC6205675::IEC6205675(const char* d, Timezone* tz, uint8_t useMeterType, MeterC l1voltage = ntohl(data->dlu.data) / 10.0; } - if(listType >= 2 && memcmp(meterModel.c_str(), "MA304T3", 7) == 0) { + if(listType >= 2 && memcmp(meterModel, "MA304T3", 7) == 0) { l2voltage = sqrt(pow(l1voltage - l3voltage * cos(60 * (PI/180)), 2) + pow(l3voltage * sin(60 * (PI/180)),2)); l2currentMissing = true; } @@ -330,8 +329,8 @@ IEC6205675::IEC6205675(const char* d, Timezone* tz, uint8_t useMeterType, MeterC } lastUpdateMillis = millis64(); - } else if(listId.startsWith("ISK")) { // Iskra special case - this->listId = listId; + } else if(strncmp(listId, "ISK", 3) == 0) { // Iskra special case + strncpy(this->listId, str, sizeof(this->listId) - 1); meterType = AmsTypeIskra; uint8_t idx = 0; @@ -347,7 +346,7 @@ IEC6205675::IEC6205675(const char* d, Timezone* tz, uint8_t useMeterType, MeterC data = getCosemDataAt(idx++, ((char *) (d))); memcpy(str, data->oct.data, data->oct.length); str[data->oct.length] = 0x00; - meterId = String(str); + strncpy(meterId, str, sizeof(meterId) - 1); // 1.7.0 data = getCosemDataAt(idx++, ((char *) (d))); @@ -427,7 +426,7 @@ IEC6205675::IEC6205675(const char* d, Timezone* tz, uint8_t useMeterType, MeterC data = getCosemDataAt(idx++, ((char *) (d))); memcpy(str, data->oct.data, data->oct.length); str[data->oct.length] = 0x00; - meterId = String(str); + strncpy(meterId, str, sizeof(meterId) - 1); // 96.3.10 Disconnect control // 96.14.0 Currently acrive energy tariff @@ -469,7 +468,7 @@ IEC6205675::IEC6205675(const char* d, Timezone* tz, uint8_t useMeterType, MeterC data = getCosemDataAt(idx++, ((char *) (d))); memcpy(str, data->oct.data, data->oct.length); str[data->oct.length] = 0x00; - meterId = String(str); + strncpy(meterId, str, sizeof(meterId) - 1); // 32.7.0 data = getCosemDataAt(idx++, ((char *) (d))); @@ -526,7 +525,7 @@ IEC6205675::IEC6205675(const char* d, Timezone* tz, uint8_t useMeterType, MeterC data = getCosemDataAt(idx++, ((char *) (d))); memcpy(str, data->oct.data, data->oct.length); str[data->oct.length] = 0x00; - meterId = String(str); + strncpy(meterId, str, sizeof(meterId) - 1); // 1.7.0 data = getCosemDataAt(idx++, ((char *) (d))); @@ -572,7 +571,7 @@ IEC6205675::IEC6205675(const char* d, Timezone* tz, uint8_t useMeterType, MeterC data = getCosemDataAt(idx++, ((char *) (d))); memcpy(str, data->oct.data, data->oct.length); str[data->oct.length] = 0x00; - meterId = String(str); + strncpy(meterId, str, sizeof(meterId) - 1); // 1.8.1 data = getCosemDataAt(idx++, ((char *) (d))); @@ -633,7 +632,7 @@ IEC6205675::IEC6205675(const char* d, Timezone* tz, uint8_t useMeterType, MeterC data = getCosemDataAt(idx++, ((char *) (d))); memcpy(str, data->oct.data, data->oct.length); str[data->oct.length] = 0x00; - meterId = String(str); + strncpy(meterId, str, sizeof(meterId) - 1); // 1.7.0 data = getCosemDataAt(idx++, ((char *) (d))); @@ -707,7 +706,7 @@ IEC6205675::IEC6205675(const char* d, Timezone* tz, uint8_t useMeterType, MeterC data = getCosemDataAt(idx++, ((char *) (d))); memcpy(str, data->oct.data, data->oct.length); str[data->oct.length] = 0x00; - meterId = String(str); + strncpy(meterId, str, sizeof(meterId) - 1); // 32.7.0 data = getCosemDataAt(idx++, ((char *) (d))); @@ -778,7 +777,7 @@ IEC6205675::IEC6205675(const char* d, Timezone* tz, uint8_t useMeterType, MeterC str_len = getString(AMS_OBIS_UNKNOWN_1, sizeof(AMS_OBIS_UNKNOWN_1), ((char *) (d)), str); if(str_len > 0) { meterType = AmsTypeIskra; - meterId = String(str); + strncpy(meterId, str, sizeof(meterId) - 1); lastUpdateMillis = millis64(); listType = 3; } @@ -810,7 +809,7 @@ IEC6205675::IEC6205675(const char* d, Timezone* tz, uint8_t useMeterType, MeterC uint8_t str_len = 0; str_len = getString(AMS_OBIS_VERSION, sizeof(AMS_OBIS_VERSION), ((char *) (d)), str); if(str_len > 0) { - listId = String(str); + strncpy(listId, str, sizeof(listId) - 1); } val = getNumber(AMS_OBIS_ACTIVE_EXPORT, sizeof(AMS_OBIS_ACTIVE_EXPORT), ((char *) (d))); @@ -885,21 +884,21 @@ IEC6205675::IEC6205675(const char* d, Timezone* tz, uint8_t useMeterType, MeterC str_len = getString(AMS_OBIS_METER_MODEL, sizeof(AMS_OBIS_METER_MODEL), ((char *) (d)), str); if(str_len > 0) { - meterModel = String(str); + strncpy(meterModel, str, sizeof(meterModel) - 1); } else { str_len = getString(AMS_OBIS_METER_MODEL_2, sizeof(AMS_OBIS_METER_MODEL_2), ((char *) (d)), str); if(str_len > 0) { - meterModel = String(str); + strncpy(meterModel, str, sizeof(meterModel) - 1); } } str_len = getString(AMS_OBIS_METER_ID, sizeof(AMS_OBIS_METER_ID), ((char *) (d)), str); if(str_len > 0) { - meterId = String(str); + strncpy(meterId, str, sizeof(meterId) - 1); } else { str_len = getString(AMS_OBIS_METER_ID_2, sizeof(AMS_OBIS_METER_ID_2), ((char *) (d)), str); if(str_len > 0) { - meterId = String(str); + strncpy(meterId, str, sizeof(meterId) - 1); } } @@ -1035,12 +1034,12 @@ IEC6205675::IEC6205675(const char* d, Timezone* tz, uint8_t useMeterType, MeterC case CosemTypeString: memcpy(str, mid->oct.data, mid->oct.length); str[mid->oct.length] = 0x00; - meterId = String(str); + strncpy(meterId, str, sizeof(meterId) - 1); break; case CosemTypeOctetString: memcpy(str, mid->str.data, mid->str.length); str[mid->str.length] = 0x00; - meterId = String(str); + strncpy(meterId, str, sizeof(meterId) - 1); break; } } @@ -1059,9 +1058,9 @@ IEC6205675::IEC6205675(const char* d, Timezone* tz, uint8_t useMeterType, MeterC meterType = AmsTypeIskra; } - if(meterId.isEmpty() && meterType != AmsTypeUnknown) { + if(meterId[0] == '\0' && meterType != AmsTypeUnknown) { stripNonAscii((uint8_t*) ctx.system_title, 8); - meterId = String((const char*)ctx.system_title); + strncpy(meterId, (const char*)ctx.system_title, sizeof(meterId) - 1); } } @@ -1105,7 +1104,13 @@ IEC6205675::IEC6205675(const char* d, Timezone* tz, uint8_t useMeterType, MeterC threePhase = true; } } - meterId.trim(); + // Trim trailing whitespace from meterId + { + int len = strlen(meterId); + while(len > 0 && (meterId[len-1] == ' ' || meterId[len-1] == '\t' || meterId[len-1] == '\r' || meterId[len-1] == '\n')) { + meterId[--len] = '\0'; + } + } } CosemData* IEC6205675::getCosemDataAt(uint8_t index, const char* ptr) { diff --git a/lib/MeterCommunicators/src/LNG.cpp b/lib/MeterCommunicators/src/LNG.cpp index 14425d96..ff460291 100644 --- a/lib/MeterCommunicators/src/LNG.cpp +++ b/lib/MeterCommunicators/src/LNG.cpp @@ -210,13 +210,13 @@ LNG::LNG(AmsData& meterState, const char* payload, uint8_t useMeterType, MeterCo char str[item->oct.length+1]; memcpy(str, item->oct.data, item->oct.length); str[item->oct.length] = '\0'; - meterId = String(str); + strncpy(meterId, str, sizeof(meterId) - 1); listType = listType >= 2 ? listType : 2; } else if(descriptor->obis[4] == 1) { char str[item->oct.length+1]; memcpy(str, item->oct.data, item->oct.length); str[item->oct.length] = '\0'; - meterModel = String(str); + strncpy(meterModel, str, sizeof(meterModel) - 1); listType = listType >= 2 ? listType : 2; } } diff --git a/lib/MeterCommunicators/src/LNG2.cpp b/lib/MeterCommunicators/src/LNG2.cpp index 57ffd33d..ffb4c803 100644 --- a/lib/MeterCommunicators/src/LNG2.cpp +++ b/lib/MeterCommunicators/src/LNG2.cpp @@ -31,7 +31,7 @@ LNG2::LNG2(AmsData& meterState, const char* payload, uint8_t useMeterType, Meter char str[64]; uint8_t str_len = getString((CosemData*) &d->meterId, str); if(str_len > 0) { - this->meterId = String(str); + strncpy(this->meterId, str, sizeof(this->meterId) - 1); } listType = 3; lastUpdateMillis = millis64(); @@ -57,7 +57,7 @@ LNG2::LNG2(AmsData& meterState, const char* payload, uint8_t useMeterType, Meter char str[64]; uint8_t str_len = getString((CosemData*) &d->meterId, str); if(str_len > 0) { - this->meterId = String(str); + strncpy(this->meterId, str, sizeof(this->meterId) - 1); } listType = 3; lastUpdateMillis = millis64(); diff --git a/lib/RawMqttHandler/src/RawMqttHandler.cpp b/lib/RawMqttHandler/src/RawMqttHandler.cpp index 961ea6b4..4672ef49 100644 --- a/lib/RawMqttHandler/src/RawMqttHandler.cpp +++ b/lib/RawMqttHandler/src/RawMqttHandler.cpp @@ -409,7 +409,7 @@ bool RawMqttHandler::publishRaw(uint8_t* raw, size_t length) { } void RawMqttHandler::onMessage(String &topic, String &payload) { - if(topic.equals(subTopic)) { + if(topic == subTopic) { if(payload.equals("fwupgrade")) { if(strcmp(updater->getNextVersion(), FirmwareVersion::VersionString) != 0) { updater->setTargetVersion(updater->getNextVersion()); diff --git a/lib/RealtimePlot/include/RealtimePlot.h b/lib/RealtimePlot/include/RealtimePlot.h index fc73c426..71c63218 100644 --- a/lib/RealtimePlot/include/RealtimePlot.h +++ b/lib/RealtimePlot/include/RealtimePlot.h @@ -21,8 +21,8 @@ public: int16_t getSize(); private: - int8_t* values; - uint8_t* scaling; + int8_t values[REALTIME_SIZE]; + uint8_t scaling[REALTIME_SIZE]; unsigned long lastMillis = 0; double lastReading = 0; diff --git a/lib/RealtimePlot/src/RealtimePlot.cpp b/lib/RealtimePlot/src/RealtimePlot.cpp index 1b9a9e12..b42ec049 100644 --- a/lib/RealtimePlot/src/RealtimePlot.cpp +++ b/lib/RealtimePlot/src/RealtimePlot.cpp @@ -5,11 +5,8 @@ */ #include "RealtimePlot.h" -#include RealtimePlot::RealtimePlot() { - values = (int8_t*) malloc(REALTIME_SIZE); - scaling = (uint8_t*) malloc(REALTIME_SIZE); memset(values, 0, REALTIME_SIZE); memset(scaling, 0, REALTIME_SIZE); } diff --git a/lib/SvelteUi/include/AmsWebServer.h b/lib/SvelteUi/include/AmsWebServer.h index e846406a..771b6883 100644 --- a/lib/SvelteUi/include/AmsWebServer.h +++ b/lib/SvelteUi/include/AmsWebServer.h @@ -96,12 +96,12 @@ private: bool uploading = false; File file; bool performRestart = false; - String priceRegion = ""; - String priceCurrency = ""; + char priceRegion[8] = {}; + char priceCurrency[4] = {}; #if defined(AMS2MQTT_FIRMWARE_URL) - String customFirmwareUrl = AMS2MQTT_FIRMWARE_URL; + char customFirmwareUrl[128] = AMS2MQTT_FIRMWARE_URL; #else - String customFirmwareUrl; + char customFirmwareUrl[128] = {}; #endif char* buf; diff --git a/lib/SvelteUi/src/AmsWebServer.cpp b/lib/SvelteUi/src/AmsWebServer.cpp index ec4643e6..23b16f9a 100644 --- a/lib/SvelteUi/src/AmsWebServer.cpp +++ b/lib/SvelteUi/src/AmsWebServer.cpp @@ -648,8 +648,8 @@ void AmsWebServer::dataJson() { ea->getProducedThisMonth(), ea->getIncomeThisMonth(), price == PRICE_NO_VALUE ? "false" : "true", - priceRegion.c_str(), - priceCurrency.c_str(), + priceRegion, + priceCurrency, meterState->getLastError(), ps == NULL ? 0 : ps->getLastError(), (uint32_t) now, @@ -1385,12 +1385,12 @@ void AmsWebServer::handleSave() { } if(server.hasArg(F("p")) && server.arg(F("p")) == F("true")) { - priceRegion = server.arg(F("pr")); + strncpy(priceRegion, server.arg(F("pr")).c_str(), sizeof(priceRegion) - 1); PriceServiceConfig price; price.enabled = server.hasArg(F("pe")) && server.arg(F("pe")) == F("true"); strcpy(price.entsoeToken, server.arg(F("pt")).c_str()); - strcpy(price.area, priceRegion.c_str()); + strcpy(price.area, priceRegion); strcpy(price.currency, server.arg(F("pc")).c_str()); price.resolutionInMinutes = server.arg(F("pm")).toInt(); config->setPriceServiceConfig(price); @@ -2022,8 +2022,8 @@ void AmsWebServer::realtimeJson() { } void AmsWebServer::setPriceSettings(String region, String currency) { - this->priceRegion = region; - this->priceCurrency = currency; + strncpy(this->priceRegion, region.c_str(), sizeof(this->priceRegion) - 1); + strncpy(this->priceCurrency, currency.c_str(), sizeof(this->priceCurrency) - 1); } void AmsWebServer::configFileDownload() {