1
0
mirror of https://github.com/esphome/esphome.git synced 2025-10-05 19:33:47 +01:00

Add max_telegram_length option to dsmr (#2674)

Co-authored-by: Maurice Makaay <mmakaay1@xs4all.net>
Co-authored-by: Oxan van Leeuwen <oxan@oxanvanleeuwen.nl>
This commit is contained in:
Maurice Makaay
2021-11-17 18:24:02 +01:00
committed by GitHub
parent df6730be55
commit dee5d639e2
4 changed files with 50 additions and 27 deletions

View File

@@ -12,11 +12,15 @@ namespace dsmr {
static const char *const TAG = "dsmr";
void Dsmr::setup() {
telegram_ = new char[max_telegram_len_]; // NOLINT
}
void Dsmr::loop() {
if (this->decryption_key_.empty())
this->receive_telegram_();
if (decryption_key_.empty())
receive_telegram_();
else
this->receive_encrypted_();
receive_encrypted_();
}
bool Dsmr::available_within_timeout_() {
@@ -51,10 +55,10 @@ void Dsmr::receive_telegram_() {
continue;
// Check for buffer overflow.
if (telegram_len_ >= MAX_TELEGRAM_LENGTH) {
if (telegram_len_ >= max_telegram_len_) {
header_found_ = false;
footer_found_ = false;
ESP_LOGE(TAG, "Error: telegram larger than buffer (%d bytes)", MAX_TELEGRAM_LENGTH);
ESP_LOGE(TAG, "Error: telegram larger than buffer (%d bytes)", max_telegram_len_);
return;
}
@@ -86,9 +90,7 @@ void Dsmr::receive_telegram_() {
}
void Dsmr::receive_encrypted_() {
// Encrypted buffer
uint8_t buffer[MAX_TELEGRAM_LENGTH];
size_t buffer_length = 0;
encrypted_telegram_len_ = 0;
size_t packet_size = 0;
while (true) {
@@ -114,39 +116,39 @@ void Dsmr::receive_encrypted_() {
}
// Check for buffer overflow.
if (buffer_length >= MAX_TELEGRAM_LENGTH) {
if (encrypted_telegram_len_ >= max_telegram_len_) {
header_found_ = false;
ESP_LOGE(TAG, "Error: encrypted telegram larger than buffer (%d bytes)", MAX_TELEGRAM_LENGTH);
ESP_LOGE(TAG, "Error: encrypted telegram larger than buffer (%d bytes)", max_telegram_len_);
return;
}
buffer[buffer_length++] = c;
encrypted_telegram_[encrypted_telegram_len_++] = c;
if (packet_size == 0 && buffer_length > 20) {
if (packet_size == 0 && encrypted_telegram_len_ > 20) {
// Complete header + data bytes
packet_size = 13 + (buffer[11] << 8 | buffer[12]);
packet_size = 13 + (encrypted_telegram_[11] << 8 | encrypted_telegram_[12]);
ESP_LOGV(TAG, "Encrypted telegram size: %d bytes", packet_size);
}
if (buffer_length == packet_size && packet_size > 0) {
if (encrypted_telegram_len_ == packet_size && packet_size > 0) {
ESP_LOGV(TAG, "End of encrypted telegram found");
GCM<AES128> *gcmaes128{new GCM<AES128>()};
gcmaes128->setKey(this->decryption_key_.data(), gcmaes128->keySize());
gcmaes128->setKey(decryption_key_.data(), gcmaes128->keySize());
// the iv is 8 bytes of the system title + 4 bytes frame counter
// system title is at byte 2 and frame counter at byte 15
for (int i = 10; i < 14; i++)
buffer[i] = buffer[i + 4];
encrypted_telegram_[i] = encrypted_telegram_[i + 4];
constexpr uint16_t iv_size{12};
gcmaes128->setIV(&buffer[2], iv_size);
gcmaes128->decrypt(reinterpret_cast<uint8_t *>(this->telegram_),
gcmaes128->setIV(&encrypted_telegram_[2], iv_size);
gcmaes128->decrypt(reinterpret_cast<uint8_t *>(telegram_),
// the ciphertext start at byte 18
&buffer[18],
&encrypted_telegram_[18],
// cipher size
buffer_length - 17);
encrypted_telegram_len_ - 17);
delete gcmaes128; // NOLINT(cppcoreguidelines-owning-memory)
telegram_len_ = strnlen(this->telegram_, sizeof(this->telegram_));
telegram_len_ = strnlen(telegram_, max_telegram_len_);
ESP_LOGV(TAG, "Decrypted telegram size: %d bytes", telegram_len_);
ESP_LOGVV(TAG, "Decrypted telegram: %s", this->telegram_);
ESP_LOGVV(TAG, "Decrypted telegram: %s", telegram_);
parse_telegram();
@@ -162,7 +164,7 @@ bool Dsmr::parse_telegram() {
ESP_LOGV(TAG, "Trying to parse telegram");
::dsmr::ParseResult<void> res =
::dsmr::P1Parser::parse(&data, telegram_, telegram_len_, false,
this->crc_check_); // Parse telegram according to data definition. Ignore unknown values.
crc_check_); // Parse telegram according to data definition. Ignore unknown values.
if (res.err) {
// Parsing error, show it
auto err_str = res.fullError(telegram_, telegram_ + telegram_len_);
@@ -177,6 +179,7 @@ bool Dsmr::parse_telegram() {
void Dsmr::dump_config() {
ESP_LOGCONFIG(TAG, "DSMR:");
ESP_LOGCONFIG(TAG, " Max telegram length: %d", max_telegram_len_);
#define DSMR_LOG_SENSOR(s) LOG_SENSOR(" ", #s, this->s_##s##_);
DSMR_SENSOR_LIST(DSMR_LOG_SENSOR, )
@@ -188,7 +191,11 @@ void Dsmr::dump_config() {
void Dsmr::set_decryption_key(const std::string &decryption_key) {
if (decryption_key.length() == 0) {
ESP_LOGI(TAG, "Disabling decryption");
this->decryption_key_.clear();
decryption_key_.clear();
if (encrypted_telegram_ != nullptr) {
delete[] encrypted_telegram_;
encrypted_telegram_ = nullptr;
}
return;
}
@@ -196,7 +203,7 @@ void Dsmr::set_decryption_key(const std::string &decryption_key) {
ESP_LOGE(TAG, "Error, decryption key must be 32 character long");
return;
}
this->decryption_key_.clear();
decryption_key_.clear();
ESP_LOGI(TAG, "Decryption key is set");
// Verbose level prints decryption key
@@ -207,8 +214,14 @@ void Dsmr::set_decryption_key(const std::string &decryption_key) {
strncpy(temp, &(decryption_key.c_str()[i * 2]), 2);
decryption_key_.push_back(std::strtoul(temp, nullptr, 16));
}
if (encrypted_telegram_ == nullptr) {
encrypted_telegram_ = new uint8_t[max_telegram_len_]; // NOLINT
}
}
void Dsmr::set_max_telegram_length(size_t length) { max_telegram_len_ = length; }
} // namespace dsmr
} // namespace esphome