Skip to content

Commit

Permalink
Merge pull request #99 from atanasenko/config_alt_modes
Browse files Browse the repository at this point in the history
Allow configuring alt and swing modes
  • Loading branch information
lanwin authored Feb 19, 2024
2 parents 3589e33 + 102a957 commit ed3e90b
Show file tree
Hide file tree
Showing 8 changed files with 226 additions and 124 deletions.
83 changes: 83 additions & 0 deletions components/samsung_ac/__init__.py
Original file line number Diff line number Diff line change
Expand Up @@ -50,6 +50,13 @@

CONF_DEVICE_ID = "samsung_ac_device_id"
CONF_DEVICE_ADDRESS = "address"
CONF_CAPABILITIES = "capabilities"
CONF_HORIZONTAL_SWING = "horizontal_swing"
CONF_VERTICAL_SWING = "vertical_swing"
CONF_PRESETS = "presets"
CONF_PRESET_NAME = "name"
CONF_PRESET_ENABLED = "enabled"
CONF_PRESET_VALUE = "value"
CONF_DEVICE_ROOM_TEMPERATURE = "room_temperature"
CONF_DEVICE_TARGET_TEMPERATURE = "target_temperature"
CONF_DEVICE_OUTDOOR_TEMPERATURE = "outdoor_temperature"
Expand All @@ -63,6 +70,36 @@
CONF_DEVICE_ROOM_HUMIDITY = "room_humidity"
CONF_DEVICE_WATER_TEMPERATURE = "water_temperature"

def preset_entry(
name: str,
value: int,
displayName: str
): return (
cv.Optional(name, default=False), cv.Any(cv.boolean, cv.All({
cv.Optional(CONF_PRESET_ENABLED, default=False): cv.boolean,
cv.Optional(CONF_PRESET_NAME, default=displayName): cv.string,
cv.Optional(CONF_PRESET_VALUE, default=value): cv.int_
}))
)

PRESETS = {
"sleep": {"value": 1, "displayName": "Sleep"},
"quiet": {"value": 2, "displayName": "Quiet"},
"fast": {"value": 3, "displayName": "Fast"},
"longreach": {"value": 6, "displayName": "LongReach"},
"windfree": {"value": 9, "displayName": "WindFree"},
}

CAPABILITIES_SCHEMA = (
cv.Schema({
cv.Optional(CONF_HORIZONTAL_SWING, default=False): cv.boolean,
cv.Optional(CONF_VERTICAL_SWING, default=False): cv.boolean,
cv.Optional(CONF_PRESETS): cv.Schema(dict(
[preset_entry(name, PRESETS[name]["value"], PRESETS[name]["displayName"]) for name in PRESETS]
))
})
)

