ESPHome 2026.11.0-dev
Loading...
Searching...
No Matches
sensor.cpp
Go to the documentation of this file.
1#include "sensor.h"
2
3#include "esphome/core/hal.h"
4#include "esphome/core/log.h"
5
6namespace esphome::duco {
7
8ESPHOME_LOG_TAG(TAG, "duco.sensor");
9
15
18struct ReadingLayout {
19 uint8_t function;
20 uint8_t offset;
21 DucoValueFormat format;
22 uint8_t divisor;
23 int16_t minimum;
24 uint16_t maximum;
25};
26
27// Indexed by DucoReading
28static constexpr ReadingLayout READINGS[] PROGMEM = {
29 {FUNCTION_NODE_DATA, 4, DucoValueFormat::DUCO_VALUE_FORMAT_UINT16, 1, 300, 10000}, // CO2
30 {FUNCTION_NODE_DATA, 2, DucoValueFormat::DUCO_VALUE_FORMAT_UINT16, 10, 0, 1000}, // node temperature
31 {FUNCTION_NODE_DATA, 6, DucoValueFormat::DUCO_VALUE_FORMAT_UINT16, 100, 0, 10000}, // humidity
32 {FUNCTION_PARAMETER, 3, DucoValueFormat::DUCO_VALUE_FORMAT_UINT8, 1, 0, 255}, // filter remaining
33 {FUNCTION_NODE, 2, DucoValueFormat::DUCO_VALUE_FORMAT_UINT8, 1, 0, 255}, // flow level
34 {FUNCTION_NODE, 12, DucoValueFormat::DUCO_VALUE_FORMAT_UINT16, 1, 0, 65535}, // time remaining
35 {FUNCTION_PARAMETER, 3, DucoValueFormat::DUCO_VALUE_FORMAT_INT16, 10, -999, 1000}, // box temperature
36 {FUNCTION_PARAMETER, 3, DucoValueFormat::DUCO_VALUE_FORMAT_UINT8, 1, 0, 100}, // bypass
37};
38
39static ReadingLayout layout_of(DucoReading reading) {
40 ReadingLayout layout;
41 progmem_memcpy(&layout, &READINGS[static_cast<uint8_t>(reading)], sizeof(layout));
42 return layout;
43}
44
46 switch (layout_of(this->reading_).function) {
47 case FUNCTION_NODE_DATA:
48 this->parent_->send(this, FUNCTION_NODE_DATA, {0x01, this->argument_, 0x00, 0x49, 0x04});
49 break;
50 case FUNCTION_PARAMETER:
51 this->parent_->send(this, FUNCTION_PARAMETER, {0x00, this->argument_, 0x09});
52 break;
53 case FUNCTION_NODE:
54 this->parent_->send(this, FUNCTION_NODE, {0x02, this->argument_});
55 break;
56 }
57}
58
60 const ReadingLayout layout = layout_of(this->reading_);
61 const bool wide = layout.format != DucoValueFormat::DUCO_VALUE_FORMAT_UINT8;
62 if (message.size < layout.offset + (wide ? 2 : 1)) {
63 ESP_LOGV(TAG, "Answer of %u bytes is too short", message.size);
64 return;
65 }
66
67 const uint8_t *field = message.data + layout.offset;
68 int32_t value = field[0];
69 if (layout.format == DucoValueFormat::DUCO_VALUE_FORMAT_UINT16) {
70 value = encode_value_le<uint16_t>(field);
71 } else if (layout.format == DucoValueFormat::DUCO_VALUE_FORMAT_INT16) {
72 value = encode_value_le<int16_t>(field);
73 }
74 if (value >= layout.minimum && value <= layout.maximum)
75 this->publish_state(static_cast<float>(value) / layout.divisor);
76}
77
78} // namespace esphome::duco
void receive_response(const DucoMessage &message) override
Definition sensor.cpp:59
DucoReading reading_
Definition sensor.h:30
void update() override
Definition sensor.cpp:45
void publish_state(float state)
Publish a new state to the front-end.
Definition sensor.cpp:65
const LogString * message
Definition component.cpp:35
ESPHOME_LOG_TAG(TAG, "duco")
DucoReading
What a sensor reads; the request and where the value is in the answer are in READINGS in sensor....
Definition sensor.h:10
void progmem_memcpy(void *dst, const void *src, size_t len)
Definition hal.h:56
constexpr T encode_value_le(const uint8_t *bytes)
Encode a value from its constituent bytes (from least to most significant) in an array with length si...
Definition helpers.h:1039
A received message; data points into the receive buffer and is valid only during the callback.
Definition duco.h:22