mirror of
https://github.com/esphome/esphome.git
synced 2026-08-22 22:26:21 +00:00
[mitsubishi_cn105] Add vertical vane direction select (#16723)
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
82a63658f9
commit
c8d2c3691a
@@ -2,16 +2,16 @@
|
||||
|
||||
namespace esphome::mitsubishi_cn105::testing {
|
||||
|
||||
struct TestContext {
|
||||
struct MitsubishiCN105TestsContext {
|
||||
MockUARTComponent uart;
|
||||
uart::UARTDevice device{&uart};
|
||||
TestableMitsubishiCN105 sut{device};
|
||||
|
||||
TestContext() { this->sut.set_current_time(0); }
|
||||
MitsubishiCN105TestsContext() { this->sut.set_current_time(0); }
|
||||
};
|
||||
|
||||
TEST(MitsubishiCN105Tests, InitSendsConnectPacket) {
|
||||
auto ctx = TestContext{};
|
||||
MitsubishiCN105TestsContext ctx;
|
||||
|
||||
ctx.sut.set_current_time(123);
|
||||
EXPECT_EQ(ctx.sut.state_, TestableMitsubishiCN105::State::NOT_CONNECTED);
|
||||
@@ -26,7 +26,7 @@ TEST(MitsubishiCN105Tests, InitSendsConnectPacket) {
|
||||
}
|
||||
|
||||
TEST(MitsubishiCN105Tests, ConnectAndUpdateStatus) {
|
||||
auto ctx = TestContext{};
|
||||
MitsubishiCN105TestsContext ctx;
|
||||
|
||||
ctx.sut.initialize();
|
||||
ctx.uart.tx.clear(); // Remove first connect packet bytes
|
||||
@@ -106,7 +106,7 @@ TEST(MitsubishiCN105Tests, ConnectAndUpdateStatus) {
|
||||
}
|
||||
|
||||
TEST(MitsubishiCN105Tests, NoResponseTriggersReconnect) {
|
||||
auto ctx = TestContext{};
|
||||
MitsubishiCN105TestsContext ctx;
|
||||
|
||||
ctx.sut.initialize();
|
||||
ctx.uart.tx.clear(); // Remove first connect packet bytes
|
||||
@@ -133,7 +133,7 @@ TEST(MitsubishiCN105Tests, NoResponseTriggersReconnect) {
|
||||
}
|
||||
|
||||
TEST(MitsubishiCN105Tests, RxWatchdogLimitsProcessingPerUpdate) {
|
||||
auto ctx = TestContext{};
|
||||
MitsubishiCN105TestsContext ctx;
|
||||
|
||||
ctx.sut.initialize();
|
||||
ctx.uart.tx.clear(); // Remove first connect packet bytes
|
||||
@@ -164,7 +164,7 @@ TEST(MitsubishiCN105Tests, RxWatchdogLimitsProcessingPerUpdate) {
|
||||
}
|
||||
|
||||
TEST(MitsubishiCN105Tests, ParserHandlesMixedRxStream) {
|
||||
auto ctx = TestContext{};
|
||||
MitsubishiCN105TestsContext ctx;
|
||||
|
||||
ctx.sut.initialize();
|
||||
ctx.uart.tx.clear(); // Remove first connect packet bytes
|
||||
@@ -228,7 +228,7 @@ TEST(MitsubishiCN105Tests, ParserHandlesMixedRxStream) {
|
||||
}
|
||||
|
||||
TEST(MitsubishiCN105Tests, NextStatusUpdateAfterUpdateIntervalMilliseconds) {
|
||||
auto ctx = TestContext{};
|
||||
MitsubishiCN105TestsContext ctx;
|
||||
|
||||
ctx.sut.set_update_interval(2000);
|
||||
ctx.sut.set_current_time(80000);
|
||||
@@ -258,7 +258,7 @@ TEST(MitsubishiCN105Tests, NextStatusUpdateAfterUpdateIntervalMilliseconds) {
|
||||
}
|
||||
|
||||
TEST(MitsubishiCN105Tests, DecodeStatusSettingsPackageTempEncodedA) {
|
||||
auto ctx = TestContext{};
|
||||
MitsubishiCN105TestsContext ctx;
|
||||
|
||||
ctx.uart.push_rx(
|
||||
{0xFC, 0x62, 0x01, 0x30, 0x0C, 0x02, 0x00, 0x00, 0x01, 0x03, 0x05, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x55});
|
||||
@@ -273,7 +273,7 @@ TEST(MitsubishiCN105Tests, DecodeStatusSettingsPackageTempEncodedA) {
|
||||
}
|
||||
|
||||
TEST(MitsubishiCN105Tests, DecodeStatusSettingsPackageTempEncodedB) {
|
||||
auto ctx = TestContext{};
|
||||
MitsubishiCN105TestsContext ctx;
|
||||
|
||||
ctx.uart.push_rx(
|
||||
{0xFC, 0x62, 0x01, 0x30, 0x0C, 0x02, 0x00, 0x00, 0x00, 0x07, 0x00, 0x06, 0x00, 0x00, 0x00, 0x00, 0xA5, 0xAD});
|
||||
@@ -288,7 +288,7 @@ TEST(MitsubishiCN105Tests, DecodeStatusSettingsPackageTempEncodedB) {
|
||||
}
|
||||
|
||||
TEST(MitsubishiCN105Tests, DecodeStatusRoomTempPackageTempEncodedA) {
|
||||
auto ctx = TestContext{};
|
||||
MitsubishiCN105TestsContext ctx;
|
||||
|
||||
ctx.uart.push_rx({0xFC, 0x62, 0x01, 0x30, 0x07, 0x03, 0x00, 0x00, 0x06, 0x00, 0x00, 0x00, 0x5D});
|
||||
|
||||
@@ -298,7 +298,7 @@ TEST(MitsubishiCN105Tests, DecodeStatusRoomTempPackageTempEncodedA) {
|
||||
}
|
||||
|
||||
TEST(MitsubishiCN105Tests, DecodeStatusRoomTempPackageTempEncodedB) {
|
||||
auto ctx = TestContext{};
|
||||
MitsubishiCN105TestsContext ctx;
|
||||
|
||||
ctx.uart.push_rx({0xFC, 0x62, 0x01, 0x30, 0x07, 0x03, 0x00, 0x00, 0x00, 0x00, 0x00, 0xBC, 0xA7});
|
||||
|
||||
@@ -308,7 +308,7 @@ TEST(MitsubishiCN105Tests, DecodeStatusRoomTempPackageTempEncodedB) {
|
||||
}
|
||||
|
||||
TEST(MitsubishiCN105Tests, DecodeWideVanePackageHighBitNotSet) {
|
||||
auto ctx = TestContext{};
|
||||
MitsubishiCN105TestsContext ctx;
|
||||
|
||||
ctx.uart.push_rx({0xFC, 0x62, 0x01, 0x30, 0x10, 0x02, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||
0x00, 0x00, 0x00, 0x00, 0x03, 0x00, 0x00, 0x00, 0x00, 0x00, 0x58});
|
||||
@@ -320,7 +320,7 @@ TEST(MitsubishiCN105Tests, DecodeWideVanePackageHighBitNotSet) {
|
||||
}
|
||||
|
||||
TEST(MitsubishiCN105Tests, DecodeWideVanePackageHighBitSet) {
|
||||
auto ctx = TestContext{};
|
||||
MitsubishiCN105TestsContext ctx;
|
||||
|
||||
ctx.uart.push_rx({0xFC, 0x62, 0x01, 0x30, 0x10, 0x02, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||
0x00, 0x00, 0x00, 0x00, 0x83, 0x00, 0x00, 0x00, 0x00, 0x00, 0xD8});
|
||||
@@ -332,7 +332,7 @@ TEST(MitsubishiCN105Tests, DecodeWideVanePackageHighBitSet) {
|
||||
}
|
||||
|
||||
TEST(MitsubishiCN105Tests, ApplySettingsPowerOn) {
|
||||
auto ctx = TestContext{};
|
||||
MitsubishiCN105TestsContext ctx;
|
||||
|
||||
ctx.sut.set_power(true);
|
||||
ctx.sut.apply_settings();
|
||||
@@ -342,7 +342,7 @@ TEST(MitsubishiCN105Tests, ApplySettingsPowerOn) {
|
||||
}
|
||||
|
||||
TEST(MitsubishiCN105Tests, ApplySettingsTemperatureEncodedA) {
|
||||
auto ctx = TestContext{};
|
||||
MitsubishiCN105TestsContext ctx;
|
||||
|
||||
ctx.sut.set_target_temperature(23.0f);
|
||||
ctx.sut.apply_settings();
|
||||
@@ -352,7 +352,7 @@ TEST(MitsubishiCN105Tests, ApplySettingsTemperatureEncodedA) {
|
||||
}
|
||||
|
||||
TEST(MitsubishiCN105Tests, ApplySettingsTemperatureEncodedB) {
|
||||
auto ctx = TestContext{};
|
||||
MitsubishiCN105TestsContext ctx;
|
||||
|
||||
ctx.sut.use_temperature_encoding_b_ = true;
|
||||
ctx.sut.set_target_temperature(26.0f);
|
||||
@@ -363,7 +363,7 @@ TEST(MitsubishiCN105Tests, ApplySettingsTemperatureEncodedB) {
|
||||
}
|
||||
|
||||
TEST(MitsubishiCN105Tests, ApplySettingsHalfDegreeTemperatureEncodedB) {
|
||||
auto ctx = TestContext{};
|
||||
MitsubishiCN105TestsContext ctx;
|
||||
|
||||
ctx.sut.use_temperature_encoding_b_ = true;
|
||||
ctx.sut.set_target_temperature(26.5f);
|
||||
@@ -374,7 +374,7 @@ TEST(MitsubishiCN105Tests, ApplySettingsHalfDegreeTemperatureEncodedB) {
|
||||
}
|
||||
|
||||
TEST(MitsubishiCN105Tests, ApplyModeCool) {
|
||||
auto ctx = TestContext{};
|
||||
MitsubishiCN105TestsContext ctx;
|
||||
|
||||
ctx.sut.set_mode(MitsubishiCN105::Mode::COOL);
|
||||
ctx.sut.apply_settings();
|
||||
@@ -384,7 +384,7 @@ TEST(MitsubishiCN105Tests, ApplyModeCool) {
|
||||
}
|
||||
|
||||
TEST(MitsubishiCN105Tests, ApplyFanModeSpeed1) {
|
||||
auto ctx = TestContext{};
|
||||
MitsubishiCN105TestsContext ctx;
|
||||
|
||||
ctx.sut.set_fan_mode(MitsubishiCN105::FanMode::SPEED_1);
|
||||
ctx.sut.apply_settings();
|
||||
@@ -394,7 +394,7 @@ TEST(MitsubishiCN105Tests, ApplyFanModeSpeed1) {
|
||||
}
|
||||
|
||||
TEST(MitsubishiCN105Tests, ApplyVaneModeSwing) {
|
||||
auto ctx = TestContext{};
|
||||
MitsubishiCN105TestsContext ctx;
|
||||
|
||||
ctx.sut.set_vane_mode(MitsubishiCN105::VaneMode::SWING);
|
||||
ctx.sut.apply_settings();
|
||||
@@ -404,7 +404,7 @@ TEST(MitsubishiCN105Tests, ApplyVaneModeSwing) {
|
||||
}
|
||||
|
||||
TEST(MitsubishiCN105Tests, ApplyWideVaneModeLeftAndHighBitNotSet) {
|
||||
auto ctx = TestContext{};
|
||||
MitsubishiCN105TestsContext ctx;
|
||||
|
||||
ctx.sut.set_wide_vane_mode(MitsubishiCN105::WideVaneMode::LEFT);
|
||||
ctx.sut.apply_settings();
|
||||
@@ -414,7 +414,7 @@ TEST(MitsubishiCN105Tests, ApplyWideVaneModeLeftAndHighBitNotSet) {
|
||||
}
|
||||
|
||||
TEST(MitsubishiCN105Tests, ApplyWideVaneModeLeftAndHighBitSet) {
|
||||
auto ctx = TestContext{};
|
||||
MitsubishiCN105TestsContext ctx;
|
||||
|
||||
ctx.sut.set_wide_vane_high_bit_ = true;
|
||||
ctx.sut.set_wide_vane_mode(MitsubishiCN105::WideVaneMode::LEFT);
|
||||
@@ -425,7 +425,7 @@ TEST(MitsubishiCN105Tests, ApplyWideVaneModeLeftAndHighBitSet) {
|
||||
}
|
||||
|
||||
TEST(MitsubishiCN105Tests, WriteInterruptsWaitingForNextStatusUpdate) {
|
||||
auto ctx = TestContext{};
|
||||
MitsubishiCN105TestsContext ctx;
|
||||
|
||||
ctx.sut.set_update_interval(2000);
|
||||
ctx.sut.set_current_time(5000);
|
||||
@@ -470,7 +470,7 @@ TEST(MitsubishiCN105Tests, WriteInterruptsWaitingForNextStatusUpdate) {
|
||||
}
|
||||
|
||||
TEST(MitsubishiCN105Tests, SetAndClearRemoteRoomTemp) {
|
||||
auto ctx = TestContext{};
|
||||
MitsubishiCN105TestsContext ctx;
|
||||
|
||||
// Set remote temperature
|
||||
ctx.sut.set_remote_temperature(28.5f);
|
||||
@@ -505,7 +505,7 @@ TEST(MitsubishiCN105Tests, SetAndClearRemoteRoomTemp) {
|
||||
}
|
||||
|
||||
TEST(MitsubishiCN105Tests, ApplyQueuedSettingsThenRemoteRoomTempInSecondWrite) {
|
||||
auto ctx = TestContext{};
|
||||
MitsubishiCN105TestsContext ctx;
|
||||
|
||||
// Queue normal settings plus remote temperature together.
|
||||
ctx.sut.use_temperature_encoding_b_ = true;
|
||||
@@ -545,7 +545,7 @@ TEST(MitsubishiCN105Tests, ApplyQueuedSettingsThenRemoteRoomTempInSecondWrite) {
|
||||
}
|
||||
|
||||
TEST(MitsubishiCN105Tests, WriteTimeoutClearsStatusUpdateWaitCreditOnReconnect) {
|
||||
auto ctx = TestContext{};
|
||||
MitsubishiCN105TestsContext ctx;
|
||||
ctx.sut.set_update_interval(2000);
|
||||
ctx.sut.set_current_time(5000);
|
||||
|
||||
@@ -578,7 +578,7 @@ TEST(MitsubishiCN105Tests, WriteTimeoutClearsStatusUpdateWaitCreditOnReconnect)
|
||||
}
|
||||
|
||||
TEST(MitsubishiCN105Tests, SetOutOfRangeRemoteRoomTempIsIgnored) {
|
||||
auto ctx = TestContext{};
|
||||
MitsubishiCN105TestsContext ctx;
|
||||
|
||||
ctx.sut.set_remote_temperature(7.0f);
|
||||
EXPECT_FALSE(ctx.sut.pending_updates_.contains(TestableMitsubishiCN105::UpdateFlag::REMOTE_TEMPERATURE));
|
||||
@@ -591,13 +591,13 @@ TEST(MitsubishiCN105Tests, SetOutOfRangeRemoteRoomTempIsIgnored) {
|
||||
}
|
||||
|
||||
TEST(MitsubishiCN105Tests, SetMinRemoteRoomTemp) {
|
||||
auto ctx = TestContext{};
|
||||
MitsubishiCN105TestsContext ctx;
|
||||
ctx.sut.set_remote_temperature(8.0f);
|
||||
EXPECT_TRUE(ctx.sut.pending_updates_.contains(TestableMitsubishiCN105::UpdateFlag::REMOTE_TEMPERATURE));
|
||||
}
|
||||
|
||||
TEST(MitsubishiCN105Tests, SetMaxRemoteRoomTemp) {
|
||||
auto ctx = TestContext{};
|
||||
MitsubishiCN105TestsContext ctx;
|
||||
ctx.sut.set_remote_temperature(39.5f);
|
||||
EXPECT_TRUE(ctx.sut.pending_updates_.contains(TestableMitsubishiCN105::UpdateFlag::REMOTE_TEMPERATURE));
|
||||
}
|
||||
|
||||
@@ -10,6 +10,12 @@ climate:
|
||||
name: "AC Test"
|
||||
supported_swing_modes: BOTH
|
||||
|
||||
select:
|
||||
- platform: mitsubishi_cn105
|
||||
mitsubishi_cn105_id: ac
|
||||
vertical_vane_direction:
|
||||
name: "Vertical Vane"
|
||||
|
||||
esphome:
|
||||
on_boot:
|
||||
then:
|
||||
|
||||
+111
@@ -0,0 +1,111 @@
|
||||
#include "../common.h"
|
||||
#include "esphome/components/mitsubishi_cn105/select/mitsubishi_cn105_vane_select_vertical.h"
|
||||
|
||||
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;
|
||||
};
|
||||
|
||||
struct VerticalVaneDirectionSelectTestContext {
|
||||
TestableMitsubishiCN105Component hub;
|
||||
TestableMitsubishiCN105VerticalVaneDirectionSelect select;
|
||||
|
||||
VerticalVaneDirectionSelectTestContext() {
|
||||
this->select.traits.set_options({"Auto", "1", "2", "3", "4", "5", "Swing"});
|
||||
this->select.set_parent(&this->hub);
|
||||
this->select.setup();
|
||||
}
|
||||
};
|
||||
|
||||
TEST(MitsubishiCN105VerticalVaneDirectionSelectTests, MapsIndexesToVaneModes) {
|
||||
VerticalVaneDirectionSelectTestContext ctx;
|
||||
|
||||
constexpr std::array expected_modes{
|
||||
MitsubishiCN105::VaneMode::AUTO, MitsubishiCN105::VaneMode::POSITION_1,
|
||||
MitsubishiCN105::VaneMode::POSITION_2, MitsubishiCN105::VaneMode::POSITION_3,
|
||||
MitsubishiCN105::VaneMode::POSITION_4, MitsubishiCN105::VaneMode::POSITION_5,
|
||||
MitsubishiCN105::VaneMode::SWING,
|
||||
};
|
||||
|
||||
for (size_t i = 0; i < expected_modes.size(); ++i) {
|
||||
SCOPED_TRACE(i);
|
||||
ctx.select.control(i);
|
||||
EXPECT_EQ(ctx.hub.status().vane_mode, expected_modes[i]);
|
||||
}
|
||||
}
|
||||
|
||||
TEST(MitsubishiCN105VerticalVaneDirectionSelectTests, PublishesIncomingVaneModes) {
|
||||
VerticalVaneDirectionSelectTestContext ctx;
|
||||
|
||||
constexpr std::array modes{
|
||||
MitsubishiCN105::VaneMode::AUTO, MitsubishiCN105::VaneMode::POSITION_1,
|
||||
MitsubishiCN105::VaneMode::POSITION_2, MitsubishiCN105::VaneMode::POSITION_3,
|
||||
MitsubishiCN105::VaneMode::POSITION_4, MitsubishiCN105::VaneMode::POSITION_5,
|
||||
MitsubishiCN105::VaneMode::SWING,
|
||||
};
|
||||
|
||||
for (size_t i = 0; i < modes.size(); ++i) {
|
||||
SCOPED_TRACE(i);
|
||||
ctx.hub.mutable_status().vane_mode = modes[i];
|
||||
ctx.hub.notify_status();
|
||||
EXPECT_EQ(ctx.select.active_index(), std::optional{i});
|
||||
}
|
||||
|
||||
ctx.hub.mutable_status().vane_mode = MitsubishiCN105::VaneMode::UNKNOWN;
|
||||
ctx.hub.notify_status();
|
||||
EXPECT_EQ(ctx.select.active_index(), std::optional{modes.size() - 1});
|
||||
}
|
||||
|
||||
TEST(MitsubishiCN105VerticalVaneDirectionSelectTests, ControlPublishesSelectAndClimateThroughHub) {
|
||||
VerticalVaneDirectionSelectTestContext ctx;
|
||||
MitsubishiCN105Climate climate_entity;
|
||||
climate_entity.set_parent(&ctx.hub);
|
||||
climate_entity.set_supported_swing_mode(climate::CLIMATE_SWING_VERTICAL);
|
||||
|
||||
ctx.hub.mutable_status().room_temperature = 20.0f;
|
||||
climate_entity.setup();
|
||||
|
||||
ctx.select.control(6);
|
||||
EXPECT_EQ(ctx.select.active_index(), std::optional<size_t>{6});
|
||||
EXPECT_EQ(climate_entity.swing_mode, climate::CLIMATE_SWING_VERTICAL);
|
||||
|
||||
ctx.select.control(3);
|
||||
EXPECT_EQ(ctx.select.active_index(), std::optional<size_t>{3});
|
||||
EXPECT_EQ(climate_entity.swing_mode, climate::CLIMATE_SWING_OFF);
|
||||
}
|
||||
|
||||
TEST(MitsubishiCN105VerticalVaneDirectionSelectTests, ClimateControlPublishesSelectThroughHub) {
|
||||
VerticalVaneDirectionSelectTestContext ctx;
|
||||
MitsubishiCN105Climate climate_entity;
|
||||
climate_entity.set_parent(&ctx.hub);
|
||||
climate_entity.set_supported_swing_mode(climate::CLIMATE_SWING_VERTICAL);
|
||||
|
||||
ctx.hub.mutable_status().room_temperature = 20.0f;
|
||||
climate_entity.setup();
|
||||
|
||||
climate_entity.make_call().set_swing_mode(climate::CLIMATE_SWING_VERTICAL).perform();
|
||||
EXPECT_EQ(ctx.select.active_index(), std::optional<size_t>{6});
|
||||
|
||||
climate_entity.make_call().set_swing_mode(climate::CLIMATE_SWING_OFF).perform();
|
||||
EXPECT_EQ(ctx.select.active_index(), std::optional<size_t>{0});
|
||||
}
|
||||
|
||||
TEST(MitsubishiCN105VerticalVaneDirectionSelectTests, BeforeInitializationDoesNotPublishSelectState) {
|
||||
VerticalVaneDirectionSelectTestContext ctx;
|
||||
|
||||
ctx.select.control(3);
|
||||
|
||||
EXPECT_EQ(ctx.hub.status().vane_mode, MitsubishiCN105::VaneMode::POSITION_3);
|
||||
EXPECT_FALSE(ctx.select.has_state());
|
||||
}
|
||||
|
||||
} // namespace esphome::mitsubishi_cn105::testing
|
||||
Reference in New Issue
Block a user