mirror of
https://github.com/esphome/esphome.git
synced 2026-08-22 22:26:21 +00:00
[mitsubishi_cn105] Extract top-level hub (#16987)
This commit is contained in:
@@ -0,0 +1,137 @@
|
||||
from esphome import automation
|
||||
import esphome.codegen as cg
|
||||
from esphome.components import uart
|
||||
import esphome.config_validation as cv
|
||||
from esphome.const import CONF_ID, CONF_TEMPERATURE, CONF_UPDATE_INTERVAL
|
||||
from esphome.core import ID
|
||||
from esphome.cpp_generator import MockObj
|
||||
from esphome.types import ConfigType, TemplateArgsType
|
||||
|
||||
CODEOWNERS = ["@crnjan"]
|
||||
DEPENDENCIES = ["uart"]
|
||||
DOMAIN = "mitsubishi_cn105"
|
||||
|
||||
CONF_MITSUBISHI_CN105_ID = f"{DOMAIN}_id"
|
||||
CONF_TELEMETRY_REQUEST_MIN_INTERVAL = "telemetry_request_min_interval"
|
||||
|
||||
mitsubishi_ns = cg.esphome_ns.namespace(DOMAIN)
|
||||
|
||||
MitsubishiCN105Component = mitsubishi_ns.class_(
|
||||
"MitsubishiCN105Component",
|
||||
cg.Component,
|
||||
uart.UARTDevice,
|
||||
)
|
||||
|
||||
SetRemoteTemperatureAction = mitsubishi_ns.class_(
|
||||
"SetRemoteTemperatureAction",
|
||||
automation.Action,
|
||||
cg.Parented.template(MitsubishiCN105Component),
|
||||
)
|
||||
|
||||
ClearRemoteTemperatureAction = mitsubishi_ns.class_(
|
||||
"ClearRemoteTemperatureAction",
|
||||
automation.Action,
|
||||
cg.Parented.template(MitsubishiCN105Component),
|
||||
)
|
||||
|
||||
CONFIG_SCHEMA = (
|
||||
cv.Schema(
|
||||
{
|
||||
cv.GenerateID(): cv.declare_id(MitsubishiCN105Component),
|
||||
cv.Optional(CONF_UPDATE_INTERVAL, default="1s"): cv.update_interval,
|
||||
cv.Optional(
|
||||
CONF_TELEMETRY_REQUEST_MIN_INTERVAL, default="60s"
|
||||
): cv.update_interval,
|
||||
}
|
||||
)
|
||||
.extend(cv.COMPONENT_SCHEMA)
|
||||
.extend(uart.UART_DEVICE_SCHEMA)
|
||||
)
|
||||
|
||||
MITSUBISHI_CN105_DEVICE_SCHEMA = cv.Schema(
|
||||
{
|
||||
cv.GenerateID(CONF_MITSUBISHI_CN105_ID): cv.use_id(MitsubishiCN105Component),
|
||||
}
|
||||
)
|
||||
|
||||
FINAL_VALIDATE_SCHEMA = cv.All(
|
||||
uart.final_validate_device_schema(
|
||||
DOMAIN,
|
||||
require_rx=True,
|
||||
require_tx=True,
|
||||
data_bits=8,
|
||||
parity="EVEN",
|
||||
stop_bits=1,
|
||||
)
|
||||
)
|
||||
|
||||
|
||||
async def register_mitsubishi_cn105_device(var: MockObj, config: ConfigType) -> None:
|
||||
parent = await cg.get_variable(config[CONF_MITSUBISHI_CN105_ID])
|
||||
cg.add(var.set_parent(parent))
|
||||
|
||||
|
||||
async def to_code(config: ConfigType) -> None:
|
||||
var = cg.new_Pvariable(config[CONF_ID])
|
||||
await cg.register_component(var, config)
|
||||
await uart.register_uart_device(var, config)
|
||||
cg.add(
|
||||
var.set_telemetry_request_min_interval(
|
||||
config[CONF_TELEMETRY_REQUEST_MIN_INTERVAL]
|
||||
)
|
||||
)
|
||||
|
||||
|
||||
REMOTE_TEMPERATURE_ACTION_SCHEMA = cv.Schema(
|
||||
{
|
||||
cv.Required(CONF_ID): cv.use_id(MitsubishiCN105Component),
|
||||
cv.Required(CONF_TEMPERATURE): cv.templatable(
|
||||
cv.All(
|
||||
cv.temperature,
|
||||
cv.Range(min=8.0, max=39.5),
|
||||
)
|
||||
),
|
||||
}
|
||||
)
|
||||
|
||||
CLEAR_REMOTE_TEMPERATURE_ACTION_SCHEMA = cv.Schema(
|
||||
{
|
||||
cv.Required(CONF_ID): cv.use_id(MitsubishiCN105Component),
|
||||
}
|
||||
)
|
||||
|
||||
|
||||
@automation.register_action(
|
||||
f"{DOMAIN}.set_remote_temperature",
|
||||
SetRemoteTemperatureAction,
|
||||
REMOTE_TEMPERATURE_ACTION_SCHEMA,
|
||||
synchronous=True,
|
||||
)
|
||||
async def remote_temperature_action_to_code(
|
||||
config: ConfigType,
|
||||
action_id: ID,
|
||||
template_arg: cg.TemplateArguments,
|
||||
args: TemplateArgsType,
|
||||
) -> MockObj:
|
||||
var = cg.new_Pvariable(action_id, template_arg)
|
||||
await cg.register_parented(var, config[CONF_ID])
|
||||
temperature = await cg.templatable(config[CONF_TEMPERATURE], args, float)
|
||||
cg.add(var.set_temperature(temperature))
|
||||
return var
|
||||
|
||||
|
||||
@automation.register_action(
|
||||
f"{DOMAIN}.clear_remote_temperature",
|
||||
ClearRemoteTemperatureAction,
|
||||
CLEAR_REMOTE_TEMPERATURE_ACTION_SCHEMA,
|
||||
synchronous=True,
|
||||
)
|
||||
async def clear_temperature_action_to_code(
|
||||
config: ConfigType,
|
||||
action_id: ID,
|
||||
template_arg: cg.TemplateArguments,
|
||||
args: TemplateArgsType,
|
||||
) -> MockObj:
|
||||
var = cg.new_Pvariable(action_id, template_arg)
|
||||
await cg.register_parented(var, config[CONF_ID])
|
||||
return var
|
||||
|
||||
@@ -0,0 +1,23 @@
|
||||
#pragma once
|
||||
|
||||
#include "mitsubishi_cn105_component.h"
|
||||
|
||||
#include "esphome/core/automation.h"
|
||||
|
||||
namespace esphome::mitsubishi_cn105 {
|
||||
|
||||
template<typename... Ts>
|
||||
class SetRemoteTemperatureAction : public Action<Ts...>, public Parented<MitsubishiCN105Component> {
|
||||
public:
|
||||
TEMPLATABLE_VALUE(float, temperature)
|
||||
|
||||
void play(const Ts &...x) override { this->parent_->set_remote_temperature(this->temperature_.value(x...)); }
|
||||
};
|
||||
|
||||
template<typename... Ts>
|
||||
class ClearRemoteTemperatureAction : public Action<Ts...>, public Parented<MitsubishiCN105Component> {
|
||||
public:
|
||||
void play(const Ts &...x) override { this->parent_->clear_remote_temperature(); }
|
||||
};
|
||||
|
||||
} // namespace esphome::mitsubishi_cn105
|
||||
@@ -1,3 +1,5 @@
|
||||
import logging
|
||||
|
||||
from esphome import automation
|
||||
import esphome.codegen as cg
|
||||
from esphome.components import climate, uart
|
||||
@@ -7,83 +9,182 @@ from esphome.const import (
|
||||
CONF_ID,
|
||||
CONF_SUPPORTED_SWING_MODES,
|
||||
CONF_TEMPERATURE,
|
||||
CONF_UART_ID,
|
||||
CONF_UPDATE_INTERVAL,
|
||||
)
|
||||
from esphome.core import ID
|
||||
from esphome.core import CORE, ID
|
||||
from esphome.cpp_generator import MockObj
|
||||
from esphome.schema_extractors import SCHEMA_EXTRACT, schema_extractor
|
||||
from esphome.types import ConfigType, TemplateArgsType
|
||||
|
||||
from . import (
|
||||
CONF_MITSUBISHI_CN105_ID,
|
||||
DOMAIN,
|
||||
MITSUBISHI_CN105_DEVICE_SCHEMA,
|
||||
MitsubishiCN105Component,
|
||||
mitsubishi_ns,
|
||||
register_mitsubishi_cn105_device,
|
||||
)
|
||||
|
||||
# Legacy climate-owned hub compatibility. Remove in 2027.2.0.
|
||||
DEPENDENCIES = ["uart"]
|
||||
AUTO_LOAD = ["climate"]
|
||||
CODEOWNERS = ["@crnjan"]
|
||||
|
||||
_LOGGER = logging.getLogger(__name__)
|
||||
|
||||
# Deprecated legacy climate-owned hub option. Remove in 2027.2.0.
|
||||
CONF_CURRENT_TEMPERATURE_MIN_INTERVAL = "current_temperature_min_interval"
|
||||
|
||||
mitsubishi_ns = cg.esphome_ns.namespace("mitsubishi_cn105")
|
||||
# Legacy climate-owned hub compatibility. Remove in 2027.2.0.
|
||||
CONF_LEGACY_MITSUBISHI_CN105_ID = "legacy_mitsubishi_cn105_id"
|
||||
|
||||
MitsubishiCN105Climate = mitsubishi_ns.class_(
|
||||
"MitsubishiCN105Climate",
|
||||
climate.Climate,
|
||||
cg.Component,
|
||||
uart.UARTDevice,
|
||||
cg.Parented.template(MitsubishiCN105Component),
|
||||
)
|
||||
|
||||
SetRemoteTemperatureAction = mitsubishi_ns.class_(
|
||||
"SetRemoteTemperatureAction",
|
||||
# Legacy climate action compatibility. Remove in 2027.2.0.
|
||||
LegacySetRemoteTemperatureAction = mitsubishi_ns.class_(
|
||||
"LegacySetRemoteTemperatureAction",
|
||||
automation.Action,
|
||||
cg.Parented.template(MitsubishiCN105Climate),
|
||||
)
|
||||
|
||||
ClearRemoteTemperatureAction = mitsubishi_ns.class_(
|
||||
"ClearRemoteTemperatureAction",
|
||||
# Legacy climate action compatibility. Remove in 2027.2.0.
|
||||
LegacyClearRemoteTemperatureAction = mitsubishi_ns.class_(
|
||||
"LegacyClearRemoteTemperatureAction",
|
||||
automation.Action,
|
||||
cg.Parented.template(MitsubishiCN105Climate),
|
||||
)
|
||||
|
||||
CONFIG_SCHEMA = (
|
||||
climate.climate_schema(MitsubishiCN105Climate)
|
||||
.extend(uart.UART_DEVICE_SCHEMA)
|
||||
.extend(
|
||||
|
||||
# Legacy climate-owned hub compatibility. Remove in 2027.2.0.
|
||||
def _has_top_level_hub_config() -> bool:
|
||||
return DOMAIN in (CORE.raw_config or {})
|
||||
|
||||
|
||||
# Legacy climate-owned hub compatibility. Remove in 2027.2.0.
|
||||
def _prepare_legacy_hub_config(config: ConfigType) -> ConfigType:
|
||||
_LOGGER.warning(
|
||||
"Defining 'climate.mitsubishi_cn105' without a top-level '%s:' hub is "
|
||||
"deprecated. Declare '%s:' and reference it with '%s:' instead. Will "
|
||||
"be removed in ESPHome 2027.2.0.",
|
||||
DOMAIN,
|
||||
DOMAIN,
|
||||
CONF_MITSUBISHI_CN105_ID,
|
||||
)
|
||||
|
||||
# Add the hidden hub declaration only for legacy climate-owned configs,
|
||||
# so normal auto-ID resolution does not see it as a top-level hub.
|
||||
config[CONF_LEGACY_MITSUBISHI_CN105_ID] = cv.declare_id(MitsubishiCN105Component)(
|
||||
None
|
||||
)
|
||||
return config
|
||||
|
||||
|
||||
_BASE_SCHEMA = climate.climate_schema(MitsubishiCN105Climate).extend(
|
||||
{
|
||||
cv.Optional(CONF_UPDATE_INTERVAL, default="1s"): cv.update_interval,
|
||||
cv.Optional(
|
||||
CONF_CURRENT_TEMPERATURE_MIN_INTERVAL, default="60s"
|
||||
): cv.update_interval,
|
||||
cv.Optional(
|
||||
CONF_SUPPORTED_SWING_MODES, default="OFF"
|
||||
): validate_climate_swing_mode,
|
||||
}
|
||||
)
|
||||
)
|
||||
|
||||
FINAL_VALIDATE_SCHEMA = cv.All(
|
||||
uart.final_validate_device_schema(
|
||||
"mitsubishi_cn105",
|
||||
_HUB_SCHEMA = _BASE_SCHEMA.extend(MITSUBISHI_CN105_DEVICE_SCHEMA)
|
||||
|
||||
# Hub options accepted in the legacy climate-owned configuration. When a
|
||||
# top-level hub exists, leaving these on the climate is always a migration
|
||||
# mistake and the generic schema error does not explain where they belong.
|
||||
# Legacy climate-owned hub compatibility. Remove in 2027.2.0.
|
||||
_LEGACY_HUB_KEYS = (
|
||||
CONF_CURRENT_TEMPERATURE_MIN_INTERVAL,
|
||||
CONF_UART_ID,
|
||||
CONF_UPDATE_INTERVAL,
|
||||
)
|
||||
|
||||
|
||||
# Legacy climate-owned hub compatibility. Remove in 2027.2.0.
|
||||
def _validate_no_legacy_hub_keys(config: ConfigType) -> ConfigType:
|
||||
legacy_keys = [key for key in _LEGACY_HUB_KEYS if key in config]
|
||||
if not legacy_keys:
|
||||
return config
|
||||
|
||||
keys = ", ".join(f"'{key}'" for key in legacy_keys)
|
||||
message = f"{keys} must be moved under the top-level '{DOMAIN}:' block"
|
||||
if CONF_CURRENT_TEMPERATURE_MIN_INTERVAL in legacy_keys:
|
||||
message += (
|
||||
f"; rename '{CONF_CURRENT_TEMPERATURE_MIN_INTERVAL}' to "
|
||||
"'telemetry_request_min_interval' there"
|
||||
)
|
||||
raise cv.Invalid(message)
|
||||
|
||||
|
||||
# Legacy climate-owned hub compatibility. Remove in 2027.2.0.
|
||||
_LEGACY_SCHEMA = (
|
||||
_BASE_SCHEMA.extend(uart.UART_DEVICE_SCHEMA)
|
||||
.extend(
|
||||
{
|
||||
cv.Optional(CONF_CURRENT_TEMPERATURE_MIN_INTERVAL): cv.update_interval,
|
||||
cv.Optional(CONF_UPDATE_INTERVAL): cv.update_interval,
|
||||
}
|
||||
)
|
||||
.add_extra(_prepare_legacy_hub_config)
|
||||
)
|
||||
|
||||
|
||||
@schema_extractor("schema")
|
||||
def CONFIG_SCHEMA(config: ConfigType) -> ConfigType:
|
||||
if config is SCHEMA_EXTRACT:
|
||||
return _HUB_SCHEMA
|
||||
if CONF_MITSUBISHI_CN105_ID in config or _has_top_level_hub_config():
|
||||
return _HUB_SCHEMA(_validate_no_legacy_hub_keys(config))
|
||||
return _LEGACY_SCHEMA(config)
|
||||
|
||||
|
||||
# Legacy climate-owned hub compatibility. Remove in 2027.2.0.
|
||||
def _legacy_final_validate(config: ConfigType) -> ConfigType:
|
||||
if CONF_MITSUBISHI_CN105_ID in config:
|
||||
return config
|
||||
|
||||
return uart.final_validate_device_schema(
|
||||
DOMAIN,
|
||||
require_rx=True,
|
||||
require_tx=True,
|
||||
data_bits=8,
|
||||
parity="EVEN",
|
||||
stop_bits=1,
|
||||
)
|
||||
)
|
||||
)(config)
|
||||
|
||||
|
||||
FINAL_VALIDATE_SCHEMA = _legacy_final_validate
|
||||
|
||||
|
||||
async def to_code(config: ConfigType) -> None:
|
||||
var = await climate.new_climate(config)
|
||||
await cg.register_component(var, config)
|
||||
await uart.register_uart_device(var, config)
|
||||
cg.add(var.set_supported_swing_mode(config[CONF_SUPPORTED_SWING_MODES]))
|
||||
climate_config = config.copy()
|
||||
# update_interval configures the protocol hub, not the climate entity.
|
||||
climate_config.pop(CONF_UPDATE_INTERVAL, None)
|
||||
await cg.register_component(var, climate_config)
|
||||
if CONF_MITSUBISHI_CN105_ID in config:
|
||||
await register_mitsubishi_cn105_device(var, config)
|
||||
else:
|
||||
# Legacy climate-owned hub compatibility. Remove in 2027.2.0.
|
||||
parent = cg.new_Pvariable(config[CONF_LEGACY_MITSUBISHI_CN105_ID])
|
||||
await cg.register_component(parent, config)
|
||||
await uart.register_uart_device(parent, config)
|
||||
if CONF_CURRENT_TEMPERATURE_MIN_INTERVAL in config:
|
||||
cg.add(
|
||||
var.set_current_temperature_min_interval(
|
||||
parent.set_telemetry_request_min_interval(
|
||||
config[CONF_CURRENT_TEMPERATURE_MIN_INTERVAL]
|
||||
)
|
||||
)
|
||||
cg.add(var.set_parent(parent))
|
||||
cg.add(var.set_supported_swing_mode(config[CONF_SUPPORTED_SWING_MODES]))
|
||||
|
||||
|
||||
@automation.register_action(
|
||||
"climate.mitsubishi_cn105.set_remote_temperature",
|
||||
SetRemoteTemperatureAction,
|
||||
cv.Schema(
|
||||
# Legacy climate action compatibility. Remove in 2027.2.0.
|
||||
LEGACY_REMOTE_TEMPERATURE_ACTION_SCHEMA = cv.Schema(
|
||||
{
|
||||
cv.Required(CONF_ID): cv.use_id(MitsubishiCN105Climate),
|
||||
cv.Required(CONF_TEMPERATURE): cv.templatable(
|
||||
@@ -93,40 +194,63 @@ async def to_code(config: ConfigType) -> None:
|
||||
)
|
||||
),
|
||||
}
|
||||
),
|
||||
synchronous=True,
|
||||
)
|
||||
async def set_remote_temperature_action_to_code(
|
||||
config: ConfigType,
|
||||
action_id: ID,
|
||||
template_arg: cg.TemplateArguments,
|
||||
args: TemplateArgsType,
|
||||
) -> MockObj:
|
||||
var = cg.new_Pvariable(action_id, template_arg)
|
||||
await cg.register_parented(var, config[CONF_ID])
|
||||
|
||||
temperature = await cg.templatable(config[CONF_TEMPERATURE], args, float)
|
||||
cg.add(var.set_temperature(temperature))
|
||||
|
||||
return var
|
||||
|
||||
|
||||
@automation.register_action(
|
||||
"climate.mitsubishi_cn105.clear_remote_temperature",
|
||||
ClearRemoteTemperatureAction,
|
||||
cv.Schema(
|
||||
# Legacy climate action compatibility. Remove in 2027.2.0.
|
||||
LEGACY_CLEAR_REMOTE_TEMPERATURE_ACTION_SCHEMA = cv.Schema(
|
||||
{
|
||||
cv.Required(CONF_ID): cv.use_id(MitsubishiCN105Climate),
|
||||
}
|
||||
),
|
||||
)
|
||||
|
||||
|
||||
# Legacy climate action compatibility. Remove in 2027.2.0.
|
||||
@automation.register_action(
|
||||
f"climate.{DOMAIN}.set_remote_temperature",
|
||||
LegacySetRemoteTemperatureAction,
|
||||
LEGACY_REMOTE_TEMPERATURE_ACTION_SCHEMA,
|
||||
synchronous=True,
|
||||
)
|
||||
async def clear_remote_temperature_action_to_code(
|
||||
async def legacy_remote_temperature_action_to_code(
|
||||
config: ConfigType,
|
||||
action_id: ID,
|
||||
template_arg: cg.TemplateArguments,
|
||||
args: TemplateArgsType,
|
||||
) -> MockObj:
|
||||
_LOGGER.warning(
|
||||
"The 'climate.%s.set_remote_temperature' action is deprecated. Use "
|
||||
"'%s.set_remote_temperature' instead. It will be removed in ESPHome "
|
||||
"2027.2.0.",
|
||||
DOMAIN,
|
||||
DOMAIN,
|
||||
)
|
||||
var = cg.new_Pvariable(action_id, template_arg)
|
||||
await cg.register_parented(var, config[CONF_ID])
|
||||
temperature = await cg.templatable(config[CONF_TEMPERATURE], args, float)
|
||||
cg.add(var.set_temperature(temperature))
|
||||
return var
|
||||
|
||||
|
||||
# Legacy climate action compatibility. Remove in 2027.2.0.
|
||||
@automation.register_action(
|
||||
f"climate.{DOMAIN}.clear_remote_temperature",
|
||||
LegacyClearRemoteTemperatureAction,
|
||||
LEGACY_CLEAR_REMOTE_TEMPERATURE_ACTION_SCHEMA,
|
||||
synchronous=True,
|
||||
)
|
||||
async def legacy_clear_temperature_action_to_code(
|
||||
config: ConfigType,
|
||||
action_id: ID,
|
||||
template_arg: cg.TemplateArguments,
|
||||
args: TemplateArgsType,
|
||||
) -> MockObj:
|
||||
_LOGGER.warning(
|
||||
"The 'climate.%s.clear_remote_temperature' action is deprecated. Use "
|
||||
"'%s.clear_remote_temperature' instead. It will be removed in ESPHome "
|
||||
"2027.2.0.",
|
||||
DOMAIN,
|
||||
DOMAIN,
|
||||
)
|
||||
var = cg.new_Pvariable(action_id, template_arg)
|
||||
await cg.register_parented(var, config[CONF_ID])
|
||||
return var
|
||||
|
||||
@@ -1,8 +1,9 @@
|
||||
#include "mitsubishi_cn105.h"
|
||||
|
||||
#include <algorithm>
|
||||
#include <array>
|
||||
#include <cmath>
|
||||
#include <numeric>
|
||||
#include "mitsubishi_cn105.h"
|
||||
|
||||
namespace esphome::mitsubishi_cn105 {
|
||||
|
||||
@@ -25,7 +26,7 @@ static constexpr std::array<uint8_t, 2> CONNECT_REQUEST_PAYLOAD = {0xCA, 0x01};
|
||||
static constexpr uint8_t PACKET_TYPE_STATUS_REQUEST = 0x42;
|
||||
static constexpr uint8_t PACKET_TYPE_STATUS_RESPONSE = 0x62;
|
||||
static constexpr uint8_t STATUS_MSG_SETTINGS = 0x02;
|
||||
static constexpr uint8_t STATUS_MSG_ROOM_TEMP = 0x03;
|
||||
static constexpr uint8_t STATUS_MSG_TELEMETRY = 0x03;
|
||||
|
||||
static constexpr uint8_t PACKET_TYPE_WRITE_SETTINGS_REQUEST = 0x41;
|
||||
static constexpr uint8_t PACKET_TYPE_WRITE_SETTINGS_RESPONSE = 0x61;
|
||||
@@ -229,8 +230,8 @@ void MitsubishiCN105::did_transition_(State to) {
|
||||
case State::STATUS_UPDATED: {
|
||||
if (this->pending_updates_.any() && this->is_status_initialized()) {
|
||||
this->set_state_(State::APPLYING_SETTINGS);
|
||||
} else if (this->current_status_msg_type_ == STATUS_MSG_SETTINGS && this->should_request_room_temperature_()) {
|
||||
this->current_status_msg_type_ = STATUS_MSG_ROOM_TEMP;
|
||||
} else if (this->current_status_msg_type_ == STATUS_MSG_SETTINGS && this->should_request_telemetry_()) {
|
||||
this->current_status_msg_type_ = STATUS_MSG_TELEMETRY;
|
||||
this->set_state_(State::UPDATING_STATUS);
|
||||
} else {
|
||||
this->set_state_(State::SCHEDULE_NEXT_STATUS_UPDATE);
|
||||
@@ -264,16 +265,16 @@ void MitsubishiCN105::did_transition_(State to) {
|
||||
}
|
||||
}
|
||||
|
||||
bool MitsubishiCN105::should_request_room_temperature_() const {
|
||||
if (!this->is_room_temperature_enabled()) {
|
||||
bool MitsubishiCN105::should_request_telemetry_() const {
|
||||
if (!this->is_telemetry_polling_enabled()) {
|
||||
return false;
|
||||
}
|
||||
|
||||
if (!this->last_room_temperature_update_ms_.has_value()) {
|
||||
if (!this->last_telemetry_update_ms_.has_value()) {
|
||||
return true;
|
||||
}
|
||||
|
||||
return (get_loop_time_ms() - *this->last_room_temperature_update_ms_) >= this->room_temperature_min_interval_ms_;
|
||||
return (get_loop_time_ms() - *this->last_telemetry_update_ms_) >= this->telemetry_request_min_interval_ms_;
|
||||
}
|
||||
|
||||
void MitsubishiCN105::send_packet_(const uint8_t *packet, size_t len) {
|
||||
@@ -327,7 +328,7 @@ bool MitsubishiCN105::process_status_packet_(const uint8_t *payload, size_t len)
|
||||
previous.fan_mode != this->status_.fan_mode || previous.target_temperature != this->status_.target_temperature ||
|
||||
previous.vane_mode != this->status_.vane_mode || previous.wide_vane_mode != this->status_.wide_vane_mode;
|
||||
|
||||
if (this->is_room_temperature_enabled()) {
|
||||
if (this->is_telemetry_polling_enabled()) {
|
||||
changed |= previous.room_temperature != this->status_.room_temperature;
|
||||
}
|
||||
|
||||
@@ -339,8 +340,8 @@ bool MitsubishiCN105::parse_status_payload_(uint8_t msg_type, const uint8_t *pay
|
||||
case STATUS_MSG_SETTINGS:
|
||||
return this->parse_status_settings_(payload, len);
|
||||
|
||||
case STATUS_MSG_ROOM_TEMP:
|
||||
return this->parse_status_room_temperature_(payload, len);
|
||||
case STATUS_MSG_TELEMETRY:
|
||||
return this->parse_status_telemetry_(payload, len);
|
||||
|
||||
default:
|
||||
ESP_LOGVV(TAG, "RX unsupported status msg type 0x%02X", msg_type);
|
||||
@@ -384,14 +385,14 @@ bool MitsubishiCN105::parse_status_settings_(const uint8_t *payload, size_t len)
|
||||
return true;
|
||||
}
|
||||
|
||||
bool MitsubishiCN105::parse_status_room_temperature_(const uint8_t *payload, size_t len) {
|
||||
bool MitsubishiCN105::parse_status_telemetry_(const uint8_t *payload, size_t len) {
|
||||
if (len <= 5) {
|
||||
ESP_LOGVV(TAG, "RX room temperature payload too short");
|
||||
ESP_LOGVV(TAG, "RX telemetry payload too short");
|
||||
return false;
|
||||
}
|
||||
|
||||
this->status_.room_temperature = decode_temperature(payload[2], payload[5], 10);
|
||||
this->last_room_temperature_update_ms_ = get_loop_time_ms();
|
||||
this->last_telemetry_update_ms_ = get_loop_time_ms();
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
@@ -1,9 +1,10 @@
|
||||
#pragma once
|
||||
|
||||
#include "esphome/components/uart/uart.h"
|
||||
#include "esphome/core/finite_set_mask.h"
|
||||
|
||||
#include <cmath>
|
||||
#include <optional>
|
||||
#include "esphome/components/uart/uart.h"
|
||||
#include "esphome/core/finite_set_mask.h"
|
||||
|
||||
namespace esphome::mitsubishi_cn105 {
|
||||
|
||||
@@ -70,15 +71,15 @@ class MitsubishiCN105 {
|
||||
uint32_t get_update_interval() const { return this->update_interval_ms_; }
|
||||
void set_update_interval(uint32_t interval_ms) { this->update_interval_ms_ = interval_ms; }
|
||||
|
||||
uint32_t get_room_temperature_min_interval() const { return this->room_temperature_min_interval_ms_; }
|
||||
bool is_room_temperature_enabled() const { return this->room_temperature_min_interval_ms_ != SCHEDULER_DONT_RUN; }
|
||||
void set_room_temperature_min_interval(uint32_t interval_ms) {
|
||||
this->room_temperature_min_interval_ms_ = interval_ms;
|
||||
uint32_t get_telemetry_request_min_interval() const { return this->telemetry_request_min_interval_ms_; }
|
||||
bool is_telemetry_polling_enabled() const { return this->telemetry_request_min_interval_ms_ != SCHEDULER_DONT_RUN; }
|
||||
void set_telemetry_request_min_interval(uint32_t interval_ms) {
|
||||
this->telemetry_request_min_interval_ms_ = interval_ms;
|
||||
}
|
||||
|
||||
const Status &status() const { return this->status_; }
|
||||
bool is_status_initialized() const {
|
||||
return this->is_room_temperature_enabled() ? !std::isnan(this->status_.room_temperature)
|
||||
return this->is_telemetry_polling_enabled() ? !std::isnan(this->status_.room_temperature)
|
||||
: !std::isnan(this->status_.target_temperature);
|
||||
}
|
||||
|
||||
@@ -150,10 +151,10 @@ class MitsubishiCN105 {
|
||||
bool process_status_packet_(const uint8_t *payload, size_t len);
|
||||
bool parse_status_payload_(uint8_t msg_type, const uint8_t *payload, size_t len);
|
||||
bool parse_status_settings_(const uint8_t *payload, size_t len);
|
||||
bool parse_status_room_temperature_(const uint8_t *payload, size_t len);
|
||||
bool parse_status_telemetry_(const uint8_t *payload, size_t len);
|
||||
void send_packet_(const uint8_t *packet, size_t len);
|
||||
void update_status_();
|
||||
bool should_request_room_temperature_() const;
|
||||
bool should_request_telemetry_() const;
|
||||
void apply_settings_();
|
||||
bool has_timed_out_(uint32_t timeout) const { return ((get_loop_time_ms() - this->operation_start_ms_) >= timeout); }
|
||||
void set_remote_temperature_half_deg_(uint8_t temperature_half_deg);
|
||||
@@ -162,11 +163,15 @@ class MitsubishiCN105 {
|
||||
static const LogString *state_to_string(State state);
|
||||
|
||||
uart::UARTDevice &device_;
|
||||
// Default 1s; legacy climate-owned hub compatibility relies on this when update_interval is omitted.
|
||||
// Remove legacy note in 2027.2.0.
|
||||
uint32_t update_interval_ms_{1000};
|
||||
uint32_t status_update_wait_credit_ms_{0};
|
||||
uint32_t operation_start_ms_{0};
|
||||
uint32_t room_temperature_min_interval_ms_{60000};
|
||||
std::optional<uint32_t> last_room_temperature_update_ms_;
|
||||
// Default 60s; legacy climate-owned hub compatibility relies on this when current_temperature_min_interval is
|
||||
// omitted. Remove legacy note in 2027.2.0.
|
||||
uint32_t telemetry_request_min_interval_ms_{60000};
|
||||
std::optional<uint32_t> last_telemetry_update_ms_;
|
||||
Status status_{};
|
||||
State state_{State::NOT_CONNECTED};
|
||||
UpdateFlags pending_updates_;
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
#include <cinttypes>
|
||||
#include "mitsubishi_cn105_climate.h"
|
||||
|
||||
#include "esphome/core/log.h"
|
||||
|
||||
namespace esphome::mitsubishi_cn105 {
|
||||
@@ -50,25 +50,11 @@ static constexpr std::optional<Left> reverse_map_lookup(const std::array<std::pa
|
||||
return key.has_value() ? reverse_map_lookup(map, *key) : std::nullopt;
|
||||
}
|
||||
|
||||
void MitsubishiCN105Climate::dump_config() {
|
||||
LOG_CLIMATE("", "Mitsubishi CN105 Climate", this);
|
||||
if (this->hp_.is_room_temperature_enabled()) {
|
||||
ESP_LOGCONFIG(TAG, " Current temperature min interval: %" PRIu32 " ms",
|
||||
this->hp_.get_room_temperature_min_interval());
|
||||
} else {
|
||||
ESP_LOGCONFIG(TAG, " Current temperature: DISABLED");
|
||||
}
|
||||
ESP_LOGCONFIG(TAG,
|
||||
" Update interval: %" PRIu32 " ms\n"
|
||||
" UART: baud_rate=%" PRIu32 " data_bits=%u parity=%s stop_bits=%u",
|
||||
this->hp_.get_update_interval(), this->parent_->get_baud_rate(), this->parent_->get_data_bits(),
|
||||
LOG_STR_ARG(parity_to_str(this->parent_->get_parity())), this->parent_->get_stop_bits());
|
||||
}
|
||||
void MitsubishiCN105Climate::dump_config() { LOG_CLIMATE("", "Mitsubishi CN105 Climate", this); }
|
||||
|
||||
void MitsubishiCN105Climate::setup() { this->hp_.initialize(); }
|
||||
|
||||
void MitsubishiCN105Climate::loop() {
|
||||
if (this->hp_.update()) {
|
||||
void MitsubishiCN105Climate::setup() {
|
||||
this->parent_->add_on_status_callback([this]() { this->apply_values_(); });
|
||||
if (this->parent_->is_status_initialized()) {
|
||||
this->apply_values_();
|
||||
}
|
||||
}
|
||||
@@ -90,7 +76,7 @@ climate::ClimateTraits MitsubishiCN105Climate::traits() {
|
||||
traits.set_visual_max_temperature(31.0f);
|
||||
traits.set_visual_temperature_step(1.0f);
|
||||
|
||||
if (this->hp_.is_room_temperature_enabled()) {
|
||||
if (this->parent_->is_telemetry_polling_enabled()) {
|
||||
traits.add_feature_flags(climate::CLIMATE_SUPPORTS_CURRENT_TEMPERATURE);
|
||||
traits.set_visual_current_temperature_step(0.5f);
|
||||
}
|
||||
@@ -100,20 +86,20 @@ climate::ClimateTraits MitsubishiCN105Climate::traits() {
|
||||
|
||||
void MitsubishiCN105Climate::control(const climate::ClimateCall &call) {
|
||||
if (const auto target_temperature = call.get_target_temperature()) {
|
||||
this->hp_.set_target_temperature(*target_temperature);
|
||||
this->parent_->set_target_temperature(*target_temperature);
|
||||
}
|
||||
|
||||
if (const auto mode = call.get_mode()) {
|
||||
if (*mode == climate::CLIMATE_MODE_OFF) {
|
||||
this->hp_.set_power(false);
|
||||
this->parent_->set_power(false);
|
||||
} else if (const auto mapped = reverse_map_lookup(MODE_MAP, *mode)) {
|
||||
this->hp_.set_power(true);
|
||||
this->hp_.set_mode(*mapped);
|
||||
this->parent_->set_power(true);
|
||||
this->parent_->set_mode(*mapped);
|
||||
}
|
||||
}
|
||||
|
||||
if (const auto fan_mode = reverse_map_lookup(FAN_MODE_MAP, call.get_fan_mode())) {
|
||||
this->hp_.set_fan_mode(*fan_mode);
|
||||
this->parent_->set_fan_mode(*fan_mode);
|
||||
}
|
||||
|
||||
if (const auto swing_mode = call.get_swing_mode()) {
|
||||
@@ -140,24 +126,24 @@ void MitsubishiCN105Climate::control(const climate::ClimateCall &call) {
|
||||
}
|
||||
|
||||
if (this->supported_swing_modes_.count(climate::CLIMATE_SWING_VERTICAL)) {
|
||||
this->hp_.set_vane_mode(vane);
|
||||
this->parent_->set_vane_mode(vane);
|
||||
}
|
||||
if (this->supported_swing_modes_.count(climate::CLIMATE_SWING_HORIZONTAL)) {
|
||||
this->hp_.set_wide_vane_mode(wide);
|
||||
this->parent_->set_wide_vane_mode(wide);
|
||||
}
|
||||
}
|
||||
|
||||
if (this->hp_.is_status_initialized()) {
|
||||
if (this->parent_->is_status_initialized()) {
|
||||
this->apply_values_();
|
||||
}
|
||||
}
|
||||
|
||||
void MitsubishiCN105Climate::apply_values_() {
|
||||
const auto &status = this->hp_.status();
|
||||
const auto &status = this->parent_->status();
|
||||
|
||||
this->target_temperature = status.target_temperature;
|
||||
|
||||
if (this->hp_.is_room_temperature_enabled()) {
|
||||
if (this->parent_->is_telemetry_polling_enabled()) {
|
||||
this->current_temperature = status.room_temperature;
|
||||
}
|
||||
|
||||
|
||||
@@ -1,51 +1,47 @@
|
||||
#pragma once
|
||||
|
||||
#include "mitsubishi_cn105_component.h"
|
||||
#include "mitsubishi_cn105.h"
|
||||
|
||||
#include "esphome/core/automation.h"
|
||||
#include "esphome/core/component.h"
|
||||
#include "esphome/components/climate/climate.h"
|
||||
#include "esphome/components/uart/uart.h"
|
||||
#include "mitsubishi_cn105.h"
|
||||
|
||||
namespace esphome::mitsubishi_cn105 {
|
||||
|
||||
class MitsubishiCN105Climate : public climate::Climate, public Component, public uart::UARTDevice {
|
||||
class MitsubishiCN105Climate : public climate::Climate, public Component, public Parented<MitsubishiCN105Component> {
|
||||
public:
|
||||
explicit MitsubishiCN105Climate() : hp_(*this) {}
|
||||
|
||||
void setup() override;
|
||||
void loop() override;
|
||||
void dump_config() override;
|
||||
|
||||
climate::ClimateTraits traits() override;
|
||||
void control(const climate::ClimateCall &call) override;
|
||||
|
||||
void set_update_interval(uint32_t ms) { this->hp_.set_update_interval(ms); }
|
||||
void set_current_temperature_min_interval(uint32_t ms) { this->hp_.set_room_temperature_min_interval(ms); }
|
||||
|
||||
void set_remote_temperature(float temperature) { this->hp_.set_remote_temperature(temperature); }
|
||||
void clear_remote_temperature() { this->hp_.clear_remote_temperature(); }
|
||||
|
||||
void set_supported_swing_mode(climate::ClimateSwingMode mode);
|
||||
// Legacy climate action compatibility. Remove in 2027.2.0.
|
||||
void set_remote_temperature(float temperature) { this->parent_->set_remote_temperature(temperature); }
|
||||
void clear_remote_temperature() { this->parent_->clear_remote_temperature(); }
|
||||
|
||||
protected:
|
||||
void apply_values_();
|
||||
|
||||
MitsubishiCN105 hp_;
|
||||
climate::ClimateSwingModeMask supported_swing_modes_{};
|
||||
MitsubishiCN105::VaneMode last_non_swing_vane_mode_{MitsubishiCN105::VaneMode::AUTO};
|
||||
MitsubishiCN105::WideVaneMode last_non_swing_wide_vane_mode_{MitsubishiCN105::WideVaneMode::CENTER};
|
||||
};
|
||||
|
||||
// Legacy climate action compatibility. Remove in 2027.2.0.
|
||||
template<typename... Ts>
|
||||
class SetRemoteTemperatureAction : public Action<Ts...>, public Parented<MitsubishiCN105Climate> {
|
||||
class LegacySetRemoteTemperatureAction : public Action<Ts...>, public Parented<MitsubishiCN105Climate> {
|
||||
public:
|
||||
TEMPLATABLE_VALUE(float, temperature)
|
||||
|
||||
void play(const Ts &...x) override { this->parent_->set_remote_temperature(this->temperature_.value(x...)); }
|
||||
};
|
||||
|
||||
// Legacy climate action compatibility. Remove in 2027.2.0.
|
||||
template<typename... Ts>
|
||||
class ClearRemoteTemperatureAction : public Action<Ts...>, public Parented<MitsubishiCN105Climate> {
|
||||
class LegacyClearRemoteTemperatureAction : public Action<Ts...>, public Parented<MitsubishiCN105Climate> {
|
||||
public:
|
||||
void play(const Ts &...x) override { this->parent_->clear_remote_temperature(); }
|
||||
};
|
||||
|
||||
@@ -0,0 +1,34 @@
|
||||
#include "mitsubishi_cn105_component.h"
|
||||
|
||||
#include "esphome/core/log.h"
|
||||
|
||||
#include <cinttypes>
|
||||
|
||||
namespace esphome::mitsubishi_cn105 {
|
||||
|
||||
static const char *const TAG = "mitsubishi_cn105";
|
||||
|
||||
void MitsubishiCN105Component::dump_config() {
|
||||
ESP_LOGCONFIG(TAG, "Mitsubishi CN105:");
|
||||
if (this->hp_.is_telemetry_polling_enabled()) {
|
||||
ESP_LOGCONFIG(TAG, " Telemetry polling min interval: %" PRIu32 " ms",
|
||||
this->hp_.get_telemetry_request_min_interval());
|
||||
} else {
|
||||
ESP_LOGCONFIG(TAG, " Telemetry polling: DISABLED");
|
||||
}
|
||||
ESP_LOGCONFIG(TAG,
|
||||
" Update interval: %" PRIu32 " ms\n"
|
||||
" UART: baud_rate=%" PRIu32 " data_bits=%u parity=%s stop_bits=%u",
|
||||
this->hp_.get_update_interval(), this->parent_->get_baud_rate(), this->parent_->get_data_bits(),
|
||||
LOG_STR_ARG(parity_to_str(this->parent_->get_parity())), this->parent_->get_stop_bits());
|
||||
}
|
||||
|
||||
void MitsubishiCN105Component::setup() { this->hp_.initialize(); }
|
||||
|
||||
void MitsubishiCN105Component::loop() {
|
||||
if (this->hp_.update()) {
|
||||
this->status_callback_.call();
|
||||
}
|
||||
}
|
||||
|
||||
} // namespace esphome::mitsubishi_cn105
|
||||
@@ -0,0 +1,46 @@
|
||||
#pragma once
|
||||
|
||||
#include "mitsubishi_cn105.h"
|
||||
|
||||
#include "esphome/core/component.h"
|
||||
#include "esphome/components/uart/uart.h"
|
||||
|
||||
#include <utility>
|
||||
|
||||
namespace esphome::mitsubishi_cn105 {
|
||||
|
||||
class MitsubishiCN105Component : public Component, public uart::UARTDevice {
|
||||
public:
|
||||
explicit MitsubishiCN105Component() : hp_(*this) {}
|
||||
|
||||
void setup() override;
|
||||
void loop() override;
|
||||
void dump_config() override;
|
||||
|
||||
void set_update_interval(uint32_t ms) { this->hp_.set_update_interval(ms); }
|
||||
void set_telemetry_request_min_interval(uint32_t ms) { this->hp_.set_telemetry_request_min_interval(ms); }
|
||||
|
||||
void set_remote_temperature(float temperature) { this->hp_.set_remote_temperature(temperature); }
|
||||
void clear_remote_temperature() { this->hp_.clear_remote_temperature(); }
|
||||
|
||||
void set_power(bool power_on) { this->hp_.set_power(power_on); }
|
||||
void set_target_temperature(float target_temperature) { this->hp_.set_target_temperature(target_temperature); }
|
||||
void set_mode(MitsubishiCN105::Mode mode) { this->hp_.set_mode(mode); }
|
||||
void set_fan_mode(MitsubishiCN105::FanMode fan_mode) { this->hp_.set_fan_mode(fan_mode); }
|
||||
void set_vane_mode(MitsubishiCN105::VaneMode vane_mode) { this->hp_.set_vane_mode(vane_mode); }
|
||||
void set_wide_vane_mode(MitsubishiCN105::WideVaneMode mode) { this->hp_.set_wide_vane_mode(mode); }
|
||||
|
||||
const MitsubishiCN105::Status &status() const { return this->hp_.status(); }
|
||||
bool is_status_initialized() const { return this->hp_.is_status_initialized(); }
|
||||
bool is_telemetry_polling_enabled() const { return this->hp_.is_telemetry_polling_enabled(); }
|
||||
|
||||
template<typename F> void add_on_status_callback(F &&callback) {
|
||||
this->status_callback_.add(std::forward<F>(callback));
|
||||
}
|
||||
|
||||
protected:
|
||||
MitsubishiCN105 hp_;
|
||||
CallbackManager<void()> status_callback_;
|
||||
};
|
||||
|
||||
} // namespace esphome::mitsubishi_cn105
|
||||
+10
@@ -0,0 +1,10 @@
|
||||
mitsubishi_cn105:
|
||||
id: ac_hub
|
||||
|
||||
climate:
|
||||
- platform: mitsubishi_cn105
|
||||
mitsubishi_cn105_id: ac_hub
|
||||
name: AC
|
||||
current_temperature_min_interval: 30s
|
||||
uart_id: uart_bus
|
||||
update_interval: 10s
|
||||
@@ -0,0 +1,30 @@
|
||||
"""Tests for Mitsubishi CN105 climate configuration migration diagnostics."""
|
||||
|
||||
from collections.abc import Callable
|
||||
from pathlib import Path
|
||||
|
||||
import pytest
|
||||
|
||||
from esphome.components.mitsubishi_cn105 import climate
|
||||
import esphome.config_validation as cv
|
||||
from esphome.core import CORE
|
||||
from esphome.yaml_util import load_yaml
|
||||
|
||||
|
||||
def test_top_level_hub_rejects_leftover_legacy_climate_keys(
|
||||
component_fixture_path: Callable[[str], Path],
|
||||
) -> None:
|
||||
config = load_yaml(
|
||||
component_fixture_path("top_level_hub_with_legacy_climate_keys.yaml")
|
||||
)
|
||||
CORE.raw_config = config
|
||||
|
||||
with pytest.raises(cv.Invalid) as exc_info:
|
||||
climate.CONFIG_SCHEMA(config["climate"][0])
|
||||
|
||||
message = str(exc_info.value)
|
||||
assert "'current_temperature_min_interval'" in message
|
||||
assert "'uart_id'" in message
|
||||
assert "'update_interval'" in message
|
||||
assert "top-level 'mitsubishi_cn105:' block" in message
|
||||
assert "'telemetry_request_min_interval'" in message
|
||||
@@ -75,7 +75,7 @@ TEST(MitsubishiCN105Tests, ConnectAndUpdateStatus) {
|
||||
EXPECT_EQ(ctx.sut.status().vane_mode, MitsubishiCN105::VaneMode::POSITION_4);
|
||||
EXPECT_EQ(ctx.sut.status().wide_vane_mode, MitsubishiCN105::WideVaneMode::SWING);
|
||||
|
||||
// Now fetch room temperature (0x03)
|
||||
// Now fetch telemetry (0x03)
|
||||
EXPECT_EQ(ctx.sut.state_, TestableMitsubishiCN105::State::UPDATING_STATUS);
|
||||
EXPECT_THAT(ctx.uart.tx, ::testing::ElementsAre(0xFC, 0x42, 0x01, 0x30, 0x10, 0x03, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x7A));
|
||||
@@ -84,11 +84,11 @@ TEST(MitsubishiCN105Tests, ConnectAndUpdateStatus) {
|
||||
// Clear TX bytes.
|
||||
ctx.uart.tx.clear();
|
||||
|
||||
// Room temperature response
|
||||
// Telemetry response
|
||||
ctx.uart.push_rx({0xFC, 0x62, 0x01, 0x30, 0x10, 0x03, 0x00, 0x00, 0x0B, 0x00, 0x00,
|
||||
0xAA, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xA5});
|
||||
|
||||
// Room temperature should still have initial value
|
||||
// Room temperature from telemetry should still have initial value
|
||||
EXPECT_THAT(ctx.sut.status().room_temperature, ::testing::IsNan());
|
||||
|
||||
ctx.sut.set_current_time(400);
|
||||
@@ -97,7 +97,7 @@ TEST(MitsubishiCN105Tests, ConnectAndUpdateStatus) {
|
||||
EXPECT_TRUE(ctx.uart.rx.empty());
|
||||
EXPECT_TRUE(ctx.sut.is_status_initialized());
|
||||
|
||||
// Check room temperature we just read from received package
|
||||
// Check room temperature we just read from telemetry package
|
||||
EXPECT_EQ(ctx.sut.status().room_temperature, 21.0f);
|
||||
|
||||
EXPECT_TRUE(ctx.uart.tx.empty());
|
||||
|
||||
@@ -8,6 +8,7 @@
|
||||
#include <vector>
|
||||
#include "esphome/components/uart/uart_component.h"
|
||||
#include "esphome/components/mitsubishi_cn105/mitsubishi_cn105.h"
|
||||
#include "esphome/components/mitsubishi_cn105/mitsubishi_cn105_component.h"
|
||||
#include "esphome/components/mitsubishi_cn105/mitsubishi_cn105_climate.h"
|
||||
|
||||
namespace esphome::mitsubishi_cn105::testing {
|
||||
@@ -65,11 +66,16 @@ class TestableMitsubishiCN105 : public MitsubishiCN105 {
|
||||
|
||||
class TestableMitsubishiCN105Climate : public MitsubishiCN105Climate {
|
||||
public:
|
||||
TestableMitsubishiCN105Climate() { this->set_parent(&this->component_); }
|
||||
|
||||
using MitsubishiCN105Climate::apply_values_;
|
||||
using MitsubishiCN105Climate::last_non_swing_vane_mode_;
|
||||
using MitsubishiCN105Climate::last_non_swing_wide_vane_mode_;
|
||||
|
||||
MitsubishiCN105::Status &status() { return static_cast<TestableMitsubishiCN105 &>(this->hp_).status_; }
|
||||
MitsubishiCN105::Status &status() { return const_cast<MitsubishiCN105::Status &>(this->component_.status()); }
|
||||
|
||||
protected:
|
||||
MitsubishiCN105Component component_;
|
||||
};
|
||||
|
||||
} // namespace esphome::mitsubishi_cn105::testing
|
||||
|
||||
@@ -1,17 +1,20 @@
|
||||
climate:
|
||||
- platform: mitsubishi_cn105
|
||||
mitsubishi_cn105:
|
||||
id: ac
|
||||
name: "AC Test"
|
||||
uart_id: uart_bus
|
||||
update_interval: 30s
|
||||
current_temperature_min_interval: 120s
|
||||
telemetry_request_min_interval: 120s
|
||||
|
||||
climate:
|
||||
- platform: mitsubishi_cn105
|
||||
mitsubishi_cn105_id: ac
|
||||
name: "AC Test"
|
||||
supported_swing_modes: BOTH
|
||||
|
||||
esphome:
|
||||
on_boot:
|
||||
then:
|
||||
- climate.mitsubishi_cn105.set_remote_temperature:
|
||||
- mitsubishi_cn105.set_remote_temperature:
|
||||
id: ac
|
||||
temperature: 22.0
|
||||
- climate.mitsubishi_cn105.clear_remote_temperature:
|
||||
- mitsubishi_cn105.clear_remote_temperature:
|
||||
id: ac
|
||||
|
||||
@@ -0,0 +1,16 @@
|
||||
packages:
|
||||
uart_9600_even: !include ../../test_build_components/common/uart_9600_even/esp32-idf.yaml
|
||||
|
||||
climate:
|
||||
- platform: mitsubishi_cn105
|
||||
id: ac
|
||||
name: "AC Test"
|
||||
|
||||
esphome:
|
||||
on_boot:
|
||||
then:
|
||||
- climate.mitsubishi_cn105.set_remote_temperature:
|
||||
id: ac
|
||||
temperature: 22.0
|
||||
- climate.mitsubishi_cn105.clear_remote_temperature:
|
||||
id: ac
|
||||
+7
@@ -0,0 +1,7 @@
|
||||
packages:
|
||||
uart_9600_even: !include ../../test_build_components/common/uart_9600_even/esp32-idf.yaml
|
||||
|
||||
climate:
|
||||
- platform: mitsubishi_cn105
|
||||
name: "AC Test"
|
||||
current_temperature_min_interval: 30s
|
||||
@@ -0,0 +1,6 @@
|
||||
packages:
|
||||
uart_9600_even: !include ../../test_build_components/common/uart_9600_even/esp32-idf.yaml
|
||||
|
||||
climate:
|
||||
- platform: mitsubishi_cn105
|
||||
name: "AC Test"
|
||||
@@ -0,0 +1,7 @@
|
||||
packages:
|
||||
uart_9600_even: !include ../../test_build_components/common/uart_9600_even/esp32-idf.yaml
|
||||
|
||||
climate:
|
||||
- platform: mitsubishi_cn105
|
||||
name: "AC Test"
|
||||
uart_id: uart_bus
|
||||
+7
@@ -0,0 +1,7 @@
|
||||
packages:
|
||||
uart_9600_even: !include ../../test_build_components/common/uart_9600_even/esp32-idf.yaml
|
||||
|
||||
climate:
|
||||
- platform: mitsubishi_cn105
|
||||
name: "AC Test"
|
||||
update_interval: 30s
|
||||
@@ -0,0 +1,8 @@
|
||||
packages:
|
||||
uart_9600_even: !include ../../test_build_components/common/uart_9600_even/esp32-idf.yaml
|
||||
|
||||
mitsubishi_cn105:
|
||||
|
||||
climate:
|
||||
- platform: mitsubishi_cn105
|
||||
name: "AC Test"
|
||||
Reference in New Issue
Block a user