mirror of
https://github.com/esphome/esphome.git
synced 2026-10-21 21:36:14 +00:00
[midea] Add display_control and send the display toggle over UART without a transmitter (#18671)
Co-authored-by: J. Nick Koston <nick@koston.org> Co-authored-by: J. Nick Koston <nick@home-assistant.io>
This commit is contained in:
co-authored by
J. Nick Koston
J. Nick Koston
parent
4b8af08155
commit
f45e6f0bf4
@@ -127,6 +127,19 @@ ClimateTraits AirConditioner::traits() {
|
||||
return traits;
|
||||
}
|
||||
|
||||
#ifdef USE_REMOTE_TRANSMITTER
|
||||
static const LogString *display_control_str(DisplayControl control) {
|
||||
switch (control) {
|
||||
case DisplayControl::DISPLAY_CONTROL_UART:
|
||||
return LOG_STR("UART");
|
||||
case DisplayControl::DISPLAY_CONTROL_IR:
|
||||
return LOG_STR("IR");
|
||||
default:
|
||||
return LOG_STR("AUTO");
|
||||
}
|
||||
}
|
||||
#endif
|
||||
|
||||
void AirConditioner::dump_config() {
|
||||
ESP_LOGCONFIG(Constants::TAG,
|
||||
"MideaDongle:\n"
|
||||
@@ -135,7 +148,10 @@ void AirConditioner::dump_config() {
|
||||
" [x] Request attempts: %d",
|
||||
this->base_.getPeriod(), this->base_.getTimeout(), this->base_.getNumAttempts());
|
||||
#ifdef USE_REMOTE_TRANSMITTER
|
||||
ESP_LOGCONFIG(Constants::TAG, " [x] Using RemoteTransmitter");
|
||||
ESP_LOGCONFIG(Constants::TAG,
|
||||
" [x] Using RemoteTransmitter\n"
|
||||
" [x] Display control: %s",
|
||||
LOG_STR_ARG(display_control_str(this->display_control_)));
|
||||
#endif
|
||||
if (this->base_.getAutoconfStatus() == dudanov::midea::AUTOCONF_OK) {
|
||||
this->base_.getCapabilities().dump();
|
||||
@@ -183,16 +199,20 @@ void AirConditioner::do_swing_step() {
|
||||
}
|
||||
|
||||
void AirConditioner::do_display_toggle() {
|
||||
if (this->base_.getCapabilities().supportLightControl()) {
|
||||
this->base_.displayToggle();
|
||||
} else {
|
||||
#ifdef USE_REMOTE_TRANSMITTER
|
||||
// AUTO uses IR unless the appliance reports light control over UART. Without a transmitter
|
||||
// built in, every setting sends the UART request: Mundoclima, Rotenso and others accept it
|
||||
// without advertising it in the 0xB5 capabilities report.
|
||||
const bool use_ir = this->display_control_ == DisplayControl::DISPLAY_CONTROL_IR ||
|
||||
(this->display_control_ == DisplayControl::DISPLAY_CONTROL_AUTO &&
|
||||
!this->base_.getCapabilities().supportLightControl());
|
||||
if (use_ir) {
|
||||
IrSpecialData data(0x08);
|
||||
this->transmitter_.transmit(data);
|
||||
#else
|
||||
ESP_LOGW(Constants::TAG, "Action needs remote_transmitter component");
|
||||
#endif
|
||||
return;
|
||||
}
|
||||
#endif
|
||||
this->base_.displayToggle();
|
||||
}
|
||||
|
||||
} // namespace esphome::midea::ac
|
||||
|
||||
@@ -21,12 +21,20 @@ using climate::ClimateModeMask;
|
||||
using climate::ClimateSwingModeMask;
|
||||
using climate::ClimatePresetMask;
|
||||
|
||||
// How the display toggle reaches the appliance; the AUTO rules are in do_display_toggle()
|
||||
enum class DisplayControl : uint8_t {
|
||||
DISPLAY_CONTROL_UART, // always the UART request
|
||||
DISPLAY_CONTROL_AUTO, // UART when the appliance reports it or no transmitter is built in, else IR
|
||||
DISPLAY_CONTROL_IR, // always the IR remote, needs a transmitter
|
||||
};
|
||||
|
||||
class AirConditioner final : public ApplianceBase<dudanov::midea::ac::AirConditioner>, public climate::Climate {
|
||||
public:
|
||||
void dump_config() override;
|
||||
void set_outdoor_temperature_sensor(Sensor *sensor) { this->outdoor_sensor_ = sensor; }
|
||||
void set_humidity_setpoint_sensor(Sensor *sensor) { this->humidity_sensor_ = sensor; }
|
||||
void set_power_sensor(Sensor *sensor) { this->power_sensor_ = sensor; }
|
||||
void set_display_control(DisplayControl control) { this->display_control_ = control; }
|
||||
void on_status_change() override;
|
||||
|
||||
/* ############### */
|
||||
@@ -54,6 +62,7 @@ class AirConditioner final : public ApplianceBase<dudanov::midea::ac::AirConditi
|
||||
ClimateSwingModeMask supported_swing_modes_{};
|
||||
ClimatePresetMask supported_presets_{};
|
||||
bool frost_protection_set_{false};
|
||||
DisplayControl display_control_{DisplayControl::DISPLAY_CONTROL_AUTO};
|
||||
Sensor *outdoor_sensor_{nullptr};
|
||||
Sensor *humidity_sensor_{nullptr};
|
||||
Sensor *power_sensor_{nullptr};
|
||||
|
||||
@@ -33,15 +33,18 @@ from esphome.const import (
|
||||
UNIT_WATT,
|
||||
)
|
||||
from esphome.core import CORE
|
||||
from esphome.types import ConfigType
|
||||
|
||||
CODEOWNERS = ["@dudanov"]
|
||||
DEPENDENCIES = ["climate", "uart"]
|
||||
AUTO_LOAD = ["sensor"]
|
||||
CONF_POWER_USAGE = "power_usage"
|
||||
CONF_HUMIDITY_SETPOINT = "humidity_setpoint"
|
||||
CONF_DISPLAY_CONTROL = "display_control"
|
||||
midea_ac_ns = cg.esphome_ns.namespace("midea").namespace("ac")
|
||||
AirConditioner = midea_ac_ns.class_("AirConditioner", climate.Climate, cg.Component)
|
||||
Capabilities = midea_ac_ns.namespace("Constants")
|
||||
DisplayControl = midea_ac_ns.enum("DisplayControl", is_class=True)
|
||||
|
||||
|
||||
def templatize(value):
|
||||
@@ -82,11 +85,29 @@ CUSTOM_PRESETS = {
|
||||
"FREEZE_PROTECTION": Capabilities.FREEZE_PROTECTION,
|
||||
}
|
||||
|
||||
# How midea_ac.display_toggle reaches the appliance; see do_display_toggle() for the AUTO rules
|
||||
DISPLAY_CONTROLS = {
|
||||
"UART": DisplayControl.DISPLAY_CONTROL_UART,
|
||||
"AUTO": DisplayControl.DISPLAY_CONTROL_AUTO,
|
||||
"IR": DisplayControl.DISPLAY_CONTROL_IR,
|
||||
}
|
||||
|
||||
validate_modes = cv.enum(ALLOWED_CLIMATE_MODES, upper=True)
|
||||
validate_presets = cv.enum(ALLOWED_CLIMATE_PRESETS, upper=True)
|
||||
validate_swing_modes = cv.enum(ALLOWED_CLIMATE_SWING_MODES, upper=True)
|
||||
validate_custom_fan_modes = cv.enum(CUSTOM_FAN_MODES, upper=True)
|
||||
validate_custom_presets = cv.enum(CUSTOM_PRESETS, upper=True)
|
||||
validate_display_control = cv.enum(DISPLAY_CONTROLS, upper=True)
|
||||
|
||||
|
||||
def validate_display_control_with_transmitter(config: ConfigType) -> ConfigType:
|
||||
"""`display_control: IR` needs a `remote_transmitter` to send through; UART and AUTO do not."""
|
||||
if config.get(CONF_DISPLAY_CONTROL) == "IR" and CONF_TRANSMITTER_ID not in config:
|
||||
raise cv.Invalid(
|
||||
f"'{CONF_DISPLAY_CONTROL}: IR' requires '{CONF_TRANSMITTER_ID}' to be set"
|
||||
)
|
||||
return config
|
||||
|
||||
|
||||
CONFIG_SCHEMA = cv.All(
|
||||
climate.climate_schema(AirConditioner)
|
||||
@@ -100,6 +121,7 @@ CONFIG_SCHEMA = cv.All(
|
||||
),
|
||||
cv.Optional(CONF_BEEPER, default=False): cv.boolean,
|
||||
cv.Optional(CONF_AUTOCONF, default=True): cv.boolean,
|
||||
cv.Optional(CONF_DISPLAY_CONTROL, default="AUTO"): validate_display_control,
|
||||
cv.Optional(CONF_SUPPORTED_MODES): cv.ensure_list(validate_modes),
|
||||
cv.Optional(CONF_SUPPORTED_SWING_MODES): cv.ensure_list(
|
||||
validate_swing_modes
|
||||
@@ -134,6 +156,7 @@ CONFIG_SCHEMA = cv.All(
|
||||
)
|
||||
.extend(uart.UART_DEVICE_SCHEMA)
|
||||
.extend(cv.COMPONENT_SCHEMA),
|
||||
validate_display_control_with_transmitter,
|
||||
cv.only_on(
|
||||
[
|
||||
PLATFORM_ESP32,
|
||||
@@ -204,6 +227,7 @@ async def to_code(config):
|
||||
cg.add(var.set_transmitter(transmitter_))
|
||||
cg.add(var.set_beeper_feedback(config[CONF_BEEPER]))
|
||||
cg.add(var.set_autoconf(config[CONF_AUTOCONF]))
|
||||
cg.add(var.set_display_control(config[CONF_DISPLAY_CONTROL]))
|
||||
if CONF_SUPPORTED_MODES in config:
|
||||
cg.add(var.set_supported_modes(config[CONF_SUPPORTED_MODES]))
|
||||
if CONF_SUPPORTED_SWING_MODES in config:
|
||||
|
||||
@@ -0,0 +1,6 @@
|
||||
climate:
|
||||
- platform: midea
|
||||
id: midea_uart_only
|
||||
name: Midea Climate UART Only
|
||||
autoconf: true
|
||||
display_control: UART
|
||||
@@ -33,6 +33,7 @@ climate:
|
||||
timeout: 2s
|
||||
beeper: false
|
||||
autoconf: true
|
||||
display_control: AUTO
|
||||
visual:
|
||||
min_temperature: 17 °C
|
||||
max_temperature: 30 °C
|
||||
|
||||
@@ -0,0 +1,8 @@
|
||||
packages:
|
||||
uart: !include ../../test_build_components/common/uart/esp32-idf.yaml
|
||||
midea: !include common-uart_only.yaml
|
||||
|
||||
# The MideaUART library includes esp_wifi.h on ESP-IDF
|
||||
wifi:
|
||||
ssid: MySSID
|
||||
password: password1
|
||||
Reference in New Issue
Block a user