CUSTOM_SENSOR_SCHEMA = sensor.sensor_schema().extend({
cv.Required(CONF_DEVICE_MESSAGE): cv.hex_int,
})
Expand Down Expand Up @@ -115,6 +152,7 @@ def humidity_sensor_schema(message: int):
cv.Schema(
{
cv.GenerateID(CONF_DEVICE_ID): cv.declare_id(Samsung_AC_Device),
cv.Optional(CONF_CAPABILITIES): CAPABILITIES_SCHEMA,
cv.Required(CONF_DEVICE_ADDRESS): cv.string,
cv.Optional(CONF_DEVICE_ROOM_TEMPERATURE): sensor.sensor_schema(
unit_of_measurement=UNIT_CELSIUS,
Expand Down Expand Up @@ -168,6 +206,7 @@ def humidity_sensor_schema(message: int):
cv.Optional(CONF_DEBUG_MQTT_PASSWORD, default=""): cv.string,
cv.Optional(CONF_DEBUG_LOG_MESSAGES, default=False): cv.boolean,
cv.Optional(CONF_DEBUG_LOG_MESSAGES_RAW, default=False): cv.boolean,
cv.Optional(CONF_CAPABILITIES): CAPABILITIES_SCHEMA,
cv.Required(CONF_DEVICES): cv.ensure_list(DEVICE_SCHEMA),
}
)
Expand All @@ -186,6 +225,50 @@ async def to_code(config):
var_dev = cg.new_Pvariable(
device[CONF_DEVICE_ID], device[CONF_DEVICE_ADDRESS], var)

# setup capabilities
if CONF_CAPABILITIES in device and CONF_VERTICAL_SWING in device[CONF_CAPABILITIES]:
cg.add(var_dev.set_supports_vertical_swing(device[CONF_CAPABILITIES][CONF_VERTICAL_SWING]))
elif CONF_CAPABILITIES in config and CONF_VERTICAL_SWING in config[CONF_CAPABILITIES]:
cg.add(var_dev.set_supports_vertical_swing(config[CONF_CAPABILITIES][CONF_VERTICAL_SWING]))

if CONF_CAPABILITIES in device and CONF_HORIZONTAL_SWING in device[CONF_CAPABILITIES]:
cg.add(var_dev.set_supports_horizontal_swing(device[CONF_CAPABILITIES][CONF_HORIZONTAL_SWING]))
elif CONF_CAPABILITIES in config and CONF_HORIZONTAL_SWING in config[CONF_CAPABILITIES]:
cg.add(var_dev.set_supports_horizontal_swing(config[CONF_CAPABILITIES][CONF_HORIZONTAL_SWING]))


none_added = False
for preset in PRESETS:
device_preset_conf = device[CONF_CAPABILITIES][CONF_PRESETS][preset] if (
CONF_CAPABILITIES in device
and CONF_PRESETS in device[CONF_CAPABILITIES]
and preset in device[CONF_CAPABILITIES][CONF_PRESETS]) else None
global_preset_conf = config[CONF_CAPABILITIES][CONF_PRESETS][preset] if (
CONF_CAPABILITIES in config
and CONF_PRESETS in config[CONF_CAPABILITIES]
and preset in config[CONF_CAPABILITIES][CONF_PRESETS]) else None

preset_conf = global_preset_conf if device_preset_conf is None else device_preset_conf
preset_dict = isinstance(preset_conf, dict)
if preset_conf == True or (preset_dict and preset_conf[CONF_PRESET_ENABLED] == True):
if not none_added:
none_added = True
cg.add(var_dev.add_alt_mode("None", 0))

cg.add(var_dev.add_alt_mode(
preset_conf[CONF_PRESET_NAME] if preset_dict and CONF_PRESET_NAME in preset_conf else PRESETS[preset]["displayName"],
preset_conf[CONF_PRESET_VALUE] if preset_dict and CONF_PRESET_VALUE in preset_conf else PRESETS[preset]["value"]
))

# if CONF_CAPABILITIES in device and CONF_ALT_MODES in device[CONF_CAPABILITIES]:
# cg.add(var_dev.add_alt_mode("None", 0))
# for alt in device[CONF_CAPABILITIES][CONF_ALT_MODES]:
# cg.add(var_dev.add_alt_mode(alt[CONF_ALT_MODE_NAME], alt[CONF_ALT_MODE_VALUE]))
# elif CONF_CAPABILITIES in config and CONF_ALT_MODES in config[CONF_CAPABILITIES]:
# cg.add(var_dev.add_alt_mode("None", 0))
# for alt in config[CONF_CAPABILITIES][CONF_ALT_MODES]:
# cg.add(var_dev.add_alt_mode(alt[CONF_ALT_MODE_NAME], alt[CONF_ALT_MODE_VALUE]))

if CONF_DEVICE_POWER in device:
conf = device[CONF_DEVICE_POWER]
sens = await switch.new_switch(conf)
Expand Down
76 changes: 33 additions & 43 deletions components/samsung_ac/conversions.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -128,59 +128,49 @@ namespace esphome
return FanMode::Auto;
}

