ESPHome 2026.11.0-dev
Loading...
Searching...
No Matches
siemens_ira211.cpp
Go to the documentation of this file.
1#include "siemens_ira211.h"
2#include "esphome/core/hal.h"
4
6
7using namespace remote_base;
8
9struct PresetMapping {
11 IRA211Mode mode;
12};
13
14static const PresetMapping PRESETS[] PROGMEM = {
15 {climate::CLIMATE_PRESET_COMFORT, IRA211Mode::IRA211_MODE_COMFORT},
16 {climate::CLIMATE_PRESET_ECO, IRA211Mode::IRA211_MODE_TIMER},
17};
18
19struct FanMapping {
21 IRA211Fan fan;
22};
23
24static const FanMapping FANS[] PROGMEM = {
25 {climate::CLIMATE_FAN_AUTO, IRA211Fan::IRA211_FAN_AUTO},
26 {climate::CLIMATE_FAN_LOW, IRA211Fan::IRA211_FAN_LOW},
27 {climate::CLIMATE_FAN_MEDIUM, IRA211Fan::IRA211_FAN_MEDIUM},
28 {climate::CLIMATE_FAN_HIGH, IRA211Fan::IRA211_FAN_HIGH},
29};
30
31// The tables live in flash, so entries are copied out before use
32template<typename T> static T load_entry(const T &slot) {
33 T entry;
34 progmem_memcpy(&entry, &slot, sizeof(T));
35 return entry;
36}
37
38// The first entry of each table is the fallback for values the other side does not know
39static IRA211Mode to_ira211_mode(climate::ClimatePreset preset) {
40 for (const auto &slot : PRESETS) {
41 const auto entry = load_entry(slot);
42 if (entry.preset == preset)
43 return entry.mode;
44 }
45 return load_entry(PRESETS[0]).mode;
46}
47
48static climate::ClimatePreset to_climate_preset(IRA211Mode mode) {
49 for (const auto &slot : PRESETS) {
50 const auto entry = load_entry(slot);
51 if (entry.mode == mode)
52 return entry.preset;
53 }
54 return load_entry(PRESETS[0]).preset;
55}
56
57static IRA211Fan to_ira211_fan(climate::ClimateFanMode fan_mode) {
58 for (const auto &slot : FANS) {
59 const auto entry = load_entry(slot);
60 if (entry.fan_mode == fan_mode)
61 return entry.fan;
62 }
63 return load_entry(FANS[0]).fan;
64}
65
66static climate::ClimateFanMode to_climate_fan_mode(IRA211Fan fan) {
67 for (const auto &slot : FANS) {
68 const auto entry = load_entry(slot);
69 if (entry.fan == fan)
70 return entry.fan_mode;
71 }
72 return load_entry(FANS[0]).fan_mode;
73}
74
76 // The thermostat decides between heating and cooling itself, so one mode stands for both
80 }
82 // Match the restored state, so the first command after a reboot does not send a needless POWER frame
83 this->is_on_ = this->mode != climate::CLIMATE_MODE_OFF;
84}
85
93
95 IRA211Data data{};
96 data.command = command;
97 data.set_temperature(this->target_temperature);
98 data.mode = mode;
99 data.fan = fan;
100 this->transmit_<IRA211Protocol>(data);
101}
102
104 const IRA211Mode mode = to_ira211_mode(this->preset.value_or(climate::CLIMATE_PRESET_COMFORT));
105 const IRA211Fan fan = to_ira211_fan(this->fan_mode.value_or(climate::CLIMATE_FAN_AUTO));
106 // Show the preset that is actually sent, so a fresh entity does not stay on "none"
107 this->preset = to_climate_preset(mode);
108
109 if (this->mode == climate::CLIMATE_MODE_OFF) {
110 this->transmit_frame_(IRA211Command::IRA211_COMMAND_POWER, IRA211Mode::IRA211_MODE_PROTECTION, fan);
111 this->is_on_ = false;
112 return;
113 }
114 if (!this->is_on_) {
115 // Turning on takes a POWER frame before the state is sent
116 this->transmit_frame_(IRA211Command::IRA211_COMMAND_POWER, mode, fan);
117 this->is_on_ = true;
118 }
119 this->transmit_frame_(IRA211Command::IRA211_COMMAND_SYNC, mode, fan);
120}
121
123 // The thermostat reports "off" as the PROTECTION mode
124 if (mode == IRA211Mode::IRA211_MODE_PROTECTION) {
125 this->mode = climate::CLIMATE_MODE_OFF;
126 this->is_on_ = false;
127 return;
128 }
129 if (!this->is_on_) {
130 this->mode = this->active_mode_();
131 this->is_on_ = true;
132 }
133 this->preset = to_climate_preset(mode);
134}
135
137 auto decoded = IRA211Protocol().decode(data);
138 if (!decoded.has_value())
139 return false;
140
141 const IRA211Data &frame = *decoded;
142 switch (frame.command) {
143 case IRA211Command::IRA211_COMMAND_SYNC:
144 case IRA211Command::IRA211_COMMAND_POWER:
145 this->apply_mode_(frame.mode);
146 this->target_temperature = frame.get_temperature();
147 this->fan_mode = to_climate_fan_mode(frame.fan);
148 break;
149 case IRA211Command::IRA211_COMMAND_TEMP_UP:
150 case IRA211Command::IRA211_COMMAND_TEMP_DOWN:
151 this->target_temperature = frame.get_temperature();
152 break;
153 case IRA211Command::IRA211_COMMAND_MODE:
154 this->apply_mode_(frame.mode);
155 break;
156 case IRA211Command::IRA211_COMMAND_FAN:
157 this->fan_mode = to_climate_fan_mode(frame.fan);
158 break;
159 default:
160 return false;
161 }
162
163 this->publish_state();
164 return true;
165}
166
167} // namespace esphome::siemens_ira211
BedjetMode mode
BedJet operating mode.
constexpr size_t count(ValueType value) const
Check if the set contains a specific value (std::set compatibility) Returns 1 if present,...
constexpr void erase(ValueType value)
Remove a value from the set (std::set compatibility)
ClimateMode mode
The active mode of the climate device.
Definition climate.h:304
float target_temperature
The target temperature of the climate device.
Definition climate.h:285
void publish_state()
Publish the state of the climate device, to be called from integrations.
Definition climate.cpp:429
climate::ClimateModeMask modes_
Definition climate_ir.h:77
optional< IRA211Data > decode(RemoteReceiveData src)
void transmit_(const typename Protocol::ProtocolData &data, uint32_t send_times=1, uint32_t send_wait=0)
bool on_receive(remote_base::RemoteReceiveData data) override
void transmit_frame_(remote_base::IRA211Command command, remote_base::IRA211Mode mode, remote_base::IRA211Fan fan)
void apply_mode_(remote_base::IRA211Mode mode)
ClimateFanMode fan_mode
Definition climate.h:3
ClimatePreset preset
Definition climate.h:8
ClimatePreset
Enum for all preset modes NOTE: If adding values, update ClimatePresetMask in climate_traits....
@ CLIMATE_PRESET_COMFORT
Device is in comfort preset.
@ CLIMATE_PRESET_ECO
Device is running an energy-saving preset.
ClimateMode
Enum for all modes a climate device can be in.
@ CLIMATE_MODE_HEAT
The climate device is set to heat to reach the target temperature.
@ CLIMATE_MODE_COOL
The climate device is set to cool to reach the target temperature.
@ CLIMATE_MODE_HEAT_COOL
The climate device is set to heat/cool to reach the target temperature.
@ CLIMATE_MODE_OFF
The climate device is off.
ClimateFanMode
NOTE: If adding values, update ClimateFanModeMask in climate_traits.h to use the new last value.
@ CLIMATE_FAN_MEDIUM
The fan mode is set to Medium.
@ CLIMATE_FAN_AUTO
The fan mode is set to Auto.
@ CLIMATE_FAN_LOW
The fan mode is set to Low.
@ CLIMATE_FAN_HIGH
The fan mode is set to High.
void progmem_memcpy(void *dst, const void *src, size_t len)
Definition hal.h:56