From a055465ce09d231f549b3948e811213428356378 Mon Sep 17 00:00:00 2001 From: Gunnar Skjold Date: Tue, 16 Aug 2022 08:22:43 +0200 Subject: [PATCH 01/31] Untestet L&G data parser --- frames/lng.raw | 34 +++++++++++++++++++++ src/AmsData.h | 1 + src/AmsToMqttBridge.ino | 4 ++- src/LNG.cpp | 65 ++++++++++++++++++++++++++++++++++++++++ src/LNG.h | 29 ++++++++++++++++++ src/web/AmsWebServer.cpp | 3 ++ 6 files changed, 135 insertions(+), 1 deletion(-) create mode 100644 src/LNG.cpp create mode 100644 src/LNG.h diff --git a/frames/lng.raw b/frames/lng.raw index 9dc84a6e..00b2b497 100644 --- a/frames/lng.raw +++ b/frames/lng.raw @@ -43,3 +43,37 @@ FF // Last byte of OBIS in previous block 0600000000 // Accumulated export 8BA4 7E + + + + +7E A1 23 CE FF 03 13 21 55 E6 E7 00 + +0F 00 00 08 E2 +0C 07 E5 07 13 01 0C 1A 0A FF 80 00 00 + +02 0B // 11 + 01 0B // 11 + 02 04 12 00 28 09 06 00 08 19 09 00 FF 0F 02 12 00 00 + 02 04 12 00 28 09 06 00 08 19 09 00 FF 0F 01 12 00 00 + 02 04 12 00 01 09 06 00 00 60 01 00 FF 0F 02 12 00 00 + 02 04 12 00 03 09 06 01 00 01 07 00 FF 0F 02 12 00 00 + 02 04 12 00 03 09 06 01 00 02 07 00 FF 0F 02 12 00 00 + 02 04 12 00 03 09 06 01 01 01 08 00 FF 0F 02 12 00 00 + 02 04 12 00 03 09 06 01 01 02 08 00 FF 0F 02 12 00 00 + 02 04 12 00 03 09 06 01 01 05 08 00 FF 0F 02 12 00 00 + 02 04 12 00 03 09 06 01 01 06 08 00 FF 0F 02 12 00 00 + 02 04 12 00 03 09 06 01 01 07 08 00 FF 0F 02 12 00 00 + 02 04 12 00 03 09 06 01 01 08 08 00 FF 0F 02 12 00 00 + 09 06 00 08 19 09 00 FF + 09 08 34 33 30 39 34 33 35 31 + 06 00 00 00 0B + 06 00 00 00 00 + 06 00 00 00 10 + 06 00 00 00 04 + 06 00 00 00 00 + 06 00 00 00 08 + 06 00 00 00 00 + 06 00 00 00 01 +7C 8B +7E \ No newline at end of file diff --git a/src/AmsData.h b/src/AmsData.h index 3ffcd296..21d29827 100644 --- a/src/AmsData.h +++ b/src/AmsData.h @@ -12,6 +12,7 @@ enum AmsType { AmsTypeIskra = 0x08, AmsTypeLandis = 0x09, AmsTypeSagemcom = 0x0A, + AmsTypeLng = 0x0B, AmsTypeCustom = 0x88, AmsTypeUnknown = 0xFF }; diff --git a/src/AmsToMqttBridge.ino b/src/AmsToMqttBridge.ino index 19136294..6c722baa 100644 --- a/src/AmsToMqttBridge.ino +++ b/src/AmsToMqttBridge.ino @@ -65,6 +65,7 @@ ADC_MODE(ADC_VCC); #include "IEC6205621.h" #include "IEC6205675.h" +#include "LNG.h" #include "ams/DataParsers.h" @@ -851,7 +852,8 @@ bool readHanPort() { if(Debug.isActive(RemoteDebug::VERBOSE)) debugPrint(hanBuffer+pos, 0, ctx.length); // TODO: Split IEC6205675 into DataParserKaifa and DataParserObis. This way we can add other means of parsing, for those other proprietary formats - data = IEC6205675(((char *) (hanBuffer)) + pos, meterState.getMeterType(), &meterConfig, ctx); + //data = IEC6205675(((char *) (hanBuffer)) + pos, meterState.getMeterType(), &meterConfig, ctx); + data = LNG(((char *) (hanBuffer)) + pos, meterState.getMeterType(), &meterConfig, ctx); } else if(ctx.type == DATA_TAG_DSMR) { data = IEC6205621(((char *) (hanBuffer)) + pos); } diff --git a/src/LNG.cpp b/src/LNG.cpp new file mode 100644 index 00000000..d982f874 --- /dev/null +++ b/src/LNG.cpp @@ -0,0 +1,65 @@ +#include "LNG.h" +#include "lwip/def.h" +#include "ams/Cosem.h" + +LNG::LNG(const char* payload, uint8_t useMeterType, MeterConfig* meterConfig, DataParserContext &ctx) { + LngHeader* h = (LngHeader*) payload; + if(h->tag == CosemTypeStructure && h->arrayTag == CosemTypeArray) { + meterType = AmsTypeLng; + this->packageTimestamp = ctx.timestamp; + + uint8_t* ptr = (uint8_t*) &h[1]; + uint8_t* data = ptr + (18*h->arrayLength); // Skip descriptors + + for(uint8_t i = 0; i < h->arrayLength; i++) { + LngObisDescriptor* descriptor = (LngObisDescriptor*) ptr; + if(descriptor->obis[2] == 1) { + if(descriptor->obis[3] == 7) { + if(descriptor->obis[4] == 0) { + CosemDLongUnsigned* item = (CosemDLongUnsigned*) data; + activeImportPower = ntohl(item->data); + listType = listType >= 1 ? listType : 1; + } + } else if(descriptor->obis[3] == 8) { + if(descriptor->obis[4] == 0) { + CosemDLongUnsigned* item = (CosemDLongUnsigned*) data; + activeImportCounter = ntohl(item->data); + listType = listType >= 3 ? listType : 3; + } + } + } else if(descriptor->obis[2] == 2) { + if(descriptor->obis[3] == 7) { + if(descriptor->obis[4] == 0) { + CosemDLongUnsigned* item = (CosemDLongUnsigned*) data; + activeExportPower = ntohl(item->data); + listType = listType >= 2 ? listType : 2; + } + } else if(descriptor->obis[3] == 8) { + if(descriptor->obis[4] == 0) { + CosemDLongUnsigned* item = (CosemDLongUnsigned*) data; + activeExportCounter = ntohl(item->data); + listType = listType >= 3 ? listType : 3; + } + } + } else if(descriptor->obis[2] == 96) { + if(descriptor->obis[3] == 1) { + if(descriptor->obis[4] == 0) { + CosemString* item = (CosemString*) data; + char str[item->length+1]; + memcpy(str, item->data, item->length); + str[item->length] = '\0'; + meterId = String(str); + } + } + } + + ptr = (uint8_t*) &descriptor[1]; + + if((*data) == 0x09) { + data += (*data+1)+2; + } else { + data += 5; + } + } + } +} \ No newline at end of file diff --git a/src/LNG.h b/src/LNG.h new file mode 100644 index 00000000..19b14061 --- /dev/null +++ b/src/LNG.h @@ -0,0 +1,29 @@ +#ifndef _LNG_H +#define _LNG_H + +#include "AmsData.h" +#include "AmsConfiguration.h" +#include "ams/DataParser.h" + +struct LngHeader { + uint8_t tag; + uint8_t values; + uint8_t arrayTag; + uint8_t arrayLength; +} __attribute__((packed)); + +struct LngObisDescriptor { + uint8_t ignore1[5]; + uint8_t octetTag; + uint8_t octetLength; + uint8_t obis[6]; + uint8_t ignore2[5]; +} __attribute__((packed)); + + +class LNG : public AmsData { +public: + LNG(const char* payload, uint8_t useMeterType, MeterConfig* meterConfig, DataParserContext &ctx); +}; + +#endif diff --git a/src/web/AmsWebServer.cpp b/src/web/AmsWebServer.cpp index 13770818..bbbf7238 100644 --- a/src/web/AmsWebServer.cpp +++ b/src/web/AmsWebServer.cpp @@ -336,6 +336,9 @@ void AmsWebServer::configMeterHtml() { case AmsTypeSagemcom: manufacturer = "Sagemcom"; break; + case AmsTypeLng: + manufacturer = "L&G"; + break; default: manufacturer = "Unknown"; break; From 01547f9a521462b21a4db5998261f190e0c77b49 Mon Sep 17 00:00:00 2001 From: Gunnar Skjold Date: Fri, 19 Aug 2022 13:26:29 +0200 Subject: [PATCH 02/31] Adjustments to make L&G parser work --- src/AmsToMqttBridge.ino | 2 +- src/LNG.cpp | 47 ++++++++++++++++++++++++++--------------- src/LNG.h | 3 ++- 3 files changed, 33 insertions(+), 19 deletions(-) diff --git a/src/AmsToMqttBridge.ino b/src/AmsToMqttBridge.ino index 320a7238..a5726a84 100644 --- a/src/AmsToMqttBridge.ino +++ b/src/AmsToMqttBridge.ino @@ -859,7 +859,7 @@ bool readHanPort() { // TODO: Split IEC6205675 into DataParserKaifa and DataParserObis. This way we can add other means of parsing, for those other proprietary formats //data = IEC6205675(((char *) (hanBuffer)) + pos, meterState.getMeterType(), &meterConfig, ctx); - data = LNG(((char *) (hanBuffer)) + pos, meterState.getMeterType(), &meterConfig, ctx); + data = LNG(((char *) (hanBuffer)) + pos, meterState.getMeterType(), &meterConfig, ctx, &Debug); } else if(ctx.type == DATA_TAG_DSMR) { data = IEC6205621(((char *) (hanBuffer)) + pos); } diff --git a/src/LNG.cpp b/src/LNG.cpp index d982f874..dea4ecf5 100644 --- a/src/LNG.cpp +++ b/src/LNG.cpp @@ -2,7 +2,7 @@ #include "lwip/def.h" #include "ams/Cosem.h" -LNG::LNG(const char* payload, uint8_t useMeterType, MeterConfig* meterConfig, DataParserContext &ctx) { +LNG::LNG(const char* payload, uint8_t useMeterType, MeterConfig* meterConfig, DataParserContext &ctx, RemoteDebug* debugger) { LngHeader* h = (LngHeader*) payload; if(h->tag == CosemTypeStructure && h->arrayTag == CosemTypeArray) { meterType = AmsTypeLng; @@ -11,55 +11,68 @@ LNG::LNG(const char* payload, uint8_t useMeterType, MeterConfig* meterConfig, Da uint8_t* ptr = (uint8_t*) &h[1]; uint8_t* data = ptr + (18*h->arrayLength); // Skip descriptors - for(uint8_t i = 0; i < h->arrayLength; i++) { - LngObisDescriptor* descriptor = (LngObisDescriptor*) ptr; + LngObisDescriptor* descriptor = (LngObisDescriptor*) ptr; + for(uint8_t x = 0; x < h->arrayLength-1; x++) { + ptr = (uint8_t*) &descriptor[1]; + descriptor = (LngObisDescriptor*) ptr; + if(debugger->isActive(RemoteDebug::VERBOSE)) debugger->printf("(L&G) OBIS %d.%d.%d with type 0x%02X", descriptor->obis[2], descriptor->obis[3], descriptor->obis[4], *data); + + CosemData* item = (CosemData*) data; if(descriptor->obis[2] == 1) { if(descriptor->obis[3] == 7) { if(descriptor->obis[4] == 0) { - CosemDLongUnsigned* item = (CosemDLongUnsigned*) data; - activeImportPower = ntohl(item->data); + activeImportPower = ntohl(item->dlu.data); listType = listType >= 1 ? listType : 1; + if(debugger->isActive(RemoteDebug::VERBOSE)) debugger->printf(" and value %d (dlu)", ntohl(item->dlu.data)); } } else if(descriptor->obis[3] == 8) { if(descriptor->obis[4] == 0) { - CosemDLongUnsigned* item = (CosemDLongUnsigned*) data; - activeImportCounter = ntohl(item->data); + activeImportCounter = ntohl(item->dlu.data); listType = listType >= 3 ? listType : 3; + if(debugger->isActive(RemoteDebug::VERBOSE)) debugger->printf(" and value %d (dlu)", ntohl(item->dlu.data)); } } } else if(descriptor->obis[2] == 2) { if(descriptor->obis[3] == 7) { if(descriptor->obis[4] == 0) { - CosemDLongUnsigned* item = (CosemDLongUnsigned*) data; - activeExportPower = ntohl(item->data); + activeExportPower = ntohl(item->dlu.data); listType = listType >= 2 ? listType : 2; + if(debugger->isActive(RemoteDebug::VERBOSE)) debugger->printf(" and value %d (dlu)", ntohl(item->dlu.data)); } } else if(descriptor->obis[3] == 8) { if(descriptor->obis[4] == 0) { - CosemDLongUnsigned* item = (CosemDLongUnsigned*) data; - activeExportCounter = ntohl(item->data); + activeExportCounter = ntohl(item->dlu.data); listType = listType >= 3 ? listType : 3; + if(debugger->isActive(RemoteDebug::VERBOSE)) debugger->printf(" and value %d (dlu)", ntohl(item->dlu.data)); } } } else if(descriptor->obis[2] == 96) { if(descriptor->obis[3] == 1) { if(descriptor->obis[4] == 0) { - CosemString* item = (CosemString*) data; - char str[item->length+1]; - memcpy(str, item->data, item->length); - str[item->length] = '\0'; + char str[item->oct.length+1]; + memcpy(str, item->oct.data, item->oct.length); + str[item->oct.length] = '\0'; meterId = String(str); + if(debugger->isActive(RemoteDebug::VERBOSE)) debugger->printf(" and value %s (oct)", str); + } 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); + if(debugger->isActive(RemoteDebug::VERBOSE)) debugger->printf(" and value %s (oct)", str); } } } - ptr = (uint8_t*) &descriptor[1]; + if(debugger->isActive(RemoteDebug::VERBOSE)) debugger->printf("\n"); if((*data) == 0x09) { - data += (*data+1)+2; + data += (*(data+1))+2; } else { data += 5; } + + lastUpdateMillis = millis(); } } } \ No newline at end of file diff --git a/src/LNG.h b/src/LNG.h index 19b14061..f448b105 100644 --- a/src/LNG.h +++ b/src/LNG.h @@ -4,6 +4,7 @@ #include "AmsData.h" #include "AmsConfiguration.h" #include "ams/DataParser.h" +#include "RemoteDebug.h" struct LngHeader { uint8_t tag; @@ -23,7 +24,7 @@ struct LngObisDescriptor { class LNG : public AmsData { public: - LNG(const char* payload, uint8_t useMeterType, MeterConfig* meterConfig, DataParserContext &ctx); + LNG(const char* payload, uint8_t useMeterType, MeterConfig* meterConfig, DataParserContext &ctx, RemoteDebug* debugger); }; #endif From 44bcd386d175d85f808377466aea77ce78e2043f Mon Sep 17 00:00:00 2001 From: Gunnar Skjold Date: Tue, 23 Aug 2022 09:04:45 +0200 Subject: [PATCH 03/31] aggregate obis 1.8.x and 2.8.x for L&G --- src/LNG.cpp | 23 +++++++++++++++++++++++ 1 file changed, 23 insertions(+) diff --git a/src/LNG.cpp b/src/LNG.cpp index dea4ecf5..607e80e0 100644 --- a/src/LNG.cpp +++ b/src/LNG.cpp @@ -11,6 +11,8 @@ LNG::LNG(const char* payload, uint8_t useMeterType, MeterConfig* meterConfig, Da uint8_t* ptr = (uint8_t*) &h[1]; uint8_t* data = ptr + (18*h->arrayLength); // Skip descriptors + uint16_t o181 = 0, o182 = 0; + uint16_t o281 = 0, o282 = 0; LngObisDescriptor* descriptor = (LngObisDescriptor*) ptr; for(uint8_t x = 0; x < h->arrayLength-1; x++) { ptr = (uint8_t*) &descriptor[1]; @@ -30,6 +32,12 @@ LNG::LNG(const char* payload, uint8_t useMeterType, MeterConfig* meterConfig, Da activeImportCounter = ntohl(item->dlu.data); listType = listType >= 3 ? listType : 3; if(debugger->isActive(RemoteDebug::VERBOSE)) debugger->printf(" and value %d (dlu)", ntohl(item->dlu.data)); + } else if(descriptor->obis[4] == 1) { + o181 = ntohl(item->dlu.data); + if(debugger->isActive(RemoteDebug::VERBOSE)) debugger->printf(" and value %d (dlu)", ntohl(item->dlu.data)); + } else if(descriptor->obis[4] == 2) { + o182 = ntohl(item->dlu.data); + if(debugger->isActive(RemoteDebug::VERBOSE)) debugger->printf(" and value %d (dlu)", ntohl(item->dlu.data)); } } } else if(descriptor->obis[2] == 2) { @@ -44,6 +52,12 @@ LNG::LNG(const char* payload, uint8_t useMeterType, MeterConfig* meterConfig, Da activeExportCounter = ntohl(item->dlu.data); listType = listType >= 3 ? listType : 3; if(debugger->isActive(RemoteDebug::VERBOSE)) debugger->printf(" and value %d (dlu)", ntohl(item->dlu.data)); + } else if(descriptor->obis[4] == 1) { + o281 = ntohl(item->dlu.data); + if(debugger->isActive(RemoteDebug::VERBOSE)) debugger->printf(" and value %d (dlu)", ntohl(item->dlu.data)); + } else if(descriptor->obis[4] == 2) { + o282 = ntohl(item->dlu.data); + if(debugger->isActive(RemoteDebug::VERBOSE)) debugger->printf(" and value %d (dlu)", ntohl(item->dlu.data)); } } } else if(descriptor->obis[2] == 96) { @@ -66,6 +80,15 @@ LNG::LNG(const char* payload, uint8_t useMeterType, MeterConfig* meterConfig, Da if(debugger->isActive(RemoteDebug::VERBOSE)) debugger->printf("\n"); + if(o181 > 0 || o182 > 0) { + activeImportCounter = o181 + o182; + listType = listType >= 3 ? listType : 3; + } + if(o281 > 0 || o282 > 0) { + activeExportCounter = o281 + o282; + listType = listType >= 3 ? listType : 3; + } + if((*data) == 0x09) { data += (*(data+1))+2; } else { From 9cc75299345922cb6a7ba800edc6340ff217a973 Mon Sep 17 00:00:00 2001 From: Gunnar Skjold Date: Wed, 31 Aug 2022 08:19:09 +0200 Subject: [PATCH 04/31] Fixed L&G scaling --- src/LNG.cpp | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/src/LNG.cpp b/src/LNG.cpp index 607e80e0..881953a5 100644 --- a/src/LNG.cpp +++ b/src/LNG.cpp @@ -29,7 +29,7 @@ LNG::LNG(const char* payload, uint8_t useMeterType, MeterConfig* meterConfig, Da } } else if(descriptor->obis[3] == 8) { if(descriptor->obis[4] == 0) { - activeImportCounter = ntohl(item->dlu.data); + activeImportCounter = ntohl(item->dlu.data) / 1000.0; listType = listType >= 3 ? listType : 3; if(debugger->isActive(RemoteDebug::VERBOSE)) debugger->printf(" and value %d (dlu)", ntohl(item->dlu.data)); } else if(descriptor->obis[4] == 1) { @@ -49,7 +49,7 @@ LNG::LNG(const char* payload, uint8_t useMeterType, MeterConfig* meterConfig, Da } } else if(descriptor->obis[3] == 8) { if(descriptor->obis[4] == 0) { - activeExportCounter = ntohl(item->dlu.data); + activeExportCounter = ntohl(item->dlu.data) / 1000.0; listType = listType >= 3 ? listType : 3; if(debugger->isActive(RemoteDebug::VERBOSE)) debugger->printf(" and value %d (dlu)", ntohl(item->dlu.data)); } else if(descriptor->obis[4] == 1) { @@ -81,11 +81,11 @@ LNG::LNG(const char* payload, uint8_t useMeterType, MeterConfig* meterConfig, Da if(debugger->isActive(RemoteDebug::VERBOSE)) debugger->printf("\n"); if(o181 > 0 || o182 > 0) { - activeImportCounter = o181 + o182; + activeImportCounter = (o181 + o182) / 1000.0; listType = listType >= 3 ? listType : 3; } if(o281 > 0 || o282 > 0) { - activeExportCounter = o281 + o282; + activeExportCounter = (o281 + o282) / 1000.0; listType = listType >= 3 ? listType : 3; } From 992e1b6121c1997aa44ee2244b4dad66e1792861 Mon Sep 17 00:00:00 2001 From: Gunnar Skjold Date: Mon, 12 Sep 2022 08:03:32 +0200 Subject: [PATCH 05/31] Net value for active power (L&G) --- src/LNG.cpp | 18 ++++++++++++++---- 1 file changed, 14 insertions(+), 4 deletions(-) diff --git a/src/LNG.cpp b/src/LNG.cpp index 881953a5..b5c9817b 100644 --- a/src/LNG.cpp +++ b/src/LNG.cpp @@ -11,6 +11,7 @@ LNG::LNG(const char* payload, uint8_t useMeterType, MeterConfig* meterConfig, Da uint8_t* ptr = (uint8_t*) &h[1]; uint8_t* data = ptr + (18*h->arrayLength); // Skip descriptors + uint16_t o170 = 0, o270 = 0; uint16_t o181 = 0, o182 = 0; uint16_t o281 = 0, o282 = 0; LngObisDescriptor* descriptor = (LngObisDescriptor*) ptr; @@ -23,8 +24,7 @@ LNG::LNG(const char* payload, uint8_t useMeterType, MeterConfig* meterConfig, Da if(descriptor->obis[2] == 1) { if(descriptor->obis[3] == 7) { if(descriptor->obis[4] == 0) { - activeImportPower = ntohl(item->dlu.data); - listType = listType >= 1 ? listType : 1; + o170 = ntohl(item->dlu.data); if(debugger->isActive(RemoteDebug::VERBOSE)) debugger->printf(" and value %d (dlu)", ntohl(item->dlu.data)); } } else if(descriptor->obis[3] == 8) { @@ -43,8 +43,7 @@ LNG::LNG(const char* payload, uint8_t useMeterType, MeterConfig* meterConfig, Da } else if(descriptor->obis[2] == 2) { if(descriptor->obis[3] == 7) { if(descriptor->obis[4] == 0) { - activeExportPower = ntohl(item->dlu.data); - listType = listType >= 2 ? listType : 2; + o270 = ntohl(item->dlu.data); if(debugger->isActive(RemoteDebug::VERBOSE)) debugger->printf(" and value %d (dlu)", ntohl(item->dlu.data)); } } else if(descriptor->obis[3] == 8) { @@ -80,6 +79,17 @@ LNG::LNG(const char* payload, uint8_t useMeterType, MeterConfig* meterConfig, Da if(debugger->isActive(RemoteDebug::VERBOSE)) debugger->printf("\n"); + if(o170 > 0 || o270 > 0) { + int32_t sum = o170-o270; + if(sum > 0) { + listType = listType >= 1 ? listType : 1; + activeImportPower = sum; + } else { + listType = listType >= 2 ? listType : 2; + activeExportPower = sum * -1; + } + } + if(o181 > 0 || o182 > 0) { activeImportCounter = (o181 + o182) / 1000.0; listType = listType >= 3 ? listType : 3; From c4af1ee74f183ecc8d68ae3642eb4883909f587e Mon Sep 17 00:00:00 2001 From: Gunnar Skjold Date: Sun, 25 Sep 2022 10:50:09 +0200 Subject: [PATCH 06/31] Fixed saving tariff thresholds --- src/AmsConfiguration.cpp | 1 + 1 file changed, 1 insertion(+) diff --git a/src/AmsConfiguration.cpp b/src/AmsConfiguration.cpp index 0d03f68c..1b6d3f9e 100644 --- a/src/AmsConfiguration.cpp +++ b/src/AmsConfiguration.cpp @@ -525,6 +525,7 @@ bool AmsConfiguration::setEnergyAccountingConfig(EnergyAccountingConfig& config) } } config.thresholds[9] = 255; + energyAccountingChanged |= config.hours != existing.hours; } else { energyAccountingChanged = true; } From feb8e5007bb210557c74cacfcd2699ad836595a8 Mon Sep 17 00:00:00 2001 From: Gunnar Skjold Date: Sun, 25 Sep 2022 10:50:34 +0200 Subject: [PATCH 07/31] Fixed MQTT buffer size --- src/AmsToMqttBridge.ino | 15 ++------------- 1 file changed, 2 insertions(+), 13 deletions(-) diff --git a/src/AmsToMqttBridge.ino b/src/AmsToMqttBridge.ino index a10be9ac..6a11d910 100644 --- a/src/AmsToMqttBridge.ino +++ b/src/AmsToMqttBridge.ino @@ -65,7 +65,7 @@ ADC_MODE(ADC_VCC); #include "RemoteDebug.h" #define BUF_SIZE_COMMON (2048) -#define BUF_SIZE_HAN (1024) +#define BUF_SIZE_HAN (1280) #include "IEC6205621.h" #include "IEC6205675.h" @@ -1260,18 +1260,7 @@ void MQTT_connect() { mqtt->disconnect(); yield(); } else { - uint16_t size = 256; - switch(mqttConfig.payloadFormat) { - case 0: // JSON - case 4: // Home Assistant - size = 768; - break; - case 255: // Raw frame - size = 1024; - break; - } - - mqtt = new MQTTClient(size); + mqtt = new MQTTClient(1024); ws.setMqtt(mqtt); } From f1f74082087daf57bc2e70d5d881b66fb8e35138 Mon Sep 17 00:00:00 2001 From: Gunnar Skjold Date: Sun, 25 Sep 2022 11:46:04 +0200 Subject: [PATCH 08/31] Added price zones --- src/web/AmsWebServer.cpp | 14 ++++++++++++++ web/entsoe.html | 13 +++++++++++++ 2 files changed, 27 insertions(+) diff --git a/src/web/AmsWebServer.cpp b/src/web/AmsWebServer.cpp index c9e1e4a6..b551eaf9 100644 --- a/src/web/AmsWebServer.cpp +++ b/src/web/AmsWebServer.cpp @@ -567,6 +567,20 @@ void AmsWebServer::configEntsoeHtml() { html.replace("{eaDk1}", strcmp(entsoe.area, "10YDK-1--------W") == 0 ? "selected" : ""); html.replace("{eaDk2}", strcmp(entsoe.area, "10YDK-2--------M") == 0 ? "selected" : ""); + html.replace("{at}", strcmp(entsoe.area, "10YAT-APG------L") == 0 ? "selected" : ""); + html.replace("{be}", strcmp(entsoe.area, "10YBE----------2") == 0 ? "selected" : ""); + html.replace("{cz}", strcmp(entsoe.area, "10YCZ-CEPS-----N") == 0 ? "selected" : ""); + html.replace("{ee}", strcmp(entsoe.area, "10Y1001A1001A39I") == 0 ? "selected" : ""); + html.replace("{fi}", strcmp(entsoe.area, "10YFI-1--------U") == 0 ? "selected" : ""); + html.replace("{fr}", strcmp(entsoe.area, "10YFR-RTE------C") == 0 ? "selected" : ""); + html.replace("{de}", strcmp(entsoe.area, "10Y1001A1001A83F") == 0 ? "selected" : ""); + html.replace("{gb}", strcmp(entsoe.area, "10YGB----------A") == 0 ? "selected" : ""); + html.replace("{lv}", strcmp(entsoe.area, "10YLV-1001A00074") == 0 ? "selected" : ""); + html.replace("{lt}", strcmp(entsoe.area, "10YLT-1001A0008Q") == 0 ? "selected" : ""); + html.replace("{nl}", strcmp(entsoe.area, "10YNL----------L") == 0 ? "selected" : ""); + html.replace("{pl}", strcmp(entsoe.area, "10YPL-AREA-----S") == 0 ? "selected" : ""); + html.replace("{ch}", strcmp(entsoe.area, "10YCH-SWISSGRIDZ") == 0 ? "selected" : ""); + html.replace("{ecNOK}", strcmp(entsoe.currency, "NOK") == 0 ? "selected" : ""); html.replace("{ecSEK}", strcmp(entsoe.currency, "SEK") == 0 ? "selected" : ""); html.replace("{ecDKK}", strcmp(entsoe.currency, "DKK") == 0 ? "selected" : ""); diff --git a/web/entsoe.html b/web/entsoe.html index 43b254c9..44b4847e 100644 --- a/web/entsoe.html +++ b/web/entsoe.html @@ -34,6 +34,19 @@ + + + + + + + + + + + + + From 2a4772fe259d2cd26218289794cd0488c1f21fef Mon Sep 17 00:00:00 2001 From: Gunnar Skjold Date: Tue, 27 Sep 2022 19:59:37 +0200 Subject: [PATCH 09/31] Fixed memory leak when reconnecting to MQTT/SSL --- src/AmsToMqttBridge.ino | 105 ++++++++++++++++++++++------------------ 1 file changed, 57 insertions(+), 48 deletions(-) diff --git a/src/AmsToMqttBridge.ino b/src/AmsToMqttBridge.ino index 6a11d910..36b3919a 100644 --- a/src/AmsToMqttBridge.ino +++ b/src/AmsToMqttBridge.ino @@ -512,6 +512,7 @@ void loop() { if (mqttEnabled || config.isMqttChanged()) { if(mqtt == NULL || !mqtt->connected() || config.isMqttChanged()) { MQTT_connect(); + config.ackMqttChange(); } } else if(mqtt != NULL && mqtt->connected()) { mqttClient->stop(); @@ -1243,7 +1244,6 @@ void MQTT_connect() { if(Debug.isActive(RemoteDebug::WARNING)) debugW("No MQTT config"); mqttEnabled = false; ws.setMqttEnabled(false); - config.ackMqttChange(); return; } if(mqtt != NULL) { @@ -1258,6 +1258,16 @@ void MQTT_connect() { } mqtt->disconnect(); + if(config.isMqttChanged()) { + if(mqttSecureClient != NULL) { + mqttSecureClient->stop(); + delete mqttSecureClient; + mqttSecureClient = NULL; + } else { + mqttClient->stop(); + } + mqttClient = NULL; + } yield(); } else { mqtt = new MQTTClient(1024); @@ -1295,54 +1305,54 @@ void MQTT_connect() { debugI("MQTT SSL is configured (%dkb free heap)", ESP.getFreeHeap()); if(mqttSecureClient == NULL) { mqttSecureClient = new WiFiClientSecure(); - } - #if defined(ESP8266) - mqttSecureClient->setBufferSizes(512, 512); - #endif - - if(LittleFS.begin()) { - File file; + #if defined(ESP8266) + mqttSecureClient->setBufferSizes(512, 512); + #endif + + if(LittleFS.begin()) { + File file; - if(LittleFS.exists(FILE_MQTT_CA)) { - debugI("Found MQTT CA file (%dkb free heap)", ESP.getFreeHeap()); - file = LittleFS.open(FILE_MQTT_CA, "r"); - #if defined(ESP8266) - BearSSL::X509List *serverTrustedCA = new BearSSL::X509List(file); - mqttSecureClient->setTrustAnchors(serverTrustedCA); - #elif defined(ESP32) - mqttSecureClient->loadCACert(file, file.size()); - #endif - file.close(); + if(LittleFS.exists(FILE_MQTT_CA)) { + debugI("Found MQTT CA file (%dkb free heap)", ESP.getFreeHeap()); + file = LittleFS.open(FILE_MQTT_CA, "r"); + #if defined(ESP8266) + BearSSL::X509List *serverTrustedCA = new BearSSL::X509List(file); + mqttSecureClient->setTrustAnchors(serverTrustedCA); + #elif defined(ESP32) + mqttSecureClient->loadCACert(file, file.size()); + #endif + file.close(); + } + + if(LittleFS.exists(FILE_MQTT_CERT) && LittleFS.exists(FILE_MQTT_KEY)) { + #if defined(ESP8266) + debugI("Found MQTT certificate file (%dkb free heap)", ESP.getFreeHeap()); + file = LittleFS.open(FILE_MQTT_CERT, "r"); + BearSSL::X509List *serverCertList = new BearSSL::X509List(file); + file.close(); + + debugI("Found MQTT key file (%dkb free heap)", ESP.getFreeHeap()); + file = LittleFS.open(FILE_MQTT_KEY, "r"); + BearSSL::PrivateKey *serverPrivKey = new BearSSL::PrivateKey(file); + file.close(); + + debugD("Setting client certificates (%dkb free heap)", ESP.getFreeHeap()); + mqttSecureClient->setClientRSACert(serverCertList, serverPrivKey); + #elif defined(ESP32) + debugI("Found MQTT certificate file (%dkb free heap)", ESP.getFreeHeap()); + file = LittleFS.open(FILE_MQTT_CERT, "r"); + mqttSecureClient->loadCertificate(file, file.size()); + file.close(); + + debugI("Found MQTT key file (%dkb free heap)", ESP.getFreeHeap()); + file = LittleFS.open(FILE_MQTT_KEY, "r"); + mqttSecureClient->loadPrivateKey(file, file.size()); + file.close(); + #endif + } + LittleFS.end(); + debugD("MQTT SSL setup complete (%dkb free heap)", ESP.getFreeHeap()); } - - if(LittleFS.exists(FILE_MQTT_CERT) && LittleFS.exists(FILE_MQTT_KEY)) { - #if defined(ESP8266) - debugI("Found MQTT certificate file (%dkb free heap)", ESP.getFreeHeap()); - file = LittleFS.open(FILE_MQTT_CERT, "r"); - BearSSL::X509List *serverCertList = new BearSSL::X509List(file); - file.close(); - - debugI("Found MQTT key file (%dkb free heap)", ESP.getFreeHeap()); - file = LittleFS.open(FILE_MQTT_KEY, "r"); - BearSSL::PrivateKey *serverPrivKey = new BearSSL::PrivateKey(file); - file.close(); - - debugD("Setting client certificates (%dkb free heap)", ESP.getFreeHeap()); - mqttSecureClient->setClientRSACert(serverCertList, serverPrivKey); - #elif defined(ESP32) - debugI("Found MQTT certificate file (%dkb free heap)", ESP.getFreeHeap()); - file = LittleFS.open(FILE_MQTT_CERT, "r"); - mqttSecureClient->loadCertificate(file, file.size()); - file.close(); - - debugI("Found MQTT key file (%dkb free heap)", ESP.getFreeHeap()); - file = LittleFS.open(FILE_MQTT_KEY, "r"); - mqttSecureClient->loadPrivateKey(file, file.size()); - file.close(); - #endif - } - LittleFS.end(); - debugD("MQTT SSL setup complete (%dkb free heap)", ESP.getFreeHeap()); } mqttClient = mqttSecureClient; } else if(mqttClient == NULL) { @@ -1367,7 +1377,6 @@ void MQTT_connect() { if ((strlen(mqttConfig.username) == 0 && mqtt->connect(mqttConfig.clientId)) || (strlen(mqttConfig.username) > 0 && mqtt->connect(mqttConfig.clientId, mqttConfig.username, mqttConfig.password))) { if (Debug.isActive(RemoteDebug::INFO)) debugI("Successfully connected to MQTT!"); - config.ackMqttChange(); if(mqttHandler != NULL) { mqttHandler->publishSystem(&hw); From e7c25fafda16fa1b4bab605bb3ff9fc35b3bd6e9 Mon Sep 17 00:00:00 2001 From: Gunnar Skjold Date: Wed, 28 Sep 2022 20:13:03 +0200 Subject: [PATCH 10/31] Prices and realtime HA sensors --- src/AmsToMqttBridge.ino | 4 +- src/mqtt/AmsMqttHandler.h | 2 +- src/mqtt/DomoticzMqttHandler.cpp | 2 +- src/mqtt/DomoticzMqttHandler.h | 2 +- src/mqtt/HomeAssistantMqttHandler.cpp | 71 +++++++++++++++++++++------ src/mqtt/HomeAssistantMqttHandler.h | 4 +- src/mqtt/HomeAssistantStatic.h | 71 ++++++++++++++++++++++++--- src/mqtt/JsonMqttHandler.cpp | 2 +- src/mqtt/JsonMqttHandler.h | 2 +- src/mqtt/RawMqttHandler.cpp | 2 +- src/mqtt/RawMqttHandler.h | 2 +- web/realtime.json | 20 ++++++++ 12 files changed, 149 insertions(+), 35 deletions(-) create mode 100644 web/realtime.json diff --git a/src/AmsToMqttBridge.ino b/src/AmsToMqttBridge.ino index 36b3919a..1ce6b331 100644 --- a/src/AmsToMqttBridge.ino +++ b/src/AmsToMqttBridge.ino @@ -594,7 +594,7 @@ void loop() { } if(now - lastSysupdate > 10000) { if(mqtt != NULL && mqttHandler != NULL && WiFi.getMode() != WIFI_AP && WiFi.status() == WL_CONNECTED && mqtt->connected() && !topic.isEmpty()) { - mqttHandler->publishSystem(&hw); + mqttHandler->publishSystem(&hw, eapi, &ea); } lastSysupdate = now; } @@ -1379,7 +1379,7 @@ void MQTT_connect() { if (Debug.isActive(RemoteDebug::INFO)) debugI("Successfully connected to MQTT!"); if(mqttHandler != NULL) { - mqttHandler->publishSystem(&hw); + mqttHandler->publishSystem(&hw, eapi, &ea); } // Subscribe to the chosen MQTT topic, if set in configuration diff --git a/src/mqtt/AmsMqttHandler.h b/src/mqtt/AmsMqttHandler.h index e5364e4e..4ec71634 100644 --- a/src/mqtt/AmsMqttHandler.h +++ b/src/mqtt/AmsMqttHandler.h @@ -19,7 +19,7 @@ public: virtual bool publish(AmsData* data, AmsData* previousState, EnergyAccounting* ea); virtual bool publishTemperatures(AmsConfiguration*, HwTools*); virtual bool publishPrices(EntsoeApi* eapi); - virtual bool publishSystem(HwTools*); + virtual bool publishSystem(HwTools*, EntsoeApi*, EnergyAccounting*); protected: MQTTClient* mqtt; diff --git a/src/mqtt/DomoticzMqttHandler.cpp b/src/mqtt/DomoticzMqttHandler.cpp index 11975d34..d173e0dd 100644 --- a/src/mqtt/DomoticzMqttHandler.cpp +++ b/src/mqtt/DomoticzMqttHandler.cpp @@ -71,6 +71,6 @@ bool DomoticzMqttHandler::publishPrices(EntsoeApi* eapi) { return false; } -bool DomoticzMqttHandler::publishSystem(HwTools* hw) { +bool DomoticzMqttHandler::publishSystem(HwTools* hw, EntsoeApi* eapi, EnergyAccounting* ea) { return false; } diff --git a/src/mqtt/DomoticzMqttHandler.h b/src/mqtt/DomoticzMqttHandler.h index 145bffe5..2c1d68b0 100644 --- a/src/mqtt/DomoticzMqttHandler.h +++ b/src/mqtt/DomoticzMqttHandler.h @@ -12,7 +12,7 @@ public: bool publish(AmsData* data, AmsData* previousState, EnergyAccounting* ea); bool publishTemperatures(AmsConfiguration*, HwTools*); bool publishPrices(EntsoeApi*); - bool publishSystem(HwTools*); + bool publishSystem(HwTools* hw, EntsoeApi* eapi, EnergyAccounting* ea); private: DomoticzConfig config; diff --git a/src/mqtt/HomeAssistantMqttHandler.cpp b/src/mqtt/HomeAssistantMqttHandler.cpp index f8678796..544ece33 100644 --- a/src/mqtt/HomeAssistantMqttHandler.cpp +++ b/src/mqtt/HomeAssistantMqttHandler.cpp @@ -9,6 +9,7 @@ #include "web/root/jsonsys_json.h" #include "web/root/jsonprices_json.h" #include "web/root/hadiscover_json.h" +#include "web/root/realtime_json.h" bool HomeAssistantMqttHandler::publish(AmsData* data, AmsData* previousState, EnergyAccounting* ea) { if(topic.isEmpty() || !mqtt->connected()) @@ -32,7 +33,7 @@ bool HomeAssistantMqttHandler::publish(AmsData* data, AmsData* previousState, En snprintf_P(json, BufferSize, HA1_JSON, data->getActiveImportPower() ); - return mqtt->publish(topic + "/power", json); + mqtt->publish(topic + "/power", json); } else if(data->getListType() >= 2) { // publish power counts and volts/amps snprintf_P(json, BufferSize, HA3_JSON, data->getListId().c_str(), @@ -53,9 +54,31 @@ bool HomeAssistantMqttHandler::publish(AmsData* data, AmsData* previousState, En data->getPowerFactor() == 0 ? 1 : data->getL2PowerFactor(), data->getPowerFactor() == 0 ? 1 : data->getL3PowerFactor() ); - return mqtt->publish(topic + "/power", json); + mqtt->publish(topic + "/power", json); } - return false; + + String peaks = ""; + for(uint8_t i = 1; i <= ea->getConfig()->hours; i++) { + if(!peaks.isEmpty()) peaks += ","; + peaks += String(ea->getPeak(i)); + } + snprintf_P(json, BufferSize, REALTIME_JSON, + ea->getMonthMax(), + peaks.c_str(), + ea->getCurrentThreshold(), + ea->getUseThisHour(), + ea->getCostThisHour(), + ea->getProducedThisHour(), + ea->getUseToday(), + ea->getCostToday(), + ea->getProducedToday(), + ea->getUseThisMonth(), + ea->getCostThisMonth(), + ea->getProducedThisMonth() + ); + mqtt->publish(topic + "/realtime", json); + + return true; } bool HomeAssistantMqttHandler::publishTemperatures(AmsConfiguration* config, HwTools* hw) { @@ -187,10 +210,10 @@ bool HomeAssistantMqttHandler::publishPrices(EntsoeApi* eapi) { ts3hr, ts6hr ); - return mqtt->publish(topic + "/prices", json); + return mqtt->publish(topic + "/prices", json, true, 0); } -bool HomeAssistantMqttHandler::publishSystem(HwTools* hw) { +bool HomeAssistantMqttHandler::publishSystem(HwTools* hw, EntsoeApi* eapi, EnergyAccounting* ea) { if(topic.isEmpty() || !mqtt->connected()){ sequence = 0; return false; @@ -218,26 +241,42 @@ bool HomeAssistantMqttHandler::publishSystem(HwTools* hw) { String haUrl = "http://" + haUID + ".local/"; // Could this be necessary? haUID.replace("-", "_"); - for(int i=0;igetCurrency()); + } + if(strncmp(sensor.path, "peaks[", 6) == 0) { + if(peaks >= ea->getConfig()->hours) continue; + peaks++; + } snprintf_P(json, BufferSize, HADISCOVER_JSON, - FPSTR(HA_NAMES[i]), - topic.c_str(), FPSTR(HA_TOPICS[i]), - haUID.c_str(), FPSTR(HA_PARAMS[i]), - haUID.c_str(), FPSTR(HA_PARAMS[i]), - FPSTR(HA_UOM[i]), - FPSTR(HA_PARAMS[i]), - FPSTR(HA_DEVCL[i]), + FPSTR(sensor.name), + topic.c_str(), FPSTR(sensor.topic), + haUID.c_str(), uid.c_str(), + haUID.c_str(), uid.c_str(), + uom.c_str(), + FPSTR(sensor.path), + FPSTR(sensor.devcl), haUID.c_str(), haName.c_str(), haModel.c_str(), VERSION, haManuf.c_str(), haUrl.c_str(), - strlen_P(HA_STACL[i]) > 0 ? ", \"stat_cla\" :" : "", - strlen_P(HA_STACL[i]) > 0 ? (char *) FPSTR(HA_STACL[i]) : "" + strlen_P(sensor.stacl) > 0 ? ", \"stat_cla\" :" : "", + strlen_P(sensor.stacl) > 0 ? (char *) FPSTR(sensor.stacl) : "" ); - mqtt->publish(haTopic + haUID + "_" + FPSTR(HA_PARAMS[i]) + "/config", json, true, 0); + mqtt->publish(haTopic + haUID + "_" + uid.c_str() + "/config", json, true, 0); } + autodiscoverInit = true; } if(listType>0) sequence++; diff --git a/src/mqtt/HomeAssistantMqttHandler.h b/src/mqtt/HomeAssistantMqttHandler.h index d4b8f50e..05675eee 100644 --- a/src/mqtt/HomeAssistantMqttHandler.h +++ b/src/mqtt/HomeAssistantMqttHandler.h @@ -13,11 +13,9 @@ public: bool publish(AmsData* data, AmsData* previousState, EnergyAccounting* ea); bool publishTemperatures(AmsConfiguration*, HwTools*); bool publishPrices(EntsoeApi*); - bool publishSystem(HwTools*); + bool publishSystem(HwTools* hw, EntsoeApi* eapi, EnergyAccounting* ea); private: - static const uint8_t sensors = 17; - String haTopic = "homeassistant/sensor/"; String haName = "AMS reader"; diff --git a/src/mqtt/HomeAssistantStatic.h b/src/mqtt/HomeAssistantStatic.h index 5f5b5b26..d60361ab 100644 --- a/src/mqtt/HomeAssistantStatic.h +++ b/src/mqtt/HomeAssistantStatic.h @@ -3,12 +3,69 @@ #include "Arduino.h" -const char* HA_TOPICS[17] PROGMEM = {"/state", "/state", "/state", "/power", "/power", "/power", "/power", "/power", "/power", "/power", "/power", "/power", "/power", "/energy", "/energy", "/energy", "/energy"}; -const char* HA_NAMES[17] PROGMEM = {"Status", "Supply volt", "Temperature", "Active import", "Reactive import", "Active export", "Reactive export", "L1 current", "L2 current", "L3 current", - "L1 voltage", "L2 voltage", "L3 voltage", "Accumulated active import", "Accumulated active export", "Accumulated reactive import", "Accumulated reactive export"}; -const char* HA_PARAMS[17] PROGMEM = {"rssi", "vcc", "temp", "P", "Q", "PO", "QO", "I1", "I2", "I3", "U1", "U2", "U3", "tPI", "tPO", "tQI", "tQO"}; -const char* HA_UOM[17] PROGMEM = {"dBm", "V", "C", "W", "W", "W", "W", "A", "A", "A", "V", "V", "V", "kWh", "kWh", "kWh", "kWh"}; -const char* HA_DEVCL[17] PROGMEM = {"signal_strength", "voltage", "temperature", "power", "power", "power", "power", "current", "current", "current", "voltage", "voltage", "voltage", "energy", "energy", "energy", "energy"}; -const char* HA_STACL[17] PROGMEM = {"", "", "", "\"measurement\"", "\"measurement\"", "\"measurement\"", "\"measurement\"", "", "", "", "", "", "", "\"total_increasing\"", "\"total_increasing\"", "\"total_increasing\"", "\"total_increasing\""}; +struct HomeAssistantSensor { + char* name; + char* topic; + char* path; + char* uom; + char* devcl; + char* stacl; +}; + + +const uint8_t HA_SENSOR_COUNT PROGMEM = 50; +HomeAssistantSensor HA_SENSORS[HA_SENSOR_COUNT] PROGMEM = { + {"Status", "/state", "rssi", "dBm", "signal_strength", "\"measurement\""}, + {"Supply volt", "/state", "vcc", "V", "voltage", "\"measurement\""}, + {"Temperature", "/state", "temp", "C", "temperature", "\"measurement\""}, + {"Active import", "/power", "P", "W", "power", "\"measurement\""}, + {"Reactive import", "/power", "Q", "VAr", "reactive_power", "\"measurement\""}, + {"Active export", "/power", "PO", "W", "power", "\"measurement\""}, + {"Reactive export", "/power", "QO", "VAr", "reactive_power", "\"measurement\""}, + {"L1 current", "/power", "I1", "A", "current", "\"measurement\""}, + {"L2 current", "/power", "I2", "A", "current", "\"measurement\""}, + {"L3 current", "/power", "I3", "A", "current", "\"measurement\""}, + {"L1 voltage", "/power", "U1", "V", "voltage", "\"measurement\""}, + {"L2 voltage", "/power", "U2", "V", "voltage", "\"measurement\""}, + {"L3 voltage", "/power", "U3", "V", "voltage", "\"measurement\""}, + {"Accumulated active import", "/energy", "tPI", "kWh", "energy", "\"total_increasing\""}, + {"Accumulated active export", "/energy", "tPO", "kWh", "energy", "\"total_increasing\""}, + {"Accumulated reactive import","/energy", "tQI", "kVArh","energy", "\"total_increasing\""}, + {"Accumulated reactive export","/energy", "tQO", "kVArh","energy", "\"total_increasing\""}, + {"Price current hour", "/prices", "prices.0", "", "monetary", ""}, + {"Price next hour", "/prices", "prices.1", "", "monetary", ""}, + {"Price in two hour", "/prices", "prices.2", "", "monetary", ""}, + {"Price in three hour", "/prices", "prices.3", "", "monetary", ""}, + {"Price in four hour", "/prices", "prices.4", "", "monetary", ""}, + {"Price in five hour", "/prices", "prices.5", "", "monetary", ""}, + {"Price in six hour", "/prices", "prices.6", "", "monetary", ""}, + {"Price in seven hour", "/prices", "prices.7", "", "monetary", ""}, + {"Price in eight hour", "/prices", "prices.8", "", "monetary", ""}, + {"Price in nine hour", "/prices", "prices.9", "", "monetary", ""}, + {"Price in ten hour", "/prices", "prices.10", "", "monetary", ""}, + {"Price in eleven hour", "/prices", "prices.11", "", "monetary", ""}, + {"Minimum price ahead", "/prices", "prices.min", "", "monetary", ""}, + {"Maximum price ahead", "/prices", "prices.max", "", "monetary", ""}, + {"Cheapest 1hr period ahead", "/prices", "prices.cheapest1hr","", "timestamp", ""}, + {"Cheapest 3hr period ahead", "/prices", "prices.cheapest3hr","", "timestamp", ""}, + {"Cheapest 6hr period ahead", "/prices", "prices.cheapest6hr","", "timestamp", ""}, + {"Month max", "/realtime","max", "kWh", "energy", "\"total_increasing\""}, + {"Tariff threshold", "/realtime","threshold", "kWh", "energy", "\"total_increasing\""}, + {"Current hour used", "/realtime","hour.use", "kWh", "energy", "\"total_increasing\""}, + {"Current hour cost", "/realtime","hour.cost", "", "monetary", "\"total_increasing\""}, + {"Current hour produced", "/realtime","hour.produced", "kWh", "energy", "\"total_increasing\""}, + {"Current day used", "/realtime","day.use", "kWh", "energy", "\"total_increasing\""}, + {"Current day cost", "/realtime","day.cost", "", "monetary", "\"total_increasing\""}, + {"Current day produced", "/realtime","day.produced", "kWh", "energy", "\"total_increasing\""}, + {"Current month used", "/realtime","month.use", "kWh", "energy", "\"total_increasing\""}, + {"Current month cost", "/realtime","month.cost", "", "monetary", "\"total_increasing\""}, + {"Current month produced", "/realtime","month.produced", "kWh", "energy", "\"total_increasing\""}, + {"Current month peak 1", "/realtime","peaks[0]", "kWh", "energy", ""}, + {"Current month peak 2", "/realtime","peaks[1]", "kWh", "energy", ""}, + {"Current month peak 3", "/realtime","peaks[2]", "kWh", "energy", ""}, + {"Current month peak 4", "/realtime","peaks[3]", "kWh", "energy", ""}, + {"Current month peak 5", "/realtime","peaks[4]", "kWh", "energy", ""}, +}; + #endif diff --git a/src/mqtt/JsonMqttHandler.cpp b/src/mqtt/JsonMqttHandler.cpp index 132d8e32..6329b389 100644 --- a/src/mqtt/JsonMqttHandler.cpp +++ b/src/mqtt/JsonMqttHandler.cpp @@ -271,7 +271,7 @@ bool JsonMqttHandler::publishPrices(EntsoeApi* eapi) { return mqtt->publish(topic, json); } -bool JsonMqttHandler::publishSystem(HwTools* hw) { +bool JsonMqttHandler::publishSystem(HwTools* hw, EntsoeApi* eapi, EnergyAccounting* ea) { if(init || topic.isEmpty() || !mqtt->connected()) return false; diff --git a/src/mqtt/JsonMqttHandler.h b/src/mqtt/JsonMqttHandler.h index b799bbbe..db3e12bc 100644 --- a/src/mqtt/JsonMqttHandler.h +++ b/src/mqtt/JsonMqttHandler.h @@ -13,7 +13,7 @@ public: bool publish(AmsData* data, AmsData* previousState, EnergyAccounting* ea); bool publishTemperatures(AmsConfiguration*, HwTools*); bool publishPrices(EntsoeApi*); - bool publishSystem(HwTools*); + bool publishSystem(HwTools* hw, EntsoeApi* eapi, EnergyAccounting* ea); private: String clientId; diff --git a/src/mqtt/RawMqttHandler.cpp b/src/mqtt/RawMqttHandler.cpp index 48f48a3f..c6763ed3 100644 --- a/src/mqtt/RawMqttHandler.cpp +++ b/src/mqtt/RawMqttHandler.cpp @@ -211,7 +211,7 @@ bool RawMqttHandler::publishPrices(EntsoeApi* eapi) { return true; } -bool RawMqttHandler::publishSystem(HwTools* hw) { +bool RawMqttHandler::publishSystem(HwTools* hw, EntsoeApi* eapi, EnergyAccounting* ea) { if(topic.isEmpty() || !mqtt->connected()) return false; diff --git a/src/mqtt/RawMqttHandler.h b/src/mqtt/RawMqttHandler.h index 091103cb..737b72a3 100644 --- a/src/mqtt/RawMqttHandler.h +++ b/src/mqtt/RawMqttHandler.h @@ -12,7 +12,7 @@ public: bool publish(AmsData* data, AmsData* previousState, EnergyAccounting* ea); bool publishTemperatures(AmsConfiguration*, HwTools*); bool publishPrices(EntsoeApi*); - bool publishSystem(HwTools*); + bool publishSystem(HwTools* hw, EntsoeApi* eapi, EnergyAccounting* ea); private: String topic; diff --git a/web/realtime.json b/web/realtime.json new file mode 100644 index 00000000..06ca2d73 --- /dev/null +++ b/web/realtime.json @@ -0,0 +1,20 @@ +{ + "max" : %.1f, + "peaks" : [ %s ], + "threshold" : %d, + "hour" : { + "use" : %.2f, + "cost" : %.2f, + "produced" : %.2f + }, + "day" : { + "use" : %.2f, + "cost" : %.2f, + "produced" : %.2f + }, + "month" : { + "use" : %.2f, + "cost" : %.2f, + "produced" : %.2f + } +} \ No newline at end of file From 57e6d0fbe3d89fc1ea6c7d41cbdfc96b301e3a45 Mon Sep 17 00:00:00 2001 From: Gunnar Skjold Date: Fri, 30 Sep 2022 19:18:23 +0200 Subject: [PATCH 11/31] Modifications to make price sensors work in HA --- src/mqtt/HomeAssistantMqttHandler.cpp | 1 + src/mqtt/HomeAssistantStatic.h | 24 ++++++++++++------------ 2 files changed, 13 insertions(+), 12 deletions(-) diff --git a/src/mqtt/HomeAssistantMqttHandler.cpp b/src/mqtt/HomeAssistantMqttHandler.cpp index 544ece33..64d7f6d8 100644 --- a/src/mqtt/HomeAssistantMqttHandler.cpp +++ b/src/mqtt/HomeAssistantMqttHandler.cpp @@ -248,6 +248,7 @@ bool HomeAssistantMqttHandler::publishSystem(HwTools* hw, EntsoeApi* eapi, Energ uid.replace(".", ""); uid.replace("[", ""); uid.replace("]", ""); + uid.replace("'", ""); String uom = String(sensor.uom); if(strncmp(sensor.devcl, "monetary", 8) == 0) { if(eapi == NULL) continue; diff --git a/src/mqtt/HomeAssistantStatic.h b/src/mqtt/HomeAssistantStatic.h index d60361ab..7428959a 100644 --- a/src/mqtt/HomeAssistantStatic.h +++ b/src/mqtt/HomeAssistantStatic.h @@ -32,18 +32,18 @@ HomeAssistantSensor HA_SENSORS[HA_SENSOR_COUNT] PROGMEM = { {"Accumulated active export", "/energy", "tPO", "kWh", "energy", "\"total_increasing\""}, {"Accumulated reactive import","/energy", "tQI", "kVArh","energy", "\"total_increasing\""}, {"Accumulated reactive export","/energy", "tQO", "kVArh","energy", "\"total_increasing\""}, - {"Price current hour", "/prices", "prices.0", "", "monetary", ""}, - {"Price next hour", "/prices", "prices.1", "", "monetary", ""}, - {"Price in two hour", "/prices", "prices.2", "", "monetary", ""}, - {"Price in three hour", "/prices", "prices.3", "", "monetary", ""}, - {"Price in four hour", "/prices", "prices.4", "", "monetary", ""}, - {"Price in five hour", "/prices", "prices.5", "", "monetary", ""}, - {"Price in six hour", "/prices", "prices.6", "", "monetary", ""}, - {"Price in seven hour", "/prices", "prices.7", "", "monetary", ""}, - {"Price in eight hour", "/prices", "prices.8", "", "monetary", ""}, - {"Price in nine hour", "/prices", "prices.9", "", "monetary", ""}, - {"Price in ten hour", "/prices", "prices.10", "", "monetary", ""}, - {"Price in eleven hour", "/prices", "prices.11", "", "monetary", ""}, + {"Price current hour", "/prices", "prices['0']", "", "monetary", ""}, + {"Price next hour", "/prices", "prices['1']", "", "monetary", ""}, + {"Price in two hour", "/prices", "prices['2']", "", "monetary", ""}, + {"Price in three hour", "/prices", "prices['3']", "", "monetary", ""}, + {"Price in four hour", "/prices", "prices['4']", "", "monetary", ""}, + {"Price in five hour", "/prices", "prices['5']", "", "monetary", ""}, + {"Price in six hour", "/prices", "prices['6']", "", "monetary", ""}, + {"Price in seven hour", "/prices", "prices['7']", "", "monetary", ""}, + {"Price in eight hour", "/prices", "prices['8']", "", "monetary", ""}, + {"Price in nine hour", "/prices", "prices['9']", "", "monetary", ""}, + {"Price in ten hour", "/prices", "prices['10']", "", "monetary", ""}, + {"Price in eleven hour", "/prices", "prices['11']", "", "monetary", ""}, {"Minimum price ahead", "/prices", "prices.min", "", "monetary", ""}, {"Maximum price ahead", "/prices", "prices.max", "", "monetary", ""}, {"Cheapest 1hr period ahead", "/prices", "prices.cheapest1hr","", "timestamp", ""}, From 2f0c9123886eabcf29ce5d35017b5d829913cc32 Mon Sep 17 00:00:00 2001 From: Gunnar Skjold Date: Sat, 1 Oct 2022 09:22:09 +0200 Subject: [PATCH 12/31] Exclude decimals in BUILD_EPOCH flag --- scripts/addversion.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/scripts/addversion.py b/scripts/addversion.py index 47fc1d48..c2295ea4 100644 --- a/scripts/addversion.py +++ b/scripts/addversion.py @@ -19,6 +19,6 @@ hf = """ #define VERSION "{}" #endif #define BUILD_EPOCH {} -""".format(version, time()) +""".format(version, round(time())) with open(FILENAME_VERSION_H, 'w+') as f: f.write(hf) From 7d557b2679bcdb5479b381249f03283104715efe Mon Sep 17 00:00:00 2001 From: Gunnar Skjold Date: Sat, 1 Oct 2022 09:24:07 +0200 Subject: [PATCH 13/31] Only show new version when actually new in firmware page. Also be more specific on USB power in upgrade warning --- web/application.js | 14 ++++++++++---- web/firmware.html | 2 +- 2 files changed, 11 insertions(+), 5 deletions(-) diff --git a/web/application.js b/web/application.js index 04d603d6..228bf19a 100644 --- a/web/application.js +++ b/web/application.js @@ -316,6 +316,7 @@ $(function() { url: swv.data('url'), dataType: 'json' }).done(function(releases) { + var isnew = false; if(/^v\d{1,2}\.\d{1,2}\.\d{1,2}$/.test(swv.text()) && fwl.length == 0) { releases.reverse(); var next_patch; @@ -352,10 +353,13 @@ $(function() { }); if(next_minor) { nextVersion = next_minor; + isnew = true; } else if(next_major) { nextVersion = next_major; + isnew = true; } else if(next_patch) { nextVersion = next_patch; + isnew = true; } } else { nextVersion = releases[0]; @@ -375,9 +379,11 @@ $(function() { } }); }; - $('#newVersionTag').text(nextVersion.tag_name); - $('#newVersionUrl').prop('href', nextVersion.html_url); - $('#newVersion').removeClass('d-none'); + if(isnew) { + $('#newVersionTag').text(nextVersion.tag_name); + $('#newVersionUrl').prop('href', nextVersion.html_url); + $('#newVersion').removeClass('d-none'); + } } }); } @@ -884,7 +890,7 @@ var fetch = function() { var upgrade = function() { if(nextVersion) { - if(confirm("WARNING: Please keep USB power connected while upgrading. Are you sure you want to perform upgrade to " + nextVersion.tag_name + "?")) { + if(confirm("WARNING: If you have a BUS powered device (Pow-U), please keep USB power connected while upgrading.\n\nAre you sure you want to perform upgrade to " + nextVersion.tag_name + "?")) { $('#loading-indicator').show(); window.location.href="/upgrade?version=" + nextVersion.tag_name; } diff --git a/web/firmware.html b/web/firmware.html index 0ed23db2..b7c99222 100644 --- a/web/firmware.html +++ b/web/firmware.html @@ -1,5 +1,5 @@
- WARNING: Units powered over M-bus must be connected to an external power supply during firmware upload. Failure to do so may cause power-down during upload resulting in non-functioning unit. + WARNING: Units powered by BUS (Pow-U) must be connected to an external power supply during firmware upload. Failure to do so may cause power-down during upload resulting in non-functioning unit.
Your board is using {chipset} chipset. Only upload firmware designed for this chipset. Failure to do so may result in non-functioning unit. From 8ca771fa5a5e46fe001e4cd02dcb7ecf40d92555 Mon Sep 17 00:00:00 2001 From: Gunnar Skjold Date: Sat, 1 Oct 2022 09:25:56 +0200 Subject: [PATCH 14/31] Changed "BUS" to "M-BUS" --- web/application.js | 2 +- web/firmware.html | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/web/application.js b/web/application.js index 228bf19a..152bc726 100644 --- a/web/application.js +++ b/web/application.js @@ -890,7 +890,7 @@ var fetch = function() { var upgrade = function() { if(nextVersion) { - if(confirm("WARNING: If you have a BUS powered device (Pow-U), please keep USB power connected while upgrading.\n\nAre you sure you want to perform upgrade to " + nextVersion.tag_name + "?")) { + if(confirm("WARNING: If you have a M-BUS powered device (Pow-U), please keep USB power connected while upgrading.\n\nAre you sure you want to perform upgrade to " + nextVersion.tag_name + "?")) { $('#loading-indicator').show(); window.location.href="/upgrade?version=" + nextVersion.tag_name; } diff --git a/web/firmware.html b/web/firmware.html index b7c99222..3ae1fd88 100644 --- a/web/firmware.html +++ b/web/firmware.html @@ -1,5 +1,5 @@
- WARNING: Units powered by BUS (Pow-U) must be connected to an external power supply during firmware upload. Failure to do so may cause power-down during upload resulting in non-functioning unit. + WARNING: Units powered by M-BUS (Pow-U) must be connected to an external power supply during firmware upload. Failure to do so may cause power-down during upload resulting in non-functioning unit.
Your board is using {chipset} chipset. Only upload firmware designed for this chipset. Failure to do so may result in non-functioning unit. From d50181c3478823ec3f17911a8631e8f2d979953e Mon Sep 17 00:00:00 2001 From: Gunnar Skjold Date: Sat, 1 Oct 2022 11:43:42 +0200 Subject: [PATCH 15/31] Upgrade with custom URL --- src/web/AmsWebServer.cpp | 35 ++++++++++++++++++++++++++++++++--- src/web/AmsWebServer.h | 2 ++ web/firmware.html | 24 ++++++++++++++++++++---- 3 files changed, 54 insertions(+), 7 deletions(-) diff --git a/src/web/AmsWebServer.cpp b/src/web/AmsWebServer.cpp index b551eaf9..855ae6cf 100644 --- a/src/web/AmsWebServer.cpp +++ b/src/web/AmsWebServer.cpp @@ -90,7 +90,7 @@ void AmsWebServer::setup(AmsConfiguration* config, GpioConfig* gpioConfig, Meter server.on("/debugging", HTTP_GET, std::bind(&AmsWebServer::configDebugHtml, this)); server.on("/firmware", HTTP_GET, std::bind(&AmsWebServer::firmwareHtml, this)); - server.on("/firmware", HTTP_POST, std::bind(&AmsWebServer::uploadPost, this), std::bind(&AmsWebServer::firmwareUpload, this)); + server.on("/firmware", HTTP_POST, std::bind(&AmsWebServer::firmwarePost, this), std::bind(&AmsWebServer::firmwareUpload, this)); server.on("/upgrade", HTTP_GET, std::bind(&AmsWebServer::firmwareDownload, this)); server.on("/restart", HTTP_GET, std::bind(&AmsWebServer::restartHtml, this)); server.on("/restart", HTTP_POST, std::bind(&AmsWebServer::restartPost, this)); @@ -1663,13 +1663,40 @@ void AmsWebServer::firmwareHtml() { server.sendContent_P(FOOT_HTML); } +void AmsWebServer::firmwarePost() { + printD("Handlling firmware post..."); + if(!checkSecurity(1)) + return; + + if(rebootForUpgrade) { + server.send(200); + } else { + if(server.hasArg("url")) { + String url = server.arg("url"); + if(!url.isEmpty() && (url.startsWith("http://") || url.startsWith("https://"))) { + printD("Custom firmware URL was provided"); + customFirmwareUrl = url; + performUpgrade = true; + server.sendHeader("Location","/restart-wait"); + server.send(303); + return; + } + } + server.sendHeader("Location","/firmware"); + server.send(303); + } +} + void AmsWebServer::firmwareUpload() { + printD("Handlling firmware upload..."); if(!checkSecurity(1)) return; HTTPUpload& upload = server.upload(); + String filename = upload.filename; + if(filename.isEmpty()) return; + if(upload.status == UPLOAD_FILE_START) { - String filename = upload.filename; if(!filename.endsWith(".bin")) { server.send(500, MIME_PLAIN, "500: couldn't create file"); } else { @@ -1778,7 +1805,7 @@ void AmsWebServer::restartWaitHtml() { performRestart = false; } else if(performUpgrade) { WiFiClient client; - String url = "http://ams2mqtt.rewiredinvent.no/hub/firmware/update"; + String url = customFirmwareUrl.isEmpty() || !customFirmwareUrl.startsWith("http") ? "http://ams2mqtt.rewiredinvent.no/hub/firmware/update" : customFirmwareUrl; #if defined(ESP8266) String chipType = "esp8266"; #elif defined(CONFIG_IDF_TARGET_ESP32S2) @@ -1792,9 +1819,11 @@ void AmsWebServer::restartWaitHtml() { #endif #if defined(ESP8266) + ESPhttpUpdate.setFollowRedirects(HTTPC_STRICT_FOLLOW_REDIRECTS); t_httpUpdate_return ret = ESPhttpUpdate.update(client, url, VERSION); #elif defined(ESP32) HTTPUpdate httpUpdate; + httpUpdate.setFollowRedirects(HTTPC_STRICT_FOLLOW_REDIRECTS); HTTPUpdateResult ret = httpUpdate.update(client, url, String(VERSION) + "-" + chipType); #endif diff --git a/src/web/AmsWebServer.h b/src/web/AmsWebServer.h index 0a0ac6b3..f2fbbe7c 100644 --- a/src/web/AmsWebServer.h +++ b/src/web/AmsWebServer.h @@ -61,6 +61,7 @@ private: bool performRestart = false; bool performUpgrade = false; bool rebootForUpgrade = false; + String customFirmwareUrl; static const uint16_t BufferSize = 2048; char* buf; @@ -104,6 +105,7 @@ private: String getSerialSelectOptions(int selected); void firmwareHtml(); + void firmwarePost(); void firmwareUpload(); void firmwareDownload(); void restartHtml(); diff --git a/web/firmware.html b/web/firmware.html index 3ae1fd88..0bdbf086 100644 --- a/web/firmware.html +++ b/web/firmware.html @@ -5,14 +5,17 @@ Your board is using {chipset} chipset. Only upload firmware designed for this chipset. Failure to do so may result in non-functioning unit.
+
+ When using URL, only a valid ESP OTA server response will be accepted. +
-
+
- Upload + Upload file
@@ -21,6 +24,19 @@
+
+
or
+
+
+
+
+
+ Use URL +
+ +
+
+

@@ -28,7 +44,7 @@ Back
- +
- + \ No newline at end of file From fe7be81f1e0b25485afb238b20cf8cc5e2b13035 Mon Sep 17 00:00:00 2001 From: Gunnar Skjold Date: Sat, 1 Oct 2022 12:11:46 +0200 Subject: [PATCH 16/31] Rudimentary detection for L&G data. Probably change this in the future --- src/AmsToMqttBridge.ino | 17 +++++++++++------ 1 file changed, 11 insertions(+), 6 deletions(-) diff --git a/src/AmsToMqttBridge.ino b/src/AmsToMqttBridge.ino index fbc706fe..20ee5ee5 100644 --- a/src/AmsToMqttBridge.ino +++ b/src/AmsToMqttBridge.ino @@ -850,21 +850,26 @@ bool readHanPort() { } AmsData data; + char* payload = ((char *) (hanBuffer)) + pos; if(ctx.type == DATA_TAG_DLMS) { // If MQTT bytestream payload is selected (mqttHandler == NULL), send the payload to MQTT if(mqttEnabled && mqtt != NULL && mqttHandler == NULL) { - mqtt->publish(topic.c_str(), toHex(hanBuffer+pos, ctx.length)); + mqtt->publish(topic.c_str(), toHex((byte*) payload, ctx.length)); mqtt->loop(); } debugV("Using application data:"); - if(Debug.isActive(RemoteDebug::VERBOSE)) debugPrint(hanBuffer+pos, 0, ctx.length); + if(Debug.isActive(RemoteDebug::VERBOSE)) debugPrint((byte*) payload, 0, ctx.length); - // TODO: Split IEC6205675 into DataParserKaifa and DataParserObis. This way we can add other means of parsing, for those other proprietary formats - //data = IEC6205675(((char *) (hanBuffer)) + pos, meterState.getMeterType(), &meterConfig, ctx); - data = LNG(((char *) (hanBuffer)) + pos, meterState.getMeterType(), &meterConfig, ctx, &Debug); + // Rudimentary detector for L&G proprietary format + if(payload[0] == CosemTypeStructure && payload[2] == CosemTypeArray && payload[1] == payload[3]) { + data = LNG(payload, meterState.getMeterType(), &meterConfig, ctx, &Debug); + } else { + // TODO: Split IEC6205675 into DataParserKaifa and DataParserObis. This way we can add other means of parsing, for those other proprietary formats + data = IEC6205675(payload, meterState.getMeterType(), &meterConfig, ctx); + } } else if(ctx.type == DATA_TAG_DSMR) { - data = IEC6205621(((char *) (hanBuffer)) + pos); + data = IEC6205621(payload); } len = 0; From ad78ff308214af451a17f065624d86328a2f9377 Mon Sep 17 00:00:00 2001 From: Thomas Barnekov Date: Wed, 5 Oct 2022 21:59:30 +0200 Subject: [PATCH 17/31] Fix implicit cast and non-const char pointer warnings --- src/AmsToMqttBridge.ino | 2 +- src/mqtt/HomeAssistantStatic.h | 12 ++++++------ src/web/AmsWebServer.cpp | 16 ++++++++-------- 3 files changed, 15 insertions(+), 15 deletions(-) diff --git a/src/AmsToMqttBridge.ino b/src/AmsToMqttBridge.ino index 20ee5ee5..23e7b52b 100644 --- a/src/AmsToMqttBridge.ino +++ b/src/AmsToMqttBridge.ino @@ -1122,7 +1122,7 @@ void WiFi_connect() { void mqttMessageReceived(String &topic, String &payload) { debugI("Received message for topic %s", topic.c_str() ); if(meterConfig.source == METER_SOURCE_MQTT) { - DataParserContext ctx = {payload.length()/2}; + DataParserContext ctx = {static_cast(payload.length()/2)}; fromHex(hanBuffer, payload, ctx.length); uint16_t pos = unwrapData(hanBuffer, ctx); // TODO: Run through DLMS/DMSR parser and apply AmsData diff --git a/src/mqtt/HomeAssistantStatic.h b/src/mqtt/HomeAssistantStatic.h index 7428959a..4aa2b286 100644 --- a/src/mqtt/HomeAssistantStatic.h +++ b/src/mqtt/HomeAssistantStatic.h @@ -4,12 +4,12 @@ #include "Arduino.h" struct HomeAssistantSensor { - char* name; - char* topic; - char* path; - char* uom; - char* devcl; - char* stacl; + const char* name; + const char* topic; + const char* path; + const char* uom; + const char* devcl; + const char* stacl; }; diff --git a/src/web/AmsWebServer.cpp b/src/web/AmsWebServer.cpp index fa510cbc..4e3e1688 100644 --- a/src/web/AmsWebServer.cpp +++ b/src/web/AmsWebServer.cpp @@ -1007,7 +1007,7 @@ void AmsWebServer::handleSetup() { server.sendHeader("Location", String("/"), true); server.send (302, MIME_PLAIN, ""); } else { - SystemConfig sys { server.arg("board").toInt() }; + SystemConfig sys { static_cast(server.arg("board").toInt()) }; DebugConfig debugConfig; config->getDebugConfig(debugConfig); @@ -1277,11 +1277,11 @@ void AmsWebServer::handleSave() { if(server.hasArg("dc") && server.arg("dc") == "true") { printD("Received Domoticz config"); DomoticzConfig domo { - server.arg("elidx").toInt(), - server.arg("vl1idx").toInt(), - server.arg("vl2idx").toInt(), - server.arg("vl3idx").toInt(), - server.arg("cl1idx").toInt() + static_cast(server.arg("elidx").toInt()), + static_cast(server.arg("vl1idx").toInt()), + static_cast(server.arg("vl2idx").toInt()), + static_cast(server.arg("vl3idx").toInt()), + static_cast(server.arg("cl1idx").toInt()) }; config->setDomoticzConfig(domo); } @@ -1358,8 +1358,8 @@ void AmsWebServer::handleSave() { NtpConfig ntp { server.hasArg("n") && server.arg("n") == "true", server.hasArg("nd") && server.arg("nd") == "true", - server.arg("o").toInt() / 10, - server.arg("so").toInt() / 10 + static_cast(server.arg("o").toInt() / 10), + static_cast(server.arg("so").toInt() / 10) }; strcpy(ntp.server, server.arg("ns").c_str()); config->setNtpConfig(ntp); From 7cd52d5689cda98b1ec57c91a775d94eae7301cf Mon Sep 17 00:00:00 2001 From: Thomas Barnekov Date: Wed, 5 Oct 2022 23:53:40 +0200 Subject: [PATCH 18/31] Add individual power reading for all phases (include in HA) --- src/AmsData.cpp | 30 +++++++++++++++++++++++++ src/AmsData.h | 10 +++++++++ src/IEC6205675.cpp | 32 +++++++++++++++++++++++++++ src/IEC6205675.h | 6 +++++ src/mqtt/HomeAssistantMqttHandler.cpp | 6 +++++ src/mqtt/HomeAssistantStatic.h | 12 +++++++++- src/mqtt/JsonMqttHandler.cpp | 6 +++++ src/mqtt/RawMqttHandler.cpp | 18 +++++++++++++++ web/ha3.json | 6 +++++ web/json4.json | 6 +++++ 10 files changed, 131 insertions(+), 1 deletion(-) diff --git a/src/AmsData.cpp b/src/AmsData.cpp index f3db56e8..e6d536bf 100644 --- a/src/AmsData.cpp +++ b/src/AmsData.cpp @@ -45,6 +45,12 @@ void AmsData::apply(AmsData& other) { this->l1PowerFactor = other.getL1PowerFactor(); this->l2PowerFactor = other.getL2PowerFactor(); this->l3PowerFactor = other.getL3PowerFactor(); + this->l1activeImportPower = other.getL1ActiveImportPower(); + this->l2activeImportPower = other.getL2ActiveImportPower(); + this->l3activeImportPower = other.getL3ActiveImportPower(); + this->l1activeExportPower = other.getL1ActiveExportPower(); + this->l2activeExportPower = other.getL2ActiveExportPower(); + this->l3activeExportPower = other.getL3ActiveExportPower(); case 3: this->meterTimestamp = other.getMeterTimestamp(); this->activeImportCounter = other.getActiveImportCounter(); @@ -161,6 +167,30 @@ float AmsData::getL3PowerFactor() { return this->l3PowerFactor; } +float AmsData::getL1ActiveImportPower() { + return this->l1activeImportPower; +} + +float AmsData::getL2ActiveImportPower() { + return this->l2activeImportPower; +} + +float AmsData::getL3ActiveImportPower() { + return this->l3activeImportPower; +} + +float AmsData::getL1ActiveExportPower() { + return this->l1activeExportPower; +} + +float AmsData::getL2ActiveExportPower() { + return this->l2activeExportPower; +} + +float AmsData::getL3ActiveExportPower() { + return this->l3activeExportPower; +} + double AmsData::getActiveImportCounter() { return this->activeImportCounter; } diff --git a/src/AmsData.h b/src/AmsData.h index 21d29827..9445472a 100644 --- a/src/AmsData.h +++ b/src/AmsData.h @@ -54,6 +54,14 @@ public: float getL2PowerFactor(); float getL3PowerFactor(); + float getL1ActiveImportPower(); + float getL2ActiveImportPower(); + float getL3ActiveImportPower(); + + float getL1ActiveExportPower(); + float getL2ActiveExportPower(); + float getL3ActiveExportPower(); + double getActiveImportCounter(); double getReactiveImportCounter(); double getActiveExportCounter(); @@ -71,6 +79,8 @@ protected: time_t meterTimestamp = 0; uint16_t activeImportPower = 0, reactiveImportPower = 0, activeExportPower = 0, reactiveExportPower = 0; float l1voltage = 0, l2voltage = 0, l3voltage = 0, l1current = 0, l2current = 0, l3current = 0; + float l1activeImportPower = 0, l2activeImportPower = 0, l3activeImportPower = 0; + float l1activeExportPower = 0, l2activeExportPower = 0, l3activeExportPower = 0; float powerFactor = 0, l1PowerFactor = 0, l2PowerFactor = 0, l3PowerFactor = 0; double activeImportCounter = 0, reactiveImportCounter = 0, activeExportCounter = 0, reactiveExportCounter = 0; bool threePhase = false, twoPhase = false, counterEstimated = false; diff --git a/src/IEC6205675.cpp b/src/IEC6205675.cpp index 8ebe54f8..10ebda8f 100644 --- a/src/IEC6205675.cpp +++ b/src/IEC6205675.cpp @@ -296,6 +296,38 @@ IEC6205675::IEC6205675(const char* d, uint8_t useMeterType, MeterConfig* meterCo l3PowerFactor = val; } + val = getNumber(AMS_OBIS_ACTIVE_IMPORT_L1, sizeof(AMS_OBIS_ACTIVE_IMPORT_L1), ((char *) (d))); + if (val != NOVALUE) { + listType = 4; + l1activeImportPower = val; + } + val = getNumber(AMS_OBIS_ACTIVE_IMPORT_L2, sizeof(AMS_OBIS_ACTIVE_IMPORT_L2), ((char *) (d))); + if (val != NOVALUE) { + listType = 4; + l2activeImportPower = val; + } + val = getNumber(AMS_OBIS_ACTIVE_IMPORT_L3, sizeof(AMS_OBIS_ACTIVE_IMPORT_L3), ((char *) (d))); + if (val != NOVALUE) { + listType = 4; + l3activeImportPower = val; + } + + val = getNumber(AMS_OBIS_ACTIVE_EXPORT_L1, sizeof(AMS_OBIS_ACTIVE_EXPORT_L1), ((char *) (d))); + if (val != NOVALUE) { + listType = 4; + l1activeExportPower = val; + } + val = getNumber(AMS_OBIS_ACTIVE_EXPORT_L2, sizeof(AMS_OBIS_ACTIVE_EXPORT_L2), ((char *) (d))); + if (val != NOVALUE) { + listType = 4; + l2activeExportPower = val; + } + val = getNumber(AMS_OBIS_ACTIVE_EXPORT_L3, sizeof(AMS_OBIS_ACTIVE_EXPORT_L3), ((char *) (d))); + if (val != NOVALUE) { + listType = 4; + l3activeExportPower = val; + } + if(meterType == AmsTypeKamstrup) { if(listType >= 3) { activeImportCounter *= 10; diff --git a/src/IEC6205675.h b/src/IEC6205675.h index 3fb3df29..75cf0134 100644 --- a/src/IEC6205675.h +++ b/src/IEC6205675.h @@ -49,6 +49,12 @@ private: uint8_t AMS_OBIS_POWER_FACTOR_L1[4] = { 33, 7, 0, 255 }; uint8_t AMS_OBIS_POWER_FACTOR_L2[4] = { 53, 7, 0, 255 }; uint8_t AMS_OBIS_POWER_FACTOR_L3[4] = { 73, 7, 0, 255 }; + uint8_t AMS_OBIS_ACTIVE_IMPORT_L1[4] = { 21, 7, 0, 255 }; + uint8_t AMS_OBIS_ACTIVE_IMPORT_L2[4] = { 41, 7, 0, 255 }; + uint8_t AMS_OBIS_ACTIVE_IMPORT_L3[4] = { 61, 7, 0, 255 }; + uint8_t AMS_OBIS_ACTIVE_EXPORT_L1[4] = { 22, 7, 0, 255 }; + uint8_t AMS_OBIS_ACTIVE_EXPORT_L2[4] = { 42, 7, 0, 255 }; + uint8_t AMS_OBIS_ACTIVE_EXPORT_L3[4] = { 62, 7, 0, 255 }; }; #endif diff --git a/src/mqtt/HomeAssistantMqttHandler.cpp b/src/mqtt/HomeAssistantMqttHandler.cpp index 64d7f6d8..6794946b 100644 --- a/src/mqtt/HomeAssistantMqttHandler.cpp +++ b/src/mqtt/HomeAssistantMqttHandler.cpp @@ -40,8 +40,14 @@ bool HomeAssistantMqttHandler::publish(AmsData* data, AmsData* previousState, En data->getMeterId().c_str(), meterModel.c_str(), data->getActiveImportPower(), + data->getL1ActiveImportPower(), + data->getL2ActiveImportPower(), + data->getL3ActiveImportPower(), data->getReactiveImportPower(), data->getActiveExportPower(), + data->getL1ActiveExportPower(), + data->getL2ActiveExportPower(), + data->getL3ActiveExportPower(), data->getReactiveExportPower(), data->getL1Current(), data->getL2Current(), diff --git a/src/mqtt/HomeAssistantStatic.h b/src/mqtt/HomeAssistantStatic.h index 4aa2b286..8f781d6f 100644 --- a/src/mqtt/HomeAssistantStatic.h +++ b/src/mqtt/HomeAssistantStatic.h @@ -13,14 +13,20 @@ struct HomeAssistantSensor { }; -const uint8_t HA_SENSOR_COUNT PROGMEM = 50; +const uint8_t HA_SENSOR_COUNT PROGMEM = 60; HomeAssistantSensor HA_SENSORS[HA_SENSOR_COUNT] PROGMEM = { {"Status", "/state", "rssi", "dBm", "signal_strength", "\"measurement\""}, {"Supply volt", "/state", "vcc", "V", "voltage", "\"measurement\""}, {"Temperature", "/state", "temp", "C", "temperature", "\"measurement\""}, {"Active import", "/power", "P", "W", "power", "\"measurement\""}, + {"L1 active import", "/power", "P1", "W", "power", "\"measurement\""}, + {"L2 active import", "/power", "P2", "W", "power", "\"measurement\""}, + {"L3 active import", "/power", "P3", "W", "power", "\"measurement\""}, {"Reactive import", "/power", "Q", "VAr", "reactive_power", "\"measurement\""}, {"Active export", "/power", "PO", "W", "power", "\"measurement\""}, + {"L1 active export", "/power", "PO1", "W", "power", "\"measurement\""}, + {"L2 active export", "/power", "PO2", "W", "power", "\"measurement\""}, + {"L3 active export", "/power", "PO3", "W", "power", "\"measurement\""}, {"Reactive export", "/power", "QO", "VAr", "reactive_power", "\"measurement\""}, {"L1 current", "/power", "I1", "A", "current", "\"measurement\""}, {"L2 current", "/power", "I2", "A", "current", "\"measurement\""}, @@ -32,6 +38,10 @@ HomeAssistantSensor HA_SENSORS[HA_SENSOR_COUNT] PROGMEM = { {"Accumulated active export", "/energy", "tPO", "kWh", "energy", "\"total_increasing\""}, {"Accumulated reactive import","/energy", "tQI", "kVArh","energy", "\"total_increasing\""}, {"Accumulated reactive export","/energy", "tQO", "kVArh","energy", "\"total_increasing\""}, + {"Power factor", "/power", "PF", "", "power_factor", "\"measurement\""}, + {"L1 power factor", "/power", "PF1", "", "power_factor", "\"measurement\""}, + {"L2 power factor", "/power", "PF2", "", "power_factor", "\"measurement\""}, + {"L3 power factor", "/power", "PF3", "", "power_factor", "\"measurement\""}, {"Price current hour", "/prices", "prices['0']", "", "monetary", ""}, {"Price next hour", "/prices", "prices['1']", "", "monetary", ""}, {"Price in two hour", "/prices", "prices['2']", "", "monetary", ""}, diff --git a/src/mqtt/JsonMqttHandler.cpp b/src/mqtt/JsonMqttHandler.cpp index 6329b389..1b406c93 100644 --- a/src/mqtt/JsonMqttHandler.cpp +++ b/src/mqtt/JsonMqttHandler.cpp @@ -111,8 +111,14 @@ bool JsonMqttHandler::publish(AmsData* data, AmsData* previousState, EnergyAccou data->getMeterId().c_str(), meterModel.c_str(), data->getActiveImportPower(), + data->getL1ActiveImportPower(), + data->getL2ActiveImportPower(), + data->getL3ActiveImportPower(), data->getReactiveImportPower(), data->getActiveExportPower(), + data->getL1ActiveExportPower(), + data->getL2ActiveExportPower(), + data->getL3ActiveExportPower(), data->getReactiveExportPower(), data->getL1Current(), data->getL2Current(), diff --git a/src/mqtt/RawMqttHandler.cpp b/src/mqtt/RawMqttHandler.cpp index c6763ed3..f2b681b4 100644 --- a/src/mqtt/RawMqttHandler.cpp +++ b/src/mqtt/RawMqttHandler.cpp @@ -11,6 +11,24 @@ bool RawMqttHandler::publish(AmsData* data, AmsData* meterState, EnergyAccountin } switch(data->getListType()) { case 4: + if(full || meterState->getL1ActiveImportPower() != data->getL1ActiveImportPower()) { + mqtt->publish(topic + "/meter/import/l1", String(data->getL1ActiveImportPower(), 2)); + } + if(full || meterState->getL2ActiveImportPower() != data->getL2ActiveImportPower()) { + mqtt->publish(topic + "/meter/import/l2", String(data->getL2ActiveImportPower(), 2)); + } + if(full || meterState->getL3ActiveImportPower() != data->getL3ActiveImportPower()) { + mqtt->publish(topic + "/meter/import/l3", String(data->getL3ActiveImportPower(), 2)); + } + if(full || meterState->getL1ActiveExportPower() != data->getL1ActiveExportPower()) { + mqtt->publish(topic + "/meter/export/l1", String(data->getL1ActiveExportPower(), 2)); + } + if(full || meterState->getL2ActiveExportPower() != data->getL2ActiveExportPower()) { + mqtt->publish(topic + "/meter/export/l2", String(data->getL2ActiveExportPower(), 2)); + } + if(full || meterState->getL3ActiveExportPower() != data->getL3ActiveExportPower()) { + mqtt->publish(topic + "/meter/export/l3", String(data->getL3ActiveExportPower(), 2)); + } if(full || meterState->getPowerFactor() != data->getPowerFactor()) { mqtt->publish(topic + "/meter/powerfactor", String(data->getPowerFactor(), 2)); } diff --git a/web/ha3.json b/web/ha3.json index 41fad56b..faee4724 100644 --- a/web/ha3.json +++ b/web/ha3.json @@ -3,8 +3,14 @@ "id" : "%s", "type" : "%s", "P" : %d, + "P1" : %.2f, + "P2" : %.2f, + "P3" : %.2f, "Q" : %d, "PO" : %d, + "PO1" : %.2f, + "PO2" : %.2f, + "PO3" : %.2f, "QO" : %d, "I1" : %.2f, "I2" : %.2f, diff --git a/web/json4.json b/web/json4.json index 701c06f4..cb61fb90 100644 --- a/web/json4.json +++ b/web/json4.json @@ -11,8 +11,14 @@ "id" : "%s", "type" : "%s", "P" : %d, + "P1" : %.2f, + "P2" : %.2f, + "P3" : %.2f, "Q" : %d, "PO" : %d, + "PO1" : %.2f, + "PO2" : %.2f, + "PO3" : %.2f, "QO" : %d, "I1" : %.2f, "I2" : %.2f, From b420a0e6f4d3dabeb6071c2e3fbc2d595a0cd4b9 Mon Sep 17 00:00:00 2001 From: Gunnar Skjold Date: Thu, 6 Oct 2022 17:12:12 +0200 Subject: [PATCH 19/31] Limit peak count if over 5 --- src/mqtt/HomeAssistantMqttHandler.cpp | 8 ++++++-- 1 file changed, 6 insertions(+), 2 deletions(-) diff --git a/src/mqtt/HomeAssistantMqttHandler.cpp b/src/mqtt/HomeAssistantMqttHandler.cpp index 64d7f6d8..9a563664 100644 --- a/src/mqtt/HomeAssistantMqttHandler.cpp +++ b/src/mqtt/HomeAssistantMqttHandler.cpp @@ -58,7 +58,9 @@ bool HomeAssistantMqttHandler::publish(AmsData* data, AmsData* previousState, En } String peaks = ""; - for(uint8_t i = 1; i <= ea->getConfig()->hours; i++) { + uint8_t peakCount = ea->getConfig()->hours; + if(peakCount > 5) peakCount = 5; + for(uint8_t i = 1; i <= peakCount; i++) { if(!peaks.isEmpty()) peaks += ","; peaks += String(ea->getPeak(i)); } @@ -240,6 +242,8 @@ bool HomeAssistantMqttHandler::publishSystem(HwTools* hw, EntsoeApi* eapi, Energ #endif String haUrl = "http://" + haUID + ".local/"; // Could this be necessary? haUID.replace("-", "_"); + uint8_t peakCount = ea->getConfig()->hours; + if(peakCount > 5) peakCount = 5; uint8_t peaks = 0; for(int i=0;igetCurrency()); } if(strncmp(sensor.path, "peaks[", 6) == 0) { - if(peaks >= ea->getConfig()->hours) continue; + if(peaks >= peakCount) continue; peaks++; } snprintf_P(json, BufferSize, HADISCOVER_JSON, From 06ec97b42a1f31d56f562ae3f8c654422f549af6 Mon Sep 17 00:00:00 2001 From: Gunnar Skjold Date: Thu, 6 Oct 2022 17:20:13 +0200 Subject: [PATCH 20/31] Make sure we dont use more than 5 peaks if defined higher --- src/EnergyAccounting.cpp | 11 +++++------ src/mqtt/HomeAssistantMqttHandler.cpp | 2 +- 2 files changed, 6 insertions(+), 7 deletions(-) diff --git a/src/EnergyAccounting.cpp b/src/EnergyAccounting.cpp index 60deaa43..d31441fb 100644 --- a/src/EnergyAccounting.cpp +++ b/src/EnergyAccounting.cpp @@ -237,11 +237,12 @@ float EnergyAccounting::getMonthMax() { uint32_t maxHour = 0.0; bool included[5] = { false, false, false, false, false }; - while(count < config->hours) { + while(count < config->hours && count <= 5) { uint8_t maxIdx = 0; uint16_t maxVal = 0; for(uint8_t i = 0; i < 5; i++) { if(included[i]) continue; + if(data.peaks[i].day == 0) continue; if(data.peaks[i].value > maxVal) { maxVal = data.peaks[i].value; maxIdx = i; @@ -253,9 +254,7 @@ float EnergyAccounting::getMonthMax() { for(uint8_t i = 0; i < 5; i++) { if(!included[i]) continue; - if(data.peaks[i].day > 0) { - maxHour += data.peaks[i].value; - } + maxHour += data.peaks[i].value; } return maxHour > 0 ? maxHour / count / 100.0 : 0.0; } @@ -266,7 +265,7 @@ float EnergyAccounting::getPeak(uint8_t num) { uint8_t count = 0; bool included[5] = { false, false, false, false, false }; - while(count < config->hours) { + while(count < config->hours && count <= 5) { uint8_t maxIdx = 0; uint16_t maxVal = 0; for(uint8_t i = 0; i < 5; i++) { @@ -341,7 +340,7 @@ bool EnergyAccounting::load() { this->data.peaks[b].day = b; memcpy(&this->data.peaks[b].value, buf+i, 2); b++; - if(b >= config->hours) break; + if(b >= config->hours || b >= 5) break; } ret = true; } else if(buf[0] == 1) { diff --git a/src/mqtt/HomeAssistantMqttHandler.cpp b/src/mqtt/HomeAssistantMqttHandler.cpp index 9a563664..ff273e3e 100644 --- a/src/mqtt/HomeAssistantMqttHandler.cpp +++ b/src/mqtt/HomeAssistantMqttHandler.cpp @@ -62,7 +62,7 @@ bool HomeAssistantMqttHandler::publish(AmsData* data, AmsData* previousState, En if(peakCount > 5) peakCount = 5; for(uint8_t i = 1; i <= peakCount; i++) { if(!peaks.isEmpty()) peaks += ","; - peaks += String(ea->getPeak(i)); + peaks += String(ea->getPeak(i), 2); } snprintf_P(json, BufferSize, REALTIME_JSON, ea->getMonthMax(), From 026cd25c8cbf5d9dfd5ed0d2bc37504f45a167b9 Mon Sep 17 00:00:00 2001 From: Gunnar Skjold Date: Thu, 6 Oct 2022 17:30:37 +0200 Subject: [PATCH 21/31] Setting modem sleep to max --- src/AmsConfiguration.cpp | 1 + src/AmsToMqttBridge.ino | 2 +- 2 files changed, 2 insertions(+), 1 deletion(-) diff --git a/src/AmsConfiguration.cpp b/src/AmsConfiguration.cpp index 1b6d3f9e..3f391e99 100644 --- a/src/AmsConfiguration.cpp +++ b/src/AmsConfiguration.cpp @@ -517,6 +517,7 @@ bool AmsConfiguration::getEnergyAccountingConfig(EnergyAccountingConfig& config) } bool AmsConfiguration::setEnergyAccountingConfig(EnergyAccountingConfig& config) { + if(config.hours > 5) config.hours = 5; EnergyAccountingConfig existing; if(getEnergyAccountingConfig(existing)) { for(int i = 0; i < 9; i++) { diff --git a/src/AmsToMqttBridge.ino b/src/AmsToMqttBridge.ino index 20ee5ee5..e4f50fbe 100644 --- a/src/AmsToMqttBridge.ino +++ b/src/AmsToMqttBridge.ino @@ -1051,7 +1051,7 @@ void WiFi_connect() { } #endif WiFi.mode(WIFI_STA); - WiFi.setSleep(WIFI_PS_MIN_MODEM); + WiFi.setSleep(WIFI_PS_MAX_MODEM); #if defined(ESP32) if(wifi.power >= 195) WiFi.setTxPower(WIFI_POWER_19_5dBm); From 5e03e3d3c2124d60cf36e34793889b5a791e2a77 Mon Sep 17 00:00:00 2001 From: Thomas Barnekov Date: Fri, 7 Oct 2022 13:40:29 +0200 Subject: [PATCH 22/31] Move per-phase power consumption and power factor values to new ha4.json --- src/mqtt/HomeAssistantMqttHandler.cpp | 20 +++++++++++++++++++- web/ha3.json | 12 +----------- web/ha4.json | 25 +++++++++++++++++++++++++ 3 files changed, 45 insertions(+), 12 deletions(-) create mode 100644 web/ha4.json diff --git a/src/mqtt/HomeAssistantMqttHandler.cpp b/src/mqtt/HomeAssistantMqttHandler.cpp index 18057c2b..969db87c 100644 --- a/src/mqtt/HomeAssistantMqttHandler.cpp +++ b/src/mqtt/HomeAssistantMqttHandler.cpp @@ -6,6 +6,7 @@ #include "web/root/ha1_json.h" #include "web/root/ha2_json.h" #include "web/root/ha3_json.h" +#include "web/root/ha4_json.h" #include "web/root/jsonsys_json.h" #include "web/root/jsonprices_json.h" #include "web/root/hadiscover_json.h" @@ -34,8 +35,25 @@ bool HomeAssistantMqttHandler::publish(AmsData* data, AmsData* previousState, En data->getActiveImportPower() ); mqtt->publish(topic + "/power", json); - } else if(data->getListType() >= 2) { // publish power counts and volts/amps + } else if(data->getListType() <= 3) { // publish power counts and volts/amps snprintf_P(json, BufferSize, HA3_JSON, + data->getListId().c_str(), + data->getMeterId().c_str(), + meterModel.c_str(), + data->getActiveImportPower(), + data->getReactiveImportPower(), + data->getActiveExportPower(), + data->getReactiveExportPower(), + data->getL1Current(), + data->getL2Current(), + data->getL3Current(), + data->getL1Voltage(), + data->getL2Voltage(), + data->getL3Voltage() + ); + mqtt->publish(topic + "/power", json); + } else if(data->getListType() == 4) { // publish power counts and volts/amps/phase power and PF + snprintf_P(json, BufferSize, HA4_JSON, data->getListId().c_str(), data->getMeterId().c_str(), meterModel.c_str(), diff --git a/web/ha3.json b/web/ha3.json index faee4724..8fa16c93 100644 --- a/web/ha3.json +++ b/web/ha3.json @@ -3,23 +3,13 @@ "id" : "%s", "type" : "%s", "P" : %d, - "P1" : %.2f, - "P2" : %.2f, - "P3" : %.2f, "Q" : %d, "PO" : %d, - "PO1" : %.2f, - "PO2" : %.2f, - "PO3" : %.2f, "QO" : %d, "I1" : %.2f, "I2" : %.2f, "I3" : %.2f, "U1" : %.2f, "U2" : %.2f, - "U3" : %.2f, - "PF" : %.2f, - "PF1" : %.2f, - "PF2" : %.2f, - "PF3" : %.2f + "U3" : %.2f } diff --git a/web/ha4.json b/web/ha4.json new file mode 100644 index 00000000..faee4724 --- /dev/null +++ b/web/ha4.json @@ -0,0 +1,25 @@ +{ + "lv" : "%s", + "id" : "%s", + "type" : "%s", + "P" : %d, + "P1" : %.2f, + "P2" : %.2f, + "P3" : %.2f, + "Q" : %d, + "PO" : %d, + "PO1" : %.2f, + "PO2" : %.2f, + "PO3" : %.2f, + "QO" : %d, + "I1" : %.2f, + "I2" : %.2f, + "I3" : %.2f, + "U1" : %.2f, + "U2" : %.2f, + "U3" : %.2f, + "PF" : %.2f, + "PF1" : %.2f, + "PF2" : %.2f, + "PF3" : %.2f +} From 867ab9d6c202a3f899906b3eaba20051f41079c4 Mon Sep 17 00:00:00 2001 From: Gunnar Skjold Date: Fri, 7 Oct 2022 19:35:30 +0200 Subject: [PATCH 23/31] Build variable for upgrade URL --- src/web/AmsWebServer.h | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/src/web/AmsWebServer.h b/src/web/AmsWebServer.h index f2fbbe7c..00417d48 100644 --- a/src/web/AmsWebServer.h +++ b/src/web/AmsWebServer.h @@ -61,7 +61,11 @@ private: bool performRestart = false; bool performUpgrade = false; bool rebootForUpgrade = false; + #if defined(AMS2MQTT_FIRMWARE_URL) + String customFirmwareUrl = AMS2MQTT_FIRMWARE_URL; + #else String customFirmwareUrl; + #endif static const uint16_t BufferSize = 2048; char* buf; From 39a4761415fb16d02532028fc83ec060268dc6d5 Mon Sep 17 00:00:00 2001 From: Thomas Barnekov Date: Mon, 10 Oct 2022 16:59:39 +0200 Subject: [PATCH 24/31] Add DOCTYPE to html to fix quirks mode --- web/head.html | 1 + 1 file changed, 1 insertion(+) diff --git a/web/head.html b/web/head.html index 343c3c8f..6e34c7aa 100644 --- a/web/head.html +++ b/web/head.html @@ -1,3 +1,4 @@ + From ce3a47a7e6e0a6b896b2ce99a2b198725c8802b8 Mon Sep 17 00:00:00 2001 From: Gunnar Skjold Date: Wed, 12 Oct 2022 19:25:48 +0200 Subject: [PATCH 25/31] Fixed error blinks and improved WiFi reconnect --- src/AmsToMqttBridge.h | 2 +- src/AmsToMqttBridge.ino | 45 +++++++++++++++++++++++++++-------------- src/HwTools.cpp | 4 ++-- 3 files changed, 33 insertions(+), 18 deletions(-) diff --git a/src/AmsToMqttBridge.h b/src/AmsToMqttBridge.h index aa2e148a..477fbba2 100644 --- a/src/AmsToMqttBridge.h +++ b/src/AmsToMqttBridge.h @@ -1,7 +1,7 @@ #ifndef _AMSTOMQTTBRIDGE_H #define _AMSTOMQTTBRIDGE_H -#define WIFI_CONNECTION_TIMEOUT 30000; +#define WIFI_CONNECTION_TIMEOUT 30000 #define INVALID_BUTTON_PIN 0xFFFFFFFF diff --git a/src/AmsToMqttBridge.ino b/src/AmsToMqttBridge.ino index e4f50fbe..92a527d1 100644 --- a/src/AmsToMqttBridge.ino +++ b/src/AmsToMqttBridge.ino @@ -436,6 +436,10 @@ void loop() { } } + if(now > 10000 && now - lastErrorBlink > 3000) { + errorBlink(); + } + // Only do normal stuff if we're not booted as AP if (WiFi.getMode() != WIFI_AP) { if (WiFi.status() != WL_CONNECTED) { @@ -506,10 +510,6 @@ void loop() { MDNS.update(); #endif - if(now > 10000 && now - lastErrorBlink > 3000) { - errorBlink(); - } - if (mqttEnabled || config.isMqttChanged()) { if(mqtt == NULL || !mqtt->connected() || config.isMqttChanged()) { MQTT_connect(); @@ -725,22 +725,25 @@ void errorBlink() { if(lastError == 3) lastError = 0; lastErrorBlink = millis(); - for(;lastError < 3;lastError++) { - switch(lastError) { + while(lastError < 3) { + switch(lastError++) { case 0: if(lastErrorBlink - meterState.getLastUpdateMillis() > 30000) { + debugW("No HAN data received last 30s, single blink"); hw.ledBlink(LED_RED, 1); // If no message received from AMS in 30 sec, blink once return; } break; case 1: if(mqttEnabled && mqtt != NULL && mqtt->lastError() != 0) { + debugW("MQTT connection not available, double blink"); hw.ledBlink(LED_RED, 2); // If MQTT error, blink twice return; } break; case 2: if(WiFi.getMode() != WIFI_AP && WiFi.status() != WL_CONNECTED) { + debugW("WiFi not connected, tripe blink"); hw.ledBlink(LED_RED, 3); // If WiFi not connected, blink three times return; } @@ -985,17 +988,29 @@ void debugPrint(byte *buffer, int start, int length) { Debug.println(""); } -unsigned long wifiTimeout = WIFI_CONNECTION_TIMEOUT; unsigned long lastWifiRetry = -WIFI_CONNECTION_TIMEOUT; void WiFi_connect() { - if(millis() - lastWifiRetry < wifiTimeout) { - delay(50); - return; - } - lastWifiRetry = millis(); - if (WiFi.status() != WL_CONNECTED) { + if(WiFi.status() == WL_DISCONNECTED) { + if(millis() - lastWifiRetry < WIFI_CONNECTION_TIMEOUT) { + return; + } + } if(WiFi.getMode() != WIFI_OFF) { + switch(WiFi.status()) { + case WL_NO_SSID_AVAIL: + debugE("WiFi error, no SSID available"); + break; + case WL_CONNECT_FAILED: + debugE("WiFi error, connection failed"); + break; + case WL_CONNECTION_LOST: + debugE("WiFi error, connection lost"); + break; + case WL_WRONG_PASSWORD: + debugE("WiFi error, wrong password"); + break; + } if(wifiReconnectCount > 3) { ESP.restart(); return; @@ -1029,11 +1044,11 @@ void WiFi_connect() { WiFi.softAPdisconnect(true); WiFi.enableAP(false); WiFi.mode(WIFI_OFF); + WiFi.forceSleepBegin(); yield(); - wifiTimeout = 5000; return; } - wifiTimeout = WIFI_CONNECTION_TIMEOUT; + lastWifiRetry = millis(); WiFiConfig wifi; if(!config.getWiFiConfig(wifi) || strlen(wifi.ssid) == 0) { diff --git a/src/HwTools.cpp b/src/HwTools.cpp index 007c06a4..7683621b 100644 --- a/src/HwTools.cpp +++ b/src/HwTools.cpp @@ -373,8 +373,8 @@ bool HwTools::ledBlink(uint8_t color, uint8_t blink) { if(!ledOn(color)) return false; delay(50); ledOff(color); - if(i != blink) - delay(50); + if(i != blink-1) + delay(200); } return true; } From a64f960cc7cba3fcf22db69f1f7261d2c0001b75 Mon Sep 17 00:00:00 2001 From: Gunnar Skjold Date: Wed, 12 Oct 2022 19:30:00 +0200 Subject: [PATCH 26/31] Added Pow-U+ profile --- src/web/AmsWebServer.cpp | 10 ++++++++++ web/setup.html | 1 + 2 files changed, 11 insertions(+) diff --git a/src/web/AmsWebServer.cpp b/src/web/AmsWebServer.cpp index fa510cbc..e7e6047d 100644 --- a/src/web/AmsWebServer.cpp +++ b/src/web/AmsWebServer.cpp @@ -1077,6 +1077,16 @@ void AmsWebServer::handleSetup() { gpioConfig->vccResistorGnd = 22; gpioConfig->vccResistorVcc = 33; break; + case 7: // Pow-U+ + gpioConfig->hanPin = 16; + gpioConfig->apPin = 0; + gpioConfig->ledPinRed = 13; + gpioConfig->ledPinGreen = 14; + gpioConfig->ledRgbInverted = true; + gpioConfig->vccPin = 10; + gpioConfig->vccResistorGnd = 22; + gpioConfig->vccResistorVcc = 33; + break; case 101: // D1 gpioConfig->hanPin = 5; gpioConfig->apPin = 4; diff --git a/web/setup.html b/web/setup.html index 65846332..87d047f9 100644 --- a/web/setup.html +++ b/web/setup.html @@ -26,6 +26,7 @@ +
GPIO settings
@@ -8,18 +8,18 @@
HAN
- + ${h}
LED
- +
@@ -27,12 +27,12 @@
RGB
- - - + + +
@@ -40,31 +40,31 @@
AP button
- +
Temperature
- +
Analog temp
- +
Vcc
- +
GND resistor
- +
@@ -73,7 +73,7 @@
Vcc resistor
- +
@@ -82,19 +82,19 @@
Multiplier
- +
Offset
- +
Boot limit
- +
From 6d81b0a8566a33552744a45d5048a2ac25853447 Mon Sep 17 00:00:00 2001 From: Gunnar Skjold Date: Thu, 13 Oct 2022 20:24:56 +0200 Subject: [PATCH 30/31] Fixed all build warnings --- src/AmsToMqttBridge.ino | 21 +++++++++++---------- src/EnergyAccounting.cpp | 2 +- src/IEC6205675.cpp | 10 +++++++--- src/Uptime.cpp | 3 +++ src/Uptime.h | 2 -- src/entsoe/EntsoeA44Parser.cpp | 6 +++++- src/entsoe/EntsoeA44Parser.h | 1 + src/entsoe/EntsoeApi.cpp | 4 ++-- src/mqtt/AmsMqttHandler.h | 1 + src/mqtt/HomeAssistantMqttHandler.cpp | 16 ++++++++-------- src/mqtt/JsonMqttHandler.cpp | 11 ++++++----- src/mqtt/RawMqttHandler.cpp | 8 ++++---- src/web/AmsWebServer.cpp | 12 ++++++------ web/data.json | 6 +++--- web/ha2.json | 2 +- web/json1.json | 4 ++-- web/json2.json | 4 ++-- web/json3.json | 6 +++--- web/json4.json | 6 +++--- 19 files changed, 69 insertions(+), 56 deletions(-) diff --git a/src/AmsToMqttBridge.ino b/src/AmsToMqttBridge.ino index 9956cde0..5d988fac 100644 --- a/src/AmsToMqttBridge.ino +++ b/src/AmsToMqttBridge.ino @@ -119,7 +119,6 @@ DLMSParser *dlmsParser = NULL; DSMRParser *dsmrParser = NULL; void setup() { - WiFiConfig wifi; Serial.begin(115200); if(!config.getGpioConfig(gpioConfig)) { @@ -246,7 +245,6 @@ void setup() { } Debug.setSerialEnabled(true); - DebugConfig debug; delay(1); float vcc = hw.getVcc(); @@ -591,7 +589,7 @@ void loop() { if(mqtt != NULL && mqttHandler != NULL && WiFi.getMode() != WIFI_AP && WiFi.status() == WL_CONNECTED && mqtt->connected() && !topic.isEmpty()) { mqttHandler->publishTemperatures(&config, &hw); } - debugD("Used %d ms to update temperature", millis()-start); + debugD("Used %ld ms to update temperature", millis()-start); } if(now - lastSysupdate > 10000) { if(mqtt != NULL && mqttHandler != NULL && WiFi.getMode() != WIFI_AP && WiFi.status() == WL_CONNECTED && mqtt->connected() && !topic.isEmpty()) { @@ -1017,6 +1015,9 @@ void WiFi_connect() { debugE("WiFi error, wrong password"); break; #endif + default: + debugE("WiFi error, %d", WiFi.status()); + break; } if(wifiReconnectCount > 3) { ESP.restart(); @@ -1145,16 +1146,16 @@ void WiFi_connect() { void mqttMessageReceived(String &topic, String &payload) { debugI("Received message for topic %s", topic.c_str() ); - if(meterConfig.source == METER_SOURCE_MQTT) { - DataParserContext ctx = {static_cast(payload.length()/2)}; - fromHex(hanBuffer, payload, ctx.length); - uint16_t pos = unwrapData(hanBuffer, ctx); + //if(meterConfig.source == METER_SOURCE_MQTT) { + //DataParserContext ctx = {static_cast(payload.length()/2)}; + //fromHex(hanBuffer, payload, ctx.length); + //uint16_t pos = unwrapData(hanBuffer, ctx); // TODO: Run through DLMS/DMSR parser and apply AmsData - } + //} } int16_t unwrapData(uint8_t *buf, DataParserContext &context) { - int16_t ret; + int16_t ret = 0; bool doRet = false; uint16_t end = BUF_SIZE_HAN; uint8_t tag = (*buf); @@ -1399,7 +1400,7 @@ void MQTT_connect() { #if defined(ESP8266) if(mqttSecureClient) { time_t epoch = time(nullptr); - debugD("Setting NTP time %i for secure MQTT connection", epoch); + debugD("Setting NTP time %lld for secure MQTT connection", epoch); mqttSecureClient->setX509Time(epoch); } #endif diff --git a/src/EnergyAccounting.cpp b/src/EnergyAccounting.cpp index d31441fb..87a0d252 100644 --- a/src/EnergyAccounting.cpp +++ b/src/EnergyAccounting.cpp @@ -57,7 +57,7 @@ bool EnergyAccounting::update(AmsData* amsData) { for(uint8_t i = 0; i < 5; i++) { debugger->printf("(EnergyAccounting) Peak hour from day %d: %d\n", data.peaks[i].day, data.peaks[i].value*10); } - debugger->printf("(EnergyAccounting) Loaded cost yesterday: %d, this month: %d, last month: %d\n", data.costYesterday / 10.0, data.costThisMonth, data.costLastMonth); + debugger->printf("(EnergyAccounting) Loaded cost yesterday: %.2f, this month: %d, last month: %d\n", data.costYesterday / 10.0, data.costThisMonth, data.costLastMonth); } init = true; } diff --git a/src/IEC6205675.cpp b/src/IEC6205675.cpp index 10ebda8f..8a4ccab6 100644 --- a/src/IEC6205675.cpp +++ b/src/IEC6205675.cpp @@ -368,12 +368,16 @@ IEC6205675::IEC6205675(const char* d, uint8_t useMeterType, MeterConfig* meterCo if(mid != NULL) { switch(mid->base.type) { case CosemTypeString: - memcpy(&meterId, mid->str.data, mid->str.length); + memcpy(str, mid->oct.data, mid->oct.length); + str[mid->oct.length] = 0x00; + meterId = String(str); meterId[mid->str.length] = 0; break; case CosemTypeOctetString: - memcpy(&meterId, mid->oct.data, mid->oct.length); - meterId[mid->oct.length] = 0; + memcpy(str, mid->str.data, mid->str.length); + str[mid->str.length] = 0x00; + meterId = String(str); + meterId[mid->str.length] = 0; break; } } diff --git a/src/Uptime.cpp b/src/Uptime.cpp index d3f739fd..65b5bd1d 100644 --- a/src/Uptime.cpp +++ b/src/Uptime.cpp @@ -1,5 +1,8 @@ #include "Uptime.h" +uint32_t _uptime_last_value = 0; +uint32_t _uptime_rollovers = 0; + uint64_t millis64() { uint32_t new_low32 = millis(); if (new_low32 < _uptime_last_value) _uptime_rollovers++; diff --git a/src/Uptime.h b/src/Uptime.h index 9b1a14a9..aeea9732 100644 --- a/src/Uptime.h +++ b/src/Uptime.h @@ -3,8 +3,6 @@ #include "Arduino.h" -static uint32_t _uptime_last_value = 0; -static uint32_t _uptime_rollovers = 0; uint64_t millis64(); #endif diff --git a/src/entsoe/EntsoeA44Parser.cpp b/src/entsoe/EntsoeA44Parser.cpp index 1d7fa9b2..9dc41de6 100644 --- a/src/entsoe/EntsoeA44Parser.cpp +++ b/src/entsoe/EntsoeA44Parser.cpp @@ -5,6 +5,10 @@ EntsoeA44Parser::EntsoeA44Parser() { for(int i = 0; i < 24; i++) points[i] = ENTSOE_NO_VALUE; } +EntsoeA44Parser::~EntsoeA44Parser() { + +} + char* EntsoeA44Parser::getCurrency() { return currency; } @@ -35,7 +39,7 @@ void EntsoeA44Parser::flush() { } size_t EntsoeA44Parser::write(const uint8_t *buffer, size_t size) { - for(int i = 0; i < size; i++) { + for(size_t i = 0; i < size; i++) { write(buffer[i]); } return size; diff --git a/src/entsoe/EntsoeA44Parser.h b/src/entsoe/EntsoeA44Parser.h index 4d860214..2f538d10 100644 --- a/src/entsoe/EntsoeA44Parser.h +++ b/src/entsoe/EntsoeA44Parser.h @@ -14,6 +14,7 @@ class EntsoeA44Parser: public Stream { public: EntsoeA44Parser(); + virtual ~EntsoeA44Parser(); char* getCurrency(); char* getMeasurementUnit(); diff --git a/src/entsoe/EntsoeApi.cpp b/src/entsoe/EntsoeApi.cpp index 886e7201..922220a2 100644 --- a/src/entsoe/EntsoeApi.cpp +++ b/src/entsoe/EntsoeApi.cpp @@ -106,11 +106,11 @@ bool EntsoeApi::loop() { if(midnightMillis == 0) { uint32_t curDayMillis = (((((tm.Hour * 60) + tm.Minute) * 60) + tm.Second) * 1000); midnightMillis = now + (SECS_PER_DAY * 1000) - curDayMillis; - if(debugger->isActive(RemoteDebug::INFO)) debugger->printf("(EntsoeApi) Setting midnight millis %lu\n", midnightMillis); + if(debugger->isActive(RemoteDebug::INFO)) debugger->printf("(EntsoeApi) Setting midnight millis %llu\n", midnightMillis); currentDay = tm.Day; return false; } else if(now > midnightMillis && currentDay != tm.Day) { - if(debugger->isActive(RemoteDebug::INFO)) debugger->printf("(EntsoeApi) Rotating price objects at %lu\n", t); + if(debugger->isActive(RemoteDebug::INFO)) debugger->printf("(EntsoeApi) Rotating price objects at %lld\n", t); if(today != NULL) delete today; if(tomorrow != NULL) { today = tomorrow; diff --git a/src/mqtt/AmsMqttHandler.h b/src/mqtt/AmsMqttHandler.h index 4ec71634..109c2a8d 100644 --- a/src/mqtt/AmsMqttHandler.h +++ b/src/mqtt/AmsMqttHandler.h @@ -15,6 +15,7 @@ public: this->mqtt = mqtt; this->json = buf; }; + virtual ~AmsMqttHandler() {}; virtual bool publish(AmsData* data, AmsData* previousState, EnergyAccounting* ea); virtual bool publishTemperatures(AmsConfiguration*, HwTools*); diff --git a/src/mqtt/HomeAssistantMqttHandler.cpp b/src/mqtt/HomeAssistantMqttHandler.cpp index 969db87c..7880c254 100644 --- a/src/mqtt/HomeAssistantMqttHandler.cpp +++ b/src/mqtt/HomeAssistantMqttHandler.cpp @@ -141,7 +141,7 @@ bool HomeAssistantMqttHandler::publishPrices(EntsoeApi* eapi) { time_t now = time(nullptr); - float min1hr, min3hr, min6hr; + float min1hr = 0.0, min3hr = 0.0, min6hr = 0.0; int8_t min1hrIdx = -1, min3hrIdx = -1, min6hrIdx = -1; float min = INT16_MAX, max = INT16_MIN; float values[24]; @@ -191,7 +191,7 @@ bool HomeAssistantMqttHandler::publishPrices(EntsoeApi* eapi) { } - char ts1hr[21]; + char ts1hr[24]; if(min1hrIdx > -1) { time_t ts = now + (SECS_PER_HOUR * min1hrIdx); //Serial.printf("1hr: %d %lu\n", min1hrIdx, ts); @@ -199,7 +199,7 @@ bool HomeAssistantMqttHandler::publishPrices(EntsoeApi* eapi) { breakTime(ts, tm); sprintf(ts1hr, "%04d-%02d-%02dT%02d:00:00Z", tm.Year+1970, tm.Month, tm.Day, tm.Hour); } - char ts3hr[21]; + char ts3hr[24]; if(min3hrIdx > -1) { time_t ts = now + (SECS_PER_HOUR * min3hrIdx); //Serial.printf("3hr: %d %lu\n", min3hrIdx, ts); @@ -207,7 +207,7 @@ bool HomeAssistantMqttHandler::publishPrices(EntsoeApi* eapi) { breakTime(ts, tm); sprintf(ts3hr, "%04d-%02d-%02dT%02d:00:00Z", tm.Year+1970, tm.Month, tm.Day, tm.Hour); } - char ts6hr[21]; + char ts6hr[24]; if(min6hrIdx > -1) { time_t ts = now + (SECS_PER_HOUR * min6hrIdx); //Serial.printf("6hr: %d %lu\n", min6hrIdx, ts); @@ -287,13 +287,13 @@ bool HomeAssistantMqttHandler::publishSystem(HwTools* hw, EntsoeApi* eapi, Energ peaks++; } snprintf_P(json, BufferSize, HADISCOVER_JSON, - FPSTR(sensor.name), - topic.c_str(), FPSTR(sensor.topic), + sensor.name, + topic.c_str(), sensor.topic, haUID.c_str(), uid.c_str(), haUID.c_str(), uid.c_str(), uom.c_str(), - FPSTR(sensor.path), - FPSTR(sensor.devcl), + sensor.path, + sensor.devcl, haUID.c_str(), haName.c_str(), haModel.c_str(), diff --git a/src/mqtt/JsonMqttHandler.cpp b/src/mqtt/JsonMqttHandler.cpp index 1b406c93..9448b762 100644 --- a/src/mqtt/JsonMqttHandler.cpp +++ b/src/mqtt/JsonMqttHandler.cpp @@ -149,8 +149,9 @@ bool JsonMqttHandler::publish(AmsData* data, AmsData* previousState, EnergyAccou bool JsonMqttHandler::publishTemperatures(AmsConfiguration* config, HwTools* hw) { int count = hw->getTempSensorCount(); - if(count < 2) + if(count < 2) { return false; + } snprintf(json, 24, "{\"temperatures\":{"); @@ -179,7 +180,7 @@ bool JsonMqttHandler::publishPrices(EntsoeApi* eapi) { time_t now = time(nullptr); - float min1hr, min3hr, min6hr; + float min1hr = 0.0, min3hr = 0.0, min6hr = 0.0; int8_t min1hrIdx = -1, min3hrIdx = -1, min6hrIdx = -1; float min = INT16_MAX, max = INT16_MIN; float values[24]; @@ -229,7 +230,7 @@ bool JsonMqttHandler::publishPrices(EntsoeApi* eapi) { } - char ts1hr[21]; + char ts1hr[24]; if(min1hrIdx > -1) { time_t ts = now + (SECS_PER_HOUR * min1hrIdx); //Serial.printf("1hr: %d %lu\n", min1hrIdx, ts); @@ -237,7 +238,7 @@ bool JsonMqttHandler::publishPrices(EntsoeApi* eapi) { breakTime(ts, tm); sprintf(ts1hr, "%04d-%02d-%02dT%02d:00:00Z", tm.Year+1970, tm.Month, tm.Day, tm.Hour); } - char ts3hr[21]; + char ts3hr[24]; if(min3hrIdx > -1) { time_t ts = now + (SECS_PER_HOUR * min3hrIdx); //Serial.printf("3hr: %d %lu\n", min3hrIdx, ts); @@ -245,7 +246,7 @@ bool JsonMqttHandler::publishPrices(EntsoeApi* eapi) { breakTime(ts, tm); sprintf(ts3hr, "%04d-%02d-%02dT%02d:00:00Z", tm.Year+1970, tm.Month, tm.Day, tm.Hour); } - char ts6hr[21]; + char ts6hr[24]; if(min6hrIdx > -1) { time_t ts = now + (SECS_PER_HOUR * min6hrIdx); //Serial.printf("6hr: %d %lu\n", min6hrIdx, ts); diff --git a/src/mqtt/RawMqttHandler.cpp b/src/mqtt/RawMqttHandler.cpp index f2b681b4..19e6db44 100644 --- a/src/mqtt/RawMqttHandler.cpp +++ b/src/mqtt/RawMqttHandler.cpp @@ -124,7 +124,7 @@ bool RawMqttHandler::publishPrices(EntsoeApi* eapi) { time_t now = time(nullptr); - float min1hr, min3hr, min6hr; + float min1hr = 0.0, min3hr = 0.0, min6hr = 0.0; int8_t min1hrIdx = -1, min3hrIdx = -1, min6hrIdx = -1; float min = INT16_MAX, max = INT16_MIN; float values[34]; @@ -175,7 +175,7 @@ bool RawMqttHandler::publishPrices(EntsoeApi* eapi) { } - char ts1hr[21]; + char ts1hr[24]; if(min1hrIdx > -1) { time_t ts = now + (SECS_PER_HOUR * min1hrIdx); //Serial.printf("1hr: %d %lu\n", min1hrIdx, ts); @@ -183,7 +183,7 @@ bool RawMqttHandler::publishPrices(EntsoeApi* eapi) { breakTime(ts, tm); sprintf(ts1hr, "%04d-%02d-%02dT%02d:00:00Z", tm.Year+1970, tm.Month, tm.Day, tm.Hour); } - char ts3hr[21]; + char ts3hr[24]; if(min3hrIdx > -1) { time_t ts = now + (SECS_PER_HOUR * min3hrIdx); //Serial.printf("3hr: %d %lu\n", min3hrIdx, ts); @@ -191,7 +191,7 @@ bool RawMqttHandler::publishPrices(EntsoeApi* eapi) { breakTime(ts, tm); sprintf(ts3hr, "%04d-%02d-%02dT%02d:00:00Z", tm.Year+1970, tm.Month, tm.Day, tm.Hour); } - char ts6hr[21]; + char ts6hr[24]; if(min6hrIdx > -1) { time_t ts = now + (SECS_PER_HOUR * min6hrIdx); //Serial.printf("6hr: %d %lu\n", min6hrIdx, ts); diff --git a/src/web/AmsWebServer.cpp b/src/web/AmsWebServer.cpp index 0c7e44ce..20611d36 100644 --- a/src/web/AmsWebServer.cpp +++ b/src/web/AmsWebServer.cpp @@ -1599,21 +1599,21 @@ HTTPUpload& AmsWebServer::uploadFile(const char* path) { } file = LittleFS.open(path, "w"); if(debugger->isActive(RemoteDebug::DEBUG)) { - debugger->printf("handleFileUpload Open file and write: %lu\n", upload.currentSize); + debugger->printf("handleFileUpload Open file and write: %u\n", upload.currentSize); } size_t written = file.write(upload.buf, upload.currentSize); if(debugger->isActive(RemoteDebug::DEBUG)) { - debugger->printf("handleFileUpload Written: %lu\n", written); + debugger->printf("handleFileUpload Written: %u\n", written); } } } else if(upload.status == UPLOAD_FILE_WRITE) { if(debugger->isActive(RemoteDebug::DEBUG)) { - debugger->printf("handleFileUpload Writing: %lu\n", upload.currentSize); + debugger->printf("handleFileUpload Writing: %u\n", upload.currentSize); } if(file) { size_t written = file.write(upload.buf, upload.currentSize); if(debugger->isActive(RemoteDebug::DEBUG)) { - debugger->printf("handleFileUpload Written: %lu\n", written); + debugger->printf("handleFileUpload Written: %u\n", written); } delay(1); if(written != upload.currentSize) { @@ -2332,7 +2332,7 @@ void AmsWebServer::configFileDownload() { ds->getHourImport(23) )); if(day.activeExport > 0) { - server.sendContent(buf, snprintf(buf, BufferSize, " %lu %d %d %d %d %d %d %d %d %d %d %d %d %d %d %d %d %d %d %d %d %d %d %d %d\n", + server.sendContent(buf, snprintf(buf, BufferSize, " %u %d %d %d %d %d %d %d %d %d %d %d %d %d %d %d %d %d %d %d %d %d %d %d %d\n", day.activeExport, ds->getHourExport(0), ds->getHourExport(1), @@ -2401,7 +2401,7 @@ void AmsWebServer::configFileDownload() { ds->getDayImport(31) )); if(month.activeExport > 0) { - server.sendContent(buf, snprintf_P(buf, BufferSize, " %lu %d %d %d %d %d %d %d %d %d %d %d %d %d %d %d %d %d %d %d %d %d %d %d %d %d %d %d %d %d %d %d\n", + server.sendContent(buf, snprintf_P(buf, BufferSize, " %u %d %d %d %d %d %d %d %d %d %d %d %d %d %d %d %d %d %d %d %d %d %d %d %d %d %d %d %d %d %d %d\n", month.activeExport, ds->getDayExport(1), ds->getDayExport(2), diff --git a/web/data.json b/web/data.json index 0581d6ac..a713055a 100644 --- a/web/data.json +++ b/web/data.json @@ -23,8 +23,8 @@ "v" : %.3f, "r" : %d, "t" : %.2f, - "u" : %lu, - "m" : %lu, + "u" : %u, + "m" : %u, "em" : %d, "hm" : %d, "wm" : %d, @@ -53,5 +53,5 @@ "p" : %.2f } }, - "c" : %lu + "c" : %u } \ No newline at end of file diff --git a/web/ha2.json b/web/ha2.json index 06ab3f26..53fe3841 100644 --- a/web/ha2.json +++ b/web/ha2.json @@ -3,5 +3,5 @@ "tPO" : %.2f, "tQI" : %.2f, "tQO" : %.2f, - "rtc" : %lu + "rtc" : %lld } diff --git a/web/json1.json b/web/json1.json index 70f74801..e38fb4b9 100644 --- a/web/json1.json +++ b/web/json1.json @@ -1,8 +1,8 @@ { "id" : "%s", "name" : "%s", - "up" : %lu, - "t" : %lu, + "up" : %u, + "t" : %lld, "vcc" : %.3f, "rssi": %d, "temp": %.2f, diff --git a/web/json2.json b/web/json2.json index b875ac11..44bde282 100644 --- a/web/json2.json +++ b/web/json2.json @@ -1,8 +1,8 @@ { "id" : "%s", "name" : "%s", - "up" : %lu, - "t" : %lu, + "up" : %u, + "t" : %lld, "vcc" : %.3f, "rssi": %d, "temp": %.2f, diff --git a/web/json3.json b/web/json3.json index 33d022ba..09961abe 100644 --- a/web/json3.json +++ b/web/json3.json @@ -1,8 +1,8 @@ { "id" : "%s", "name" : "%s", - "up" : %lu, - "t" : %lu, + "up" : %u, + "t" : %lld, "vcc" : %.3f, "rssi": %d, "temp": %.2f, @@ -24,7 +24,7 @@ "tPO" : %.3f, "tQI" : %.3f, "tQO" : %.3f, - "rtc" : %lu + "rtc" : %lld }, "realtime" : { "h" : %.2f, diff --git a/web/json4.json b/web/json4.json index cb61fb90..417c2eed 100644 --- a/web/json4.json +++ b/web/json4.json @@ -1,8 +1,8 @@ { "id" : "%s", "name" : "%s", - "up" : %lu, - "t" : %lu, + "up" : %u, + "t" : %lld, "vcc" : %.3f, "rssi": %d, "temp": %.2f, @@ -34,7 +34,7 @@ "tPO" : %.2f, "tQI" : %.2f, "tQO" : %.2f, - "rtc" : %lu + "rtc" : %lld }, "realtime" : { "h" : %.2f, From fa299198fc12a042d6e0a6c3ec4f5d6f809051e3 Mon Sep 17 00:00:00 2001 From: Gunnar Skjold Date: Thu, 13 Oct 2022 20:33:59 +0200 Subject: [PATCH 31/31] Fixed all build warnings --- src/AmsConfiguration.cpp | 2 +- src/LNG.cpp | 16 ++++++++-------- src/ams/DsmrParser.cpp | 1 - src/ams/GcmParser.cpp | 2 +- src/ams/HdlcParser.cpp | 2 -- src/ams/LlcParser.cpp | 1 - src/ams/MbusParser.cpp | 2 -- src/entsoe/DnbCurrParser.cpp | 2 +- 8 files changed, 11 insertions(+), 17 deletions(-) diff --git a/src/AmsConfiguration.cpp b/src/AmsConfiguration.cpp index 3f391e99..450c7c06 100644 --- a/src/AmsConfiguration.cpp +++ b/src/AmsConfiguration.cpp @@ -743,7 +743,7 @@ bool AmsConfiguration::relocateConfig86() { } bool AmsConfiguration::relocateConfig87() { - MeterConfig87 meter87; + MeterConfig87 meter87 = {0,0,0,0,0,0,0}; MeterConfig meter; EEPROM.begin(EEPROM_SIZE); EEPROM.get(CONFIG_METER_START_87, meter87); diff --git a/src/LNG.cpp b/src/LNG.cpp index b5c9817b..f3ec7cd5 100644 --- a/src/LNG.cpp +++ b/src/LNG.cpp @@ -25,38 +25,38 @@ LNG::LNG(const char* payload, uint8_t useMeterType, MeterConfig* meterConfig, Da if(descriptor->obis[3] == 7) { if(descriptor->obis[4] == 0) { o170 = ntohl(item->dlu.data); - if(debugger->isActive(RemoteDebug::VERBOSE)) debugger->printf(" and value %d (dlu)", ntohl(item->dlu.data)); + if(debugger->isActive(RemoteDebug::VERBOSE)) debugger->printf(" and value %lu (dlu)", ntohl(item->dlu.data)); } } else if(descriptor->obis[3] == 8) { if(descriptor->obis[4] == 0) { activeImportCounter = ntohl(item->dlu.data) / 1000.0; listType = listType >= 3 ? listType : 3; - if(debugger->isActive(RemoteDebug::VERBOSE)) debugger->printf(" and value %d (dlu)", ntohl(item->dlu.data)); + if(debugger->isActive(RemoteDebug::VERBOSE)) debugger->printf(" and value %lu (dlu)", ntohl(item->dlu.data)); } else if(descriptor->obis[4] == 1) { o181 = ntohl(item->dlu.data); - if(debugger->isActive(RemoteDebug::VERBOSE)) debugger->printf(" and value %d (dlu)", ntohl(item->dlu.data)); + if(debugger->isActive(RemoteDebug::VERBOSE)) debugger->printf(" and value %lu (dlu)", ntohl(item->dlu.data)); } else if(descriptor->obis[4] == 2) { o182 = ntohl(item->dlu.data); - if(debugger->isActive(RemoteDebug::VERBOSE)) debugger->printf(" and value %d (dlu)", ntohl(item->dlu.data)); + if(debugger->isActive(RemoteDebug::VERBOSE)) debugger->printf(" and value %lu (dlu)", ntohl(item->dlu.data)); } } } else if(descriptor->obis[2] == 2) { if(descriptor->obis[3] == 7) { if(descriptor->obis[4] == 0) { o270 = ntohl(item->dlu.data); - if(debugger->isActive(RemoteDebug::VERBOSE)) debugger->printf(" and value %d (dlu)", ntohl(item->dlu.data)); + if(debugger->isActive(RemoteDebug::VERBOSE)) debugger->printf(" and value %lu (dlu)", ntohl(item->dlu.data)); } } else if(descriptor->obis[3] == 8) { if(descriptor->obis[4] == 0) { activeExportCounter = ntohl(item->dlu.data) / 1000.0; listType = listType >= 3 ? listType : 3; - if(debugger->isActive(RemoteDebug::VERBOSE)) debugger->printf(" and value %d (dlu)", ntohl(item->dlu.data)); + if(debugger->isActive(RemoteDebug::VERBOSE)) debugger->printf(" and value %lu (dlu)", ntohl(item->dlu.data)); } else if(descriptor->obis[4] == 1) { o281 = ntohl(item->dlu.data); - if(debugger->isActive(RemoteDebug::VERBOSE)) debugger->printf(" and value %d (dlu)", ntohl(item->dlu.data)); + if(debugger->isActive(RemoteDebug::VERBOSE)) debugger->printf(" and value %lu (dlu)", ntohl(item->dlu.data)); } else if(descriptor->obis[4] == 2) { o282 = ntohl(item->dlu.data); - if(debugger->isActive(RemoteDebug::VERBOSE)) debugger->printf(" and value %d (dlu)", ntohl(item->dlu.data)); + if(debugger->isActive(RemoteDebug::VERBOSE)) debugger->printf(" and value %lu (dlu)", ntohl(item->dlu.data)); } } } else if(descriptor->obis[2] == 96) { diff --git a/src/ams/DsmrParser.cpp b/src/ams/DsmrParser.cpp index 8ef8ef98..e6b006b1 100644 --- a/src/ams/DsmrParser.cpp +++ b/src/ams/DsmrParser.cpp @@ -4,7 +4,6 @@ int8_t DSMRParser::parse(uint8_t *buf, DataParserContext &ctx, bool verified) { uint16_t crcPos = 0; bool reachedEnd = verified; uint8_t lastByte = 0x00; - int c = 0; for(int pos = 0; pos < ctx.length; pos++) { uint8_t b = *(buf+pos); if(pos == 0 && b != '/') return DATA_PARSE_BOUNDRY_FLAG_MISSING; diff --git a/src/ams/GcmParser.cpp b/src/ams/GcmParser.cpp index 5ac92bfc..5f9e2bd5 100644 --- a/src/ams/GcmParser.cpp +++ b/src/ams/GcmParser.cpp @@ -27,7 +27,7 @@ int8_t GCMParser::parse(uint8_t *d, DataParserContext &ctx) { memcpy(ctx.system_title, ptr, systemTitleLength); memcpy(initialization_vector, ctx.system_title, systemTitleLength); - int len; + int len = 0; int headersize = 2 + systemTitleLength; ptr += systemTitleLength; if(((*ptr) & 0xFF) == 0x81) { diff --git a/src/ams/HdlcParser.cpp b/src/ams/HdlcParser.cpp index a82fd4bc..68a65ae1 100644 --- a/src/ams/HdlcParser.cpp +++ b/src/ams/HdlcParser.cpp @@ -5,8 +5,6 @@ int8_t HDLCParser::parse(uint8_t *d, DataParserContext &ctx) { int len; - uint8_t flag = *d; - uint8_t* ptr; if(ctx.length < 3) return DATA_PARSE_INCOMPLETE; diff --git a/src/ams/LlcParser.cpp b/src/ams/LlcParser.cpp index 3f348844..c6d41a56 100644 --- a/src/ams/LlcParser.cpp +++ b/src/ams/LlcParser.cpp @@ -1,7 +1,6 @@ #include "LlcParser.h" int8_t LLCParser::parse(uint8_t *buf, DataParserContext &ctx) { - LLCHeader* llc = (LLCHeader*) buf; ctx.length -= 3; return 3; } \ No newline at end of file diff --git a/src/ams/MbusParser.cpp b/src/ams/MbusParser.cpp index 731ffcaf..4a090da9 100644 --- a/src/ams/MbusParser.cpp +++ b/src/ams/MbusParser.cpp @@ -5,8 +5,6 @@ int8_t MBUSParser::parse(uint8_t *d, DataParserContext &ctx) { int headersize = 3; int footersize = 1; - uint8_t flag = *d; - uint8_t* ptr; // https://m-bus.com/documentation-wired/06-application-layer diff --git a/src/entsoe/DnbCurrParser.cpp b/src/entsoe/DnbCurrParser.cpp index c85dfb44..4c576ef1 100644 --- a/src/entsoe/DnbCurrParser.cpp +++ b/src/entsoe/DnbCurrParser.cpp @@ -22,7 +22,7 @@ void DnbCurrParser::flush() { } size_t DnbCurrParser::write(const uint8_t *buffer, size_t size) { - for(int i = 0; i < size; i++) { + for(size_t i = 0; i < size; i++) { write(buffer[i]); } return size;