ESPHome 2026.2.1
Loading...
Searching...
No Matches
heatpumpir.cpp
Go to the documentation of this file.
1#include "heatpumpir.h"
2
3#if defined(USE_ARDUINO) || defined(USE_ESP32)
4
5#include <map>
6#include <IRSender.h>
7#include <HeatpumpIRFactory.h>
9#include "esphome/core/log.h"
10
11namespace esphome {
12namespace heatpumpir {
13
14// IRSenderESPHome - bridge between ESPHome's remote_transmitter and HeatpumpIR library
15// Defined here (not in a header) to isolate HeatpumpIR's headers from the rest of ESPHome,
16// as they define conflicting symbols like millis() in the global namespace.
17class IRSenderESPHome : public IRSender {
18 public:
19 IRSenderESPHome(remote_base::RemoteTransmitterBase *transmitter) : IRSender(0), transmit_(transmitter->transmit()) {}
20
21 void setFrequency(int frequency) override { // NOLINT(readability-identifier-naming)
22 auto *data = this->transmit_.get_data();
23 data->set_carrier_frequency(1000 * frequency);
24 }
25
26 void space(int space_length) override {
27 if (space_length) {
28 auto *data = this->transmit_.get_data();
29 data->space(space_length);
30 } else {
31 this->transmit_.perform();
32 }
33 }
34
35 void mark(int mark_length) override {
36 auto *data = this->transmit_.get_data();
37 data->mark(mark_length);
38 }
39
40 protected:
42};
43
44static const char *const TAG = "heatpumpir.climate";
45
46const std::map<Protocol, std::function<HeatpumpIR *()>> PROTOCOL_CONSTRUCTOR_MAP = {
47 {PROTOCOL_AUX, []() { return new AUXHeatpumpIR(); }}, // NOLINT
48 {PROTOCOL_BALLU, []() { return new BalluHeatpumpIR(); }}, // NOLINT
49 {PROTOCOL_CARRIER_MCA, []() { return new CarrierMCAHeatpumpIR(); }}, // NOLINT
50 {PROTOCOL_CARRIER_NQV, []() { return new CarrierNQVHeatpumpIR(); }}, // NOLINT
51 {PROTOCOL_DAIKIN_ARC417, []() { return new DaikinHeatpumpARC417IR(); }}, // NOLINT
52 {PROTOCOL_DAIKIN_ARC480, []() { return new DaikinHeatpumpARC480A14IR(); }}, // NOLINT
53 {PROTOCOL_DAIKIN, []() { return new DaikinHeatpumpIR(); }}, // NOLINT
54 {PROTOCOL_ELECTROLUXYAL, []() { return new ElectroluxYALHeatpumpIR(); }}, // NOLINT
55 {PROTOCOL_FUEGO, []() { return new FuegoHeatpumpIR(); }}, // NOLINT
56 {PROTOCOL_FUJITSU_AWYZ, []() { return new FujitsuHeatpumpIR(); }}, // NOLINT
57 {PROTOCOL_GREE, []() { return new GreeGenericHeatpumpIR(); }}, // NOLINT
58 {PROTOCOL_GREEYAA, []() { return new GreeYAAHeatpumpIR(); }}, // NOLINT
59 {PROTOCOL_GREEYAN, []() { return new GreeYANHeatpumpIR(); }}, // NOLINT
60 {PROTOCOL_GREEYAC, []() { return new GreeYACHeatpumpIR(); }}, // NOLINT
61 {PROTOCOL_GREEYT, []() { return new GreeYTHeatpumpIR(); }}, // NOLINT
62 {PROTOCOL_GREEYAP, []() { return new GreeYAPHeatpumpIR(); }}, // NOLINT
63 {PROTOCOL_HISENSE_AUD, []() { return new HisenseHeatpumpIR(); }}, // NOLINT
64 {PROTOCOL_HITACHI, []() { return new HitachiHeatpumpIR(); }}, // NOLINT
65 {PROTOCOL_HYUNDAI, []() { return new HyundaiHeatpumpIR(); }}, // NOLINT
66 {PROTOCOL_IVT, []() { return new IVTHeatpumpIR(); }}, // NOLINT
67 {PROTOCOL_MIDEA, []() { return new MideaHeatpumpIR(); }}, // NOLINT
68 {PROTOCOL_MITSUBISHI_FA, []() { return new MitsubishiFAHeatpumpIR(); }}, // NOLINT
69 {PROTOCOL_MITSUBISHI_FD, []() { return new MitsubishiFDHeatpumpIR(); }}, // NOLINT
70 {PROTOCOL_MITSUBISHI_FE, []() { return new MitsubishiFEHeatpumpIR(); }}, // NOLINT
71 {PROTOCOL_MITSUBISHI_HEAVY_FDTC, []() { return new MitsubishiHeavyFDTCHeatpumpIR(); }}, // NOLINT
72 {PROTOCOL_MITSUBISHI_HEAVY_ZJ, []() { return new MitsubishiHeavyZJHeatpumpIR(); }}, // NOLINT
73 {PROTOCOL_MITSUBISHI_HEAVY_ZM, []() { return new MitsubishiHeavyZMHeatpumpIR(); }}, // NOLINT
74 {PROTOCOL_MITSUBISHI_HEAVY_ZMP, []() { return new MitsubishiHeavyZMPHeatpumpIR(); }}, // NOLINT
75 {PROTOCOL_MITSUBISHI_KJ, []() { return new MitsubishiKJHeatpumpIR(); }}, // NOLINT
76 {PROTOCOL_MITSUBISHI_MSC, []() { return new MitsubishiMSCHeatpumpIR(); }}, // NOLINT
77 {PROTOCOL_MITSUBISHI_MSY, []() { return new MitsubishiMSYHeatpumpIR(); }}, // NOLINT
78 {PROTOCOL_MITSUBISHI_SEZ, []() { return new MitsubishiSEZKDXXHeatpumpIR(); }}, // NOLINT
79 {PROTOCOL_PANASONIC_CKP, []() { return new PanasonicCKPHeatpumpIR(); }}, // NOLINT
80 {PROTOCOL_PANASONIC_DKE, []() { return new PanasonicDKEHeatpumpIR(); }}, // NOLINT
81 {PROTOCOL_PANASONIC_EKE, []() { return new PanasonicEKEHeatpumpIR(); }}, // NOLINT
82 {PROTOCOL_PANASONIC_JKE, []() { return new PanasonicJKEHeatpumpIR(); }}, // NOLINT
83 {PROTOCOL_PANASONIC_LKE, []() { return new PanasonicLKEHeatpumpIR(); }}, // NOLINT
84 {PROTOCOL_PANASONIC_NKE, []() { return new PanasonicNKEHeatpumpIR(); }}, // NOLINT
85 {PROTOCOL_SAMSUNG_AQV, []() { return new SamsungAQVHeatpumpIR(); }}, // NOLINT
86 {PROTOCOL_SAMSUNG_FJM, []() { return new SamsungFJMHeatpumpIR(); }}, // NOLINT
87 {PROTOCOL_SHARP, []() { return new SharpHeatpumpIR(); }}, // NOLINT
88 {PROTOCOL_TOSHIBA_DAISEIKAI, []() { return new ToshibaDaiseikaiHeatpumpIR(); }}, // NOLINT
89 {PROTOCOL_TOSHIBA, []() { return new ToshibaHeatpumpIR(); }}, // NOLINT
90 {PROTOCOL_ZHLT01, []() { return new ZHLT01HeatpumpIR(); }}, // NOLINT
91 {PROTOCOL_NIBE, []() { return new NibeHeatpumpIR(); }}, // NOLINT
92 {PROTOCOL_QLIMA_1, []() { return new Qlima1HeatpumpIR(); }}, // NOLINT
93 {PROTOCOL_QLIMA_2, []() { return new Qlima2HeatpumpIR(); }}, // NOLINT
94 {PROTOCOL_SAMSUNG_AQV12MSAN, []() { return new SamsungAQV12MSANHeatpumpIR(); }}, // NOLINT
95 {PROTOCOL_ZHJG01, []() { return new ZHJG01HeatpumpIR(); }}, // NOLINT
96 {PROTOCOL_AIRWAY, []() { return new AIRWAYHeatpumpIR(); }}, // NOLINT
97 {PROTOCOL_BGH_AUD, []() { return new BGHHeatpumpIR(); }}, // NOLINT
98 {PROTOCOL_PANASONIC_ALTDKE, []() { return new PanasonicAltDKEHeatpumpIR(); }}, // NOLINT
99 {PROTOCOL_PHILCO_PHS32, []() { return new PhilcoPHS32HeatpumpIR(); }}, // NOLINT
100 {PROTOCOL_VAILLANTVAI8, []() { return new VaillantHeatpumpIR(); }}, // NOLINT
101 {PROTOCOL_R51M, []() { return new R51MHeatpumpIR(); }}, // NOLINT
102};
103
105 auto protocol_constructor = PROTOCOL_CONSTRUCTOR_MAP.find(protocol_);
106 if (protocol_constructor == PROTOCOL_CONSTRUCTOR_MAP.end()) {
107 ESP_LOGE(TAG, "Invalid protocol");
108 return;
109 }
110 this->heatpump_ir_ = protocol_constructor->second();
112 if (this->sensor_) {
113 this->sensor_->add_on_state_callback([this](float state) {
115
116 IRSenderESPHome esp_sender(this->transmitter_);
117 this->heatpump_ir_->send(esp_sender, uint8_t(lround(this->current_temperature + 0.5)));
118
119 // current temperature changed, publish state
120 this->publish_state();
121 });
122 this->current_temperature = this->sensor_->state;
123 } else {
124 this->current_temperature = NAN;
125 }
126}
127
129 uint8_t power_mode_cmd;
130 uint8_t operating_mode_cmd;
131 uint8_t temperature_cmd;
132 uint8_t fan_speed_cmd;
133
134 uint8_t swing_v_cmd;
137 swing_v_cmd = VDIR_AUTO;
138 break;
140 swing_v_cmd = VDIR_UP;
141 break;
143 swing_v_cmd = VDIR_MUP;
144 break;
146 swing_v_cmd = VDIR_MIDDLE;
147 break;
149 swing_v_cmd = VDIR_MDOWN;
150 break;
152 swing_v_cmd = VDIR_DOWN;
153 break;
154 default:
155 ESP_LOGE(TAG, "Invalid default vertical direction");
156 return;
157 }
159 swing_v_cmd = VDIR_SWING;
160 }
161
162 uint8_t swing_h_cmd;
165 swing_h_cmd = HDIR_AUTO;
166 break;
168 swing_h_cmd = HDIR_MIDDLE;
169 break;
171 swing_h_cmd = HDIR_LEFT;
172 break;
174 swing_h_cmd = HDIR_MLEFT;
175 break;
177 swing_h_cmd = HDIR_MRIGHT;
178 break;
180 swing_h_cmd = HDIR_RIGHT;
181 break;
182 default:
183 ESP_LOGE(TAG, "Invalid default horizontal direction");
184 return;
185 }
187 swing_h_cmd = HDIR_SWING;
188 }
189
192 fan_speed_cmd = FAN_2;
193 break;
195 fan_speed_cmd = FAN_3;
196 break;
198 fan_speed_cmd = FAN_4;
199 break;
201 default:
202 fan_speed_cmd = FAN_AUTO;
203 break;
204 }
205
206 switch (this->mode) {
208 power_mode_cmd = POWER_ON;
209 operating_mode_cmd = MODE_COOL;
210 break;
212 power_mode_cmd = POWER_ON;
213 operating_mode_cmd = MODE_HEAT;
214 break;
215 // Map HEAT_COOL to hardware AUTO mode (automatic heat/cool changeover based on temperature).
216 // In hardware AUTO mode, the device automatically switches between heating and cooling
217 // based on the current temperature versus the target temperature.
218 // See https://github.com/esphome/esphome/issues/11161 for further discussion.
221 power_mode_cmd = POWER_ON;
222 operating_mode_cmd = MODE_AUTO;
223 break;
225 power_mode_cmd = POWER_ON;
226 operating_mode_cmd = MODE_FAN;
227 break;
229 power_mode_cmd = POWER_ON;
230 operating_mode_cmd = MODE_DRY;
231 break;
233 default:
234 power_mode_cmd = POWER_OFF;
235 operating_mode_cmd = MODE_AUTO;
236 break;
237 }
238
239 temperature_cmd = (uint8_t) clamp(this->target_temperature, this->min_temperature_, this->max_temperature_);
240
241 IRSenderESPHome esp_sender(this->transmitter_);
242 heatpump_ir_->send(esp_sender, power_mode_cmd, operating_mode_cmd, fan_speed_cmd, temperature_cmd, swing_v_cmd,
243 swing_h_cmd);
244}
245
246} // namespace heatpumpir
247} // namespace esphome
248
249#endif
uint16_le_t frequency
Definition bl0942.h:6
ClimateMode mode
The active mode of the climate device.
Definition climate.h:262
optional< ClimateFanMode > fan_mode
The active fan mode of the climate device.
Definition climate.h:256
float target_temperature
The target temperature of the climate device.
Definition climate.h:243
ClimateSwingMode swing_mode
The active swing mode of the climate device.
Definition climate.h:268
float current_temperature
The current temperature of the climate device, as reported from the integration.
Definition climate.h:236
void publish_state()
Publish the state of the climate device, to be called from integrations.
Definition climate.cpp:437
VerticalDirection default_vertical_direction_
Definition heatpumpir.h:123
void transmit_state() override
Transmit via IR the state of this climate controller.
HorizontalDirection default_horizontal_direction_
Definition heatpumpir.h:122
value_type value_or(U const &v) const
Definition optional.h:98
void set_carrier_frequency(uint32_t carrier_frequency)
Definition remote_base.h:30
void add_on_state_callback(std::function< void(float)> &&callback)
Add a callback that will be called every time a filtered value arrives.
Definition sensor.cpp:78
float state
This member variable stores the last state that has passed through all filters.
Definition sensor.h:117
bool state
Definition fan.h:2
@ CLIMATE_SWING_HORIZONTAL
The fan mode is set to Horizontal.
@ CLIMATE_SWING_VERTICAL
The fan mode is set to Vertical.
@ CLIMATE_SWING_BOTH
The fan mode is set to Both.
@ CLIMATE_MODE_DRY
The climate device is set to dry/humidity mode.
@ CLIMATE_MODE_FAN_ONLY
The climate device only has the fan enabled, no heating or cooling is taking place.
@ 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.
@ CLIMATE_MODE_AUTO
The climate device is adjusting the temperature dynamically.
@ 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.
const std::map< Protocol, std::function< HeatpumpIR *()> > PROTOCOL_CONSTRUCTOR_MAP
Providing packet encoding functions for exchanging data with a remote host.
Definition a01nyub.cpp:7