From 6b09ca056e41bb412f76a03028e28ba3f81763c3 Mon Sep 17 00:00:00 2001 From: Bernhard Kirchen Date: Mon, 17 Jun 2024 21:02:04 +0200 Subject: [PATCH] Feature: SML power meters: reset SML decoder implement a function which allows to reset the SML decoder. this new function is used after a datagram ends. for the SML HTTP power meter this is simple: after all bytes from the request's answer have been decoded, we reset the decoder. for the SML serial power meter, we perform the reset after a datagram ended based on timing (no new bytes have been received for a specific amount of time). --- include/PowerMeterSml.h | 1 + lib/SMLParser/sml.cpp | 6 ++++++ lib/SMLParser/sml.h | 1 + src/PowerMeterHttpSml.cpp | 2 ++ src/PowerMeterSerialSml.cpp | 2 ++ src/PowerMeterSml.cpp | 10 ++++++++-- 6 files changed, 20 insertions(+), 2 deletions(-) diff --git a/include/PowerMeterSml.h b/include/PowerMeterSml.h index a0d614201..79e37ab9a 100644 --- a/include/PowerMeterSml.h +++ b/include/PowerMeterSml.h @@ -20,6 +20,7 @@ class PowerMeterSml : public PowerMeterProvider { explicit PowerMeterSml(char const* user) : _user(user) { } + void reset(); void processSmlByte(uint8_t byte); private: diff --git a/lib/SMLParser/sml.cpp b/lib/SMLParser/sml.cpp index 574dc12df..e330ef689 100644 --- a/lib/SMLParser/sml.cpp +++ b/lib/SMLParser/sml.cpp @@ -189,6 +189,12 @@ void checkMagicByte(unsigned char &byte) } } +void smlReset(void) +{ + len = 4; // expect start sequence + currentState = SML_START; +} + sml_states_t smlState(unsigned char currentByte) { unsigned char size; diff --git a/lib/SMLParser/sml.h b/lib/SMLParser/sml.h index 6830dcc67..de844a4dc 100644 --- a/lib/SMLParser/sml.h +++ b/lib/SMLParser/sml.h @@ -92,6 +92,7 @@ typedef enum { SML_COUNT = 255 } sml_units_t; +void smlReset(void); sml_states_t smlState(unsigned char byte); bool smlOBISCheck(const unsigned char *obis); void smlOBISManufacturer(unsigned char *str, int maxSize); diff --git a/src/PowerMeterHttpSml.cpp b/src/PowerMeterHttpSml.cpp index 3331603ee..7149e12a8 100644 --- a/src/PowerMeterHttpSml.cpp +++ b/src/PowerMeterHttpSml.cpp @@ -107,5 +107,7 @@ String PowerMeterHttpSml::poll() processSmlByte(pStream->read()); } + PowerMeterSml::reset(); + return ""; } diff --git a/src/PowerMeterSerialSml.cpp b/src/PowerMeterSerialSml.cpp index 41f845a00..123a10ddd 100644 --- a/src/PowerMeterSerialSml.cpp +++ b/src/PowerMeterSerialSml.cpp @@ -110,6 +110,8 @@ void PowerMeterSerialSml::pollingLoop() lastAvailable = 0; + PowerMeterSml::reset(); + lock.lock(); } } diff --git a/src/PowerMeterSml.cpp b/src/PowerMeterSml.cpp index 021b48cd6..c44662104 100644 --- a/src/PowerMeterSml.cpp +++ b/src/PowerMeterSml.cpp @@ -30,6 +30,12 @@ void PowerMeterSml::doMqttPublish() const #undef PUB } +void PowerMeterSml::reset() +{ + smlReset(); + _cache = { std::nullopt }; +} + void PowerMeterSml::processSmlByte(uint8_t byte) { switch (smlState(byte)) { @@ -52,12 +58,12 @@ void PowerMeterSml::processSmlByte(uint8_t byte) case SML_FINAL: gotUpdate(); _values = _cache; - _cache = { std::nullopt }; + reset(); MessageOutput.printf("[%s] TotalPower: %5.2f\r\n", _user.c_str(), getPowerTotal()); break; case SML_CHECKSUM_ERROR: - _cache = { std::nullopt }; + reset(); MessageOutput.printf("[%s] checksum verification failed\r\n", _user.c_str()); break;