From 52dd79691b82e32fd9e61ade165c551109de7af8 Mon Sep 17 00:00:00 2001 From: Maurice Makaay Date: Fri, 24 Sep 2021 14:15:22 +0200 Subject: [PATCH] Read unencrypted DSMR telegrams in chunks (#2382) Co-authored-by: Maurice Makaay --- esphome/components/dsmr/dsmr.cpp | 31 +++++++++++++++++++------------ esphome/components/dsmr/dsmr.h | 1 + 2 files changed, 20 insertions(+), 12 deletions(-) diff --git a/esphome/components/dsmr/dsmr.cpp b/esphome/components/dsmr/dsmr.cpp index 54c4343cfe..b798fe5d44 100644 --- a/esphome/components/dsmr/dsmr.cpp +++ b/esphome/components/dsmr/dsmr.cpp @@ -20,19 +20,22 @@ void Dsmr::loop() { } void Dsmr::receive_telegram_() { - while (available()) { + int count = MAX_BYTES_PER_LOOP; + while (available() && count-- > 0) { const char c = read(); - if (c == '/') { // header: forward slash + // Find a new telegram header, i.e. forward slash. + if (c == '/') { ESP_LOGV(TAG, "Header found"); header_found_ = true; footer_found_ = false; telegram_len_ = 0; } - if (!header_found_) continue; - if (telegram_len_ >= MAX_TELEGRAM_LENGTH) { // Buffer overflow + + // Check for buffer overflow. + if (telegram_len_ >= MAX_TELEGRAM_LENGTH) { header_found_ = false; footer_found_ = false; ESP_LOGE(TAG, "Error: Message larger than buffer"); @@ -45,18 +48,22 @@ void Dsmr::receive_telegram_() { while (c == '(' && (telegram_[telegram_len_ - 1] == '\n' || telegram_[telegram_len_ - 1] == '\r')) telegram_len_--; + // Store the byte in the buffer. telegram_[telegram_len_] = c; telegram_len_++; - if (c == '!') { // footer: exclamation mark + + // Check for a footer, i.e. exlamation mark, followed by a hex checksum. + if (c == '!') { ESP_LOGV(TAG, "Footer found"); footer_found_ = true; - } else { - if (footer_found_ && c == 10) { // last \n after footer - header_found_ = false; - // Parse message - if (parse_telegram()) - return; - } + continue; + } + // Check for the end of the hex checksum, i.e. a newline. + if (footer_found_ && c == '\n') { + header_found_ = false; + // Parse the telegram and publish sensor values. + if (parse_telegram()) + return; } } } diff --git a/esphome/components/dsmr/dsmr.h b/esphome/components/dsmr/dsmr.h index dfee3b338a..4f9a66b3d0 100644 --- a/esphome/components/dsmr/dsmr.h +++ b/esphome/components/dsmr/dsmr.h @@ -17,6 +17,7 @@ namespace esphome { namespace dsmr { static constexpr uint32_t MAX_TELEGRAM_LENGTH = 1500; +static constexpr uint32_t MAX_BYTES_PER_LOOP = 50; static constexpr uint32_t POLL_TIMEOUT = 1000; using namespace ::dsmr::fields;