diff --git a/src/AmsConfiguration.cpp b/src/AmsConfiguration.cpp index 60042447..29aa3aae 100644 --- a/src/AmsConfiguration.cpp +++ b/src/AmsConfiguration.cpp @@ -24,6 +24,7 @@ bool AmsConfiguration::getWiFiConfig(WiFiConfig& config) { EEPROM.begin(EEPROM_SIZE); EEPROM.get(CONFIG_WIFI_START, config); EEPROM.end(); + if(config.sleep > 2) config.sleep = 1; return true; } else { clearWifi(config); @@ -33,6 +34,7 @@ bool AmsConfiguration::getWiFiConfig(WiFiConfig& config) { bool AmsConfiguration::setWiFiConfig(WiFiConfig& config) { WiFiConfig existing; + if(config.sleep > 2) config.sleep = 1; if(getWiFiConfig(existing)) { wifiChanged |= strcmp(config.ssid, existing.ssid) != 0; wifiChanged |= strcmp(config.psk, existing.psk) != 0; @@ -45,6 +47,7 @@ bool AmsConfiguration::setWiFiConfig(WiFiConfig& config) { } wifiChanged |= strcmp(config.hostname, existing.hostname) != 0; wifiChanged |= config.power != existing.power; + wifiChanged |= config.sleep != existing.sleep; } else { wifiChanged = true; } @@ -70,6 +73,7 @@ void AmsConfiguration::clearWifi(WiFiConfig& config) { #endif strcpy(config.hostname, (String("ams-") + String(chipId, HEX)).c_str()); config.mdns = true; + config.sleep = 0xFF; } void AmsConfiguration::clearWifiIp(WiFiConfig& config) { @@ -671,6 +675,14 @@ bool AmsConfiguration::hasConfig() { configVersion = 0; return false; } + case 95: + configVersion = -1; // Prevent loop + if(relocateConfig95()) { + configVersion = 96; + } else { + configVersion = 0; + return false; + } case EEPROM_CHECK_SUM: return true; default: @@ -848,6 +860,23 @@ bool AmsConfiguration::relocateConfig94() { return ret; } +bool AmsConfiguration::relocateConfig95() { + MeterConfig meter; + MeterConfig95 meter95; + EEPROM.begin(EEPROM_SIZE); + EEPROM.get(CONFIG_METER_START, meter); + EEPROM.get(CONFIG_METER_START, meter95); + meter.wattageMultiplier = meter95.wattageMultiplier; + meter.voltageMultiplier = meter95.voltageMultiplier; + meter.amperageMultiplier = meter95.amperageMultiplier; + meter.accumulatedMultiplier = meter95.accumulatedMultiplier; + EEPROM.put(CONFIG_METER_START, meter); + EEPROM.put(EEPROM_CONFIG_ADDRESS, 96); + bool ret = EEPROM.commit(); + EEPROM.end(); + return ret; +} + bool AmsConfiguration::save() { EEPROM.begin(EEPROM_SIZE); EEPROM.put(EEPROM_CONFIG_ADDRESS, EEPROM_CHECK_SUM); diff --git a/src/AmsConfiguration.h b/src/AmsConfiguration.h index f0ad1098..1413e45d 100644 --- a/src/AmsConfiguration.h +++ b/src/AmsConfiguration.h @@ -4,7 +4,7 @@ #include "Arduino.h" #define EEPROM_SIZE 1024*3 -#define EEPROM_CHECK_SUM 95 // Used to check if config is stored. Change if structure changes +#define EEPROM_CHECK_SUM 96 // Used to check if config is stored. Change if structure changes #define EEPROM_CONFIG_ADDRESS 0 #define EEPROM_TEMP_CONFIG_ADDRESS 2048 @@ -54,7 +54,8 @@ struct WiFiConfig { char hostname[32]; bool mdns; uint8_t power; -}; // 210 + uint8_t sleep; +}; // 211 struct MqttConfig86 { char host[128]; @@ -87,6 +88,23 @@ struct WebConfig { }; // 129 struct MeterConfig { + uint32_t baud; + uint8_t parity; + bool invert; + uint8_t distributionSystem; + uint8_t mainFuse; + uint8_t productionCapacity; + uint8_t encryptionKey[16]; + uint8_t authenticationKey[16]; + uint32_t wattageMultiplier; + uint32_t voltageMultiplier; + uint32_t amperageMultiplier; + uint32_t accumulatedMultiplier; + uint8_t source; + uint8_t parser; +}; // 50 + +struct MeterConfig95 { uint32_t baud; uint8_t parity; bool invert; @@ -269,6 +287,7 @@ private: bool relocateConfig92(); // 2.0.3 bool relocateConfig93(); // 2.1.0 bool relocateConfig94(); // 2.1.4 + bool relocateConfig95(); // 2.1.13 void saveToFs(); bool loadFromFs(uint8_t version); diff --git a/src/AmsToMqttBridge.ino b/src/AmsToMqttBridge.ino index 0d8a0b0a..b06b7f05 100644 --- a/src/AmsToMqttBridge.ino +++ b/src/AmsToMqttBridge.ino @@ -805,7 +805,7 @@ bool readHanPort() { hanBuffer[len++] = hanSerial->read(); ctx.length = len; pos = unwrapData((uint8_t *) hanBuffer, ctx); - if(pos >= 0) { + if(ctx.type > 0 && pos >= 0) { if(ctx.type == DATA_TAG_DLMS) { debugV("Received valid DLMS at %d", pos); } else if(ctx.type == DATA_TAG_DSMR) { @@ -821,6 +821,7 @@ bool readHanPort() { if(pos == DATA_PARSE_INCOMPLETE) { return false; } else if(pos == DATA_PARSE_UNKNOWN_DATA) { + debugV("Unknown data payload:"); len = len + hanSerial->readBytes(hanBuffer+len, BUF_SIZE_HAN-len); debugPrint(hanBuffer, 0, len); len = 0; @@ -1049,7 +1050,6 @@ void WiFi_connect() { } #endif WiFi.mode(WIFI_STA); - WiFi.setSleep(WIFI_PS_MAX_MODEM); #if defined(ESP32) if(wifi.power >= 195) WiFi.setTxPower(WIFI_POWER_19_5dBm); @@ -1110,6 +1110,19 @@ void WiFi_connect() { WiFi.setAutoReconnect(true); WiFi.persistent(true); if(WiFi.begin(wifi.ssid, wifi.psk)) { + if(wifi.sleep <= 2) { + switch(wifi.sleep) { + case 0: + WiFi.setSleep(WIFI_PS_NONE); + break; + case 1: + WiFi.setSleep(WIFI_PS_MIN_MODEM); + break; + case 2: + WiFi.setSleep(WIFI_PS_MAX_MODEM); + break; + } + } yield(); } else { if (Debug.isActive(RemoteDebug::ERROR)) debugI("Unable to start WiFi"); @@ -1168,7 +1181,7 @@ int16_t unwrapData(uint8_t *buf, DataParserContext &context) { if(res >= 0) doRet = true; break; default: - debugE("Ended up in default case while unwrapping..."); + debugE("Ended up in default case while unwrapping...(tag %02X)", tag); return DATA_PARSE_UNKNOWN_DATA; } lastTag = tag; diff --git a/src/LNG.cpp b/src/LNG.cpp index f3ec7cd5..cde094e7 100644 --- a/src/LNG.cpp +++ b/src/LNG.cpp @@ -1,6 +1,6 @@ #include "LNG.h" #include "lwip/def.h" -#include "ams/Cosem.h" +#include "ams/ntohll.h" LNG::LNG(const char* payload, uint8_t useMeterType, MeterConfig* meterConfig, DataParserContext &ctx, RemoteDebug* debugger) { LngHeader* h = (LngHeader*) payload; @@ -11,9 +11,10 @@ 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; + uint64_t o170 = 0, o270 = 0; + uint64_t o180 = 0, o280 = 0; + uint64_t o181 = 0, o182 = 0; + uint64_t o281 = 0, o282 = 0; LngObisDescriptor* descriptor = (LngObisDescriptor*) ptr; for(uint8_t x = 0; x < h->arrayLength-1; x++) { ptr = (uint8_t*) &descriptor[1]; @@ -24,39 +25,41 @@ 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) { - o170 = ntohl(item->dlu.data); - if(debugger->isActive(RemoteDebug::VERBOSE)) debugger->printf(" and value %lu (dlu)", ntohl(item->dlu.data)); + o170 = getNumber(item); + if(debugger->isActive(RemoteDebug::VERBOSE)) debugger->printf(" and value %lu", o170); } } else if(descriptor->obis[3] == 8) { if(descriptor->obis[4] == 0) { - activeImportCounter = ntohl(item->dlu.data) / 1000.0; + o180 = getNumber(item); listType = listType >= 3 ? listType : 3; - if(debugger->isActive(RemoteDebug::VERBOSE)) debugger->printf(" and value %lu (dlu)", ntohl(item->dlu.data)); + if(debugger->isActive(RemoteDebug::VERBOSE)) debugger->printf(" and value %lu", o180); + activeImportCounter = o180 / 1000.0; } else if(descriptor->obis[4] == 1) { - o181 = ntohl(item->dlu.data); - if(debugger->isActive(RemoteDebug::VERBOSE)) debugger->printf(" and value %lu (dlu)", ntohl(item->dlu.data)); + o181 = getNumber(item); + if(debugger->isActive(RemoteDebug::VERBOSE)) debugger->printf(" and value %lu", o181); } else if(descriptor->obis[4] == 2) { - o182 = ntohl(item->dlu.data); - if(debugger->isActive(RemoteDebug::VERBOSE)) debugger->printf(" and value %lu (dlu)", ntohl(item->dlu.data)); + o182 = getNumber(item); + if(debugger->isActive(RemoteDebug::VERBOSE)) debugger->printf(" and value %lu", o182); } } } 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 %lu (dlu)", ntohl(item->dlu.data)); + o270 = getNumber(item); + if(debugger->isActive(RemoteDebug::VERBOSE)) debugger->printf(" and value %lu", o270); } } else if(descriptor->obis[3] == 8) { if(descriptor->obis[4] == 0) { - activeExportCounter = ntohl(item->dlu.data) / 1000.0; + o280 = getNumber(item); listType = listType >= 3 ? listType : 3; - if(debugger->isActive(RemoteDebug::VERBOSE)) debugger->printf(" and value %lu (dlu)", ntohl(item->dlu.data)); + if(debugger->isActive(RemoteDebug::VERBOSE)) debugger->printf(" and value %lu", o280); + activeExportCounter = o280 / 1000.0; } else if(descriptor->obis[4] == 1) { - o281 = ntohl(item->dlu.data); - if(debugger->isActive(RemoteDebug::VERBOSE)) debugger->printf(" and value %lu (dlu)", ntohl(item->dlu.data)); + o281 = getNumber(item); + if(debugger->isActive(RemoteDebug::VERBOSE)) debugger->printf(" and value %lu", o281); } else if(descriptor->obis[4] == 2) { - o282 = ntohl(item->dlu.data); - if(debugger->isActive(RemoteDebug::VERBOSE)) debugger->printf(" and value %lu (dlu)", ntohl(item->dlu.data)); + o282 = getNumber(item); + if(debugger->isActive(RemoteDebug::VERBOSE)) debugger->printf(" and value %lu", o282); } } } else if(descriptor->obis[2] == 96) { @@ -101,11 +104,49 @@ LNG::LNG(const char* payload, uint8_t useMeterType, MeterConfig* meterConfig, Da if((*data) == 0x09) { data += (*(data+1))+2; - } else { + } else if((*data) == 0x15) { + data += 9; + } else if((*data) == 0x06) { data += 5; + } else if((*data) == 0x12) { + data += 3; } lastUpdateMillis = millis(); } } -} \ No newline at end of file +} + +uint64_t LNG::getNumber(CosemData* item) { + if(item != NULL) { + uint64_t ret = 0.0; + switch(item->base.type) { + case CosemTypeLongSigned: { + int16_t i16 = ntohs(item->ls.data); + return i16; + } + case CosemTypeLongUnsigned: { + uint16_t u16 = ntohs(item->lu.data); + return u16; + } + case CosemTypeDLongSigned: { + int32_t i32 = ntohl(item->dlu.data); + return i32; + } + case CosemTypeDLongUnsigned: { + uint32_t u32 = ntohl(item->dlu.data); + return u32; + } + case CosemTypeLong64Signed: { + int64_t i64 = ntohll(item->l64s.data); + return i64; + } + case CosemTypeLong64Unsigned: { + uint64_t u64 = ntohll(item->l64u.data); + return u64; + } + } + return ret; + } + return 0.0; +} diff --git a/src/LNG.h b/src/LNG.h index f448b105..0cf4e6df 100644 --- a/src/LNG.h +++ b/src/LNG.h @@ -4,6 +4,7 @@ #include "AmsData.h" #include "AmsConfiguration.h" #include "ams/DataParser.h" +#include "ams/Cosem.h" #include "RemoteDebug.h" struct LngHeader { @@ -25,6 +26,7 @@ struct LngObisDescriptor { class LNG : public AmsData { public: LNG(const char* payload, uint8_t useMeterType, MeterConfig* meterConfig, DataParserContext &ctx, RemoteDebug* debugger); + uint64_t getNumber(CosemData* item); }; #endif diff --git a/src/web/AmsWebServer.cpp b/src/web/AmsWebServer.cpp index 94cb465c..5634ebb2 100644 --- a/src/web/AmsWebServer.cpp +++ b/src/web/AmsWebServer.cpp @@ -444,6 +444,9 @@ void AmsWebServer::configWifiHtml() { html.replace(F("{h}"), wifi.hostname); html.replace(F("{m}"), wifi.mdns ? F("checked") : F("")); html.replace(F("{w}"), String(wifi.power / 10.0, 1)); + html.replace(F("{z0}"), wifi.sleep == 0 ? "selected" : ""); + html.replace(F("{z1}"), wifi.sleep == 1 ? "selected" : ""); + html.replace(F("{z2}"), wifi.sleep == 2 ? "selected" : ""); #if defined(ESP32) html.replace(F("{wm}"), "19.5"); #elif defined(ESP8266) @@ -1014,9 +1017,11 @@ void AmsWebServer::handleSetup() { DebugConfig debugConfig; config->getDebugConfig(debugConfig); - config->clear(); + WiFiConfig wifi; + config->clearWifi(wifi); + switch(sys.boardType) { case 0: // roarfred gpioConfig->hanPin = 3; @@ -1041,6 +1046,7 @@ void AmsWebServer::handleSetup() { gpioConfig->ledInverted = true; gpioConfig->tempSensorPin = 5; gpioConfig->vccBootLimit = 33; + wifi.sleep = 1; break; case 3: // Pow UART0 gpioConfig->hanPin = 3; @@ -1050,6 +1056,7 @@ void AmsWebServer::handleSetup() { gpioConfig->ledPinRed = 13; gpioConfig->ledPinGreen = 14; gpioConfig->ledRgbInverted = true; + wifi.sleep = 1; break; case 4: // Pow GPIO12 gpioConfig->hanPin = 12; @@ -1059,6 +1066,7 @@ void AmsWebServer::handleSetup() { gpioConfig->ledPinRed = 13; gpioConfig->ledPinGreen = 14; gpioConfig->ledRgbInverted = true; + wifi.sleep = 1; break; case 5: // Pow-K+ UART2 gpioConfig->hanPin = 16; @@ -1069,6 +1077,7 @@ void AmsWebServer::handleSetup() { gpioConfig->vccPin = 10; gpioConfig->vccResistorGnd = 22; gpioConfig->vccResistorVcc = 33; + wifi.sleep = 1; break; case 6: // Pow-P1 gpioConfig->hanPin = 16; @@ -1089,6 +1098,7 @@ void AmsWebServer::handleSetup() { gpioConfig->vccPin = 10; gpioConfig->vccResistorGnd = 22; gpioConfig->vccResistorVcc = 33; + wifi.sleep = 2; break; case 101: // D1 gpioConfig->hanPin = 5; @@ -1125,18 +1135,17 @@ void AmsWebServer::handleSetup() { break; case 50: // S2 gpioConfig->hanPin = 18; + wifi.sleep = 1; break; case 51: // S2-mini gpioConfig->hanPin = 18; gpioConfig->ledPin = 15; gpioConfig->ledInverted = false; gpioConfig->apPin = 0; + wifi.sleep = 1; break; } - WiFiConfig wifi; - config->clearWifi(wifi); - strcpy(wifi.ssid, server.arg(F("wifiSsid")).c_str()); strcpy(wifi.psk, server.arg(F("wifiPassword")).c_str()); @@ -1257,7 +1266,9 @@ void AmsWebServer::handleSave() { if(server.hasArg(F("h")) && !server.arg(F("h")).isEmpty()) { strcpy(wifi.hostname, server.arg(F("h")).c_str()); } + wifi.mdns = server.arg(F("m")) == F("true"); wifi.power = server.arg(F("w")).toFloat() * 10; + wifi.sleep = server.arg(F("z")).toInt(); config->setWiFiConfig(wifi); } diff --git a/web/wifi.html b/web/wifi.html index 83db137e..a99adc16 100644 --- a/web/wifi.html +++ b/web/wifi.html @@ -37,7 +37,7 @@