From 7ea4fe881cc192dca5cb33827cadaac00eac3f04 Mon Sep 17 00:00:00 2001 From: Gunnar Skjold Date: Tue, 13 Dec 2022 21:05:42 +0100 Subject: [PATCH] HAN serial autodetect --- lib/AmsConfiguration/src/AmsConfiguration.cpp | 4 +- .../app/src/lib/ConfigurationPanel.svelte | 4 +- lib/SvelteUi/app/src/lib/Helpers.js | 3 ++ lib/SvelteUi/include/AmsWebServer.h | 2 +- lib/SvelteUi/src/AmsWebServer.cpp | 31 +++++-------- src/AmsToMqttBridge.ino | 46 ++++++++++++++++++- 6 files changed, 65 insertions(+), 25 deletions(-) diff --git a/lib/AmsConfiguration/src/AmsConfiguration.cpp b/lib/AmsConfiguration/src/AmsConfiguration.cpp index 8edc4817..50b07ea1 100644 --- a/lib/AmsConfiguration/src/AmsConfiguration.cpp +++ b/lib/AmsConfiguration/src/AmsConfiguration.cpp @@ -218,8 +218,8 @@ bool AmsConfiguration::setMeterConfig(MeterConfig& config) { } void AmsConfiguration::clearMeter(MeterConfig& config) { - config.baud = 2400; - config.parity = 11; // 8E1 + config.baud = 0; + config.parity = 0; config.invert = false; config.distributionSystem = 0; config.mainFuse = 0; diff --git a/lib/SvelteUi/app/src/lib/ConfigurationPanel.svelte b/lib/SvelteUi/app/src/lib/ConfigurationPanel.svelte index 1e423e1f..73971c5e 100644 --- a/lib/SvelteUi/app/src/lib/ConfigurationPanel.svelte +++ b/lib/SvelteUi/app/src/lib/ConfigurationPanel.svelte @@ -225,6 +225,7 @@ Serial configuration
- + diff --git a/lib/SvelteUi/app/src/lib/Helpers.js b/lib/SvelteUi/app/src/lib/Helpers.js index 6712ceae..eb313ce5 100644 --- a/lib/SvelteUi/app/src/lib/Helpers.js +++ b/lib/SvelteUi/app/src/lib/Helpers.js @@ -104,6 +104,9 @@ export function hanError(err) { case -51: return "Authentication failed"; case -52: return "Decryption failed"; case -53: return "Encryption key invalid"; + case 90: return "No HAN data received last 30s"; + case 98: return "Exception in code, debugging necessary"; + case 99: return "Autodetection failed"; } if(err < 0) return "Unspecified error "+err; return ""; diff --git a/lib/SvelteUi/include/AmsWebServer.h b/lib/SvelteUi/include/AmsWebServer.h index 1a49ecfb..b5714da5 100644 --- a/lib/SvelteUi/include/AmsWebServer.h +++ b/lib/SvelteUi/include/AmsWebServer.h @@ -60,7 +60,7 @@ private: bool performRestart = false; bool performUpgrade = false; bool rebootForUpgrade = false; - String priceRegion; + String priceRegion = ""; static const uint16_t BufferSize = 2048; char* buf; diff --git a/lib/SvelteUi/src/AmsWebServer.cpp b/lib/SvelteUi/src/AmsWebServer.cpp index 81b73f37..ad410dba 100644 --- a/lib/SvelteUi/src/AmsWebServer.cpp +++ b/lib/SvelteUi/src/AmsWebServer.cpp @@ -273,16 +273,6 @@ void AmsWebServer::sysinfoJson() { ESP.restart(); #endif performRestart = false; - } else { - time_t now = time(nullptr); - if(now < BUILD_EPOCH && server.hasArg(F("t"))) { - time_t clientTime = server.arg(F("t")).toInt(); - if(clientTime > BUILD_EPOCH) { - timeval tv { clientTime, 0}; - settimeofday(&tv, nullptr); - if(debugger->isActive(RemoteDebug::INFO)) debugger->printf("Internal clock synchronized with client\n"); - } - } } } @@ -290,7 +280,7 @@ void AmsWebServer::dataJson() { if(debugger->isActive(RemoteDebug::DEBUG)) debugger->printf("Serving /data.json over http...\n"); uint64_t millis = millis64(); - if(!checkSecurity(2)) + if(!checkSecurity(2, true)) return; float vcc = hw->getVcc(); @@ -1322,6 +1312,9 @@ void AmsWebServer::handleSave() { void AmsWebServer::reboot() { if(debugger->isActive(RemoteDebug::DEBUG)) debugger->printf("Serving /reboot over http...\n"); + if(!checkSecurity(1)) + return; + server.send(200, MIME_JSON, "{\"reboot\":true}"); server.handleClient(); @@ -1407,13 +1400,13 @@ void AmsWebServer::upgrade() { void AmsWebServer::firmwareHtml() { if(debugger->isActive(RemoteDebug::DEBUG)) debugger->printf(PSTR("Serving /firmware.html over http...")); + if(!checkSecurity(1)) + return; + server.sendHeader(HEADER_CACHE_CONTROL, CACHE_CONTROL_NO_CACHE); server.sendHeader(HEADER_PRAGMA, PRAGMA_NO_CACHE); server.sendHeader(HEADER_EXPIRES, EXPIRES_OFF); - if(!checkSecurity(1)) - return; - server.setContentLength(FIRMWARE_HTML_LEN); server.send_P(200, MIME_HTML, FIRMWARE_HTML); } @@ -1979,15 +1972,15 @@ void AmsWebServer::configFileDownload() { EnergyAccountingConfig eac; config->getEnergyAccountingConfig(eac); EnergyAccountingData ead = ea->getData(); - server.sendContent(buf, snprintf_P(buf, BufferSize, PSTR("energyaccounting %d %d %.2f %.2f %.2f %.2f %d %.2f %d %.2f %d %.2f %d %.2f %d %.2f"), + server.sendContent(buf, snprintf_P(buf, BufferSize, PSTR("energyaccounting %d %d %.2f %d %d %.2f %d %d %d %.2f %d %.2f %d %.2f %d %.2f %d %.2f"), ead.version, ead.month, ead.costYesterday / 10.0, - ead.costThisMonth / 1.0, - ead.costLastMonth / 1.0, + ead.costThisMonth, + ead.costLastMonth, ead.incomeYesterday / 10.0, - ead.incomeThisMonth / 1.0, - ead.incomeLastMonth / 1.0, + ead.incomeThisMonth, + ead.incomeLastMonth, ead.peaks[0].day, ead.peaks[0].value / 100.0, ead.peaks[1].day, diff --git a/src/AmsToMqttBridge.ino b/src/AmsToMqttBridge.ino index 3cd38730..74f40306 100644 --- a/src/AmsToMqttBridge.ino +++ b/src/AmsToMqttBridge.ino @@ -233,9 +233,9 @@ void setup() { break; } #if defined(ESP32) - Serial.begin(meterConfig.baud, serialConfig, -1, -1, meterConfig.invert); + Serial.begin(meterConfig.baud == 0 ? 2400 : meterConfig.baud: , serialConfig, -1, -1, meterConfig.invert); #else - Serial.begin(meterConfig.baud, serialConfig, SERIAL_FULL, 1, meterConfig.invert); + Serial.begin(meterConfig.baud == 0 ? 2400 : meterConfig.baud, serialConfig, SERIAL_FULL, 1, meterConfig.invert); #endif } @@ -404,6 +404,13 @@ unsigned long lastSysupdate = 0; unsigned long lastErrorBlink = 0; int lastError = 0; +bool meterAutodetect = false; +unsigned long meterAutodetectLastChange = 0; +uint8_t meterAutoIndex = 0; +uint32_t bauds[] = { 2400, 2400, 115200, 115200 }; +uint8_t parities[] = { 11, 3, 3, 3 }; +bool inverts[] = { false, false, false, true }; + void loop() { Debug.handle(); unsigned long now = millis(); @@ -593,6 +600,31 @@ void loop() { } } catch(const std::exception& e) { debugE("Exception in readHanPort (%s)", e.what()); + meterState.setLastError(98); + } + try { + if(meterState.getLastError() > 0) { + if(now - meterAutodetectLastChange > 15000 && (meterConfig.baud == 0 || meterConfig.parity == 0)) { + meterAutodetect = true; + meterAutoIndex++; // Default is to try the first one in setup() + debugI("Meter serial autodetect, swapping to: %d, %d, %s", bauds[meterAutoIndex], parities[meterAutoIndex], inverts[meterAutoIndex] ? "true" : "false"); + if(meterAutoIndex >= 4) meterAutoIndex = 0; + setupHanPort(gpioConfig.hanPin, bauds[meterAutoIndex], parities[meterAutoIndex], inverts[meterAutoIndex]); + meterAutodetectLastChange = now; + } + } else if(meterAutodetect) { + meterAutoIndex--; // Last one worked, so lets use that + debugI("Meter serial autodetected, saving: %d, %d, %s", bauds[meterAutoIndex], parities[meterAutoIndex], inverts[meterAutoIndex] ? "true" : "false"); + meterAutodetect = false; + meterConfig.baud = bauds[meterAutoIndex]; + meterConfig.parity = parities[meterAutoIndex]; + meterConfig.invert = inverts[meterAutoIndex]; + config.setMeterConfig(meterConfig); + setupHanPort(gpioConfig.hanPin, meterConfig.baud, meterConfig.parity, meterConfig.invert); + } + } catch(const std::exception& e) { + debugE("Exception in meter autodetect (%s)", e.what()); + meterState.setLastError(99); } delay(1); // Needed for auto modem sleep @@ -606,6 +638,15 @@ void loop() { void setupHanPort(uint8_t pin, uint32_t baud, uint8_t parityOrdinal, bool invert) { if(Debug.isActive(RemoteDebug::INFO)) Debug.printf((char*) F("(setupHanPort) Setting up HAN on pin %d with baud %d and parity %d\n"), pin, baud, parityOrdinal); + if(baud == 0) { + baud = bauds[meterAutoIndex]; + parityOrdinal = parities[meterAutoIndex]; + invert = inverts[meterAutoIndex]; + } + if(parityOrdinal == 0) { + parityOrdinal = 3; // 8N1 + } + HardwareSerial *hwSerial = NULL; if(pin == 3 || pin == 113) { hwSerial = &Serial; @@ -723,6 +764,7 @@ void errorBlink() { 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 + if(meterState.getLastError() == 0) meterState.setLastError(90); return; } break;