ESPHome  2024.12.2
hub.cpp
Go to the documentation of this file.
1 #include "hub.h"
2 #include "esphome/core/helpers.h"
3 
4 #include <string>
5 
6 namespace esphome {
7 namespace opentherm {
8 
9 static const char *const TAG = "opentherm";
10 namespace message_data {
11 bool parse_flag8_lb_0(OpenthermData &data) { return read_bit(data.valueLB, 0); }
12 bool parse_flag8_lb_1(OpenthermData &data) { return read_bit(data.valueLB, 1); }
13 bool parse_flag8_lb_2(OpenthermData &data) { return read_bit(data.valueLB, 2); }
14 bool parse_flag8_lb_3(OpenthermData &data) { return read_bit(data.valueLB, 3); }
15 bool parse_flag8_lb_4(OpenthermData &data) { return read_bit(data.valueLB, 4); }
16 bool parse_flag8_lb_5(OpenthermData &data) { return read_bit(data.valueLB, 5); }
17 bool parse_flag8_lb_6(OpenthermData &data) { return read_bit(data.valueLB, 6); }
18 bool parse_flag8_lb_7(OpenthermData &data) { return read_bit(data.valueLB, 7); }
19 bool parse_flag8_hb_0(OpenthermData &data) { return read_bit(data.valueHB, 0); }
20 bool parse_flag8_hb_1(OpenthermData &data) { return read_bit(data.valueHB, 1); }
21 bool parse_flag8_hb_2(OpenthermData &data) { return read_bit(data.valueHB, 2); }
22 bool parse_flag8_hb_3(OpenthermData &data) { return read_bit(data.valueHB, 3); }
23 bool parse_flag8_hb_4(OpenthermData &data) { return read_bit(data.valueHB, 4); }
24 bool parse_flag8_hb_5(OpenthermData &data) { return read_bit(data.valueHB, 5); }
25 bool parse_flag8_hb_6(OpenthermData &data) { return read_bit(data.valueHB, 6); }
26 bool parse_flag8_hb_7(OpenthermData &data) { return read_bit(data.valueHB, 7); }
27 uint8_t parse_u8_lb(OpenthermData &data) { return data.valueLB; }
28 uint8_t parse_u8_hb(OpenthermData &data) { return data.valueHB; }
29 int8_t parse_s8_lb(OpenthermData &data) { return (int8_t) data.valueLB; }
30 int8_t parse_s8_hb(OpenthermData &data) { return (int8_t) data.valueHB; }
31 uint16_t parse_u16(OpenthermData &data) { return data.u16(); }
32 uint16_t parse_u8_lb_60(OpenthermData &data) { return data.valueLB * 60; }
33 uint16_t parse_u8_hb_60(OpenthermData &data) { return data.valueHB * 60; }
34 int16_t parse_s16(OpenthermData &data) { return data.s16(); }
35 float parse_f88(OpenthermData &data) { return data.f88(); }
36 
37 void write_flag8_lb_0(const bool value, OpenthermData &data) { data.valueLB = write_bit(data.valueLB, 0, value); }
38 void write_flag8_lb_1(const bool value, OpenthermData &data) { data.valueLB = write_bit(data.valueLB, 1, value); }
39 void write_flag8_lb_2(const bool value, OpenthermData &data) { data.valueLB = write_bit(data.valueLB, 2, value); }
40 void write_flag8_lb_3(const bool value, OpenthermData &data) { data.valueLB = write_bit(data.valueLB, 3, value); }
41 void write_flag8_lb_4(const bool value, OpenthermData &data) { data.valueLB = write_bit(data.valueLB, 4, value); }
42 void write_flag8_lb_5(const bool value, OpenthermData &data) { data.valueLB = write_bit(data.valueLB, 5, value); }
43 void write_flag8_lb_6(const bool value, OpenthermData &data) { data.valueLB = write_bit(data.valueLB, 6, value); }
44 void write_flag8_lb_7(const bool value, OpenthermData &data) { data.valueLB = write_bit(data.valueLB, 7, value); }
45 void write_flag8_hb_0(const bool value, OpenthermData &data) { data.valueHB = write_bit(data.valueHB, 0, value); }
46 void write_flag8_hb_1(const bool value, OpenthermData &data) { data.valueHB = write_bit(data.valueHB, 1, value); }
47 void write_flag8_hb_2(const bool value, OpenthermData &data) { data.valueHB = write_bit(data.valueHB, 2, value); }
48 void write_flag8_hb_3(const bool value, OpenthermData &data) { data.valueHB = write_bit(data.valueHB, 3, value); }
49 void write_flag8_hb_4(const bool value, OpenthermData &data) { data.valueHB = write_bit(data.valueHB, 4, value); }
50 void write_flag8_hb_5(const bool value, OpenthermData &data) { data.valueHB = write_bit(data.valueHB, 5, value); }
51 void write_flag8_hb_6(const bool value, OpenthermData &data) { data.valueHB = write_bit(data.valueHB, 6, value); }
52 void write_flag8_hb_7(const bool value, OpenthermData &data) { data.valueHB = write_bit(data.valueHB, 7, value); }
53 void write_u8_lb(const uint8_t value, OpenthermData &data) { data.valueLB = value; }
54 void write_u8_hb(const uint8_t value, OpenthermData &data) { data.valueHB = value; }
55 void write_s8_lb(const int8_t value, OpenthermData &data) { data.valueLB = (uint8_t) value; }
56 void write_s8_hb(const int8_t value, OpenthermData &data) { data.valueHB = (uint8_t) value; }
57 void write_u16(const uint16_t value, OpenthermData &data) { data.u16(value); }
58 void write_s16(const int16_t value, OpenthermData &data) { data.s16(value); }
59 void write_f88(const float value, OpenthermData &data) { data.f88(value); }
60 
61 } // namespace message_data
62 
64  OpenthermData data;
65  data.type = 0;
66  data.id = 0;
67  data.valueHB = 0;
68  data.valueLB = 0;
69 
70  // We need this special logic for STATUS message because we have two options for specifying boiler modes:
71  // with static config values in the hub, or with separate switches.
72  if (request_id == MessageId::STATUS) {
73  // NOLINTBEGIN
74  bool const ch_enabled = this->ch_enable && OPENTHERM_READ_ch_enable && OPENTHERM_READ_t_set > 0.0;
75  bool const dhw_enabled = this->dhw_enable && OPENTHERM_READ_dhw_enable;
76  bool const cooling_enabled =
77  this->cooling_enable && OPENTHERM_READ_cooling_enable && OPENTHERM_READ_cooling_control > 0.0;
78  bool const otc_enabled = this->otc_active && OPENTHERM_READ_otc_active;
79  bool const ch2_enabled = this->ch2_active && OPENTHERM_READ_ch2_active && OPENTHERM_READ_t_set_ch2 > 0.0;
80  bool const summer_mode_is_active = this->summer_mode_active && OPENTHERM_READ_summer_mode_active;
81  bool const dhw_blocked = this->dhw_block && OPENTHERM_READ_dhw_block;
82  // NOLINTEND
83 
85  data.id = MessageId::STATUS;
86  data.valueHB = ch_enabled | (dhw_enabled << 1) | (cooling_enabled << 2) | (otc_enabled << 3) | (ch2_enabled << 4) |
87  (summer_mode_is_active << 5) | (dhw_blocked << 6);
88 
89  return data;
90  }
91 
92  // Another special case is OpenTherm version number which is configured at hub level as a constant
93  if (request_id == MessageId::OT_VERSION_CONTROLLER) {
96  data.f88(this->opentherm_version_);
97 
98  return data;
99  }
100 
101 // Disable incomplete switch statement warnings, because the cases in each
102 // switch are generated based on the configured sensors and inputs.
103 #pragma GCC diagnostic push
104 #pragma GCC diagnostic ignored "-Wswitch"
105 
106  // Next, we start with the write requests from switches and other inputs,
107  // because we would want to write that data if it is available, rather than
108  // request a read for that type (in the case that both read and write are
109  // supported).
110  switch (request_id) {
111  OPENTHERM_SWITCH_MESSAGE_HANDLERS(OPENTHERM_MESSAGE_WRITE_MESSAGE, OPENTHERM_MESSAGE_WRITE_ENTITY, ,
112  OPENTHERM_MESSAGE_WRITE_POSTSCRIPT, )
113  OPENTHERM_NUMBER_MESSAGE_HANDLERS(OPENTHERM_MESSAGE_WRITE_MESSAGE, OPENTHERM_MESSAGE_WRITE_ENTITY, ,
114  OPENTHERM_MESSAGE_WRITE_POSTSCRIPT, )
115  OPENTHERM_OUTPUT_MESSAGE_HANDLERS(OPENTHERM_MESSAGE_WRITE_MESSAGE, OPENTHERM_MESSAGE_WRITE_ENTITY, ,
116  OPENTHERM_MESSAGE_WRITE_POSTSCRIPT, )
117  OPENTHERM_INPUT_SENSOR_MESSAGE_HANDLERS(OPENTHERM_MESSAGE_WRITE_MESSAGE, OPENTHERM_MESSAGE_WRITE_ENTITY, ,
118  OPENTHERM_MESSAGE_WRITE_POSTSCRIPT, )
119  }
120 
121  // Finally, handle the simple read requests, which only change with the message id.
122  switch (request_id) { OPENTHERM_SENSOR_MESSAGE_HANDLERS(OPENTHERM_MESSAGE_READ_MESSAGE, OPENTHERM_IGNORE, , , ) }
123  switch (request_id) {
124  OPENTHERM_BINARY_SENSOR_MESSAGE_HANDLERS(OPENTHERM_MESSAGE_READ_MESSAGE, OPENTHERM_IGNORE, , , )
125  }
126 #pragma GCC diagnostic pop
127 
128  // And if we get here, a message was requested which somehow wasn't handled.
129  // This shouldn't happen due to the way the defines are configured, so we
130  // log an error and just return a 0 message.
131  ESP_LOGE(TAG, "Tried to create a request with unknown id %d. This should never happen, so please open an issue.",
132  request_id);
133  return {};
134 }
135 
137 
139  ESP_LOGD(TAG, "Received OpenTherm response with id %d (%s)", data.id,
140  this->opentherm_->message_id_to_str((MessageId) data.id));
141  this->opentherm_->debug_data(data);
142 
143  switch (data.id) {
144  OPENTHERM_SENSOR_MESSAGE_HANDLERS(OPENTHERM_MESSAGE_RESPONSE_MESSAGE, OPENTHERM_MESSAGE_RESPONSE_ENTITY, ,
145  OPENTHERM_MESSAGE_RESPONSE_POSTSCRIPT, )
146  }
147  switch (data.id) {
148  OPENTHERM_BINARY_SENSOR_MESSAGE_HANDLERS(OPENTHERM_MESSAGE_RESPONSE_MESSAGE, OPENTHERM_MESSAGE_RESPONSE_ENTITY, ,
149  OPENTHERM_MESSAGE_RESPONSE_POSTSCRIPT, )
150  }
151 }
152 
154  ESP_LOGD(TAG, "Setting up OpenTherm component");
155  this->opentherm_ = make_unique<OpenTherm>(this->in_pin_, this->out_pin_);
156  if (!this->opentherm_->initialize()) {
157  ESP_LOGE(TAG, "Failed to initialize OpenTherm protocol. See previous log messages for details.");
158  this->mark_failed();
159  return;
160  }
161 
162  // Ensure that there is at least one request, as we are required to
163  // communicate at least once every second. Sending the status request is
164  // good practice anyway.
166 
167  // Also ensure that we start communication with the STATUS message
168  this->initial_messages_.insert(this->initial_messages_.begin(), MessageId::STATUS);
169 
170  if (this->opentherm_version_ > 0.0f) {
172  }
173 
174  this->current_message_iterator_ = this->initial_messages_.begin();
175 }
176 
177 void OpenthermHub::on_shutdown() { this->opentherm_->stop(); }
178 
180  if (this->sync_mode_) {
181  this->sync_loop_();
182  return;
183  }
184 
185  auto cur_time = millis();
186  auto const cur_mode = this->opentherm_->get_mode();
187  switch (cur_mode) {
189  case OperationMode::READ:
191  if (!this->check_timings_(cur_time)) {
192  break;
193  }
194  this->last_mode_ = cur_mode;
195  break;
197  if (this->last_mode_ == OperationMode::WRITE) {
199  } else if (this->last_mode_ == OperationMode::READ) {
201  }
202 
203  this->stop_opentherm_();
204  break;
206  this->handle_timeout_error_();
207  this->stop_opentherm_();
208  break;
209  case OperationMode::IDLE:
210  if (this->should_skip_loop_(cur_time)) {
211  break;
212  }
213  this->start_conversation_();
214  break;
215  case OperationMode::SENT:
216  // Message sent, now listen for the response.
217  this->opentherm_->listen();
218  break;
220  this->read_response_();
221  break;
222  }
223 }
224 
226  if (!this->opentherm_->is_idle()) {
227  ESP_LOGE(TAG, "OpenTherm is not idle at the start of the loop");
228  return;
229  }
230 
231  auto cur_time = millis();
232 
233  this->check_timings_(cur_time);
234 
235  if (this->should_skip_loop_(cur_time)) {
236  return;
237  }
238 
239  this->start_conversation_();
240 
241  if (!this->spin_wait_(1150, [&] { return this->opentherm_->is_active(); })) {
242  ESP_LOGE(TAG, "Hub timeout triggered during send");
243  this->stop_opentherm_();
244  return;
245  }
246 
247  if (this->opentherm_->is_error()) {
249  this->stop_opentherm_();
250  return;
251  } else if (!this->opentherm_->is_sent()) {
252  ESP_LOGW(TAG, "Unexpected state after sending request: %s",
253  this->opentherm_->operation_mode_to_str(this->opentherm_->get_mode()));
254  this->stop_opentherm_();
255  return;
256  }
257 
258  // Listen for the response
259  this->opentherm_->listen();
260  if (!this->spin_wait_(1150, [&] { return this->opentherm_->is_active(); })) {
261  ESP_LOGE(TAG, "Hub timeout triggered during receive");
262  this->stop_opentherm_();
263  return;
264  }
265 
266  if (this->opentherm_->is_timeout()) {
267  this->handle_timeout_error_();
268  this->stop_opentherm_();
269  return;
270  } else if (this->opentherm_->is_protocol_error()) {
272  this->stop_opentherm_();
273  return;
274  } else if (!this->opentherm_->has_message()) {
275  ESP_LOGW(TAG, "Unexpected state after receiving response: %s",
276  this->opentherm_->operation_mode_to_str(this->opentherm_->get_mode()));
277  this->stop_opentherm_();
278  return;
279  }
280 
281  this->read_response_();
282 }
283 
284 bool OpenthermHub::check_timings_(uint32_t cur_time) {
285  if (this->last_conversation_start_ > 0 && (cur_time - this->last_conversation_start_) > 1150) {
286  ESP_LOGW(TAG,
287  "%d ms elapsed since the start of the last convo, but 1150 ms are allowed at maximum. Look at other "
288  "components that might slow the loop down.",
289  (int) (cur_time - this->last_conversation_start_));
290  this->stop_opentherm_();
291  return false;
292  }
293 
294  return true;
295 }
296 
297 bool OpenthermHub::should_skip_loop_(uint32_t cur_time) const {
298  if (this->last_conversation_end_ > 0 && (cur_time - this->last_conversation_end_) < 100) {
299  ESP_LOGV(TAG, "Less than 100 ms elapsed since last convo, skipping this iteration");
300  return true;
301  }
302 
303  return false;
304 }
305 
307  if (this->sending_initial_ && this->current_message_iterator_ == this->initial_messages_.end()) {
308  this->sending_initial_ = false;
309  this->current_message_iterator_ = this->repeating_messages_.begin();
310  } else if (this->current_message_iterator_ == this->repeating_messages_.end()) {
311  this->current_message_iterator_ = this->repeating_messages_.begin();
312  }
313 
314  auto request = this->build_request_(*this->current_message_iterator_);
315 
316  ESP_LOGD(TAG, "Sending request with id %d (%s)", request.id,
317  this->opentherm_->message_id_to_str((MessageId) request.id));
318  this->opentherm_->debug_data(request);
319  // Send the request
321  this->opentherm_->send(request);
322 }
323 
325  OpenthermData response;
326  if (!this->opentherm_->get_message(response)) {
327  ESP_LOGW(TAG, "Couldn't get the response, but flags indicated success. This is a bug.");
328  this->stop_opentherm_();
329  return;
330  }
331 
332  this->stop_opentherm_();
333 
334  this->process_response(response);
335 
337 }
338 
340  this->opentherm_->stop();
341  this->last_conversation_end_ = millis();
342 }
344  ESP_LOGW(TAG, "Error while sending request: %s",
345  this->opentherm_->operation_mode_to_str(this->opentherm_->get_mode()));
346  this->opentherm_->debug_data(this->last_request_);
347 }
349  OpenThermError error;
350  this->opentherm_->get_protocol_error(error);
351  ESP_LOGW(TAG, "Protocol error occured while receiving response: %s",
352  this->opentherm_->protocol_error_to_to_str(error.error_type));
353  this->opentherm_->debug_error(error);
354 }
356  ESP_LOGW(TAG, "Receive response timed out at a protocol level");
357  this->stop_opentherm_();
358 }
359 
361  ESP_LOGCONFIG(TAG, "OpenTherm:");
362  LOG_PIN(" In: ", this->in_pin_);
363  LOG_PIN(" Out: ", this->out_pin_);
364  ESP_LOGCONFIG(TAG, " Sync mode: %d", this->sync_mode_);
365  ESP_LOGCONFIG(TAG, " Sensors: %s", SHOW(OPENTHERM_SENSOR_LIST(ID, )));
366  ESP_LOGCONFIG(TAG, " Binary sensors: %s", SHOW(OPENTHERM_BINARY_SENSOR_LIST(ID, )));
367  ESP_LOGCONFIG(TAG, " Switches: %s", SHOW(OPENTHERM_SWITCH_LIST(ID, )));
368  ESP_LOGCONFIG(TAG, " Input sensors: %s", SHOW(OPENTHERM_INPUT_SENSOR_LIST(ID, )));
369  ESP_LOGCONFIG(TAG, " Outputs: %s", SHOW(OPENTHERM_OUTPUT_LIST(ID, )));
370  ESP_LOGCONFIG(TAG, " Numbers: %s", SHOW(OPENTHERM_NUMBER_LIST(ID, )));
371  ESP_LOGCONFIG(TAG, " Initial requests:");
372  for (auto type : this->initial_messages_) {
373  ESP_LOGCONFIG(TAG, " - %d (%s)", type, this->opentherm_->message_id_to_str((type)));
374  }
375  ESP_LOGCONFIG(TAG, " Repeating requests:");
376  for (auto type : this->repeating_messages_) {
377  ESP_LOGCONFIG(TAG, " - %d (%s)", type, this->opentherm_->message_id_to_str((type)));
378  }
379 }
380 
381 } // namespace opentherm
382 } // namespace esphome
void write_flag8_lb_2(const bool value, OpenthermData &data)
Definition: hub.cpp:39
bool should_skip_loop_(uint32_t cur_time) const
Definition: hub.cpp:297
uint16_t parse_u8_lb_60(OpenthermData &data)
Definition: hub.cpp:32
uint16_t parse_u16(OpenthermData &data)
Definition: hub.cpp:31
constexpr T read_bit(T value, uint8_t bit)
Definition: opentherm.h:22
bool check_timings_(uint32_t cur_time)
Definition: hub.cpp:284
bool parse_flag8_hb_3(OpenthermData &data)
Definition: hub.cpp:22
int8_t parse_s8_lb(OpenthermData &data)
Definition: hub.cpp:29
void write_u16(const uint16_t value, OpenthermData &data)
Definition: hub.cpp:57
void write_flag8_lb_1(const bool value, OpenthermData &data)
Definition: hub.cpp:38
int16_t parse_s16(OpenthermData &data)
Definition: hub.cpp:34
void write_s8_lb(const int8_t value, OpenthermData &data)
Definition: hub.cpp:55
float parse_f88(OpenthermData &data)
Definition: hub.cpp:35
void write_flag8_lb_7(const bool value, OpenthermData &data)
Definition: hub.cpp:44
bool parse_flag8_lb_4(OpenthermData &data)
Definition: hub.cpp:15
void write_s8_hb(const int8_t value, OpenthermData &data)
Definition: hub.cpp:56
bool parse_flag8_lb_3(OpenthermData &data)
Definition: hub.cpp:14
uint32_t last_conversation_start_
Definition: hub.h:71
std::vector< MessageId >::const_iterator current_message_iterator_
Definition: hub.h:69
uint16_t parse_u8_hb_60(OpenthermData &data)
Definition: hub.cpp:33
void write_flag8_lb_3(const bool value, OpenthermData &data)
Definition: hub.cpp:40
void process_response(OpenthermData &data)
Definition: hub.cpp:138
timeout while waiting to receive bytes
Definition: i2c_bus.h:16
void write_f88(const float value, OpenthermData &data)
Definition: hub.cpp:59
InternalGPIOPin * in_pin_
Definition: hub.h:45
constexpr T write_bit(T value, uint8_t bit, uint8_t bit_value)
Definition: opentherm.h:28
OPENTHERM_OUTPUT_LIST(OPENTHERM_DECLARE_OUTPUT,) OPENTHERM_INPUT_SENSOR_LIST(OPENTHERM_DECLARE_INPUT_SENSOR
std::unique_ptr< OpenTherm > opentherm_
Definition: hub.h:47
bool parse_flag8_hb_1(OpenthermData &data)
Definition: hub.cpp:20
void write_flag8_hb_4(const bool value, OpenthermData &data)
Definition: hub.cpp:49
uint32_t IRAM_ATTR HOT millis()
Definition: core.cpp:25
OperationMode last_mode_
Definition: hub.h:73
bool parse_flag8_hb_2(OpenthermData &data)
Definition: hub.cpp:21
bool parse_flag8_lb_0(OpenthermData &data)
Definition: hub.cpp:11
bool spin_wait_(uint32_t timeout, F func)
Definition: hub.h:95
void write_s16(const int16_t value, OpenthermData &data)
Definition: hub.cpp:58
bool parse_flag8_lb_5(OpenthermData &data)
Definition: hub.cpp:16
void write_flag8_hb_6(const bool value, OpenthermData &data)
Definition: hub.cpp:51
bool parse_flag8_lb_7(OpenthermData &data)
Definition: hub.cpp:18
bool parse_flag8_lb_6(OpenthermData &data)
Definition: hub.cpp:17
void write_flag8_hb_0(const bool value, OpenthermData &data)
Definition: hub.cpp:45
void write_flag8_lb_4(const bool value, OpenthermData &data)
Definition: hub.cpp:41
int8_t parse_s8_hb(OpenthermData &data)
Definition: hub.cpp:30
uint32_t last_conversation_end_
Definition: hub.h:72
InternalGPIOPin * out_pin_
Definition: hub.h:45
bool parse_flag8_lb_1(OpenthermData &data)
Definition: hub.cpp:12
std::vector< MessageId > initial_messages_
Definition: hub.h:62
bool parse_flag8_hb_0(OpenthermData &data)
Definition: hub.cpp:19
void write_flag8_lb_6(const bool value, OpenthermData &data)
Definition: hub.cpp:43
uint8_t type
bool parse_flag8_hb_7(OpenthermData &data)
Definition: hub.cpp:26
std::vector< MessageId > repeating_messages_
Definition: hub.h:65
uint8_t parse_u8_lb(OpenthermData &data)
Definition: hub.cpp:27
void write_flag8_hb_5(const bool value, OpenthermData &data)
Definition: hub.cpp:50
void write_flag8_hb_1(const bool value, OpenthermData &data)
Definition: hub.cpp:46
bool parse_flag8_hb_4(OpenthermData &data)
Definition: hub.cpp:23
void write_flag8_hb_2(const bool value, OpenthermData &data)
Definition: hub.cpp:47
void dump_config() override
Definition: hub.cpp:360
bool parse_flag8_hb_6(OpenthermData &data)
Definition: hub.cpp:25
bool parse_flag8_lb_2(OpenthermData &data)
Definition: hub.cpp:13
virtual void mark_failed()
Mark this component as failed.
Definition: component.cpp:118
void write_flag8_hb_3(const bool value, OpenthermData &data)
Definition: hub.cpp:48
OPENTHERM_SWITCH_LIST(OPENTHERM_DECLARE_SWITCH,) OPENTHERM_NUMBER_LIST(OPENTHERM_DECLARE_NUMBER
void write_flag8_hb_7(const bool value, OpenthermData &data)
Definition: hub.cpp:52
Implementation of SPI Controller mode.
Definition: a01nyub.cpp:7
void write_u8_lb(const uint8_t value, OpenthermData &data)
Definition: hub.cpp:53
void write_u8_hb(const uint8_t value, OpenthermData &data)
Definition: hub.cpp:54
void add_repeating_message(MessageId message_id)
Definition: hub.h:136
Structure to hold Opentherm data packet content.
Definition: opentherm.h:175
OPENTHERM_SENSOR_LIST(OPENTHERM_DECLARE_SENSOR,) OPENTHERM_BINARY_SENSOR_LIST(OPENTHERM_DECLARE_BINARY_SENSOR
uint8_t parse_u8_hb(OpenthermData &data)
Definition: hub.cpp:28
void write_flag8_lb_5(const bool value, OpenthermData &data)
Definition: hub.cpp:42
void on_shutdown() override
Definition: hub.cpp:177
OpenthermData build_request_(MessageId request_id) const
Definition: hub.cpp:63
void write_flag8_lb_0(const bool value, OpenthermData &data)
Definition: hub.cpp:37
OpenthermData last_request_
Definition: hub.h:74
bool parse_flag8_hb_5(OpenthermData &data)
Definition: hub.cpp:24