AltMode preset_to_altmode(climate::ClimatePreset preset)
AltModeName preset_to_altmodename(climate::ClimatePreset preset)
{
switch (preset)
{
case climate::ClimatePreset::CLIMATE_PRESET_ECO:
return "Eco";
case climate::ClimatePreset::CLIMATE_PRESET_AWAY:
return "Away";
case climate::ClimatePreset::CLIMATE_PRESET_BOOST:
return "Boost";
case climate::ClimatePreset::CLIMATE_PRESET_COMFORT:
return "Comfort";
case climate::ClimatePreset::CLIMATE_PRESET_HOME:
return "Home";
case climate::ClimatePreset::CLIMATE_PRESET_SLEEP:
return AltMode::Sleep;
return "Sleep";
case climate::ClimatePreset::CLIMATE_PRESET_ACTIVITY:
return "Activity";
case climate::ClimatePreset::CLIMATE_PRESET_NONE:
default:
return AltMode::None;
return "None";
}
}

AltMode custompreset_to_altmode(const std::string &value)
optional<climate::ClimatePreset> altmodename_to_preset(const AltModeName& name)
{
if (value == "Quiet")
return AltMode::Quiet;
if (value == "Fast")
return AltMode::Fast;
if (value == "Long Reach")
return AltMode::LongReach;
if (value == "WindFree")
return AltMode::Windfree;
return AltMode::Unknown;
}

optional<climate::ClimatePreset> altmode_to_preset(AltMode mode)
{
switch (mode)
{
case AltMode::None:
return climate::ClimatePreset::CLIMATE_PRESET_NONE;
case AltMode::Sleep:
return climate::ClimatePreset::CLIMATE_PRESET_SLEEP;
default:
return nullopt;
};
}

std::string altmode_to_custompreset(AltMode mode)
{
switch (mode)
{
case AltMode::Quiet:
return "Quiet";
case AltMode::Fast:
return "Fast";
case AltMode::LongReach:
return "Long Reach";
case AltMode::Windfree:
return "WindFree";
default:
return "";
};
if (str_equals_case_insensitive(name, "ECO"))
return optional<climate::ClimatePreset>(climate::CLIMATE_PRESET_ECO);
if (str_equals_case_insensitive(name, "AWAY"))
return optional<climate::ClimatePreset>(climate::CLIMATE_PRESET_AWAY);
if (str_equals_case_insensitive(name, "BOOST"))
return optional<climate::ClimatePreset>(climate::CLIMATE_PRESET_BOOST);
if (str_equals_case_insensitive(name, "COMFORT"))
return optional<climate::ClimatePreset>(climate::CLIMATE_PRESET_COMFORT);
if (str_equals_case_insensitive(name, "HOME"))
return optional<climate::ClimatePreset>(climate::CLIMATE_PRESET_HOME);
if (str_equals_case_insensitive(name, "SLEEP"))
return optional<climate::ClimatePreset>(climate::CLIMATE_PRESET_SLEEP);
if (str_equals_case_insensitive(name, "ACTIVITY"))
return optional<climate::ClimatePreset>(climate::CLIMATE_PRESET_ACTIVITY);
if (str_equals_case_insensitive(name, "NONE"))
return optional<climate::ClimatePreset>(climate::CLIMATE_PRESET_NONE);
return nullopt;
}

climate::ClimateSwingMode swingmode_to_climateswingmode(SwingMode swingMode)
Expand Down
6 changes: 2 additions & 4 deletions components/samsung_ac/conversions.h
Original file line number Diff line number Diff line change
Expand Up @@ -19,10 +19,8 @@ namespace esphome
FanMode climatefanmode_to_fanmode(climate::ClimateFanMode fanmode);
FanMode customfanmode_to_fanmode(const std::string &value);

optional<climate::ClimatePreset> altmode_to_preset(AltMode mode);
std::string altmode_to_custompreset(AltMode mode);
AltMode preset_to_altmode(climate::ClimatePreset preset);
AltMode custompreset_to_altmode(const std::string &value);
AltModeName preset_to_altmodename(climate::ClimatePreset preset);
optional<climate::ClimatePreset> altmodename_to_preset(const AltModeName& name);

