mirror of
https://github.com/esphome/esphome.git
synced 2026-08-22 22:26:21 +00:00
[mitsubishi_cn105] Add vertical vane state trigger (#16727)
Co-authored-by: J. Nick Koston <nick@koston.org>
This commit is contained in:
co-authored by
J. Nick Koston
parent
3ae651af7b
commit
55bd63732d
@@ -2,7 +2,7 @@ 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.const import CONF_ID, CONF_ON_STATE, CONF_TEMPERATURE, CONF_UPDATE_INTERVAL
|
||||
from esphome.core import ID
|
||||
from esphome.cpp_generator import MockObj
|
||||
from esphome.types import ConfigType, TemplateArgsType
|
||||
@@ -13,6 +13,7 @@ DOMAIN = "mitsubishi_cn105"
|
||||
|
||||
CONF_MITSUBISHI_CN105_ID = f"{DOMAIN}_id"
|
||||
CONF_TELEMETRY_REQUEST_MIN_INTERVAL = "telemetry_request_min_interval"
|
||||
CONF_VANE = "vane"
|
||||
|
||||
mitsubishi_ns = cg.esphome_ns.namespace(DOMAIN)
|
||||
|
||||
@@ -22,6 +23,8 @@ MitsubishiCN105Component = mitsubishi_ns.class_(
|
||||
uart.UARTDevice,
|
||||
)
|
||||
|
||||
VaneState = mitsubishi_ns.struct("VaneState")
|
||||
|
||||
SetRemoteTemperatureAction = mitsubishi_ns.class_(
|
||||
"SetRemoteTemperatureAction",
|
||||
automation.Action,
|
||||
@@ -42,6 +45,11 @@ CONFIG_SCHEMA = (
|
||||
cv.Optional(
|
||||
CONF_TELEMETRY_REQUEST_MIN_INTERVAL, default="60s"
|
||||
): cv.update_interval,
|
||||
cv.Optional(CONF_VANE): cv.Schema(
|
||||
{
|
||||
cv.Optional(CONF_ON_STATE): automation.validate_automation({}),
|
||||
}
|
||||
),
|
||||
}
|
||||
)
|
||||
.extend(cv.COMPONENT_SCHEMA)
|
||||
@@ -80,6 +88,15 @@ async def to_code(config: ConfigType) -> None:
|
||||
config[CONF_TELEMETRY_REQUEST_MIN_INTERVAL]
|
||||
)
|
||||
)
|
||||
if on_state := config.get(CONF_VANE, {}).get(CONF_ON_STATE):
|
||||
cg.add_global(mitsubishi_ns.using)
|
||||
for conf in on_state:
|
||||
await automation.build_callback_automation(
|
||||
var,
|
||||
"add_on_vane_state_callback",
|
||||
[(VaneState.operator("const").operator("ref"), "x")],
|
||||
conf,
|
||||
)
|
||||
|
||||
|
||||
REMOTE_TEMPERATURE_ACTION_SCHEMA = cv.Schema(
|
||||
|
||||
@@ -27,7 +27,7 @@ void MitsubishiCN105Component::setup() { this->hp_.initialize(); }
|
||||
|
||||
void MitsubishiCN105Component::loop() {
|
||||
if (this->hp_.update()) {
|
||||
this->status_callback_.call();
|
||||
this->notify_status_listeners_();
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -9,6 +9,24 @@
|
||||
|
||||
namespace esphome::mitsubishi_cn105 {
|
||||
|
||||
enum VerticalVaneMode : uint8_t {
|
||||
VERTICAL_VANE_MODE_AUTO = static_cast<uint8_t>(MitsubishiCN105::VaneMode::AUTO),
|
||||
VERTICAL_VANE_MODE_POSITION_1 = static_cast<uint8_t>(MitsubishiCN105::VaneMode::POSITION_1),
|
||||
VERTICAL_VANE_MODE_POSITION_2 = static_cast<uint8_t>(MitsubishiCN105::VaneMode::POSITION_2),
|
||||
VERTICAL_VANE_MODE_POSITION_3 = static_cast<uint8_t>(MitsubishiCN105::VaneMode::POSITION_3),
|
||||
VERTICAL_VANE_MODE_POSITION_4 = static_cast<uint8_t>(MitsubishiCN105::VaneMode::POSITION_4),
|
||||
VERTICAL_VANE_MODE_POSITION_5 = static_cast<uint8_t>(MitsubishiCN105::VaneMode::POSITION_5),
|
||||
VERTICAL_VANE_MODE_SWING = static_cast<uint8_t>(MitsubishiCN105::VaneMode::SWING),
|
||||
};
|
||||
|
||||
struct VaneState {
|
||||
struct Vertical {
|
||||
VerticalVaneMode direction;
|
||||
};
|
||||
|
||||
Vertical vertical;
|
||||
};
|
||||
|
||||
class MitsubishiCN105Component : public Component, public uart::UARTDevice {
|
||||
public:
|
||||
explicit MitsubishiCN105Component() : hp_(*this) {}
|
||||
@@ -38,15 +56,29 @@ class MitsubishiCN105Component : public Component, public uart::UARTDevice {
|
||||
this->status_callback_.add(std::forward<F>(callback));
|
||||
}
|
||||
|
||||
template<typename F> void add_on_vane_state_callback(F &&callback) {
|
||||
this->vane_state_callback_.add(std::forward<F>(callback));
|
||||
}
|
||||
|
||||
void publish_status() {
|
||||
if (this->is_status_initialized()) {
|
||||
this->status_callback_.call();
|
||||
this->notify_status_listeners_();
|
||||
}
|
||||
}
|
||||
|
||||
protected:
|
||||
void notify_status_listeners_() {
|
||||
this->status_callback_.call();
|
||||
if (this->status().vane_mode != MitsubishiCN105::VaneMode::UNKNOWN) {
|
||||
this->vane_state_callback_.call(VaneState{
|
||||
.vertical = {.direction = static_cast<VerticalVaneMode>(this->status().vane_mode)},
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
MitsubishiCN105 hp_;
|
||||
CallbackManager<void()> status_callback_;
|
||||
LazyCallbackManager<void(const VaneState &)> vane_state_callback_;
|
||||
};
|
||||
|
||||
} // namespace esphome::mitsubishi_cn105
|
||||
|
||||
@@ -77,4 +77,11 @@ class TestableMitsubishiCN105Climate : public MitsubishiCN105Climate {
|
||||
MitsubishiCN105Component component_;
|
||||
};
|
||||
|
||||
class TestableMitsubishiCN105Component : public MitsubishiCN105Component {
|
||||
public:
|
||||
MitsubishiCN105::Status &mutable_status() { return const_cast<MitsubishiCN105::Status &>(this->status()); }
|
||||
|
||||
void notify_status() { this->status_callback_.call(); }
|
||||
};
|
||||
|
||||
} // namespace esphome::mitsubishi_cn105::testing
|
||||
|
||||
@@ -3,6 +3,11 @@ mitsubishi_cn105:
|
||||
uart_id: uart_bus
|
||||
update_interval: 30s
|
||||
telemetry_request_min_interval: 120s
|
||||
vane:
|
||||
on_state:
|
||||
- logger.log:
|
||||
format: "TRIGGER: vane on_state is auto: %s"
|
||||
args: ['x.vertical.direction == VERTICAL_VANE_MODE_AUTO ? "yes" : "no"']
|
||||
|
||||
climate:
|
||||
- platform: mitsubishi_cn105
|
||||
|
||||
@@ -0,0 +1,48 @@
|
||||
#include "common.h"
|
||||
|
||||
namespace esphome::mitsubishi_cn105::testing {
|
||||
|
||||
TEST(MitsubishiCN105ComponentTests, PublishesVaneStateForEveryValidSnapshot) {
|
||||
TestableMitsubishiCN105Component hub;
|
||||
size_t callback_count = 0;
|
||||
std::optional<VerticalVaneMode> callback_direction;
|
||||
hub.add_on_vane_state_callback([&](const VaneState &state) {
|
||||
callback_count++;
|
||||
callback_direction = state.vertical.direction;
|
||||
});
|
||||
|
||||
hub.mutable_status().room_temperature = 20.0f;
|
||||
hub.mutable_status().vane_mode = MitsubishiCN105::VaneMode::POSITION_4;
|
||||
hub.publish_status();
|
||||
|
||||
EXPECT_EQ(callback_count, 1);
|
||||
EXPECT_EQ(callback_direction, std::optional{VERTICAL_VANE_MODE_POSITION_4});
|
||||
|
||||
hub.publish_status();
|
||||
|
||||
EXPECT_EQ(callback_count, 2);
|
||||
EXPECT_EQ(callback_direction, std::optional{VERTICAL_VANE_MODE_POSITION_4});
|
||||
}
|
||||
|
||||
TEST(MitsubishiCN105ComponentTests, DoesNotPublishUnknownVaneState) {
|
||||
TestableMitsubishiCN105Component hub;
|
||||
size_t status_callback_count = 0;
|
||||
size_t vane_callback_count = 0;
|
||||
hub.add_on_status_callback([&]() { status_callback_count++; });
|
||||
hub.add_on_vane_state_callback([&](const VaneState &) { vane_callback_count++; });
|
||||
|
||||
hub.mutable_status().room_temperature = 20.0f;
|
||||
hub.mutable_status().vane_mode = MitsubishiCN105::VaneMode::UNKNOWN;
|
||||
hub.publish_status();
|
||||
|
||||
EXPECT_EQ(status_callback_count, 1);
|
||||
EXPECT_EQ(vane_callback_count, 0);
|
||||
|
||||
hub.mutable_status().vane_mode = MitsubishiCN105::VaneMode::POSITION_4;
|
||||
hub.publish_status();
|
||||
|
||||
EXPECT_EQ(status_callback_count, 2);
|
||||
EXPECT_EQ(vane_callback_count, 1);
|
||||
}
|
||||
|
||||
} // namespace esphome::mitsubishi_cn105::testing
|
||||
-7
@@ -3,13 +3,6 @@
|
||||
|
||||
namespace esphome::mitsubishi_cn105::testing {
|
||||
|
||||
class TestableMitsubishiCN105Component : public MitsubishiCN105Component {
|
||||
public:
|
||||
MitsubishiCN105::Status &mutable_status() { return const_cast<MitsubishiCN105::Status &>(this->status()); }
|
||||
|
||||
void notify_status() { this->status_callback_.call(); }
|
||||
};
|
||||
|
||||
class TestableMitsubishiCN105VerticalVaneDirectionSelect : public MitsubishiCN105VerticalVaneDirectionSelect {
|
||||
public:
|
||||
using MitsubishiCN105VerticalVaneDirectionSelect::control;
|
||||
|
||||
Reference in New Issue
Block a user