ESPHome 2026.5.0-dev
Loading...
Searching...
No Matches
air_conditioner.cpp
Go to the documentation of this file.
1#ifdef USE_ARDUINO
2
4#include "esphome/core/log.h"
5#include "air_conditioner.h"
6#include "ac_adapter.h"
7#include <cmath>
8#include <cstdint>
9
10namespace esphome {
11namespace midea {
12namespace ac {
13
14static void set_sensor(Sensor *sensor, float value) {
15 if (sensor != nullptr && (!sensor->has_state() || sensor->get_raw_state() != value))
16 sensor->publish_state(value);
17}
18
19template<typename T> void update_property(T &property, const T &value, bool &flag) {
20 if (property != value) {
21 property = value;
22 flag = true;
23 }
24}
25
27 // Add frost protection custom preset once when autoconf completes
28 if (this->base_.getAutoconfStatus() == dudanov::midea::AUTOCONF_OK &&
29 this->base_.getCapabilities().supportFrostProtectionPreset() && !this->frost_protection_set_) {
30 // Read existing presets (set by codegen), append frost protection, write back
31 auto traits = this->get_traits();
32 const auto &existing = traits.get_supported_custom_presets();
33 bool found = false;
34 for (const char *p : existing) {
35 if (strcmp(p, Constants::FREEZE_PROTECTION) == 0) {
36 found = true;
37 break;
38 }
39 }
40 if (!found) {
41 std::vector<const char *> merged(existing.begin(), existing.end());
42 merged.push_back(Constants::FREEZE_PROTECTION);
43 this->set_supported_custom_presets(merged);
44 }
45 this->frost_protection_set_ = true;
46 }
47 bool need_publish = false;
48 update_property(this->target_temperature, this->base_.getTargetTemp(), need_publish);
49 update_property(this->current_temperature, this->base_.getIndoorTemp(), need_publish);
50 auto mode = Converters::to_climate_mode(this->base_.getMode());
51 update_property(this->mode, mode, need_publish);
52 auto swing_mode = Converters::to_climate_swing_mode(this->base_.getSwingMode());
53 update_property(this->swing_mode, swing_mode, need_publish);
54 // Preset
55 auto preset = this->base_.getPreset();
58 need_publish = true;
60 need_publish = true;
61 }
62 // Fan mode
63 auto fan_mode = this->base_.getFanMode();
66 need_publish = true;
68 need_publish = true;
69 }
70 if (need_publish)
71 this->publish_state();
72 set_sensor(this->outdoor_sensor_, this->base_.getOutdoorTemp());
73 set_sensor(this->power_sensor_, this->base_.getPowerUsage());
74 set_sensor(this->humidity_sensor_, this->base_.getIndoorHum());
75}
76
78 dudanov::midea::ac::Control ctrl{};
79 auto target_temp_val = call.get_target_temperature();
80 if (target_temp_val.has_value())
81 ctrl.targetTemp = *target_temp_val;
82 auto swing_mode_val = call.get_swing_mode();
83 if (swing_mode_val.has_value())
84 ctrl.swingMode = Converters::to_midea_swing_mode(*swing_mode_val);
85 auto mode_val = call.get_mode();
86 if (mode_val.has_value())
87 ctrl.mode = Converters::to_midea_mode(*mode_val);
88 auto preset_val = call.get_preset();
89 if (preset_val.has_value()) {
90 ctrl.preset = Converters::to_midea_preset(*preset_val);
91 } else if (call.has_custom_preset()) {
92 // get_custom_preset() returns StringRef pointing to null-terminated string literals from codegen
93 ctrl.preset = Converters::to_midea_preset(call.get_custom_preset().c_str());
94 }
95 auto fan_mode_val = call.get_fan_mode();
96 if (fan_mode_val.has_value()) {
97 ctrl.fanMode = Converters::to_midea_fan_mode(*fan_mode_val);
98 } else if (call.has_custom_fan_mode()) {
99 // get_custom_fan_mode() returns StringRef pointing to null-terminated string literals from codegen
100 ctrl.fanMode = Converters::to_midea_fan_mode(call.get_custom_fan_mode().c_str());
101 }
102 this->base_.control(ctrl);
103}
104
131
133 ESP_LOGCONFIG(Constants::TAG,
134 "MideaDongle:\n"
135 " [x] Period: %dms\n"
136 " [x] Response timeout: %dms\n"
137 " [x] Request attempts: %d",
138 this->base_.getPeriod(), this->base_.getTimeout(), this->base_.getNumAttempts());
139#ifdef USE_REMOTE_TRANSMITTER
140 ESP_LOGCONFIG(Constants::TAG, " [x] Using RemoteTransmitter");
141#endif
142 if (this->base_.getAutoconfStatus() == dudanov::midea::AUTOCONF_OK) {
143 this->base_.getCapabilities().dump();
144 } else if (this->base_.getAutoconfStatus() == dudanov::midea::AUTOCONF_ERROR) {
145 ESP_LOGW(Constants::TAG,
146 "Failed to get 0xB5 capabilities report. Suggest to disable it in config and manually set your "
147 "appliance options.");
148 }
150}
151
152/* ACTIONS */
153
154void AirConditioner::do_follow_me(float temperature, bool use_fahrenheit, bool beeper) {
155#ifdef USE_REMOTE_TRANSMITTER
156 // Check if temperature is finite (not NaN or infinite)
157 if (!std::isfinite(temperature)) {
158 ESP_LOGW(Constants::TAG, "Follow me action requires a finite temperature, got: %f", temperature);
159 return;
160 }
161
162 // Round and convert temperature to long, then clamp and convert it to uint8_t
163 uint8_t temp_uint8 =
164 static_cast<uint8_t>(esphome::clamp<long>(std::lroundf(temperature), 0L, static_cast<long>(UINT8_MAX)));
165
166 char temp_symbol = use_fahrenheit ? 'F' : 'C';
167 ESP_LOGD(Constants::TAG, "Follow me action called with temperature: %.5f °%c, rounded to: %u °%c", temperature,
168 temp_symbol, temp_uint8, temp_symbol);
169
170 // Create and transmit the data
171 IrFollowMeData data(temp_uint8, use_fahrenheit, beeper);
172 this->transmitter_.transmit(data);
173#else
174 ESP_LOGW(Constants::TAG, "Action needs remote_transmitter component");
175#endif
176}
177
179#ifdef USE_REMOTE_TRANSMITTER
180 IrSpecialData data(0x01);
181 this->transmitter_.transmit(data);
182#else
183 ESP_LOGW(Constants::TAG, "Action needs remote_transmitter component");
184#endif
185}
186
188 if (this->base_.getCapabilities().supportLightControl()) {
189 this->base_.displayToggle();
190 } else {
191#ifdef USE_REMOTE_TRANSMITTER
192 IrSpecialData data(0x08);
193 this->transmitter_.transmit(data);
194#else
195 ESP_LOGW(Constants::TAG, "Action needs remote_transmitter component");
196#endif
197 }
198}
199
200} // namespace ac
201} // namespace midea
202} // namespace esphome
203
204#endif // USE_ARDUINO
constexpr bool empty() const
Check if the set is empty.
This class is used to encode all control actions on a climate device.
Definition climate.h:34
ClimateMode mode
The active mode of the climate device.
Definition climate.h:293
optional< ClimateFanMode > fan_mode
The active fan mode of the climate device.
Definition climate.h:287
ClimateTraits get_traits()
Get the traits of this climate device with all overrides applied.
Definition climate.cpp:485
float target_temperature
The target temperature of the climate device.
Definition climate.h:274
void dump_traits_(const char *tag)
Definition climate.cpp:728
ClimateSwingMode swing_mode
The active swing mode of the climate device.
Definition climate.h:299
void set_supported_custom_presets(std::initializer_list< const char * > presets)
Set the supported custom presets (stored on Climate, referenced by ClimateTraits).
Definition climate.h:250
bool set_preset_(ClimatePreset preset)
Set preset. Reset custom preset. Return true if preset has been changed.
Definition climate.cpp:695
bool set_custom_preset_(const char *preset)
Set custom preset. Reset primary preset. Return true if preset has been changed.
Definition climate.h:325
bool set_fan_mode_(ClimateFanMode mode)
Set fan mode. Reset custom fan mode. Return true if fan mode has been changed.
Definition climate.cpp:684
float current_temperature
The current temperature of the climate device, as reported from the integration.
Definition climate.h:267
void publish_state()
Publish the state of the climate device, to be called from integrations.
Definition climate.cpp:436
optional< ClimatePreset > preset
The active preset of the climate device.
Definition climate.h:290
bool set_custom_fan_mode_(const char *mode)
Set custom fan mode. Reset primary fan mode. Return true if fan mode has been changed.
Definition climate.h:315
void set_visual_max_temperature(float visual_max_temperature)
void add_feature_flags(uint32_t feature_flags)
void add_supported_fan_mode(ClimateFanMode mode)
const ClimatePresetMask & get_supported_presets() const
const ClimateSwingModeMask & get_supported_swing_modes() const
void set_visual_temperature_step(float temperature_step)
void add_supported_preset(ClimatePreset preset)
void set_supported_presets(ClimatePresetMask presets)
void set_supported_swing_modes(ClimateSwingModeMask modes)
void set_visual_min_temperature(float visual_min_temperature)
void set_supported_modes(ClimateModeMask modes)
void add_supported_mode(ClimateMode mode)
const std::vector< const char * > & get_supported_custom_presets() const
const ClimateModeMask & get_supported_modes() const
void add_supported_swing_mode(ClimateSwingMode mode)
void do_follow_me(float temperature, bool use_fahrenheit, bool beeper=false)
ClimateSwingModeMask supported_swing_modes_
void control(const ClimateCall &call) override
static const char *const TAG
Definition ac_adapter.h:22
static const char *const FREEZE_PROTECTION
Definition ac_adapter.h:23
static ClimateFanMode to_climate_fan_mode(MideaFanMode fan_mode)
static ClimateSwingMode to_climate_swing_mode(MideaSwingMode mode)
static MideaSwingMode to_midea_swing_mode(ClimateSwingMode mode)
static MideaPreset to_midea_preset(ClimatePreset preset)
static const char * to_custom_climate_preset(MideaPreset preset)
static ClimateMode to_climate_mode(MideaMode mode)
static MideaFanMode to_midea_fan_mode(ClimateFanMode fan_mode)
static ClimatePreset to_climate_preset(MideaPreset preset)
static bool is_custom_midea_fan_mode(MideaFanMode fan_mode)
static const char * to_custom_climate_fan_mode(MideaFanMode fan_mode)
static bool is_custom_midea_preset(MideaPreset preset)
static MideaMode to_midea_mode(ClimateMode mode)
static void to_climate_traits(ClimateTraits &traits, const dudanov::midea::ac::Capabilities &capabilities)
@ CLIMATE_SUPPORTS_CURRENT_TEMPERATURE
@ CLIMATE_PRESET_NONE
No preset is active.
@ CLIMATE_SWING_OFF
The swing mode is set to Off.
@ CLIMATE_MODE_OFF
The climate device is off.
@ 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 update_property(T &property, const T &value, bool &flag)
Providing packet encoding functions for exchanging data with a remote host.
Definition a01nyub.cpp:7
uint16_t temperature
Definition sun_gtil2.cpp:12