climate::ClimateSwingMode swingmode_to_climateswingmode(SwingMode swingMode);
SwingMode climateswingmode_to_swingmode(climate::ClimateSwingMode swingMode);
Expand Down
16 changes: 7 additions & 9 deletions components/samsung_ac/protocol.h
Original file line number Diff line number Diff line change
Expand Up @@ -42,15 +42,13 @@ namespace esphome
Off = 5
};

enum class AltMode
typedef std::string AltModeName;
typedef uint8_t AltMode;

struct AltModeDesc
{
Unknown = -1,
None = 0,
Sleep = 1,
Quiet = 2,
Fast = 3,
LongReach = 4,
Windfree = 5
AltModeName name;
AltMode value;
};

enum class SwingMode : uint8_t
Expand All @@ -73,7 +71,7 @@ namespace esphome
virtual void set_outdoor_temperature(const std::string address, float value) = 0;
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_altmode(const std::string address, AltMode altmode) = 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;
virtual optional<std::set<uint16_t>> get_custom_sensors(const std::string address) = 0;
Expand Down
45 changes: 2 additions & 43 deletions components/samsung_ac/protocol_nasa.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -367,26 +367,6 @@ namespace esphome
}
}

int altmode_to_nasa_altmode(AltMode mode)
{
switch (mode)
{
case AltMode::Sleep:
return 1;
case AltMode::Quiet:
return 2;
case AltMode::Fast:
return 3;
case AltMode::LongReach:
return 6;
case AltMode::Windfree:
return 9;
case AltMode::None:
default:
return 0;
}
}

void NasaProtocol::publish_request(MessageTarget *target, const std::string &address, ProtocolRequest &request)
{
Packet packet = Packet::createa_partial(Address::parse(address), DataType::Request);
Expand Down Expand Up @@ -424,7 +404,7 @@ namespace esphome
if (request.alt_mode)
{
MessageSet altmode(MessageNumber::ENUM_in_alt_mode);
altmode.value = altmode_to_nasa_altmode(request.alt_mode.value());
altmode.value = request.alt_mode.value();
packet.messages.push_back(altmode);
}

Expand Down Expand Up @@ -501,27 +481,6 @@ namespace esphome
}
}

AltMode altmode_to_nasa_altmode(int value)
{
switch (value)
{
case 0:
return AltMode::None;
case 1:
return AltMode::Sleep;
case 2:
return AltMode::Quiet;
case 3:
return AltMode::Fast;
case 6:
return AltMode::LongReach;
case 9:
return AltMode::Windfree;
default:
return AltMode::Unknown;
}
}

void process_messageset(std::string source, std::string dest, MessageSet &message, optional<std::set<uint16_t>> &custom, MessageTarget *target)
{
if (debug_mqtt_connected())
Expand Down Expand Up @@ -605,7 +564,7 @@ namespace esphome
case MessageNumber::ENUM_in_alt_mode:
{
ESP_LOGW(TAG, "s:%s d:%s ENUM_in_alt_mode %li", source.c_str(), dest.c_str(), message.value);
target->set_altmode(source, altmode_to_nasa_altmode(message.value));
target->set_altmode(source, message.value);
return;
}
case MessageNumber::ENUM_in_louver_hl_swing:
Expand Down
2 changes: 1 addition & 1 deletion components/samsung_ac/protocol_non_nasa.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -497,7 +497,7 @@ namespace esphome
target->set_mode(nonpacket_.src, nonnasa_mode_to_mode(nonpacket_.command20.mode));
target->set_fanmode(nonpacket_.src, nonnasa_fanspeed_to_fanmode(nonpacket_.command20.fanspeed));
// TODO
target->set_altmode(nonpacket_.src, AltMode::None);
target->set_altmode(nonpacket_.src, 0);
// TODO
target->set_swing_horizontal(nonpacket_.src, false);
target->set_swing_vertical(nonpacket_.src, false);
Expand Down
Loading

0 comments on commit ed3e90b

Please sign in to comment.