From 54d87ec8a913bd37cdfa5158fbfafba51d3fd568 Mon Sep 17 00:00:00 2001 From: Anton Tanasenko Date: Wed, 7 Feb 2024 16:49:53 +0200 Subject: [PATCH] Swing mode --- components/samsung_ac/converions.cpp | 33 +++++++++++++++++++++ components/samsung_ac/conversions.h | 3 ++ components/samsung_ac/protocol.h | 11 +++++++ components/samsung_ac/protocol_nasa.cpp | 25 ++++++++++++++++ components/samsung_ac/protocol_nasa.h | 3 ++ components/samsung_ac/protocol_non_nasa.cpp | 8 +++++ components/samsung_ac/protocol_non_nasa.h | 1 + components/samsung_ac/samsung_ac.h | 14 +++++++++ components/samsung_ac/samsung_ac_device.cpp | 19 ++++++++++++ components/samsung_ac/samsung_ac_device.h | 25 ++++++++++++++++ 10 files changed, 142 insertions(+) diff --git a/components/samsung_ac/converions.cpp b/components/samsung_ac/converions.cpp index 1968228f..a2894008 100644 --- a/components/samsung_ac/converions.cpp +++ b/components/samsung_ac/converions.cpp @@ -162,5 +162,38 @@ namespace esphome return ""; }; } + + climate::ClimateSwingMode swingmode_to_climateswingmode(SwingMode swingMode) + { + switch (swingMode) + { + case SwingMode::Horizontal: + return climate::ClimateSwingMode::CLIMATE_SWING_HORIZONTAL; + case SwingMode::Vertical: + return climate::ClimateSwingMode::CLIMATE_SWING_VERTICAL; + case SwingMode::All: + return climate::ClimateSwingMode::CLIMATE_SWING_BOTH; + case SwingMode::Fix: + default: + return climate::ClimateSwingMode::CLIMATE_SWING_OFF; + } + } + + SwingMode climateswingmode_to_swingmode(climate::ClimateSwingMode swingMode) + { + switch (swingMode) + { + case climate::ClimateSwingMode::CLIMATE_SWING_HORIZONTAL: + return SwingMode::Horizontal; + case climate::ClimateSwingMode::CLIMATE_SWING_VERTICAL: + return SwingMode::Vertical; + case climate::ClimateSwingMode::CLIMATE_SWING_BOTH: + return SwingMode::All; + case climate::ClimateSwingMode::CLIMATE_SWING_OFF: + default: + return SwingMode::Fix; + } + } + } // namespace samsung_ac } // namespace esphome diff --git a/components/samsung_ac/conversions.h b/components/samsung_ac/conversions.h index 06a73eca..fc1d85b7 100644 --- a/components/samsung_ac/conversions.h +++ b/components/samsung_ac/conversions.h @@ -22,5 +22,8 @@ namespace esphome AltMode preset_to_altmode(climate::ClimatePreset preset); AltMode custompreset_to_altmode(const std::string &value); + climate::ClimateSwingMode swingmode_to_climateswingmode(SwingMode swingMode); + SwingMode climateswingmode_to_swingmode(climate::ClimateSwingMode swingMode); + } // namespace samsung_ac } // namespace esphome diff --git a/components/samsung_ac/protocol.h b/components/samsung_ac/protocol.h index 7a8c6f3c..c6d20dd8 100644 --- a/components/samsung_ac/protocol.h +++ b/components/samsung_ac/protocol.h @@ -53,6 +53,14 @@ namespace esphome Windfree = 5 }; + enum class SwingMode : uint8_t + { + Fix = 0, + Vertical = 1, + Horizontal = 2, + All = 3 + }; + class MessageTarget { public: @@ -66,6 +74,8 @@ namespace esphome virtual void set_mode(const std::string address, Mode mode) = 0; virtual void set_fanmode(const std::string address, FanMode fanmode) = 0; virtual void set_altmode(const std::string address, AltMode fanmode) = 0; + virtual void set_swing_vertical(const std::string address, bool vertical) = 0; + virtual void set_swing_horizontal(const std::string address, bool horizontal) = 0; }; class Protocol @@ -76,6 +86,7 @@ namespace esphome virtual void publish_mode_message(MessageTarget *target, const std::string &address, Mode value) = 0; virtual void publish_fanmode_message(MessageTarget *target, const std::string &address, FanMode value) = 0; virtual void publish_altmode_message(MessageTarget *target, const std::string &address, AltMode value) = 0; + virtual void publish_swing_mode_message(MessageTarget *target, const std::string &address, SwingMode value) = 0; }; enum class DataResult diff --git a/components/samsung_ac/protocol_nasa.cpp b/components/samsung_ac/protocol_nasa.cpp index a305daa0..72776f1e 100644 --- a/components/samsung_ac/protocol_nasa.cpp +++ b/components/samsung_ac/protocol_nasa.cpp @@ -424,6 +424,19 @@ namespace esphome target->publish_data(data); } + void NasaProtocol::publish_swing_mode_message(MessageTarget *target, const std::string &address, SwingMode value) + { + auto packet = Packet::create(Address::parse(address), DataType::Request, MessageNumber::ENUM_in_louver_hl_swing, static_cast(value) & 1); + ESP_LOGW(TAG, "publish_swing_mode_message %s", packet.to_string().c_str()); + + MessageSet lr_swing(MessageNumber::ENUM_in_louver_lr_swing); + lr_swing.value = (static_cast(value) >> 1) & 1; + packet.messages.push_back(lr_swing); + + auto data = packet.encode(); + target->publish_data(data); + } + Mode operation_mode_to_mode(int value) { switch (value) @@ -575,6 +588,18 @@ namespace esphome target->set_altmode(source, altmode_to_nasa_altmode(message.value)); return; } + case MessageNumber::ENUM_in_louver_hl_swing: + { + ESP_LOGW(TAG, "s:%s d:%s ENUM_in_louver_hl_swing %li", source.c_str(), dest.c_str(), message.value); + target->set_swing_vertical(source, message.value == 1); + return; + } + case MessageNumber::ENUM_in_louver_lr_swing: + { + ESP_LOGW(TAG, "s:%s d:%s ENUM_in_louver_lr_swing %li", source.c_str(), dest.c_str(), message.value); + target->set_swing_horizontal(source, message.value == 1); + return; + } default: { // Test stuff diff --git a/components/samsung_ac/protocol_nasa.h b/components/samsung_ac/protocol_nasa.h index 67e13842..17f4d53f 100644 --- a/components/samsung_ac/protocol_nasa.h +++ b/components/samsung_ac/protocol_nasa.h @@ -75,6 +75,8 @@ namespace esphome ENUM_in_fan_mode = 0x4006, // Did not exists in xml...only in Remocon.dll code ENUM_in_fan_mode_real = 0x4007, ENUM_in_alt_mode = 0x4060, + ENUM_in_louver_hl_swing = 0x4011, + ENUM_in_louver_lr_swing = 0x407e, ENUM_in_state_humidity_percent = 0x4038, VAR_in_temp_room_f = 0x4203, VAR_in_temp_target_f = 0x4201, @@ -170,6 +172,7 @@ namespace esphome void publish_mode_message(MessageTarget *target, const std::string &address, Mode value) override; void publish_fanmode_message(MessageTarget *target, const std::string &address, FanMode value) override; void publish_altmode_message(MessageTarget *target, const std::string &address, AltMode value) override; + void publish_swing_mode_message(MessageTarget *target, const std::string &address, SwingMode value) override; }; } // namespace samsung_ac diff --git a/components/samsung_ac/protocol_non_nasa.cpp b/components/samsung_ac/protocol_non_nasa.cpp index 50e97a41..528cae2f 100644 --- a/components/samsung_ac/protocol_non_nasa.cpp +++ b/components/samsung_ac/protocol_non_nasa.cpp @@ -326,6 +326,11 @@ namespace esphome // TODO } + void NonNasaProtocol::publish_swing_mode_message(MessageTarget *target, const std::string &address, SwingMode value) + { + // TODO + } + Mode nonnasa_mode_to_mode(NonNasaMode value) { switch (value) @@ -387,6 +392,9 @@ namespace esphome target->set_fanmode(nonpacket_.src, nonnasa_fanspeed_to_fanmode(nonpacket_.command20.fanspeed)); // TODO target->set_altmode(nonpacket_.src, AltMode::None); + // TODO + target->set_swing_horizontal(nonpacket_.src, false); + target->set_swing_vertical(nonpacket_.src, false); } else if (nonpacket_.cmd == NonNasaCommand::CmdF8) { diff --git a/components/samsung_ac/protocol_non_nasa.h b/components/samsung_ac/protocol_non_nasa.h index 762fe3ef..7177e73f 100644 --- a/components/samsung_ac/protocol_non_nasa.h +++ b/components/samsung_ac/protocol_non_nasa.h @@ -147,6 +147,7 @@ namespace esphome void publish_mode_message(MessageTarget *target, const std::string &address, Mode value) override; void publish_fanmode_message(MessageTarget *target, const std::string &address, FanMode value) override; void publish_altmode_message(MessageTarget *target, const std::string &address, AltMode value) override; + void publish_swing_mode_message(MessageTarget *target, const std::string &address, SwingMode value) override; }; } // namespace samsung_ac } // namespace esphome diff --git a/components/samsung_ac/samsung_ac.h b/components/samsung_ac/samsung_ac.h index 3891510a..d6edb745 100644 --- a/components/samsung_ac/samsung_ac.h +++ b/components/samsung_ac/samsung_ac.h @@ -110,6 +110,20 @@ namespace esphome dev->publish_altmode(altmode); } + void /*MessageTarget::*/ set_swing_vertical(const std::string address, bool vertical) override + { + Samsung_AC_Device *dev = find_device(address); + if (dev != nullptr) + dev->publish_swing_vertical(vertical); + } + + void /*MessageTarget::*/ set_swing_horizontal(const std::string address, bool horizontal) override + { + Samsung_AC_Device *dev = find_device(address); + if (dev != nullptr) + dev->publish_swing_horizontal(horizontal); + } + protected: Samsung_AC_Device *find_device(const std::string address) { diff --git a/components/samsung_ac/samsung_ac_device.cpp b/components/samsung_ac/samsung_ac_device.cpp index 9da29cf1..5d9b6eb5 100644 --- a/components/samsung_ac/samsung_ac_device.cpp +++ b/components/samsung_ac/samsung_ac_device.cpp @@ -56,6 +56,13 @@ namespace esphome customPreset.insert("WindFree"); traits.set_supported_custom_presets(customPreset); + std::set swingMode; + swingMode.insert(climate::ClimateSwingMode::CLIMATE_SWING_OFF); + swingMode.insert(climate::ClimateSwingMode::CLIMATE_SWING_HORIZONTAL); + swingMode.insert(climate::ClimateSwingMode::CLIMATE_SWING_VERTICAL); + swingMode.insert(climate::ClimateSwingMode::CLIMATE_SWING_BOTH); + traits.set_supported_swing_modes(swingMode); + return traits; } @@ -97,6 +104,13 @@ namespace esphome { device->write_altmode(custompreset_to_altmode(customPresetOpt.value())); } + + auto swingModeOpt = call.get_swing_mode(); + if (swingModeOpt.has_value()) + { + device->write_swing_mode(climateswingmode_to_swingmode(swingModeOpt.value())); + } + } void Samsung_AC_Device::write_target_temperature(float value) @@ -119,6 +133,11 @@ namespace esphome protocol->publish_altmode_message(samsung_ac, address, value); } + void Samsung_AC_Device::write_swing_mode(SwingMode value) + { + protocol->publish_swing_mode_message(samsung_ac, address, value); + } + void Samsung_AC_Device::write_power(bool value) { protocol->publish_power_message(samsung_ac, address, value); diff --git a/components/samsung_ac/samsung_ac_device.h b/components/samsung_ac/samsung_ac_device.h index 65ea2022..6d5d3655 100644 --- a/components/samsung_ac/samsung_ac_device.h +++ b/components/samsung_ac/samsung_ac_device.h @@ -183,6 +183,30 @@ namespace esphome } } + void publish_swing_vertical(bool value) + { + if (climate != nullptr) + { + climate->swing_mode = combine(climate->swing_mode, 1, value); + climate->publish_state(); + } + } + + void publish_swing_horizontal(bool value) + { + if (climate != nullptr) + { + climate->swing_mode = combine(climate->swing_mode, 2, value); + climate->publish_state(); + } + } + + climate::ClimateSwingMode combine(climate::ClimateSwingMode climateSwingMode, uint8_t mask, bool value) + { + uint8_t swingMode = static_cast(climateswingmode_to_swingmode(climateSwingMode)); + return swingmode_to_climateswingmode(static_cast(value ? (swingMode | mask) : (swingMode & ~mask))); + } + void publish_room_temperature(float value) { if (room_temperature != nullptr) @@ -204,6 +228,7 @@ namespace esphome void write_mode(Mode value); void write_fanmode(FanMode value); void write_altmode(AltMode value); + void write_swing_mode(SwingMode value); void write_power(bool value); protected: