ESPHome  2025.2.0
hub.h
Go to the documentation of this file.
1 #pragma once
2 
3 #include "esphome/core/defines.h"
4 #include "esphome/core/hal.h"
6 #include "esphome/core/log.h"
7 #include <vector>
8 
9 #include "opentherm.h"
10 
11 #ifdef OPENTHERM_USE_SENSOR
13 #endif
14 
15 #ifdef OPENTHERM_USE_BINARY_SENSOR
17 #endif
18 
19 #ifdef OPENTHERM_USE_SWITCH
21 #endif
22 
23 #ifdef OPENTHERM_USE_OUTPUT
25 #endif
26 
27 #ifdef OPENTHERM_USE_NUMBER
29 #endif
30 
31 #include <memory>
32 #include <unordered_map>
33 #include <unordered_set>
34 #include <functional>
35 
36 #include "opentherm_macros.h"
37 
38 namespace esphome {
39 namespace opentherm {
40 
41 static const uint8_t REPEATING_MESSAGE_ORDER = 255;
42 static const uint8_t INITIAL_UNORDERED_MESSAGE_ORDER = 254;
43 
44 // OpenTherm component for ESPHome
45 class OpenthermHub : public Component {
46  protected:
47  // Communication pins for the OpenTherm interface
49  // The OpenTherm interface
50  std::unique_ptr<OpenTherm> opentherm_;
51 
52  OPENTHERM_SENSOR_LIST(OPENTHERM_DECLARE_SENSOR, )
53 
54  OPENTHERM_BINARY_SENSOR_LIST(OPENTHERM_DECLARE_BINARY_SENSOR, )
55 
56  OPENTHERM_SWITCH_LIST(OPENTHERM_DECLARE_SWITCH, )
57 
58  OPENTHERM_NUMBER_LIST(OPENTHERM_DECLARE_NUMBER, )
59 
60  OPENTHERM_OUTPUT_LIST(OPENTHERM_DECLARE_OUTPUT, )
61 
62  OPENTHERM_INPUT_SENSOR_LIST(OPENTHERM_DECLARE_INPUT_SENSOR, )
63 
64  OPENTHERM_SETTING_LIST(OPENTHERM_DECLARE_SETTING, )
65 
66  bool sending_initial_ = true;
67  std::unordered_map<MessageId, uint8_t> configured_messages_;
68  std::vector<MessageId> messages_;
69  std::vector<MessageId>::const_iterator message_iterator_;
70 
72  uint32_t last_conversation_end_ = 0;
75 
76  // Synchronous communication mode prevents other components from disabling interrupts while
77  // we are talking to the boiler. Enable if you experience random intermittent invalid response errors.
78  // Very likely to happen while using Dallas temperature sensors.
79  bool sync_mode_ = false;
80 
83 
84  // Create OpenTherm messages based on the message id
85  OpenthermData build_request_(MessageId request_id) const;
88  void handle_timeout_error_();
89  void handle_timer_error_();
90  void stop_opentherm_();
91  void start_conversation_();
92  void read_response_();
93  void check_timings_(uint32_t cur_time);
94  bool should_skip_loop_(uint32_t cur_time) const;
95  void sync_loop_();
96 
97  void write_initial_messages_(std::vector<MessageId> &target);
98  void write_repeating_messages_(std::vector<MessageId> &target);
99 
100  template<typename F> bool spin_wait_(uint32_t timeout, F func) {
101  auto start_time = millis();
102  while (func()) {
103  yield();
104  auto cur_time = millis();
105  if (cur_time - start_time >= timeout) {
106  return false;
107  }
108  }
109  return true;
110  }
111 
112  public:
113  // Constructor with references to the global interrupt handlers
114  OpenthermHub();
115 
116  // Handle responses from the OpenTherm interface
117  void process_response(OpenthermData &data);
118 
119  // Setters for the input and output OpenTherm interface pins
120  void set_in_pin(InternalGPIOPin *in_pin) { this->in_pin_ = in_pin; }
121  void set_out_pin(InternalGPIOPin *out_pin) { this->out_pin_ = out_pin; }
122 
123  OPENTHERM_SENSOR_LIST(OPENTHERM_SET_SENSOR, )
124 
125  OPENTHERM_BINARY_SENSOR_LIST(OPENTHERM_SET_BINARY_SENSOR, )
126 
127  OPENTHERM_SWITCH_LIST(OPENTHERM_SET_SWITCH, )
128 
129  OPENTHERM_NUMBER_LIST(OPENTHERM_SET_NUMBER, )
130 
131  OPENTHERM_OUTPUT_LIST(OPENTHERM_SET_OUTPUT, )
132 
133  OPENTHERM_INPUT_SENSOR_LIST(OPENTHERM_SET_INPUT_SENSOR, )
134 
135  OPENTHERM_SETTING_LIST(OPENTHERM_SET_SETTING, )
136 
137  // Add a request to the vector of initial requests
138  void add_initial_message(MessageId message_id) {
139  this->configured_messages_[message_id] = INITIAL_UNORDERED_MESSAGE_ORDER;
140  }
141  void add_initial_message(MessageId message_id, uint8_t order) { this->configured_messages_[message_id] = order; }
142  // Add a request to the set of repeating requests. Note that a large number of repeating
143  // requests will slow down communication with the boiler. Each request may take up to 1 second,
144  // so with all sensors enabled, it may take about half a minute before a change in setpoint
145  // will be processed.
146  void add_repeating_message(MessageId message_id) { this->configured_messages_[message_id] = REPEATING_MESSAGE_ORDER; }
147 
148  // There are seven status variables, which can either be set as a simple variable,
149  // or using a switch. ch_enable and dhw_enable default to true, the others to false.
150  bool ch_enable = true, dhw_enable = true, cooling_enable = false, otc_active = false, ch2_active = false,
151  summer_mode_active = false, dhw_block = false;
152 
153  // Setters for the status variables
154  void set_ch_enable(bool value) { this->ch_enable = value; }
155  void set_dhw_enable(bool value) { this->dhw_enable = value; }
156  void set_cooling_enable(bool value) { this->cooling_enable = value; }
157  void set_otc_active(bool value) { this->otc_active = value; }
158  void set_ch2_active(bool value) { this->ch2_active = value; }
159  void set_summer_mode_active(bool value) { this->summer_mode_active = value; }
160  void set_dhw_block(bool value) { this->dhw_block = value; }
161  void set_sync_mode(bool sync_mode) { this->sync_mode_ = sync_mode; }
162 
163  void add_on_before_send_callback(std::function<void(OpenthermData &)> &&callback) {
164  this->before_send_callback_.add(std::move(callback));
165  }
166  void add_on_before_process_response_callback(std::function<void(OpenthermData &)> &&callback) {
167  this->before_process_response_callback_.add(std::move(callback));
168  }
169 
170  float get_setup_priority() const override { return setup_priority::HARDWARE; }
171 
172  void setup() override;
173  void on_shutdown() override;
174  void loop() override;
175  void dump_config() override;
176 };
177 
178 } // namespace opentherm
179 } // namespace esphome
void add_on_before_process_response_callback(std::function< void(OpenthermData &)> &&callback)
Definition: hub.h:166
bool should_skip_loop_(uint32_t cur_time) const
Definition: hub.cpp:321
void set_dhw_block(bool value)
Definition: hub.h:160
void check_timings_(uint32_t cur_time)
Definition: hub.cpp:312
uint32_t last_conversation_start_
Definition: hub.h:71
std::vector< MessageId >::const_iterator message_iterator_
Definition: hub.h:69
void process_response(OpenthermData &data)
Definition: hub.cpp:132
STL namespace.
std::unordered_map< MessageId, uint8_t > configured_messages_
Definition: hub.h:67
InternalGPIOPin * in_pin_
Definition: hub.h:48
OPENTHERM_OUTPUT_LIST(OPENTHERM_DECLARE_OUTPUT,) OPENTHERM_INPUT_SENSOR_LIST(OPENTHERM_DECLARE_INPUT_SENSOR
void set_out_pin(InternalGPIOPin *out_pin)
Definition: hub.h:121
std::unique_ptr< OpenTherm > opentherm_
Definition: hub.h:50
uint32_t IRAM_ATTR HOT millis()
Definition: core.cpp:25
OperationMode last_mode_
Definition: hub.h:73
bool spin_wait_(uint32_t timeout, F func)
Definition: hub.h:100
CallbackManager< void(OpenthermData &)> before_process_response_callback_
Definition: hub.h:82
void set_sync_mode(bool sync_mode)
Definition: hub.h:161
BedjetMode mode
BedJet operating mode.
Definition: bedjet_codec.h:183
uint32_t last_conversation_end_
Definition: hub.h:72
InternalGPIOPin * out_pin_
Definition: hub.h:48
CallbackManager< void(OpenthermData &)> before_send_callback_
Definition: hub.h:81
void set_in_pin(InternalGPIOPin *in_pin)
Definition: hub.h:120
void set_cooling_enable(bool value)
Definition: hub.h:156
void write_initial_messages_(std::vector< MessageId > &target)
Definition: hub.cpp:167
void add_on_before_send_callback(std::function< void(OpenthermData &)> &&callback)
Definition: hub.h:163
void dump_config() override
Definition: hub.cpp:393
const float HARDWARE
For components that deal with hardware and are very important like GPIO switch.
Definition: component.cpp:18
float get_setup_priority() const override
Definition: hub.h:170
void IRAM_ATTR HOT yield()
Definition: core.cpp:24
void set_dhw_enable(bool value)
Definition: hub.h:155
void set_otc_active(bool value)
Definition: hub.h:157
OPENTHERM_SWITCH_LIST(OPENTHERM_DECLARE_SWITCH,) OPENTHERM_NUMBER_LIST(OPENTHERM_DECLARE_NUMBER
Implementation of SPI Controller mode.
Definition: a01nyub.cpp:7
std::vector< MessageId > messages_
Definition: hub.h:68
void write_repeating_messages_(std::vector< MessageId > &target)
Definition: hub.cpp:182
OPENTHERM_SETTING_LIST(OPENTHERM_DECLARE_SETTING,) bool sending_initial_
void set_ch_enable(bool value)
Definition: hub.h:154
void add_repeating_message(MessageId message_id)
Definition: hub.h:146
Structure to hold Opentherm data packet content.
Definition: opentherm.h:184
void set_summer_mode_active(bool value)
Definition: hub.h:159
OPENTHERM_SENSOR_LIST(OPENTHERM_DECLARE_SENSOR,) OPENTHERM_BINARY_SENSOR_LIST(OPENTHERM_DECLARE_BINARY_SENSOR
void on_shutdown() override
Definition: hub.cpp:164
OpenthermData build_request_(MessageId request_id) const
Definition: hub.cpp:63
void set_ch2_active(bool value)
Definition: hub.h:158
OpenthermData last_request_
Definition: hub.h:74
void add_initial_message(MessageId message_id, uint8_t order)
Definition: hub.h:141
bool handle_error_(OperationMode mode)
Definition: hub.cpp:229