From 78dd856a978f8d6b54a9fe0ad01bddf353ce28c7 Mon Sep 17 00:00:00 2001 From: Gunnar Skjold Date: Sun, 9 Jan 2022 20:45:25 +0100 Subject: [PATCH] Various changes --- src/AmsDataStorage.cpp | 40 +++++++++++++-------------- src/AmsToMqttBridge.ino | 8 ++++-- src/IEC6205675.cpp | 59 ++++++++++++++++++++++++++-------------- src/IEC6205675.h | 2 +- src/web/AmsWebServer.cpp | 43 +++++++++++++---------------- web/meter.html | 2 +- 6 files changed, 85 insertions(+), 69 deletions(-) diff --git a/src/AmsDataStorage.cpp b/src/AmsDataStorage.cpp index 27f07dca..f3a98b86 100644 --- a/src/AmsDataStorage.cpp +++ b/src/AmsDataStorage.cpp @@ -98,9 +98,9 @@ bool AmsDataStorage::update(AmsData* data) { day.activeImport = data->getActiveImportCounter() * 1000; day.activeExport = data->getActiveExportCounter() * 1000; day.lastMeterReadTime = now; - if(debugger->isActive(RemoteDebug::WARNING)) { +// if(debugger->isActive(RemoteDebug::WARNING)) { debugger->printf("(AmsDataStorage) Too long since last day update, clearing data\n"); - } +// } for(int i = 0; i<24; i++) { setHour(i, 0); } @@ -109,9 +109,9 @@ bool AmsDataStorage::update(AmsData* data) { int16_t val = (((data->getActiveImportCounter() * 1000) - day.activeImport) - ((data->getActiveExportCounter() * 1000) - day.activeExport)); setHour(tm.Hour, val); - if(debugger->isActive(RemoteDebug::INFO)) { +// if(debugger->isActive(RemoteDebug::INFO)) { debugger->printf("(AmsDataStorage) Usage for hour %d: %d\n", tm.Hour, val); - } +// } day.activeImport = data->getActiveImportCounter() * 1000; day.activeExport = data->getActiveExportCounter() * 1000; @@ -123,9 +123,9 @@ bool AmsDataStorage::update(AmsData* data) { float ipm = im / mins; float epm = ex / mins; - if(debugger->isActive(RemoteDebug::DEBUG)) { +// if(debugger->isActive(RemoteDebug::DEBUG)) { debugger->printf("(AmsDataStorage) Since last day update, minutes: %.1f, import: %d (%.2f/min), export: %d (%.2f/min)\n", mins, im, ipm, ex, epm); - } +// } breakTime(day.lastMeterReadTime, tm); day.lastMeterReadTime = day.lastMeterReadTime - (tm.Minute * 60) - tm.Second; @@ -140,9 +140,9 @@ bool AmsDataStorage::update(AmsData* data) { float val = ((ipm * minutes) - (epm * minutes)); setHour(last.Hour, val); - if(debugger->isActive(RemoteDebug::INFO)) { +// if(debugger->isActive(RemoteDebug::INFO)) { debugger->printf("(AmsDataStorage) Estimated usage for hour %u: %.1f (%lu)\n", last.Hour, val, cur); - } +// } day.activeImport += ipm * minutes; day.activeExport += epm * minutes; @@ -158,9 +158,9 @@ bool AmsDataStorage::update(AmsData* data) { } if(month.lastMeterReadTime > now) { - if(debugger->isActive(RemoteDebug::WARNING)) { +// if(debugger->isActive(RemoteDebug::WARNING)) { debugger->printf("(AmsDataStorage) Invalid future timestamp for month plot, resetting\n"); - } +// } month.activeImport = data->getActiveImportCounter() * 1000; month.activeExport = data->getActiveExportCounter() * 1000; month.lastMeterReadTime = now; @@ -171,18 +171,18 @@ bool AmsDataStorage::update(AmsData* data) { month.activeImport = data->getActiveImportCounter() * 1000; month.activeExport = data->getActiveExportCounter() * 1000; month.lastMeterReadTime = now; - if(debugger->isActive(RemoteDebug::WARNING)) { +// if(debugger->isActive(RemoteDebug::WARNING)) { debugger->printf("(AmsDataStorage) Too long since last month update, clearing data\n"); - } +// } for(int i = 1; i<=31; i++) { setDay(i, 0); } } else if(now - month.lastMeterReadTime < 87000) { int32_t val = (month.activeImport == 0 ? 0 : ((data->getActiveImportCounter() * 1000) - month.activeImport) - ((data->getActiveExportCounter() * 1000) - month.activeExport)); - if(debugger->isActive(RemoteDebug::INFO)) { +// if(debugger->isActive(RemoteDebug::INFO)) { debugger->printf("(AmsDataStorage) Usage for day %d: %d\n", tm.Day, val); - } +// } time_t yesterday = now - 3600; breakTime(yesterday, tm); @@ -198,9 +198,9 @@ bool AmsDataStorage::update(AmsData* data) { float iph = im / hrs; float eph = ex / hrs; - if(debugger->isActive(RemoteDebug::DEBUG)) { +// if(debugger->isActive(RemoteDebug::DEBUG)) { debugger->printf("(AmsDataStorage) Since last month update, hours: %.1f, import: %d (%.2f/hr), export: %d (%.2f/hr)\n", hrs, im, iph, ex, eph); - } +// } // Make sure last month read is at midnight if(tz != NULL) { @@ -209,9 +209,9 @@ bool AmsDataStorage::update(AmsData* data) { breakTime(month.lastMeterReadTime, tm); } month.lastMeterReadTime = month.lastMeterReadTime - (tm.Hour * 3600) - (tm.Minute * 60) - tm.Second; - if(debugger->isActive(RemoteDebug::DEBUG)) { +// if(debugger->isActive(RemoteDebug::DEBUG)) { debugger->printf("(AmsDataStorage) Last month read after resetting to midnight: %lu", month.lastMeterReadTime); - } +// } if(tz != NULL) { breakTime(tz->toLocal(now), tm); @@ -232,9 +232,9 @@ bool AmsDataStorage::update(AmsData* data) { float val = ((iph * hours) - (eph * hours)); setDay(last.Day, val); - if(debugger->isActive(RemoteDebug::INFO)) { +// if(debugger->isActive(RemoteDebug::INFO)) { debugger->printf("(AmsDataStorage) Estimated usage for day %u: %.1f (%lu)\n", last.Day, val, cur); - } +// } month.activeImport += iph * hours; month.activeExport += eph * hours; diff --git a/src/AmsToMqttBridge.ino b/src/AmsToMqttBridge.ino index 415beffb..c596f566 100644 --- a/src/AmsToMqttBridge.ino +++ b/src/AmsToMqttBridge.ino @@ -15,8 +15,8 @@ ADC_MODE(ADC_VCC); #else if defined(ESP32) #include -#define WDT_TIMEOUT 10 #endif +#define WDT_TIMEOUT 10 #include "AmsToMqttBridge.h" #include "AmsStorage.h" @@ -312,6 +312,8 @@ void setup() { #if defined(ESP32) esp_task_wdt_init(WDT_TIMEOUT, true); esp_task_wdt_add(NULL); + #elif defined(ESP8266) + ESP.wdtEnable(WDT_TIMEOUT); #endif } @@ -495,6 +497,8 @@ void loop() { delay(1); // Needed for auto modem sleep #if defined(ESP32) esp_task_wdt_reset(); + #elif defined(ESP8266) + ESP.wdtFeed(); #endif } @@ -759,7 +763,7 @@ bool readHanPort() { while(hanSerial->available()) hanSerial->read(); if(pos > 0) { debugI("Valid data, start at byte %d", pos); - data = IEC6205675(((char *) (buf)) + pos, meterState.getMeterType(), timestamp, hc); + data = IEC6205675(((char *) (buf)) + pos, meterState.getMeterType(), meterConfig.distributionSystem, timestamp, hc); } else { if(Debug.isActive(RemoteDebug::WARNING)) { switch(pos) { diff --git a/src/IEC6205675.cpp b/src/IEC6205675.cpp index 0e1c3e72..cdfe8df4 100644 --- a/src/IEC6205675.cpp +++ b/src/IEC6205675.cpp @@ -2,7 +2,7 @@ #include "lwip/def.h" #include "Timezone.h" -IEC6205675::IEC6205675(const char* d, uint8_t useMeterType, CosemDateTime packageTimestamp, HDLCConfig* hc) { +IEC6205675::IEC6205675(const char* d, uint8_t useMeterType, uint8_t distributionSystem, CosemDateTime packageTimestamp, HDLCConfig* hc) { uint32_t ui; double val; char str[64]; @@ -288,17 +288,26 @@ IEC6205675::IEC6205675(const char* d, uint8_t useMeterType, CosemDateTime packag } if(meterType == AmsTypeKamstrup) { - activeImportCounter *= 10; - activeExportCounter *= 10; - reactiveImportCounter *= 10; - reactiveExportCounter *= 10; - l1current /= 100; - l2current /= 100; - l3current /= 100; - powerFactor /= 100; - l1PowerFactor /= 100; - l2PowerFactor /= 100; - l3PowerFactor /= 100; + if(listType >= 3) { + activeImportCounter *= 10; + activeExportCounter *= 10; + reactiveImportCounter *= 10; + reactiveExportCounter *= 10; + } + if(l1current != 0) + l1current /= 100; + if(l2current != 0) + l2current /= 100; + if(l3current != 0) + l3current /= 100; + if(powerFactor != 0) + powerFactor /= 100; + if(l1PowerFactor != 0) + l1PowerFactor /= 100; + if(l2PowerFactor != 0) + l2PowerFactor /= 100; + if(l3PowerFactor != 0) + l3PowerFactor /= 100; } else if(meterType == AmsTypeSagemcom) { CosemData* meterTs = getCosemDataAt(1, ((char *) (d))); if(meterTs != NULL) { @@ -328,13 +337,19 @@ IEC6205675::IEC6205675(const char* d, uint8_t useMeterType, CosemDateTime packag threePhase = l1voltage > 0 && l2voltage > 0 && l3voltage > 0; twoPhase = (l1voltage > 0 && l2voltage > 0) || (l2voltage > 0 && l3voltage > 0) || (l3voltage > 0 && l1voltage > 0); - if(threePhase) { - if(l2current == 0 && l1current > 0 && l3current > 0) { - l2current = (((activeImportPower - activeExportPower) * sqrt(3)) - (l1voltage * l1current) - (l3voltage * l3current)) / l2voltage; + // Special case for Norwegian IT/TT meters that does not report all values + if(distributionSystem == 1) { + if(threePhase) { + if(l2current == 0.0 && l1current > 0.0 && l3current > 0.0) { + l2current = (((activeImportPower - activeExportPower) * sqrt(3)) - (l1voltage * l1current) - (l3voltage * l3current)) / l2voltage; + if(activeExportPower == 0) { + l2current = max((float) 0.0, l2current); + } + } + } else if(twoPhase && l1current > 0.0 && l2current > 0.0 && l3current > 0.0) { + l2voltage = sqrt(pow(l1voltage - l3voltage * cos(60.0 * (PI/180.0)), 2) + pow(l3voltage * sin(60.0 * (PI/180.0)),2)); + threePhase = true; } - } else if(twoPhase && l1current > 0 && l2current > 0 && l3current > 0) { - l2voltage = sqrt(pow(l1voltage - l3voltage * cos(60 * (PI/180)), 2) + pow(l3voltage * sin(60 * (PI/180)),2)); - threePhase = true; } } @@ -455,9 +470,11 @@ double IEC6205675::getNumber(CosemData* item) { pos += 3; break; } - if(*pos++ == 0x02 && *pos++ == 0x02) { - int8_t scale = *++pos; - val *= pow(10, scale); + if(pos != NULL) { + if(*pos++ == 0x02 && *pos++ == 0x02) { + int8_t scale = *++pos; + val *= pow(10, scale); + } } } return val; diff --git a/src/IEC6205675.h b/src/IEC6205675.h index 7846c5e1..c5869aef 100644 --- a/src/IEC6205675.h +++ b/src/IEC6205675.h @@ -11,7 +11,7 @@ struct AmsOctetTimestamp { class IEC6205675 : public AmsData { public: - IEC6205675(const char* payload, uint8_t useMeterType, CosemDateTime packageTimestamp, HDLCConfig* hc); + IEC6205675(const char* payload, uint8_t useMeterType, uint8_t distributionSystem, CosemDateTime packageTimestamp, HDLCConfig* hc); private: CosemData* getCosemDataAt(uint8_t index, const char* ptr); diff --git a/src/web/AmsWebServer.cpp b/src/web/AmsWebServer.cpp index dfebe566..7957eea6 100644 --- a/src/web/AmsWebServer.cpp +++ b/src/web/AmsWebServer.cpp @@ -1582,27 +1582,29 @@ void AmsWebServer::firmwareDownload() { String version = server.arg("version"); String versionStripped = version.substring(1); printI("Downloading firmware..."); - WiFiClientSecure client; -#if defined(ESP8266) - client.setBufferSizes(512, 512); - String url = "https://github.com/gskjold/AmsToMqttBridge/releases/download/" + version + "/ams2mqtt-esp8266-" + versionStripped + ".bin"; -#elif defined(ESP32) - String url = "https://github.com/gskjold/AmsToMqttBridge/releases/download/" + version + "/ams2mqtt-esp32-" + versionStripped + ".bin"; -#endif - client.setInsecure(); - HTTPClient https; - https.setFollowRedirects(HTTPC_STRICT_FOLLOW_REDIRECTS); + HTTPClient httpClient; + httpClient.setFollowRedirects(HTTPC_STRICT_FOLLOW_REDIRECTS); + httpClient.addHeader("User-Agent", "ams2mqtt/" + String(VERSION)); - https.addHeader("Referer", "https://github.com/gskjold/AmsToMqttBridge/releases"); - if(https.begin(client, url)) { +#if defined(ESP8266) + WiFiClient client; + String url = "http://0.0.0.0/releases/download/" + version + "/ams2mqtt-esp8266-" + versionStripped + ".bin"; +#elif defined(ESP32) + WiFiClientSecure client; + client.setInsecure(); + String url = "https://github.com/gskjold/AmsToMqttBridge/releases/download/" + version + "/ams2mqtt-esp32-" + versionStripped + ".bin"; + httpClient.addHeader("Referer", "https://github.com/gskjold/AmsToMqttBridge/releases"); +#endif + + if(httpClient.begin(client, url)) { printD("HTTP client setup successful"); - int status = https.GET(); + int status = httpClient.GET(); if(status == HTTP_CODE_OK) { printD("Received OK from server"); if(LittleFS.begin()) { printI("Downloading firmware to LittleFS"); file = LittleFS.open(FILE_FIRMWARE, "w"); - int len = https.writeToStream(&file); + int len = httpClient.writeToStream(&file); file.close(); LittleFS.end(); performRestart = true; @@ -1615,25 +1617,18 @@ void AmsWebServer::firmwareDownload() { } } else { printE("Communication error: "); - printE(https.errorToString(status)); + printE(httpClient.errorToString(status)); printI(url); - printD(https.getString()); + printD(httpClient.getString()); server.sendHeader("Location","/"); server.send(303); } } else { printE("Unable to configure HTTP client"); - - #if defined(ESP8266) - char buf[64]; - client.getLastSSLError(buf,64); - printE(buf); - #endif - server.sendHeader("Location","/"); server.send(303); } - https.end(); + httpClient.end(); client.stop(); } else { printI("No firmware version specified..."); diff --git a/web/meter.html b/web/meter.html index 9942e872..6383b3d7 100644 --- a/web/meter.html +++ b/web/meter.html @@ -68,7 +68,7 @@