ESPHome  2024.11.1
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 // OpenTherm component for ESPHome
42 class OpenthermHub : public Component {
43  protected:
44  // Communication pins for the OpenTherm interface
46  // The OpenTherm interface
47  std::unique_ptr<OpenTherm> opentherm_;
48 
49  OPENTHERM_SENSOR_LIST(OPENTHERM_DECLARE_SENSOR, )
50 
51  OPENTHERM_BINARY_SENSOR_LIST(OPENTHERM_DECLARE_BINARY_SENSOR, )
52 
53  OPENTHERM_SWITCH_LIST(OPENTHERM_DECLARE_SWITCH, )
54 
55  OPENTHERM_NUMBER_LIST(OPENTHERM_DECLARE_NUMBER, )
56 
57  OPENTHERM_OUTPUT_LIST(OPENTHERM_DECLARE_OUTPUT, )
58 
59  OPENTHERM_INPUT_SENSOR_LIST(OPENTHERM_DECLARE_INPUT_SENSOR, )
60 
61  // The set of initial messages to send on starting communication with the boiler
63  // and the repeating messages which are sent repeatedly to update various sensors
64  // and boiler parameters (like the setpoint).
66  // Indicates if we are still working on the initial requests or not
67  bool sending_initial_ = true;
68  // Index for the current request in one of the _requests sets.
69  std::vector<MessageId>::const_iterator current_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 
81  float opentherm_version_ = 0.0f;
82 
83  // Create OpenTherm messages based on the message id
84  OpenthermData build_request_(MessageId request_id) const;
87  void handle_timeout_error_();
88  void stop_opentherm_();
89  void start_conversation_();
90  void read_response_();
91  bool check_timings_(uint32_t cur_time);
92  bool should_skip_loop_(uint32_t cur_time) const;
93  void sync_loop_();
94 
95  template<typename F> bool spin_wait_(uint32_t timeout, F func) {
96  auto start_time = millis();
97  while (func()) {
98  yield();
99  auto cur_time = millis();
100  if (cur_time - start_time >= timeout) {
101  return false;
102  }
103  }
104  return true;
105  }
106 
107  public:
108  // Constructor with references to the global interrupt handlers
109  OpenthermHub();
110 
111  // Handle responses from the OpenTherm interface
112  void process_response(OpenthermData &data);
113 
114  // Setters for the input and output OpenTherm interface pins
115  void set_in_pin(InternalGPIOPin *in_pin) { this->in_pin_ = in_pin; }
116  void set_out_pin(InternalGPIOPin *out_pin) { this->out_pin_ = out_pin; }
117 
118  OPENTHERM_SENSOR_LIST(OPENTHERM_SET_SENSOR, )
119 
120  OPENTHERM_BINARY_SENSOR_LIST(OPENTHERM_SET_BINARY_SENSOR, )
121 
122  OPENTHERM_SWITCH_LIST(OPENTHERM_SET_SWITCH, )
123 
124  OPENTHERM_NUMBER_LIST(OPENTHERM_SET_NUMBER, )
125 
126  OPENTHERM_OUTPUT_LIST(OPENTHERM_SET_OUTPUT, )
127 
128  OPENTHERM_INPUT_SENSOR_LIST(OPENTHERM_SET_INPUT_SENSOR, )
129 
130  // Add a request to the vector of initial requests
131  void add_initial_message(MessageId message_id) { this->initial_messages_.push_back(message_id); }
132  // Add a request to the set of repeating requests. Note that a large number of repeating
133  // requests will slow down communication with the boiler. Each request may take up to 1 second,
134  // so with all sensors enabled, it may take about half a minute before a change in setpoint
135  // will be processed.
136  void add_repeating_message(MessageId message_id) { this->repeating_messages_.push_back(message_id); }
137 
138  // There are seven status variables, which can either be set as a simple variable,
139  // or using a switch. ch_enable and dhw_enable default to true, the others to false.
140  bool ch_enable = true, dhw_enable = true, cooling_enable = false, otc_active = false, ch2_active = false,
141  summer_mode_active = false, dhw_block = false;
142 
143  // Setters for the status variables
144  void set_ch_enable(bool value) { this->ch_enable = value; }
145  void set_dhw_enable(bool value) { this->dhw_enable = value; }
146  void set_cooling_enable(bool value) { this->cooling_enable = value; }
147  void set_otc_active(bool value) { this->otc_active = value; }
148  void set_ch2_active(bool value) { this->ch2_active = value; }
149  void set_summer_mode_active(bool value) { this->summer_mode_active = value; }
150  void set_dhw_block(bool value) { this->dhw_block = value; }
151  void set_sync_mode(bool sync_mode) { this->sync_mode_ = sync_mode; }
152  void set_opentherm_version(float value) { this->opentherm_version_ = value; }
153 
154  float get_setup_priority() const override { return setup_priority::HARDWARE; }
155 
156  void setup() override;
157  void on_shutdown() override;
158  void loop() override;
159  void dump_config() override;
160 };
161 
162 } // namespace opentherm
163 } // namespace esphome
bool should_skip_loop_(uint32_t cur_time) const
Definition: hub.cpp:297
void set_dhw_block(bool value)
Definition: hub.h:150
bool check_timings_(uint32_t cur_time)
Definition: hub.cpp:284
uint32_t last_conversation_start_
Definition: hub.h:71
std::vector< MessageId >::const_iterator current_message_iterator_
Definition: hub.h:69
void process_response(OpenthermData &data)
Definition: hub.cpp:138
STL namespace.
InternalGPIOPin * in_pin_
Definition: hub.h:45
OPENTHERM_OUTPUT_LIST(OPENTHERM_DECLARE_OUTPUT,) OPENTHERM_INPUT_SENSOR_LIST(OPENTHERM_DECLARE_INPUT_SENSOR
void set_out_pin(InternalGPIOPin *out_pin)
Definition: hub.h:116
std::unique_ptr< OpenTherm > opentherm_
Definition: hub.h:47
uint32_t IRAM_ATTR HOT millis()
Definition: core.cpp:25
OperationMode last_mode_
Definition: hub.h:73
void set_opentherm_version(float value)
Definition: hub.h:152
bool spin_wait_(uint32_t timeout, F func)
Definition: hub.h:95
void set_sync_mode(bool sync_mode)
Definition: hub.h:151
uint32_t last_conversation_end_
Definition: hub.h:72
InternalGPIOPin * out_pin_
Definition: hub.h:45
std::vector< MessageId > initial_messages_
Definition: hub.h:62
void set_in_pin(InternalGPIOPin *in_pin)
Definition: hub.h:115
void set_cooling_enable(bool value)
Definition: hub.h:146
std::vector< MessageId > repeating_messages_
Definition: hub.h:65
void dump_config() override
Definition: hub.cpp:361
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:154
void add_initial_message(MessageId message_id)
Definition: hub.h:131
void IRAM_ATTR HOT yield()
Definition: core.cpp:24
void set_dhw_enable(bool value)
Definition: hub.h:145
void set_otc_active(bool value)
Definition: hub.h:147
OPENTHERM_SWITCH_LIST(OPENTHERM_DECLARE_SWITCH,) OPENTHERM_NUMBER_LIST(OPENTHERM_DECLARE_NUMBER
Implementation of SPI Controller mode.
Definition: a01nyub.cpp:7
void set_ch_enable(bool value)
Definition: hub.h:144
void add_repeating_message(MessageId message_id)
Definition: hub.h:136
Structure to hold Opentherm data packet content.
Definition: opentherm.h:176
void set_summer_mode_active(bool value)
Definition: hub.h:149
OPENTHERM_SENSOR_LIST(OPENTHERM_DECLARE_SENSOR,) OPENTHERM_BINARY_SENSOR_LIST(OPENTHERM_DECLARE_BINARY_SENSOR
void on_shutdown() override
Definition: hub.cpp:177
OpenthermData build_request_(MessageId request_id) const
Definition: hub.cpp:63
void set_ch2_active(bool value)
Definition: hub.h:148
OpenthermData last_request_
Definition: hub.h:74