ESPHome 2026.6.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::midea::ac {
11
12static void set_sensor(Sensor *sensor, float value) {
13 if (sensor != nullptr && (!sensor->has_state() || sensor->get_raw_state() != value))
14 sensor->publish_state(value);
15}
16
17template<typename T> void update_property(T &property, const T &value, bool &flag) {
18 if (property != value) {
19 property = value;
20 flag = true;
21 }
22}
23
25 // Add frost protection custom preset once when autoconf completes
26 if (this->base_.getAutoconfStatus() == dudanov::midea::AUTOCONF_OK &&
27 this->base_.getCapabilities().supportFrostProtectionPreset() && !this->frost_protection_set_) {
28 // Read existing presets (set by codegen), append frost protection, write back
29 auto traits = this->get_traits();
30 const auto &existing = traits.get_supported_custom_presets();
31 bool found = false;
32 for (const char *p : existing) {
33 if (strcmp(p, Constants::FREEZE_PROTECTION) == 0) {
34 found = true;
35 break;
36 }
37 }
38 if (!found) {
39 std::vector<const char *> merged(existing.begin(), existing.end());
40 merged.push_back(Constants::FREEZE_PROTECTION);
41 this->set_supported_custom_presets(merged);
42 }
43 this->frost_protection_set_ = true;
44 }
45 bool need_publish = false;
46 update_property(this->target_temperature, this->base_.getTargetTemp(), need_publish);
47 update_property(this->current_temperature, this->base_.getIndoorTemp(), need_publish);
48 auto mode = Converters::to_climate_mode(this->base_.getMode());
49 update_property(this->mode, mode, need_publish);
50 auto swing_mode = Converters::to_climate_swing_mode(this->base_.getSwingMode());
51 update_property(this->swing_mode, swing_mode, need_publish);
52 // Preset
53 auto preset = this->base_.getPreset();
56 need_publish = true;
58 need_publish = true;
59 }
60 // Fan mode
61 auto fan_mode = this->base_.getFanMode();
64 need_publish = true;
66 need_publish = true;
67 }
68 if (need_publish)
69 this->publish_state();
70 set_sensor(this->outdoor_sensor_, this->base_.getOutdoorTemp());
71 set_sensor(this->power_sensor_, this->base_.getPowerUsage());
72 set_sensor(this->humidity_sensor_, this->base_.getIndoorHum());
73}
74
76 dudanov::midea::ac::Control ctrl{};
77 auto target_temp_val = call.get_target_temperature();
78 if (target_temp_val.has_value())
79 ctrl.targetTemp = *target_temp_val;
80 auto swing_mode_val = call.get_swing_mode();
81 if (swing_mode_val.has_value())
82 ctrl.swingMode = Converters::to_midea_swing_mode(*swing_mode_val);
83 auto mode_val = call.get_mode();
84 if (mode_val.has_value())
85 ctrl.mode = Converters::to_midea_mode(*mode_val);
86 auto preset_val = call.get_preset();
87 if (preset_val.has_value()) {
88 ctrl.preset = Converters::to_midea_preset(*preset_val);
89 } else if (call.has_custom_preset()) {
90 // get_custom_preset() returns StringRef pointing to null-terminated string literals from codegen
91 ctrl.preset = Converters::to_midea_preset(call.get_custom_preset().c_str());
92 }
93 auto fan_mode_val = call.get_fan_mode();
94 if (fan_mode_val.has_value()) {
95 ctrl.fanMode = Converters::to_midea_fan_mode(*fan_mode_val);
96 } else if (call.has_custom_fan_mode()) {
97 // get_custom_fan_mode() returns StringRef pointing to null-terminated string literals from codegen
98 ctrl.fanMode = Converters::to_midea_fan_mode(call.get_custom_fan_mode().c_str());
99 }
100 this->base_.control(ctrl);
101}
102
129
131 ESP_LOGCONFIG(Constants::TAG,
132 "MideaDongle:\n"
133 " [x] Period: %" PRIu32 "ms\n"
134 " [x] Response timeout: %" PRIu32 "ms\n"
135 " [x] Request attempts: %d",
136 this->base_.getPeriod(), this->base_.getTimeout(), this->base_.getNumAttempts());
137#ifdef USE_REMOTE_TRANSMITTER
138 ESP_LOGCONFIG(Constants::TAG, " [x] Using RemoteTransmitter");
139#endif
140 if (this->base_.getAutoconfStatus() == dudanov::midea::AUTOCONF_OK) {
141 this->base_.getCapabilities().dump();
142 } else if (this->base_.getAutoconfStatus() == dudanov::midea::AUTOCONF_ERROR) {
143 ESP_LOGW(Constants::TAG,
144 "Failed to get 0xB5 capabilities report. Suggest to disable it in config and manually set your "
145 "appliance options.");
146 }
148}
149
150/* ACTIONS */
151
152void AirConditioner::do_follow_me(float temperature, bool use_fahrenheit, bool beeper) {
153#ifdef USE_REMOTE_TRANSMITTER
154 // Check if temperature is finite (not NaN or infinite)
155 if (!std::isfinite(temperature)) {
156 ESP_LOGW(Constants::TAG, "Follow me action requires a finite temperature, got: %f", temperature);
157 return;
158 }
159
160 // Round and convert temperature to long, then clamp and convert it to uint8_t
161 uint8_t temp_uint8 =
162 static_cast<uint8_t>(esphome::clamp<long>(std::lroundf(temperature), 0L, static_cast<long>(UINT8_MAX)));
163
164 char temp_symbol = use_fahrenheit ? 'F' : 'C';
165 ESP_LOGD(Constants::TAG, "Follow me action called with temperature: %.5f °%c, rounded to: %u °%c", temperature,
166 temp_symbol, temp_uint8, temp_symbol);
167
168 // Create and transmit the data
169 IrFollowMeData data(temp_uint8, use_fahrenheit, beeper);
170 this->transmitter_.transmit(data);
171#else
172 ESP_LOGW(Constants::TAG, "Action needs remote_transmitter component");
173#endif
174}
175
177#ifdef USE_REMOTE_TRANSMITTER
178 IrSpecialData data(0x01);
179 this->transmitter_.transmit(data);
180#else
181 ESP_LOGW(Constants::TAG, "Action needs remote_transmitter component");
182#endif
183}
184
186 if (this->base_.getCapabilities().supportLightControl()) {
187 this->base_.displayToggle();
188 } else {
189#ifdef USE_REMOTE_TRANSMITTER
190 IrSpecialData data(0x08);
191 this->transmitter_.transmit(data);
192#else
193 ESP_LOGW(Constants::TAG, "Action needs remote_transmitter component");
194#endif
195 }
196}
197
198} // namespace esphome::midea::ac
199
200#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:486
float target_temperature
The target temperature of the climate device.
Definition climate.h:274
void dump_traits_(const char *tag)
Definition climate.cpp:729
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:696
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:685
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:437
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:20
static const char *const FREEZE_PROTECTION
Definition ac_adapter.h:21
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)
uint16_t temperature
Definition sun_gtil2.cpp:12