mirror of
https://github.com/esphome/esphome.git
synced 2024-12-19 12:04:54 +01:00
[midea] Add Fahrenheit support to midea_ac.follow_me
action (#7762)
Some checks are pending
CI / CI Status (push) Blocked by required conditions
CI / Create common environment (push) Waiting to run
CI / Check black (push) Blocked by required conditions
CI / Check flake8 (push) Blocked by required conditions
CI / Check pylint (push) Blocked by required conditions
CI / Check pyupgrade (push) Blocked by required conditions
CI / Run script/ci-custom (push) Blocked by required conditions
CI / Run pytest (push) Blocked by required conditions
CI / Check clang-format (push) Blocked by required conditions
CI / Run script/clang-tidy for ESP32 Arduino 1/4 (push) Blocked by required conditions
CI / Run script/clang-tidy for ESP32 Arduino 2/4 (push) Blocked by required conditions
CI / Run script/clang-tidy for ESP32 Arduino 3/4 (push) Blocked by required conditions
CI / Run script/clang-tidy for ESP32 Arduino 4/4 (push) Blocked by required conditions
CI / Run script/clang-tidy for ESP32 IDF (push) Blocked by required conditions
CI / Run script/clang-tidy for ESP8266 (push) Blocked by required conditions
CI / list-components (push) Blocked by required conditions
CI / Component test (push) Blocked by required conditions
CI / Split components for testing into 20 groups maximum (push) Blocked by required conditions
CI / Test split components (push) Blocked by required conditions
Some checks are pending
CI / CI Status (push) Blocked by required conditions
CI / Create common environment (push) Waiting to run
CI / Check black (push) Blocked by required conditions
CI / Check flake8 (push) Blocked by required conditions
CI / Check pylint (push) Blocked by required conditions
CI / Check pyupgrade (push) Blocked by required conditions
CI / Run script/ci-custom (push) Blocked by required conditions
CI / Run pytest (push) Blocked by required conditions
CI / Check clang-format (push) Blocked by required conditions
CI / Run script/clang-tidy for ESP32 Arduino 1/4 (push) Blocked by required conditions
CI / Run script/clang-tidy for ESP32 Arduino 2/4 (push) Blocked by required conditions
CI / Run script/clang-tidy for ESP32 Arduino 3/4 (push) Blocked by required conditions
CI / Run script/clang-tidy for ESP32 Arduino 4/4 (push) Blocked by required conditions
CI / Run script/clang-tidy for ESP32 IDF (push) Blocked by required conditions
CI / Run script/clang-tidy for ESP8266 (push) Blocked by required conditions
CI / list-components (push) Blocked by required conditions
CI / Component test (push) Blocked by required conditions
CI / Split components for testing into 20 groups maximum (push) Blocked by required conditions
CI / Test split components (push) Blocked by required conditions
This commit is contained in:
parent
7554e954fe
commit
a9d883b65a
5 changed files with 51 additions and 14 deletions
|
@ -19,10 +19,12 @@ template<typename... Ts> class MideaActionBase : public Action<Ts...> {
|
||||||
|
|
||||||
template<typename... Ts> class FollowMeAction : public MideaActionBase<Ts...> {
|
template<typename... Ts> class FollowMeAction : public MideaActionBase<Ts...> {
|
||||||
TEMPLATABLE_VALUE(float, temperature)
|
TEMPLATABLE_VALUE(float, temperature)
|
||||||
|
TEMPLATABLE_VALUE(bool, use_fahrenheit)
|
||||||
TEMPLATABLE_VALUE(bool, beeper)
|
TEMPLATABLE_VALUE(bool, beeper)
|
||||||
|
|
||||||
void play(Ts... x) override {
|
void play(Ts... x) override {
|
||||||
this->parent_->do_follow_me(this->temperature_.value(x...), this->beeper_.value(x...));
|
this->parent_->do_follow_me(this->temperature_.value(x...), this->use_fahrenheit_.value(x...),
|
||||||
|
this->beeper_.value(x...));
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
|
@ -1,6 +1,7 @@
|
||||||
#ifdef USE_ARDUINO
|
#ifdef USE_ARDUINO
|
||||||
|
|
||||||
#include "esphome/core/log.h"
|
#include "esphome/core/log.h"
|
||||||
|
#include "esphome/core/helpers.h"
|
||||||
#include "air_conditioner.h"
|
#include "air_conditioner.h"
|
||||||
#include "ac_adapter.h"
|
#include "ac_adapter.h"
|
||||||
#include <cmath>
|
#include <cmath>
|
||||||
|
@ -121,7 +122,7 @@ void AirConditioner::dump_config() {
|
||||||
|
|
||||||
/* ACTIONS */
|
/* ACTIONS */
|
||||||
|
|
||||||
void AirConditioner::do_follow_me(float temperature, bool beeper) {
|
void AirConditioner::do_follow_me(float temperature, bool use_fahrenheit, bool beeper) {
|
||||||
#ifdef USE_REMOTE_TRANSMITTER
|
#ifdef USE_REMOTE_TRANSMITTER
|
||||||
// Check if temperature is finite (not NaN or infinite)
|
// Check if temperature is finite (not NaN or infinite)
|
||||||
if (!std::isfinite(temperature)) {
|
if (!std::isfinite(temperature)) {
|
||||||
|
@ -131,13 +132,14 @@ void AirConditioner::do_follow_me(float temperature, bool beeper) {
|
||||||
|
|
||||||
// Round and convert temperature to long, then clamp and convert it to uint8_t
|
// Round and convert temperature to long, then clamp and convert it to uint8_t
|
||||||
uint8_t temp_uint8 =
|
uint8_t temp_uint8 =
|
||||||
static_cast<uint8_t>(std::max(0L, std::min(static_cast<long>(UINT8_MAX), std::lroundf(temperature))));
|
static_cast<uint8_t>(esphome::clamp<long>(std::lroundf(temperature), 0L, static_cast<long>(UINT8_MAX)));
|
||||||
|
|
||||||
ESP_LOGD(Constants::TAG, "Follow me action called with temperature: %f °C, rounded to: %u °C", temperature,
|
char temp_symbol = use_fahrenheit ? 'F' : 'C';
|
||||||
temp_uint8);
|
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
|
// Create and transmit the data
|
||||||
IrFollowMeData data(temp_uint8, beeper);
|
IrFollowMeData data(temp_uint8, use_fahrenheit, beeper);
|
||||||
this->transmitter_.transmit(data);
|
this->transmitter_.transmit(data);
|
||||||
#else
|
#else
|
||||||
ESP_LOGW(Constants::TAG, "Action needs remote_transmitter component");
|
ESP_LOGW(Constants::TAG, "Action needs remote_transmitter component");
|
||||||
|
|
|
@ -32,7 +32,7 @@ class AirConditioner : public ApplianceBase<dudanov::midea::ac::AirConditioner>,
|
||||||
/* ### ACTIONS ### */
|
/* ### ACTIONS ### */
|
||||||
/* ############### */
|
/* ############### */
|
||||||
|
|
||||||
void do_follow_me(float temperature, bool beeper = false);
|
void do_follow_me(float temperature, bool use_fahrenheit, bool beeper = false);
|
||||||
void do_display_toggle();
|
void do_display_toggle();
|
||||||
void do_swing_step();
|
void do_swing_step();
|
||||||
void do_beeper_on() { this->set_beeper_feedback(true); }
|
void do_beeper_on() { this->set_beeper_feedback(true); }
|
||||||
|
|
|
@ -18,6 +18,7 @@ from esphome.const import (
|
||||||
CONF_SUPPORTED_SWING_MODES,
|
CONF_SUPPORTED_SWING_MODES,
|
||||||
CONF_TIMEOUT,
|
CONF_TIMEOUT,
|
||||||
CONF_TEMPERATURE,
|
CONF_TEMPERATURE,
|
||||||
|
CONF_USE_FAHRENHEIT,
|
||||||
DEVICE_CLASS_POWER,
|
DEVICE_CLASS_POWER,
|
||||||
DEVICE_CLASS_TEMPERATURE,
|
DEVICE_CLASS_TEMPERATURE,
|
||||||
DEVICE_CLASS_HUMIDITY,
|
DEVICE_CLASS_HUMIDITY,
|
||||||
|
@ -172,11 +173,10 @@ MIDEA_ACTION_BASE_SCHEMA = cv.Schema(
|
||||||
)
|
)
|
||||||
|
|
||||||
# FollowMe action
|
# FollowMe action
|
||||||
MIDEA_FOLLOW_ME_MIN = 0
|
|
||||||
MIDEA_FOLLOW_ME_MAX = 37
|
|
||||||
MIDEA_FOLLOW_ME_SCHEMA = cv.Schema(
|
MIDEA_FOLLOW_ME_SCHEMA = cv.Schema(
|
||||||
{
|
{
|
||||||
cv.Required(CONF_TEMPERATURE): cv.templatable(cv.temperature),
|
cv.Required(CONF_TEMPERATURE): cv.templatable(cv.temperature),
|
||||||
|
cv.Optional(CONF_USE_FAHRENHEIT, default=False): cv.templatable(cv.boolean),
|
||||||
cv.Optional(CONF_BEEPER, default=False): cv.templatable(cv.boolean),
|
cv.Optional(CONF_BEEPER, default=False): cv.templatable(cv.boolean),
|
||||||
}
|
}
|
||||||
)
|
)
|
||||||
|
@ -186,6 +186,8 @@ MIDEA_FOLLOW_ME_SCHEMA = cv.Schema(
|
||||||
async def follow_me_to_code(var, config, args):
|
async def follow_me_to_code(var, config, args):
|
||||||
template_ = await cg.templatable(config[CONF_BEEPER], args, cg.bool_)
|
template_ = await cg.templatable(config[CONF_BEEPER], args, cg.bool_)
|
||||||
cg.add(var.set_beeper(template_))
|
cg.add(var.set_beeper(template_))
|
||||||
|
template_ = await cg.templatable(config[CONF_USE_FAHRENHEIT], args, cg.bool_)
|
||||||
|
cg.add(var.set_use_fahrenheit(template_))
|
||||||
template_ = await cg.templatable(config[CONF_TEMPERATURE], args, cg.float_)
|
template_ = await cg.templatable(config[CONF_TEMPERATURE], args, cg.float_)
|
||||||
cg.add(var.set_temperature(template_))
|
cg.add(var.set_temperature(template_))
|
||||||
|
|
||||||
|
|
|
@ -16,22 +16,53 @@ class IrFollowMeData : public IrData {
|
||||||
IrFollowMeData() : IrData({MIDEA_TYPE_FOLLOW_ME, 0x82, 0x48, 0x7F, 0x1F}) {}
|
IrFollowMeData() : IrData({MIDEA_TYPE_FOLLOW_ME, 0x82, 0x48, 0x7F, 0x1F}) {}
|
||||||
// Copy from Base
|
// Copy from Base
|
||||||
IrFollowMeData(const IrData &data) : IrData(data) {}
|
IrFollowMeData(const IrData &data) : IrData(data) {}
|
||||||
// Direct from temperature and beeper values
|
// Direct from temperature in celsius and beeper values
|
||||||
IrFollowMeData(uint8_t temp, bool beeper = false) : IrFollowMeData() {
|
IrFollowMeData(uint8_t temp, bool beeper = false) : IrFollowMeData() {
|
||||||
this->set_temp(temp);
|
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);
|
this->set_beeper(beeper);
|
||||||
}
|
}
|
||||||
|
|
||||||
/* TEMPERATURE */
|
/* TEMPERATURE */
|
||||||
uint8_t temp() const { return this->get_value_(4) - 1; }
|
uint8_t temp() const {
|
||||||
void set_temp(uint8_t val) { this->set_value_(4, std::min(MAX_TEMP, val) + 1); }
|
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<uint8_t>(val, MIN_TEMP_F, MAX_TEMP_F) - 31;
|
||||||
|
} else {
|
||||||
|
val = esphome::clamp<uint8_t>(val, MIN_TEMP_C, MAX_TEMP_C) + 1;
|
||||||
|
}
|
||||||
|
this->set_value_(4, val);
|
||||||
|
}
|
||||||
|
|
||||||
/* BEEPER */
|
/* BEEPER */
|
||||||
bool beeper() const { return this->get_value_(3, 128); }
|
bool beeper() const { return this->get_value_(3, 128); }
|
||||||
void set_beeper(bool val) { this->set_mask_(3, val, 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:
|
protected:
|
||||||
static const uint8_t MAX_TEMP = 37;
|
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 {
|
class IrSpecialData : public IrData {
|
||||||
|
|
Loading…
Reference in a new issue