ESPHome 2026.11.0-dev
Loading...
Searching...
No Matches
duco.h
Go to the documentation of this file.
1#pragma once
2
3#include <array>
4#include <initializer_list>
5
9
10#ifdef USE_TIME
12#endif
13
14namespace esphome::duco {
15
16// Function codes of the requests; the box answers a request with function + 2
17static constexpr uint8_t FUNCTION_NODE = 0x0c; // discovery, status and mode of a node
18static constexpr uint8_t FUNCTION_NODE_DATA = 0x10; // a block of a node's data (sensors, serial number)
19static constexpr uint8_t FUNCTION_PARAMETER = 0x24; // read or write a box parameter, set the clock
20
23 uint8_t id;
24 const uint8_t *data;
25 uint8_t size;
26};
27
28class DucoDevice;
29
33 uint8_t id;
34 uint8_t function; // 0 while nothing is open
35 bool missed; // the request before this one got no answer; sits in padding
36};
37
38class Duco : public uart::UARTDevice, public Component {
39 public:
40 void loop() override;
41 void dump_config() override;
42
43 void set_disable_crc(bool disable_crc) { this->disable_crc_ = disable_crc; }
44
45#ifdef DUCO_DEVICE_COUNT
46 void register_device(DucoDevice *device) { this->pending_.push_back({device, 0, 0, false}); }
47#endif
48
50 void close_request(DucoDevice *device);
51
54 void send(DucoDevice *device, uint8_t function, std::initializer_list<uint8_t> data);
55
56 protected:
57 // The longest answer to a request sent here is 25 bytes (node status), the longest request 9
58 static constexpr size_t MAX_FRAME_SIZE = 32;
59 static constexpr size_t MAX_REQUEST_DATA = 9;
60
61 bool parse_byte_(uint8_t byte);
62 void reset_frame_();
63#ifdef DUCO_DEVICE_COUNT
64 void update_warning_(); // warn while any device's previous request went unanswered
65#endif
66 void finalize_message_();
67 uint8_t next_id_();
68
69#ifdef DUCO_DEVICE_COUNT
71#endif
72 std::array<uint8_t, MAX_FRAME_SIZE> rx_buffer_{};
74 uint8_t rx_size_{0};
75 uint8_t last_id_{10};
76 bool escaped_{false}; // the last 0xAA was followed by a stuffing byte, so it starts no header
77 bool disable_crc_{false};
78};
79
81class DucoDevice : public PollingComponent, public Parented<Duco> {
82 public:
83 virtual void receive_response(const DucoMessage &message) = 0;
84};
85
87class DucoDiscovery : public DucoDevice {
88 public:
89 void setup() override;
90 void dump_config() override;
91 void update() override; // one discovery step, run by the step interval
92 void receive_response(const DucoMessage &message) override;
93
94 protected:
95 static constexpr uint8_t NODE_COUNT = 0x45;
96
97 std::array<uint8_t, NODE_COUNT> node_types_{}; // 0 when no node answered at that address
98 uint8_t next_node_{0};
99 uint8_t attempts_{0};
100};
101
102#ifdef USE_TIME
103class DucoTime : public PollingComponent, public Parented<Duco> {
104 public:
105 explicit DucoTime(time::RealTimeClock *clock) : clock_(clock) {}
106 void update() override;
107
108 protected:
110};
111#endif
112
113} // namespace esphome::duco
Helper class to easily give an object a parent of type T.
Definition helpers.h:2073
This class simplifies creating components that periodically check a state.
Definition component.h:519
Minimal static vector - saves memory by avoiding std::vector overhead.
Definition helpers.h:286
Every entity polls the box; deriving from PollingComponent shares its vtable.
Definition duco.h:81
virtual void receive_response(const DucoMessage &message)=0
Walks the node addresses once after boot; the nodes found are listed in the config dump.
Definition duco.h:87
void receive_response(const DucoMessage &message) override
Definition duco.cpp:235
std::array< uint8_t, NODE_COUNT > node_types_
Definition duco.h:97
static constexpr uint8_t NODE_COUNT
Definition duco.h:95
void setup() override
Definition duco.cpp:209
void dump_config() override
Definition duco.cpp:246
void update() override
Definition duco.cpp:216
uint8_t next_id_()
Definition duco.cpp:145
std::array< uint8_t, MAX_FRAME_SIZE > rx_buffer_
Definition duco.h:72
static constexpr size_t MAX_REQUEST_DATA
Definition duco.h:59
uint8_t last_id_
Definition duco.h:75
static constexpr size_t MAX_FRAME_SIZE
Definition duco.h:58
uint8_t rx_size_
Definition duco.h:74
void dump_config() override
Definition duco.cpp:138
uint32_t last_byte_
Definition duco.h:73
bool disable_crc_
Definition duco.h:77
void set_disable_crc(bool disable_crc)
Definition duco.h:43
void close_request(DucoDevice *device)
Forget device's open request, for a device that will not send again.
Definition duco.cpp:44
void send(DucoDevice *device, uint8_t function, std::initializer_list< uint8_t > data)
Send a request; its answer goes to device, or nowhere if nullptr.
Definition duco.cpp:152
void loop() override
Definition duco.cpp:21
void update_warning_()
Definition duco.cpp:127
StaticVector< DucoPendingRequest, DUCO_DEVICE_COUNT > pending_
Definition duco.h:70
void reset_frame_()
Definition duco.cpp:39
bool parse_byte_(uint8_t byte)
Definition duco.cpp:57
void finalize_message_()
Definition duco.cpp:88
void register_device(DucoDevice *device)
Definition duco.h:46
DucoTime(time::RealTimeClock *clock)
Definition duco.h:105
void update() override
Definition duco.cpp:260
time::RealTimeClock * clock_
Definition duco.h:109
The RealTimeClock class exposes common timekeeping functions via the device's local real-time clock.
const LogString * message
Definition component.cpp:35
static void uint32_t
A received message; data points into the receive buffer and is valid only during the callback.
Definition duco.h:22
const uint8_t * data
Definition duco.h:24
The open request of one device: the answer to it is function + 2 with the same message id.
Definition duco.h:31