diff --git a/esphome/components/midea/ac_automations.h b/esphome/components/midea/ac_automations.h index 84f8c5d19e..e6fffa2511 100644 --- a/esphome/components/midea/ac_automations.h +++ b/esphome/components/midea/ac_automations.h @@ -19,11 +19,11 @@ template class MideaActionBase : public Action { template class FollowMeAction : public MideaActionBase { TEMPLATABLE_VALUE(float, temperature) - TEMPLATABLE_VALUE(bool, fahrenheit) + TEMPLATABLE_VALUE(bool, use_fahrenheit) TEMPLATABLE_VALUE(bool, beeper) void play(Ts... x) override { - this->parent_->do_follow_me(this->temperature_.value(x...), this->fahrenheit_.value(x...), + this->parent_->do_follow_me(this->temperature_.value(x...), this->use_fahrenheit_.value(x...), this->beeper_.value(x...)); } }; diff --git a/esphome/components/midea/air_conditioner.cpp b/esphome/components/midea/air_conditioner.cpp index 2dc010a31d..247aea0488 100644 --- a/esphome/components/midea/air_conditioner.cpp +++ b/esphome/components/midea/air_conditioner.cpp @@ -122,7 +122,7 @@ void AirConditioner::dump_config() { /* ACTIONS */ -void AirConditioner::do_follow_me(float temperature, bool fahrenheit, bool beeper) { +void AirConditioner::do_follow_me(float temperature, bool use_fahrenheit, bool beeper) { #ifdef USE_REMOTE_TRANSMITTER // Check if temperature is finite (not NaN or infinite) if (!std::isfinite(temperature)) { @@ -134,12 +134,12 @@ void AirConditioner::do_follow_me(float temperature, bool fahrenheit, bool beepe uint8_t temp_uint8 = static_cast(esphome::clamp(std::lroundf(temperature), 0L, static_cast(UINT8_MAX))); - char temp_symbol = fahrenheit ? 'F' : 'C'; - ESP_LOGD(Constants::TAG, "Follow me action called with temperature: %f °%c, rounded to: %u °%c", temperature, + char temp_symbol = use_fahrenheit ? 'F' : 'C'; + ESP_LOGD(Constants::TAG, "Follow me action called with temperature: %.5f °%c, rounded to: %u °%c", temperature, temp_symbol, temp_uint8, temp_symbol); // Create and transmit the data - IrFollowMeData data(temp_uint8, fahrenheit, beeper); + IrFollowMeData data(temp_uint8, use_fahrenheit, beeper); this->transmitter_.transmit(data); #else ESP_LOGW(Constants::TAG, "Action needs remote_transmitter component"); diff --git a/esphome/components/midea/air_conditioner.h b/esphome/components/midea/air_conditioner.h index f5248f4bc4..e70bd34e71 100644 --- a/esphome/components/midea/air_conditioner.h +++ b/esphome/components/midea/air_conditioner.h @@ -32,7 +32,7 @@ class AirConditioner : public ApplianceBase, /* ### ACTIONS ### */ /* ############### */ - void do_follow_me(float temperature, bool fahrenheit, bool beeper = false); + void do_follow_me(float temperature, bool use_fahrenheit, bool beeper = false); void do_display_toggle(); void do_swing_step(); void do_beeper_on() { this->set_beeper_feedback(true); } diff --git a/esphome/components/midea/climate.py b/esphome/components/midea/climate.py index 47b86da895..b7fef5e1ab 100644 --- a/esphome/components/midea/climate.py +++ b/esphome/components/midea/climate.py @@ -38,7 +38,7 @@ from esphome.components.climate import ( CODEOWNERS = ["@dudanov"] DEPENDENCIES = ["climate", "uart"] -AUTO_LOAD = ["sensor", "midea_ir"] +AUTO_LOAD = ["sensor"] CONF_POWER_USAGE = "power_usage" CONF_HUMIDITY_SETPOINT = "humidity_setpoint" midea_ac_ns = cg.esphome_ns.namespace("midea").namespace("ac") @@ -187,7 +187,7 @@ async def follow_me_to_code(var, config, args): template_ = await cg.templatable(config[CONF_BEEPER], args, cg.bool_) cg.add(var.set_beeper(template_)) template_ = await cg.templatable(config[CONF_USE_FAHRENHEIT], args, cg.bool_) - cg.add(var.set_fahrenheit(template_)) + cg.add(var.set_use_fahrenheit(template_)) template_ = await cg.templatable(config[CONF_TEMPERATURE], args, cg.float_) cg.add(var.set_temperature(template_)) diff --git a/esphome/components/midea/ir_transmitter.h b/esphome/components/midea/ir_transmitter.h index 2cd5c0000c..a3e4d2a0b0 100644 --- a/esphome/components/midea/ir_transmitter.h +++ b/esphome/components/midea/ir_transmitter.h @@ -1,17 +1,76 @@ #pragma once +// TODO: see esphome/components/midea_ir/midea_data.h + #ifdef USE_ARDUINO #ifdef USE_REMOTE_TRANSMITTER #include "esphome/components/remote_base/midea_protocol.h" -#include "esphome/components/midea_ir/midea_data.h" namespace esphome { namespace midea { using remote_base::RemoteTransmitterBase; using IrData = remote_base::MideaData; -using IrFollowMeData = midea_ir::FollowMeData; -using IrSpecialData = midea_ir::SpecialData; + +class IrFollowMeData : public IrData { + public: + // Default constructor (temp: 30C, beeper: off) + IrFollowMeData() : IrData({MIDEA_TYPE_FOLLOW_ME, 0x82, 0x48, 0x7F, 0x1F}) {} + // Copy from Base + IrFollowMeData(const IrData &data) : IrData(data) {} + // Direct from temperature in celsius and beeper values + IrFollowMeData(uint8_t temp, bool beeper = false) : IrFollowMeData() { + this->set_temp(temp, false); + this->set_beeper(beeper); + } + // Direct from temperature, fahrenheit and beeper values + IrFollowMeData(uint8_t temp, bool fahrenheit, bool beeper) : IrFollowMeData() { + this->set_temp(temp, fahrenheit); + this->set_beeper(beeper); + } + + /* TEMPERATURE */ + uint8_t temp() const { + if (this->fahrenheit()) { + return this->get_value_(4) + 31; + } + return this->get_value_(4) - 1; + } + void set_temp(uint8_t val, bool fahrenheit = false) { + this->set_fahrenheit(fahrenheit); + if (this->fahrenheit()) { + // see https://github.com/esphome/feature-requests/issues/1627#issuecomment-1365639966 + val = esphome::clamp(val, MIN_TEMP_F, MAX_TEMP_F) - 31; + } else { + val = esphome::clamp(val, MIN_TEMP_C, MAX_TEMP_C) + 1; + } + this->set_value_(4, val); + } + + /* BEEPER */ + bool beeper() const { return this->get_value_(3, 128); } + void set_beeper(bool val) { this->set_mask_(3, val, 128); } + + /* FAHRENHEIT */ + bool fahrenheit() const { return this->get_value_(2, 32); } + void set_fahrenheit(bool val) { this->set_mask_(2, val, 32); } + + protected: + static const uint8_t MIN_TEMP_C = 0; + static const uint8_t MAX_TEMP_C = 37; + + // see + // https://github.com/crankyoldgit/IRremoteESP8266/blob/9bdf8abcb465268c5409db99dc83a26df64c7445/src/ir_Midea.h#L116 + static const uint8_t MIN_TEMP_F = 32; + // see + // https://github.com/crankyoldgit/IRremoteESP8266/blob/9bdf8abcb465268c5409db99dc83a26df64c7445/src/ir_Midea.h#L117 + static const uint8_t MAX_TEMP_F = 99; +}; + +class IrSpecialData : public IrData { + public: + IrSpecialData(uint8_t code) : IrData({MIDEA_TYPE_SPECIAL, code, 0xFF, 0xFF, 0xFF}) {} +}; class IrTransmitter { public: diff --git a/esphome/components/midea_ir/__init__.py b/esphome/components/midea_ir/__init__.py index db3484e0be..e69de29bb2 100644 --- a/esphome/components/midea_ir/__init__.py +++ b/esphome/components/midea_ir/__init__.py @@ -1 +0,0 @@ -AUTO_LOAD = ["climate_ir", "coolix"] diff --git a/esphome/components/midea_ir/climate.py b/esphome/components/midea_ir/climate.py index db6cca2207..8fea6b192b 100644 --- a/esphome/components/midea_ir/climate.py +++ b/esphome/components/midea_ir/climate.py @@ -3,7 +3,7 @@ import esphome.config_validation as cv from esphome.components import climate_ir from esphome.const import CONF_ID, CONF_USE_FAHRENHEIT -AUTO_LOAD = ["midea_ir"] +AUTO_LOAD = ["climate_ir", "coolix"] CODEOWNERS = ["@dudanov"] midea_ir_ns = cg.esphome_ns.namespace("midea_ir") diff --git a/esphome/components/midea_ir/midea_data.h b/esphome/components/midea_ir/midea_data.h index 874fd0b72b..15aaee4ea7 100644 --- a/esphome/components/midea_ir/midea_data.h +++ b/esphome/components/midea_ir/midea_data.h @@ -1,5 +1,7 @@ #pragma once +// TODO: make base, why? Because this file can be used by midea component also. See esphome/components/midea/ir_transmitter.h + #include "esphome/components/remote_base/midea_protocol.h" #include "esphome/components/climate/climate_mode.h" #include "esphome/core/helpers.h"