mirror of
https://github.com/esphome/esphome.git
synced 2024-11-29 02:04:13 +01:00
Add support for P1 Data Request pin control (#2676)
This commit is contained in:
parent
598f5b241f
commit
15cd602e8b
4 changed files with 174 additions and 69 deletions
|
@ -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
|
||||||
|
|
Loading…
Reference in a new issue