mirror of
				https://github.com/esphome/esphome.git
				synced 2025-10-30 22:53:59 +00:00 
			
		
		
		
	Add support for P1 Data Request pin control (#2676)
This commit is contained in:
		| @@ -1,5 +1,6 @@ | |||||||
| import esphome.codegen as cg | import esphome.codegen as cg | ||||||
| import esphome.config_validation as cv | import esphome.config_validation as cv | ||||||
|  | from esphome import pins | ||||||
| from esphome.components import uart | from esphome.components import uart | ||||||
| from esphome.const import ( | from esphome.const import ( | ||||||
|     CONF_ID, |     CONF_ID, | ||||||
| @@ -11,11 +12,13 @@ CODEOWNERS = ["@glmnet", "@zuidwijk"] | |||||||
| DEPENDENCIES = ["uart"] | DEPENDENCIES = ["uart"] | ||||||
| AUTO_LOAD = ["sensor", "text_sensor"] | AUTO_LOAD = ["sensor", "text_sensor"] | ||||||
|  |  | ||||||
| CONF_DSMR_ID = "dsmr_id" |  | ||||||
| CONF_DECRYPTION_KEY = "decryption_key" |  | ||||||
| CONF_CRC_CHECK = "crc_check" | CONF_CRC_CHECK = "crc_check" | ||||||
|  | CONF_DECRYPTION_KEY = "decryption_key" | ||||||
|  | CONF_DSMR_ID = "dsmr_id" | ||||||
| CONF_GAS_MBUS_ID = "gas_mbus_id" | CONF_GAS_MBUS_ID = "gas_mbus_id" | ||||||
| CONF_MAX_TELEGRAM_LENGTH = "max_telegram_length" | CONF_MAX_TELEGRAM_LENGTH = "max_telegram_length" | ||||||
|  | CONF_REQUEST_INTERVAL = "request_interval" | ||||||
|  | CONF_REQUEST_PIN = "request_pin" | ||||||
|  |  | ||||||
| # Hack to prevent compile error due to ambiguity with lib namespace | # Hack to prevent compile error due to ambiguity with lib namespace | ||||||
| dsmr_ns = cg.esphome_ns.namespace("esphome::dsmr") | dsmr_ns = cg.esphome_ns.namespace("esphome::dsmr") | ||||||
| @@ -48,6 +51,8 @@ CONFIG_SCHEMA = cv.All( | |||||||
|             cv.Optional(CONF_CRC_CHECK, default=True): cv.boolean, |             cv.Optional(CONF_CRC_CHECK, default=True): cv.boolean, | ||||||
|             cv.Optional(CONF_GAS_MBUS_ID, default=1): cv.int_, |             cv.Optional(CONF_GAS_MBUS_ID, default=1): cv.int_, | ||||||
|             cv.Optional(CONF_MAX_TELEGRAM_LENGTH, default=1500): cv.int_, |             cv.Optional(CONF_MAX_TELEGRAM_LENGTH, default=1500): cv.int_, | ||||||
|  |             cv.Optional(CONF_REQUEST_PIN): pins.gpio_output_pin_schema, | ||||||
|  |             cv.Optional(CONF_REQUEST_INTERVAL): cv.positive_time_period_milliseconds, | ||||||
|         } |         } | ||||||
|     ).extend(uart.UART_DEVICE_SCHEMA), |     ).extend(uart.UART_DEVICE_SCHEMA), | ||||||
|     cv.only_with_arduino, |     cv.only_with_arduino, | ||||||
| @@ -62,6 +67,14 @@ async def to_code(config): | |||||||
|         cg.add(var.set_decryption_key(config[CONF_DECRYPTION_KEY])) |         cg.add(var.set_decryption_key(config[CONF_DECRYPTION_KEY])) | ||||||
|     await cg.register_component(var, config) |     await cg.register_component(var, config) | ||||||
|  |  | ||||||
|  |     if CONF_REQUEST_PIN in config: | ||||||
|  |         request_pin = await cg.gpio_pin_expression(config[CONF_REQUEST_PIN]) | ||||||
|  |         cg.add(var.set_request_pin(request_pin)) | ||||||
|  |     if CONF_REQUEST_INTERVAL in config: | ||||||
|  |         cg.add( | ||||||
|  |             var.set_request_interval(config[CONF_REQUEST_INTERVAL].total_milliseconds) | ||||||
|  |         ) | ||||||
|  |  | ||||||
|     cg.add_define("DSMR_GAS_MBUS_ID", config[CONF_GAS_MBUS_ID]) |     cg.add_define("DSMR_GAS_MBUS_ID", config[CONF_GAS_MBUS_ID]) | ||||||
|  |  | ||||||
|     # DSMR Parser |     # DSMR Parser | ||||||
|   | |||||||
| @@ -13,147 +13,217 @@ namespace dsmr { | |||||||
| static const char *const TAG = "dsmr"; | static const char *const TAG = "dsmr"; | ||||||
|  |  | ||||||
| void Dsmr::setup() { | void Dsmr::setup() { | ||||||
|   telegram_ = new char[max_telegram_len_];  // NOLINT |   this->telegram_ = new char[this->max_telegram_len_];  // NOLINT | ||||||
|  |   if (this->request_pin_ != nullptr) { | ||||||
|  |     this->request_pin_->setup(); | ||||||
|  |   } | ||||||
| } | } | ||||||
|  |  | ||||||
| void Dsmr::loop() { | void Dsmr::loop() { | ||||||
|   if (decryption_key_.empty()) |   if (this->ready_to_request_data_()) { | ||||||
|     receive_telegram_(); |     if (this->decryption_key_.empty()) { | ||||||
|   else |       this->receive_telegram_(); | ||||||
|     receive_encrypted_(); |     } else { | ||||||
|  |       this->receive_encrypted_(); | ||||||
|  |     } | ||||||
|  |   } | ||||||
|  | } | ||||||
|  |  | ||||||
|  | bool Dsmr::ready_to_request_data_() { | ||||||
|  |   // When using a request pin, then wait for the next request interval. | ||||||
|  |   if (this->request_pin_ != nullptr) { | ||||||
|  |     if (!this->requesting_data_ && this->request_interval_reached_()) { | ||||||
|  |       this->start_requesting_data_(); | ||||||
|  |     } | ||||||
|  |   } | ||||||
|  |   // Otherwise, sink serial data until next request interval. | ||||||
|  |   else { | ||||||
|  |     if (this->request_interval_reached_()) { | ||||||
|  |       this->start_requesting_data_(); | ||||||
|  |     } | ||||||
|  |     if (!this->requesting_data_) { | ||||||
|  |       while (this->available()) { | ||||||
|  |         this->read(); | ||||||
|  |       } | ||||||
|  |     } | ||||||
|  |   } | ||||||
|  |   return this->requesting_data_; | ||||||
|  | } | ||||||
|  |  | ||||||
|  | bool Dsmr::request_interval_reached_() { | ||||||
|  |   if (this->last_request_time_ == 0) { | ||||||
|  |     return true; | ||||||
|  |   } | ||||||
|  |   return millis() - this->last_request_time_ > this->request_interval_; | ||||||
| } | } | ||||||
|  |  | ||||||
| bool Dsmr::available_within_timeout_() { | bool Dsmr::available_within_timeout_() { | ||||||
|   uint8_t tries = READ_TIMEOUT_MS / 5; |   uint8_t tries = READ_TIMEOUT_MS / 5; | ||||||
|   while (tries--) { |   while (tries--) { | ||||||
|     delay(5); |     delay(5); | ||||||
|     if (available()) { |     if (this->available()) { | ||||||
|       return true; |       return true; | ||||||
|     } |     } | ||||||
|   } |   } | ||||||
|   return false; |   return false; | ||||||
| } | } | ||||||
|  |  | ||||||
|  | void Dsmr::start_requesting_data_() { | ||||||
|  |   if (!this->requesting_data_) { | ||||||
|  |     if (this->request_pin_ != nullptr) { | ||||||
|  |       ESP_LOGV(TAG, "Start requesting data from P1 port"); | ||||||
|  |       this->request_pin_->digital_write(true); | ||||||
|  |     } else { | ||||||
|  |       ESP_LOGV(TAG, "Start reading data from P1 port"); | ||||||
|  |     } | ||||||
|  |     this->requesting_data_ = true; | ||||||
|  |     this->last_request_time_ = millis(); | ||||||
|  |   } | ||||||
|  | } | ||||||
|  |  | ||||||
|  | void Dsmr::stop_requesting_data_() { | ||||||
|  |   if (this->requesting_data_) { | ||||||
|  |     if (this->request_pin_ != nullptr) { | ||||||
|  |       ESP_LOGV(TAG, "Stop requesting data from P1 port"); | ||||||
|  |       this->request_pin_->digital_write(false); | ||||||
|  |     } else { | ||||||
|  |       ESP_LOGV(TAG, "Stop reading data from P1 port"); | ||||||
|  |     } | ||||||
|  |     while (this->available()) { | ||||||
|  |       this->read(); | ||||||
|  |     } | ||||||
|  |     this->requesting_data_ = false; | ||||||
|  |   } | ||||||
|  | } | ||||||
|  |  | ||||||
| void Dsmr::receive_telegram_() { | void Dsmr::receive_telegram_() { | ||||||
|   while (true) { |   while (true) { | ||||||
|     if (!available()) { |     if (!this->available()) { | ||||||
|       if (!header_found_ || !available_within_timeout_()) { |       if (!this->header_found_ || !this->available_within_timeout_()) { | ||||||
|         return; |         return; | ||||||
|       } |       } | ||||||
|     } |     } | ||||||
|  |  | ||||||
|     const char c = read(); |     const char c = this->read(); | ||||||
|  |  | ||||||
|     // Find a new telegram header, i.e. forward slash. |     // Find a new telegram header, i.e. forward slash. | ||||||
|     if (c == '/') { |     if (c == '/') { | ||||||
|       ESP_LOGV(TAG, "Header of telegram found"); |       ESP_LOGV(TAG, "Header of telegram found"); | ||||||
|       header_found_ = true; |       this->header_found_ = true; | ||||||
|       footer_found_ = false; |       this->footer_found_ = false; | ||||||
|       telegram_len_ = 0; |       this->telegram_len_ = 0; | ||||||
|     } |     } | ||||||
|     if (!header_found_) |     if (!this->header_found_) | ||||||
|       continue; |       continue; | ||||||
|  |  | ||||||
|     // Check for buffer overflow. |     // Check for buffer overflow. | ||||||
|     if (telegram_len_ >= max_telegram_len_) { |     if (this->telegram_len_ >= this->max_telegram_len_) { | ||||||
|       header_found_ = false; |       this->header_found_ = false; | ||||||
|       footer_found_ = false; |       this->footer_found_ = false; | ||||||
|       ESP_LOGE(TAG, "Error: telegram larger than buffer (%d bytes)", max_telegram_len_); |       ESP_LOGE(TAG, "Error: telegram larger than buffer (%d bytes)", this->max_telegram_len_); | ||||||
|       return; |       return; | ||||||
|     } |     } | ||||||
|  |  | ||||||
|     // Some v2.2 or v3 meters will send a new value which starts with '(' |     // Some v2.2 or v3 meters will send a new value which starts with '(' | ||||||
|     // in a new line while the value belongs to the previous ObisId. For |     // in a new line, while the value belongs to the previous ObisId. For | ||||||
|     // proper parsing remove these new line characters |     // proper parsing, remove these new line characters. | ||||||
|     while (c == '(' && (telegram_[telegram_len_ - 1] == '\n' || telegram_[telegram_len_ - 1] == '\r')) |     if (c == '(') { | ||||||
|       telegram_len_--; |       while (true) { | ||||||
|  |         auto previous_char = this->telegram_[this->telegram_len_ - 1]; | ||||||
|  |         if (previous_char == '\n' || previous_char == '\r') { | ||||||
|  |           this->telegram_len_--; | ||||||
|  |         } else { | ||||||
|  |           break; | ||||||
|  |         } | ||||||
|  |       } | ||||||
|  |     } | ||||||
|  |  | ||||||
|     // Store the byte in the buffer. |     // Store the byte in the buffer. | ||||||
|     telegram_[telegram_len_] = c; |     this->telegram_[this->telegram_len_] = c; | ||||||
|     telegram_len_++; |     this->telegram_len_++; | ||||||
|  |  | ||||||
|     // Check for a footer, i.e. exlamation mark, followed by a hex checksum. |     // Check for a footer, i.e. exlamation mark, followed by a hex checksum. | ||||||
|     if (c == '!') { |     if (c == '!') { | ||||||
|       ESP_LOGV(TAG, "Footer of telegram found"); |       ESP_LOGV(TAG, "Footer of telegram found"); | ||||||
|       footer_found_ = true; |       this->footer_found_ = true; | ||||||
|       continue; |       continue; | ||||||
|     } |     } | ||||||
|     // Check for the end of the hex checksum, i.e. a newline. |     // Check for the end of the hex checksum, i.e. a newline. | ||||||
|     if (footer_found_ && c == '\n') { |     if (this->footer_found_ && c == '\n') { | ||||||
|       // Parse the telegram and publish sensor values. |       // Parse the telegram and publish sensor values. | ||||||
|       parse_telegram(); |       this->parse_telegram(); | ||||||
|  |  | ||||||
|       header_found_ = false; |       this->header_found_ = false; | ||||||
|       return; |       return; | ||||||
|     } |     } | ||||||
|   } |   } | ||||||
| } | } | ||||||
|  |  | ||||||
| void Dsmr::receive_encrypted_() { | void Dsmr::receive_encrypted_() { | ||||||
|   encrypted_telegram_len_ = 0; |   this->encrypted_telegram_len_ = 0; | ||||||
|   size_t packet_size = 0; |   size_t packet_size = 0; | ||||||
|  |  | ||||||
|   while (true) { |   while (true) { | ||||||
|     if (!available()) { |     if (!this->available()) { | ||||||
|       if (!header_found_) { |       if (!this->header_found_) { | ||||||
|         return; |         return; | ||||||
|       } |       } | ||||||
|       if (!available_within_timeout_()) { |       if (!this->available_within_timeout_()) { | ||||||
|         ESP_LOGW(TAG, "Timeout while reading data for encrypted telegram"); |         ESP_LOGW(TAG, "Timeout while reading data for encrypted telegram"); | ||||||
|         return; |         return; | ||||||
|       } |       } | ||||||
|     } |     } | ||||||
|  |  | ||||||
|     const char c = read(); |     const char c = this->read(); | ||||||
|  |  | ||||||
|     // Find a new telegram start byte. |     // Find a new telegram start byte. | ||||||
|     if (!header_found_) { |     if (!this->header_found_) { | ||||||
|       if ((uint8_t) c != 0xDB) { |       if ((uint8_t) c != 0xDB) { | ||||||
|         continue; |         continue; | ||||||
|       } |       } | ||||||
|       ESP_LOGV(TAG, "Start byte 0xDB of encrypted telegram found"); |       ESP_LOGV(TAG, "Start byte 0xDB of encrypted telegram found"); | ||||||
|       header_found_ = true; |       this->header_found_ = true; | ||||||
|     } |     } | ||||||
|  |  | ||||||
|     // Check for buffer overflow. |     // Check for buffer overflow. | ||||||
|     if (encrypted_telegram_len_ >= max_telegram_len_) { |     if (this->encrypted_telegram_len_ >= this->max_telegram_len_) { | ||||||
|       header_found_ = false; |       this->header_found_ = false; | ||||||
|       ESP_LOGE(TAG, "Error: encrypted telegram larger than buffer (%d bytes)", max_telegram_len_); |       ESP_LOGE(TAG, "Error: encrypted telegram larger than buffer (%d bytes)", this->max_telegram_len_); | ||||||
|       return; |       return; | ||||||
|     } |     } | ||||||
|  |  | ||||||
|     encrypted_telegram_[encrypted_telegram_len_++] = c; |     this->encrypted_telegram_[this->encrypted_telegram_len_++] = c; | ||||||
|  |  | ||||||
|     if (packet_size == 0 && encrypted_telegram_len_ > 20) { |     if (packet_size == 0 && this->encrypted_telegram_len_ > 20) { | ||||||
|       // Complete header + data bytes |       // Complete header + data bytes | ||||||
|       packet_size = 13 + (encrypted_telegram_[11] << 8 | encrypted_telegram_[12]); |       packet_size = 13 + (this->encrypted_telegram_[11] << 8 | this->encrypted_telegram_[12]); | ||||||
|       ESP_LOGV(TAG, "Encrypted telegram size: %d bytes", packet_size); |       ESP_LOGV(TAG, "Encrypted telegram size: %d bytes", packet_size); | ||||||
|     } |     } | ||||||
|     if (encrypted_telegram_len_ == packet_size && packet_size > 0) { |     if (this->encrypted_telegram_len_ == packet_size && packet_size > 0) { | ||||||
|       ESP_LOGV(TAG, "End of encrypted telegram found"); |       ESP_LOGV(TAG, "End of encrypted telegram found"); | ||||||
|       GCM<AES128> *gcmaes128{new GCM<AES128>()}; |       GCM<AES128> *gcmaes128{new GCM<AES128>()}; | ||||||
|       gcmaes128->setKey(decryption_key_.data(), gcmaes128->keySize()); |       gcmaes128->setKey(this->decryption_key_.data(), gcmaes128->keySize()); | ||||||
|       // the iv is 8 bytes of the system title + 4 bytes frame counter |       // 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 |       // system title is at byte 2 and frame counter at byte 15 | ||||||
|       for (int i = 10; i < 14; i++) |       for (int i = 10; i < 14; i++) | ||||||
|         encrypted_telegram_[i] = encrypted_telegram_[i + 4]; |         this->encrypted_telegram_[i] = this->encrypted_telegram_[i + 4]; | ||||||
|       constexpr uint16_t iv_size{12}; |       constexpr uint16_t iv_size{12}; | ||||||
|       gcmaes128->setIV(&encrypted_telegram_[2], iv_size); |       gcmaes128->setIV(&this->encrypted_telegram_[2], iv_size); | ||||||
|       gcmaes128->decrypt(reinterpret_cast<uint8_t *>(telegram_), |       gcmaes128->decrypt(reinterpret_cast<uint8_t *>(this->telegram_), | ||||||
|                          // the ciphertext start at byte 18 |                          // the ciphertext start at byte 18 | ||||||
|                          &encrypted_telegram_[18], |                          &this->encrypted_telegram_[18], | ||||||
|                          // cipher size |                          // cipher size | ||||||
|                          encrypted_telegram_len_ - 17); |                          this->encrypted_telegram_len_ - 17); | ||||||
|       delete gcmaes128;  // NOLINT(cppcoreguidelines-owning-memory) |       delete gcmaes128;  // NOLINT(cppcoreguidelines-owning-memory) | ||||||
|  |  | ||||||
|       telegram_len_ = strnlen(telegram_, max_telegram_len_); |       this->telegram_len_ = strnlen(this->telegram_, this->max_telegram_len_); | ||||||
|       ESP_LOGV(TAG, "Decrypted telegram size: %d bytes", telegram_len_); |       ESP_LOGV(TAG, "Decrypted telegram size: %d bytes", this->telegram_len_); | ||||||
|       ESP_LOGVV(TAG, "Decrypted telegram: %s", telegram_); |       ESP_LOGVV(TAG, "Decrypted telegram: %s", this->telegram_); | ||||||
|  |  | ||||||
|       parse_telegram(); |       this->parse_telegram(); | ||||||
|  |  | ||||||
|       header_found_ = false; |       this->header_found_ = false; | ||||||
|       telegram_len_ = 0; |       this->telegram_len_ = 0; | ||||||
|       return; |       return; | ||||||
|     } |     } | ||||||
|   } |   } | ||||||
| @@ -162,24 +232,32 @@ void Dsmr::receive_encrypted_() { | |||||||
| bool Dsmr::parse_telegram() { | bool Dsmr::parse_telegram() { | ||||||
|   MyData data; |   MyData data; | ||||||
|   ESP_LOGV(TAG, "Trying to parse telegram"); |   ESP_LOGV(TAG, "Trying to parse telegram"); | ||||||
|  |   this->stop_requesting_data_(); | ||||||
|   ::dsmr::ParseResult<void> res = |   ::dsmr::ParseResult<void> res = | ||||||
|       ::dsmr::P1Parser::parse(&data, telegram_, telegram_len_, false, |       ::dsmr::P1Parser::parse(&data, this->telegram_, this->telegram_len_, false, | ||||||
|                               crc_check_);  // Parse telegram according to data definition. Ignore unknown values. |                               this->crc_check_);  // Parse telegram according to data definition. Ignore unknown values. | ||||||
|   if (res.err) { |   if (res.err) { | ||||||
|     // Parsing error, show it |     // Parsing error, show it | ||||||
|     auto err_str = res.fullError(telegram_, telegram_ + telegram_len_); |     auto err_str = res.fullError(this->telegram_, this->telegram_ + this->telegram_len_); | ||||||
|     ESP_LOGE(TAG, "%s", err_str.c_str()); |     ESP_LOGE(TAG, "%s", err_str.c_str()); | ||||||
|     return false; |     return false; | ||||||
|   } else { |   } else { | ||||||
|     this->status_clear_warning(); |     this->status_clear_warning(); | ||||||
|     publish_sensors(data); |     this->publish_sensors(data); | ||||||
|     return true; |     return true; | ||||||
|   } |   } | ||||||
| } | } | ||||||
|  |  | ||||||
| void Dsmr::dump_config() { | void Dsmr::dump_config() { | ||||||
|   ESP_LOGCONFIG(TAG, "DSMR:"); |   ESP_LOGCONFIG(TAG, "DSMR:"); | ||||||
|   ESP_LOGCONFIG(TAG, "  Max telegram length: %d", max_telegram_len_); |   ESP_LOGCONFIG(TAG, "  Max telegram length: %d", this->max_telegram_len_); | ||||||
|  |  | ||||||
|  |   if (this->request_pin_ != nullptr) { | ||||||
|  |     LOG_PIN("  Request Pin: ", this->request_pin_); | ||||||
|  |   } | ||||||
|  |   if (this->request_interval_ > 0) { | ||||||
|  |     ESP_LOGCONFIG(TAG, "  Request Interval: %.1fs", this->request_interval_ / 1e3f); | ||||||
|  |   } | ||||||
|  |  | ||||||
| #define DSMR_LOG_SENSOR(s) LOG_SENSOR("  ", #s, this->s_##s##_); | #define DSMR_LOG_SENSOR(s) LOG_SENSOR("  ", #s, this->s_##s##_); | ||||||
|   DSMR_SENSOR_LIST(DSMR_LOG_SENSOR, ) |   DSMR_SENSOR_LIST(DSMR_LOG_SENSOR, ) | ||||||
| @@ -191,10 +269,10 @@ void Dsmr::dump_config() { | |||||||
| void Dsmr::set_decryption_key(const std::string &decryption_key) { | void Dsmr::set_decryption_key(const std::string &decryption_key) { | ||||||
|   if (decryption_key.length() == 0) { |   if (decryption_key.length() == 0) { | ||||||
|     ESP_LOGI(TAG, "Disabling decryption"); |     ESP_LOGI(TAG, "Disabling decryption"); | ||||||
|     decryption_key_.clear(); |     this->decryption_key_.clear(); | ||||||
|     if (encrypted_telegram_ != nullptr) { |     if (this->encrypted_telegram_ != nullptr) { | ||||||
|       delete[] encrypted_telegram_; |       delete[] this->encrypted_telegram_; | ||||||
|       encrypted_telegram_ = nullptr; |       this->encrypted_telegram_ = nullptr; | ||||||
|     } |     } | ||||||
|     return; |     return; | ||||||
|   } |   } | ||||||
| @@ -203,7 +281,7 @@ void Dsmr::set_decryption_key(const std::string &decryption_key) { | |||||||
|     ESP_LOGE(TAG, "Error, decryption key must be 32 character long"); |     ESP_LOGE(TAG, "Error, decryption key must be 32 character long"); | ||||||
|     return; |     return; | ||||||
|   } |   } | ||||||
|   decryption_key_.clear(); |   this->decryption_key_.clear(); | ||||||
|  |  | ||||||
|   ESP_LOGI(TAG, "Decryption key is set"); |   ESP_LOGI(TAG, "Decryption key is set"); | ||||||
|   // Verbose level prints decryption key |   // Verbose level prints decryption key | ||||||
| @@ -212,11 +290,11 @@ void Dsmr::set_decryption_key(const std::string &decryption_key) { | |||||||
|   char temp[3] = {0}; |   char temp[3] = {0}; | ||||||
|   for (int i = 0; i < 16; i++) { |   for (int i = 0; i < 16; i++) { | ||||||
|     strncpy(temp, &(decryption_key.c_str()[i * 2]), 2); |     strncpy(temp, &(decryption_key.c_str()[i * 2]), 2); | ||||||
|     decryption_key_.push_back(std::strtoul(temp, nullptr, 16)); |     this->decryption_key_.push_back(std::strtoul(temp, nullptr, 16)); | ||||||
|   } |   } | ||||||
|  |  | ||||||
|   if (encrypted_telegram_ == nullptr) { |   if (this->encrypted_telegram_ == nullptr) { | ||||||
|     encrypted_telegram_ = new uint8_t[max_telegram_len_];  // NOLINT |     this->encrypted_telegram_ = new uint8_t[this->max_telegram_len_];  // NOLINT | ||||||
|   } |   } | ||||||
| } | } | ||||||
|  |  | ||||||
|   | |||||||
| @@ -52,7 +52,6 @@ class Dsmr : public Component, public uart::UARTDevice { | |||||||
|   Dsmr(uart::UARTComponent *uart, bool crc_check) : uart::UARTDevice(uart), crc_check_(crc_check) {} |   Dsmr(uart::UARTComponent *uart, bool crc_check) : uart::UARTDevice(uart), crc_check_(crc_check) {} | ||||||
|  |  | ||||||
|   void setup() override; |   void setup() override; | ||||||
|  |  | ||||||
|   void loop() override; |   void loop() override; | ||||||
|  |  | ||||||
|   bool parse_telegram(); |   bool parse_telegram(); | ||||||
| @@ -75,6 +74,9 @@ class Dsmr : public Component, public uart::UARTDevice { | |||||||
|  |  | ||||||
|   void set_max_telegram_length(size_t length); |   void set_max_telegram_length(size_t length); | ||||||
|  |  | ||||||
|  |   void set_request_pin(GPIOPin *request_pin) { this->request_pin_ = request_pin; } | ||||||
|  |   void set_request_interval(uint32_t interval) { this->request_interval_ = interval; } | ||||||
|  |  | ||||||
| // Sensor setters | // Sensor setters | ||||||
| #define DSMR_SET_SENSOR(s) \ | #define DSMR_SET_SENSOR(s) \ | ||||||
|   void set_##s(sensor::Sensor *sensor) { s_##s##_ = sensor; } |   void set_##s(sensor::Sensor *sensor) { s_##s##_ = sensor; } | ||||||
| @@ -99,6 +101,16 @@ class Dsmr : public Component, public uart::UARTDevice { | |||||||
|   /// lost in the process. |   /// lost in the process. | ||||||
|   bool available_within_timeout_(); |   bool available_within_timeout_(); | ||||||
|  |  | ||||||
|  |   // Data request | ||||||
|  |   GPIOPin *request_pin_{nullptr}; | ||||||
|  |   uint32_t request_interval_{0}; | ||||||
|  |   uint32_t last_request_time_{0}; | ||||||
|  |   bool requesting_data_{false}; | ||||||
|  |   bool ready_to_request_data_(); | ||||||
|  |   bool request_interval_reached_(); | ||||||
|  |   void start_requesting_data_(); | ||||||
|  |   void stop_requesting_data_(); | ||||||
|  |  | ||||||
|   // Telegram buffer |   // Telegram buffer | ||||||
|   size_t max_telegram_len_; |   size_t max_telegram_len_; | ||||||
|   char *telegram_{nullptr}; |   char *telegram_{nullptr}; | ||||||
|   | |||||||
| @@ -1309,6 +1309,8 @@ dsmr: | |||||||
|   decryption_key: 00112233445566778899aabbccddeeff |   decryption_key: 00112233445566778899aabbccddeeff | ||||||
|   uart_id: uart6 |   uart_id: uart6 | ||||||
|   max_telegram_length: 1000 |   max_telegram_length: 1000 | ||||||
|  |   request_pin: D5 | ||||||
|  |   request_interval: 20s | ||||||
|  |  | ||||||
| daly_bms: | daly_bms: | ||||||
|   update_interval: 20s |   update_interval: 20s | ||||||
|   | |||||||
		Reference in New Issue
	
	Block a user