diff --git a/components/samsung_ac/__init__.py b/components/samsung_ac/__init__.py index 8894100..29f70a9 100644 --- a/components/samsung_ac/__init__.py +++ b/components/samsung_ac/__init__.py @@ -55,9 +55,12 @@ CONF_DEVICE_TARGET_TEMPERATURE = "target_temperature" CONF_DEVICE_WATER_OUTLET_TARGET = "water_outlet_target" CONF_DEVICE_OUTDOOR_TEMPERATURE = "outdoor_temperature" +CONF_DEVICE_INDOOR_EVA_IN_TEMPERATURE = "indoor_eva_in_temperature" +CONF_DEVICE_INDOOR_EVA_OUT_TEMPERATURE = "indoor_eva_out_temperature" CONF_DEVICE_WATER_TEMPERATURE = "water_temperature" CONF_DEVICE_WATER_TARGET_TEMPERATURE = "water_target_temperature" CONF_DEVICE_POWER = "power" +CONF_DEVICE_AUTOMATIC_CLEANING = "automatic_cleaning" CONF_DEVICE_WATER_HEATER_POWER = "water_heater_power" CONF_DEVICE_MODE = "mode" CONF_DEVICE_CLIMATE = "climate" @@ -178,11 +181,24 @@ def humidity_sensor_schema(message: int): accuracy_decimals=1, device_class=DEVICE_CLASS_TEMPERATURE, state_class=STATE_CLASS_MEASUREMENT, + ), + cv.Optional(CONF_DEVICE_INDOOR_EVA_IN_TEMPERATURE): sensor.sensor_schema( + unit_of_measurement=UNIT_CELSIUS, + accuracy_decimals=1, + device_class=DEVICE_CLASS_TEMPERATURE, + state_class=STATE_CLASS_MEASUREMENT, + ), + cv.Optional(CONF_DEVICE_INDOOR_EVA_OUT_TEMPERATURE): sensor.sensor_schema( + unit_of_measurement=UNIT_CELSIUS, + accuracy_decimals=1, + device_class=DEVICE_CLASS_TEMPERATURE, + state_class=STATE_CLASS_MEASUREMENT, ), cv.Optional(CONF_DEVICE_TARGET_TEMPERATURE): NUMBER_SCHEMA, cv.Optional(CONF_DEVICE_WATER_OUTLET_TARGET): NUMBER_SCHEMA, cv.Optional(CONF_DEVICE_WATER_TARGET_TEMPERATURE): NUMBER_SCHEMA, cv.Optional(CONF_DEVICE_POWER): switch.switch_schema(Samsung_AC_Switch), + cv.Optional(CONF_DEVICE_AUTOMATIC_CLEANING): switch.switch_schema(Samsung_AC_Switch), cv.Optional(CONF_DEVICE_WATER_HEATER_POWER): switch.switch_schema(Samsung_AC_Switch), cv.Optional(CONF_DEVICE_MODE): SELECT_MODE_SCHEMA, cv.Optional(CONF_DEVICE_CLIMATE): CLIMATE_SCHEMA, @@ -212,6 +228,9 @@ def humidity_sensor_schema(message: int): CONF_NON_NASA_KEEPALIVE = "non_nasa_keepalive" +CONF_DEBUG_LOG_UNDEFINED_MESSAGES = "debug_log_undefined_messages" + + CONFIG_SCHEMA = ( cv.Schema( { @@ -224,6 +243,7 @@ def humidity_sensor_schema(message: int): cv.Optional(CONF_DEBUG_LOG_MESSAGES, default=False): cv.boolean, cv.Optional(CONF_DEBUG_LOG_MESSAGES_RAW, default=False): cv.boolean, cv.Optional(CONF_NON_NASA_KEEPALIVE, default=False): cv.boolean, + cv.Optional(CONF_DEBUG_LOG_UNDEFINED_MESSAGES, default=False): cv.boolean, cv.Optional(CONF_CAPABILITIES): CAPABILITIES_SCHEMA, cv.Required(CONF_DEVICES): cv.ensure_list(DEVICE_SCHEMA), } @@ -295,6 +315,11 @@ async def to_code(config): sens = await switch.new_switch(conf) cg.add(var_dev.set_power_switch(sens)) + if CONF_DEVICE_AUTOMATIC_CLEANING in device: + conf = device[CONF_DEVICE_AUTOMATIC_CLEANING] + sens = await switch.new_switch(conf) + cg.add(var_dev.set_automatic_cleaning_switch(sens)) + if CONF_DEVICE_WATER_HEATER_POWER in device: conf = device[CONF_DEVICE_WATER_HEATER_POWER] sens = await switch.new_switch(conf) @@ -313,6 +338,16 @@ async def to_code(config): conf = device[CONF_DEVICE_OUTDOOR_TEMPERATURE] sens = await sensor.new_sensor(conf) cg.add(var_dev.set_outdoor_temperature_sensor(sens)) + + if CONF_DEVICE_INDOOR_EVA_IN_TEMPERATURE in device: + conf = device[CONF_DEVICE_INDOOR_EVA_IN_TEMPERATURE] + sens = await sensor.new_sensor(conf) + cg.add(var_dev.set_indoor_eva_in_temperature_sensor(sens)) + + if CONF_DEVICE_INDOOR_EVA_OUT_TEMPERATURE in device: + conf = device[CONF_DEVICE_INDOOR_EVA_OUT_TEMPERATURE] + sens = await sensor.new_sensor(conf) + cg.add(var_dev.set_indoor_eva_out_temperature_sensor(sens)) if CONF_DEVICE_WATER_TARGET_TEMPERATURE in device: conf = device[CONF_DEVICE_WATER_TARGET_TEMPERATURE] @@ -387,6 +422,9 @@ async def to_code(config): if (CONF_NON_NASA_KEEPALIVE in config): cg.add(var.set_non_nasa_keepalive(config[CONF_NON_NASA_KEEPALIVE])) + + if (CONF_DEBUG_LOG_UNDEFINED_MESSAGES in config): + cg.add(var.set_debug_log_undefined_messages(config[CONF_DEBUG_LOG_UNDEFINED_MESSAGES])) await cg.register_component(var, config) await uart.register_uart_device(var, config) diff --git a/components/samsung_ac/conversions.cpp b/components/samsung_ac/conversions.cpp index ba6ee24..518cfe8 100644 --- a/components/samsung_ac/conversions.cpp +++ b/components/samsung_ac/conversions.cpp @@ -152,7 +152,7 @@ namespace esphome } } - optional altmodename_to_preset(const AltModeName& name) + optional altmodename_to_preset(const AltModeName &name) { if (str_equals_case_insensitive(name, "ECO")) return optional(climate::CLIMATE_PRESET_ECO); diff --git a/components/samsung_ac/conversions.h b/components/samsung_ac/conversions.h index 8bfb621..050cc88 100644 --- a/components/samsung_ac/conversions.h +++ b/components/samsung_ac/conversions.h @@ -20,7 +20,7 @@ namespace esphome FanMode customfanmode_to_fanmode(const std::string &value); AltModeName preset_to_altmodename(climate::ClimatePreset preset); - optional altmodename_to_preset(const AltModeName& name); + optional altmodename_to_preset(const AltModeName &name); climate::ClimateSwingMode swingmode_to_climateswingmode(SwingMode swingMode); SwingMode climateswingmode_to_swingmode(climate::ClimateSwingMode swingMode); diff --git a/components/samsung_ac/protocol.cpp b/components/samsung_ac/protocol.cpp index dbd67ba..676a052 100644 --- a/components/samsung_ac/protocol.cpp +++ b/components/samsung_ac/protocol.cpp @@ -8,9 +8,11 @@ namespace esphome { namespace samsung_ac { - bool debug_log_packets = false; + //bool debug_log_packets = false; bool debug_log_raw_bytes = false; bool non_nasa_keepalive = false; + bool debug_log_undefined_messages = false; + bool debug_log_messages = false; ProtocolProcessing protocol_processing = ProtocolProcessing::Auto; // This functions is designed to run after a new value was added diff --git a/components/samsung_ac/protocol.h b/components/samsung_ac/protocol.h index 0ed552c..4f21ebd 100644 --- a/components/samsung_ac/protocol.h +++ b/components/samsung_ac/protocol.h @@ -8,9 +8,11 @@ namespace esphome { namespace samsung_ac { - extern bool debug_log_packets; + //extern bool debug_log_packets; extern bool debug_log_raw_bytes; extern bool non_nasa_keepalive; + extern bool debug_log_undefined_messages; + extern bool debug_log_messages; enum class DecodeResult { @@ -67,11 +69,14 @@ namespace esphome virtual void publish_data(std::vector &data) = 0; virtual void register_address(const std::string address) = 0; virtual void set_power(const std::string address, bool value) = 0; + virtual void set_automatic_cleaning(const std::string address, bool value) = 0; virtual void set_water_heater_power(const std::string address, bool value) = 0; virtual void set_room_temperature(const std::string address, float value) = 0; virtual void set_target_temperature(const std::string address, float value) = 0; virtual void set_water_outlet_target(const std::string address, float value) = 0; virtual void set_outdoor_temperature(const std::string address, float value) = 0; + virtual void set_indoor_eva_in_temperature(const std::string address, float value) = 0; + virtual void set_indoor_eva_out_temperature(const std::string address, float value) = 0; virtual void set_target_water_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; @@ -86,6 +91,7 @@ namespace esphome { public: optional power; + optional automatic_cleaning; optional water_heater_power; optional mode; optional target_temp; diff --git a/components/samsung_ac/protocol_nasa.cpp b/components/samsung_ac/protocol_nasa.cpp index 06a12cf..11ce6ef 100644 --- a/components/samsung_ac/protocol_nasa.cpp +++ b/components/samsung_ac/protocol_nasa.cpp @@ -387,6 +387,13 @@ namespace esphome packet.messages.push_back(power); } + if (request.automatic_cleaning) + { + MessageSet automatic_cleaning(MessageNumber::ENUM_in_operation_automatic_cleaning); + automatic_cleaning.value = request.automatic_cleaning.value() ? 1 : 0; + packet.messages.push_back(automatic_cleaning); + } + if (request.water_heater_power) { MessageSet waterheaterpower(MessageNumber::ENUM_in_water_heater_power); @@ -400,14 +407,14 @@ namespace esphome targettemp.value = request.target_temp.value() * 10.0; packet.messages.push_back(targettemp); } - + if (request.water_outlet_target) { MessageSet wateroutlettarget(MessageNumber::VAR_in_temp_water_outlet_target_f); wateroutlettarget.value = request.water_outlet_target.value() * 10.0; packet.messages.push_back(wateroutlettarget); } - + if (request.target_water_temp) { MessageSet targetwatertemp(MessageNumber::VAR_in_temp_water_heater_target_f); @@ -506,17 +513,23 @@ namespace esphome { if (debug_mqtt_connected()) { - if (message.type == MessageSetType::Enum) - { - debug_mqtt_publish("samsung_ac/nasa/enum/" + long_to_hex((uint16_t)message.messageNumber), std::to_string(message.value)); - } - else if (message.type == MessageSetType::Variable) - { - debug_mqtt_publish("samsung_ac/nasa/var/" + long_to_hex((uint16_t)message.messageNumber), std::to_string(message.value)); - } - else if (message.type == MessageSetType::LongVariable) + std::string topic_prefix = "samsung_ac/nasa/"; + std::string topic_suffix = long_to_hex((uint16_t)message.messageNumber); + std::string payload = std::to_string(message.value); + + switch (message.type) { - debug_mqtt_publish("samsung_ac/nasa/var_long/" + long_to_hex((uint16_t)message.messageNumber), std::to_string(message.value)); + case MessageSetType::Enum: + debug_mqtt_publish(topic_prefix + "enum/" + topic_suffix, payload); + break; + case MessageSetType::Variable: + debug_mqtt_publish(topic_prefix + "var/" + topic_suffix, payload); + break; + case MessageSetType::LongVariable: + debug_mqtt_publish(topic_prefix + "var_long/" + topic_suffix, payload); + break; + default: + break; } } @@ -527,181 +540,157 @@ namespace esphome switch (message.messageNumber) { - case MessageNumber::VAR_in_temp_room_f: // unit = 'Celsius' from XML + case MessageNumber::VAR_in_temp_room_f: { - double temp = (double)message.value / (double)10; - ESP_LOGW(TAG, "s:%s d:%s VAR_in_temp_room_f %f", source.c_str(), dest.c_str(), temp); + double temp = message.value / 10.0; + if (debug_log_messages) + { + ESP_LOGW(TAG, "s:%s d:%s VAR_in_temp_room_f %f", source.c_str(), dest.c_str(), temp); + } target->set_room_temperature(source, temp); - return; + break; } - case MessageNumber::VAR_in_temp_target_f: // unit = 'Celsius' from XML + case MessageNumber::VAR_in_temp_target_f: { - double temp = (double)message.value / (double)10; - // if (value == 1) value = 'waterOutSetTemp'; //action in xml - ESP_LOGW(TAG, "s:%s d:%s VAR_in_temp_target_f %f", source.c_str(), dest.c_str(), temp); + double temp = message.value / 10.0; + if (debug_log_messages) + { + ESP_LOGW(TAG, "s:%s d:%s VAR_in_temp_target_f %f", source.c_str(), dest.c_str(), temp); + } target->set_target_temperature(source, temp); - return; + break; } - case MessageNumber::VAR_in_temp_water_outlet_target_f: // unit = 'Celsius' from XML + case MessageNumber::VAR_in_temp_water_outlet_target_f: { - double temp = (double)message.value / (double)10; - ESP_LOGW(TAG, "s:%s d:%s VAR_in_temp_water_outlet_target_f %f", source.c_str(), dest.c_str(), temp); + double temp = message.value / 10.0; + if (debug_log_messages) + { + ESP_LOGW(TAG, "s:%s d:%s VAR_in_temp_water_outlet_target_f %f", source.c_str(), dest.c_str(), temp); + } target->set_water_outlet_target(source, temp); - return; + break; } - case MessageNumber::VAR_in_temp_water_heater_target_f: // unit = 'Celsius' from XML + case MessageNumber::VAR_in_temp_water_heater_target_f: { - double temp = (double)message.value / (double)10; - ESP_LOGW(TAG, "s:%s d:%s VAR_in_temp_water_heater_target_f %f", source.c_str(), dest.c_str(), temp); + double temp = message.value / 10.0; + if (debug_log_messages) + { + ESP_LOGW(TAG, "s:%s d:%s VAR_in_temp_water_heater_target_f %f", source.c_str(), dest.c_str(), temp); + } target->set_target_water_temperature(source, temp); - return; + break; } case MessageNumber::ENUM_in_state_humidity_percent: - { - // XML Enum no value but in Code it adds unit - ESP_LOGW(TAG, "s:%s d:%s ENUM_in_state_humidity_percent %li", source.c_str(), dest.c_str(), message.value); - return; - } + if (debug_log_messages) + { + ESP_LOGW(TAG, "s:%s d:%s ENUM_in_state_humidity_percent %li", source.c_str(), dest.c_str(), message.value); + } + break; case MessageNumber::ENUM_in_operation_power: - { - ESP_LOGW(TAG, "s:%s d:%s ENUM_in_operation_power %s", source.c_str(), dest.c_str(), message.value == 0 ? "off" : "on"); + if (debug_log_messages) + { + ESP_LOGW(TAG, "s:%s d:%s ENUM_in_operation_power %s", source.c_str(), dest.c_str(), message.value == 0 ? "off" : "on"); + } target->set_power(source, message.value != 0); - return; - } + break; + case MessageNumber::ENUM_in_operation_automatic_cleaning: + if (debug_log_messages) + { + ESP_LOGW(TAG, "s:%s d:%s ENUM_in_operation_automatic_cleaning %s", source.c_str(), dest.c_str(), message.value == 0 ? "off" : "on"); + } + target->set_automatic_cleaning(source, message.value != 0); + break; case MessageNumber::ENUM_in_water_heater_power: - { - ESP_LOGW(TAG, "s:%s d:%s ENUM_in_water_heater_power %s", source.c_str(), dest.c_str(), message.value == 0 ? "off" : "on"); + if (debug_log_messages) + { + ESP_LOGW(TAG, "s:%s d:%s ENUM_in_water_heater_power %s", source.c_str(), dest.c_str(), message.value == 0 ? "off" : "on"); + } target->set_water_heater_power(source, message.value != 0); - return; - } + break; case MessageNumber::ENUM_in_operation_mode: - { - ESP_LOGW(TAG, "s:%s d:%s ENUM_in_operation_mode %li", source.c_str(), dest.c_str(), message.value); + if (debug_log_messages) + { + ESP_LOGW(TAG, "s:%s d:%s ENUM_in_operation_mode %li", source.c_str(), dest.c_str(), message.value); + } target->set_mode(source, operation_mode_to_mode(message.value)); - return; - } + break; case MessageNumber::ENUM_in_fan_mode: - { - ESP_LOGW(TAG, "s:%s d:%s ENUM_in_fan_mode %li", source.c_str(), dest.c_str(), message.value); - FanMode mode = FanMode::Unknown; - if (message.value == 0) - mode = FanMode::Auto; - else if (message.value == 1) - mode = FanMode::Low; - else if (message.value == 2) - mode = FanMode::Mid; - else if (message.value == 3) - mode = FanMode::High; - else if (message.value == 4) - mode = FanMode::Turbo; - target->set_fanmode(source, mode); - return; - } - case MessageNumber::ENUM_in_fan_mode_real: - { - ESP_LOGW(TAG, "s:%s d:%s ENUM_in_fan_mode_real %li", source.c_str(), dest.c_str(), message.value); - return; - } - 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, 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; - } - case MessageNumber::VAR_in_temp_water_tank_f: - { - ESP_LOGW(TAG, "s:%s d:%s VAR_in_temp_water_tank_f %li", source.c_str(), dest.c_str(), message.value); - return; - } - case MessageNumber::VAR_out_sensor_airout: - { - double temp = (double)((int16_t)message.value) / (double)10; - ESP_LOGW(TAG, "s:%s d:%s VAR_out_sensor_airout %li", source.c_str(), dest.c_str(), message.value); - target->set_outdoor_temperature(source, temp); - return; - } - - default: - { - if ((uint16_t)message.messageNumber == 0x4260) + if (debug_log_messages) { - // VAR_IN_FSV_3021 - double temp = (double)message.value / (double)10; - ESP_LOGW(TAG, "s:%s d:%s VAR_IN_FSV_3021 %f", source.c_str(), dest.c_str(), temp); - return; + ESP_LOGW(TAG, "s:%s d:%s ENUM_in_fan_mode %li", source.c_str(), dest.c_str(), message.value); } - if ((uint16_t)message.messageNumber == 0x4261) + target->set_fanmode(source, fan_mode_real_to_fanmode(message.value)); + break; + case MessageNumber::ENUM_in_fan_mode_real: + if (debug_log_messages) { - // VAR_IN_FSV_3022 - double temp = (double)message.value / (double)10; - ESP_LOGW(TAG, "s:%s d:%s VAR_IN_FSV_3022 %f", source.c_str(), dest.c_str(), temp); - return; + ESP_LOGW(TAG, "s:%s d:%s ENUM_in_fan_mode_real %li", source.c_str(), dest.c_str(), message.value); } - if ((uint16_t)message.messageNumber == 0x4262) + break; + case MessageNumber::ENUM_in_alt_mode: + if (debug_log_messages) { - // VAR_IN_FSV_3023 - double temp = (double)message.value / (double)10; - ESP_LOGW(TAG, "s:%s d:%s VAR_IN_FSV_3023 %f", source.c_str(), dest.c_str(), temp); - return; + ESP_LOGW(TAG, "s:%s d:%s ENUM_in_alt_mode %li", source.c_str(), dest.c_str(), message.value); } - - if ((uint16_t)message.messageNumber == 0x8414) + target->set_altmode(source, message.value); + break; + case MessageNumber::ENUM_in_louver_hl_swing: + if (debug_log_messages) { - // LVAR_OUT_CONTROL_WATTMETER_ALL_UNIT_ACCUM - double kwh = (double)message.value / (double)1000; - ESP_LOGW(TAG, "s:%s d:%s LVAR_OUT_CONTROL_WATTMETER_ALL_UNIT_ACCUM %fkwh", source.c_str(), dest.c_str(), kwh); - return; + ESP_LOGW(TAG, "s:%s d:%s ENUM_in_louver_hl_swing %li", source.c_str(), dest.c_str(), message.value); } - if ((uint16_t)message.messageNumber == 0x8413) + target->set_swing_vertical(source, message.value == 1); + break; + case MessageNumber::ENUM_in_louver_lr_swing: + if (debug_log_messages) { - // LVAR_OUT_CONTROL_WATTMETER_1W_1MIN_SUM - double value = (double)message.value; - ESP_LOGW(TAG, "s:%s d:%s LVAR_OUT_CONTROL_WATTMETER_1W_1MIN_SUM %f", source.c_str(), dest.c_str(), value); - return; + ESP_LOGW(TAG, "s:%s d:%s ENUM_in_louver_lr_swing %li", source.c_str(), dest.c_str(), message.value); } - if ((uint16_t)message.messageNumber == 0x8411) + target->set_swing_horizontal(source, message.value == 1); + break; + case MessageNumber::VAR_in_temp_water_tank_f: + if (debug_log_messages) { - double value = (double)message.value; - ESP_LOGW(TAG, "s:%s d:%s NASA_OUTDOOR_CONTROL_WATTMETER_1UNIT %f", source.c_str(), dest.c_str(), value); - return; + ESP_LOGW(TAG, "s:%s d:%s VAR_in_temp_water_tank_f %li", source.c_str(), dest.c_str(), message.value); } - if ((uint16_t)message.messageNumber == 0x8427) + break; + case MessageNumber::VAR_out_sensor_airout: + { + double temp = ((int16_t)message.value) / 10.0; + if (debug_log_messages) { - double value = (double)message.value; - ESP_LOGW(TAG, "s:%s d:%s total produced energy %f", source.c_str(), dest.c_str(), value); - return; + ESP_LOGW(TAG, "s:%s d:%s VAR_out_sensor_airout %li", source.c_str(), dest.c_str(), message.value); } - if ((uint16_t)message.messageNumber == 0x8426) + target->set_outdoor_temperature(source, temp); + break; + } + case MessageNumber::VAR_IN_TEMP_EVA_IN_F: + { + double temp = ((int16_t)message.value) / 10.0; + if (debug_log_messages) { - double value = (double)message.value; - ESP_LOGW(TAG, "s:%s d:%s actual produced energy %f", source.c_str(), dest.c_str(), value); - return; + ESP_LOGW(TAG, "s:%s d:%s VAR_IN_TEMP_EVA_IN_F %li", source.c_str(), dest.c_str(), message.value); } - if ((uint16_t)message.messageNumber == 0x8415) + target->set_indoor_eva_in_temperature(source, temp); + break; + } + case MessageNumber::VAR_IN_TEMP_EVA_OUT_F: + { + double temp = ((int16_t)message.value) / 10.0; + if (debug_log_messages) { - double value = (double)message.value; - ESP_LOGW(TAG, "s:%s d:%s NASA_OUTDOOR_CONTROL_WATTMETER_TOTAL_SUM %f", source.c_str(), dest.c_str(), value); - return; + ESP_LOGW(TAG, "s:%s d:%s VAR_IN_TEMP_EVA_OUT_F %li", source.c_str(), dest.c_str(), message.value); } - if ((uint16_t)message.messageNumber == 0x8416) + target->set_indoor_eva_out_temperature(source, temp); + break; + } + default: + if (debug_log_undefined_messages) { - double value = (double)message.value; - ESP_LOGW(TAG, "s:%s d:%s NASA_OUTDOOR_CONTROL_WATTMETER_TOTAL_SUM_ACCUM %f", source.c_str(), dest.c_str(), value); - return; + ESP_LOGW(TAG, "Undefined s:%s d:%s %s", source.c_str(), dest.c_str(), message.to_string().c_str()); } - } + + break; } } @@ -717,7 +706,7 @@ namespace esphome target->register_address(source); - if (debug_log_packets) + if (debug_log_messages) { ESP_LOGW(TAG, "MSG: %s", packet_.to_string().c_str()); } @@ -1150,11 +1139,20 @@ namespace esphome case 0x602: // STR_ad_option_install_2 case 0x600: // STR_ad_option_basic case 0x202: // VAR_ad_error_code1 + case 0x42d1: // VAR_IN_DUST_SENSOR_PM10_0_VALUE + { + ESP_LOGW(TAG, "s:%s d:%s VAR_IN_DUST_SENSOR_PM10_0_VALUE %s %li", source.c_str(), dest.c_str(), long_to_hex((int)message.messageNumber).c_str(), message.value); + return; // Ingore cause not important + } case 0x42d2: // VAR_IN_DUST_SENSOR_PM2_5_VALUE + { + ESP_LOGW(TAG, "s:%s d:%s VAR_IN_DUST_SENSOR_PM2_5_VALUE %s %li", source.c_str(), dest.c_str(), long_to_hex((int)message.messageNumber).c_str(), message.value); + return; // Ingore cause not important + } case 0x42d3: // VAR_IN_DUST_SENSOR_PM1_0_VALUE { - // ESP_LOGW(TAG, "s:%s d:%s Ignore %s %li", source.c_str(), dest.c_str(), long_to_hex((int)message.messageNumber).c_str(), message.value); + ESP_LOGW(TAG, "s:%s d:%s VAR_IN_DUST_SENSOR_PM1_0_VALUE %s %li", source.c_str(), dest.c_str(), long_to_hex((int)message.messageNumber).c_str(), message.value); return; // Ingore cause not important } diff --git a/components/samsung_ac/protocol_nasa.h b/components/samsung_ac/protocol_nasa.h index edae300..77abae6 100644 --- a/components/samsung_ac/protocol_nasa.h +++ b/components/samsung_ac/protocol_nasa.h @@ -71,6 +71,7 @@ namespace esphome { Undefiend = 0, ENUM_in_operation_power = 0x4000, + ENUM_in_operation_automatic_cleaning = 0x4111, ENUM_in_water_heater_power = 0x4065, ENUM_in_operation_mode = 0x4001, ENUM_in_fan_mode = 0x4006, // Did not exists in xml...only in Remocon.dll code @@ -85,6 +86,8 @@ namespace esphome VAR_in_temp_water_tank_f = 0x4237, VAR_out_sensor_airout = 0x8204, VAR_in_temp_water_heater_target_f = 0x4235, + VAR_IN_TEMP_EVA_IN_F = 0x4205, + VAR_IN_TEMP_EVA_OUT_F = 0x4206, }; struct Address diff --git a/components/samsung_ac/protocol_non_nasa.cpp b/components/samsung_ac/protocol_non_nasa.cpp index 392edc8..5f97cab 100644 --- a/components/samsung_ac/protocol_non_nasa.cpp +++ b/components/samsung_ac/protocol_non_nasa.cpp @@ -528,7 +528,7 @@ namespace esphome void process_non_nasa_packet(MessageTarget *target) { - if (debug_log_packets) + if (debug_log_messages) { ESP_LOGW(TAG, "MSG: %s", nonpacket_.to_string().c_str()); } @@ -554,39 +554,39 @@ namespace esphome item.request.fanspeed == nonpacket_.command20.fanspeed && item.request.mode == nonpacket_.command20.mode && item.request.power == nonpacket_.command20.power; }); - + // If a state update comes through after a control message has been sent, but before it // has been acknowledged, it should be ignored. This prevents the UI status bouncing // between states after a command has been issued. bool pending_control_message = false; - for (auto& item : nonnasa_requests) + for (auto &item : nonnasa_requests) { - if (item.time_sent > 0 && nonpacket_.src == item.request.dst) - { - pending_control_message = true; - break; - } + if (item.time_sent > 0 && nonpacket_.src == item.request.dst) + { + pending_control_message = true; + break; + } } if (!pending_control_message) { - last_command20s_[nonpacket_.src] = nonpacket_.command20; - target->set_target_temperature(nonpacket_.src, nonpacket_.command20.target_temp); - // TODO - target->set_water_outlet_target(nonpacket_.src, false); - // TODO - target->set_target_water_temperature(nonpacket_.src, false); - target->set_room_temperature(nonpacket_.src, nonpacket_.command20.room_temp); - target->set_power(nonpacket_.src, nonpacket_.command20.power); - // TODO - target->set_water_heater_power(nonpacket_.src, false); - 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, 0); - // TODO - target->set_swing_horizontal(nonpacket_.src, false); - target->set_swing_vertical(nonpacket_.src, false); + last_command20s_[nonpacket_.src] = nonpacket_.command20; + target->set_target_temperature(nonpacket_.src, nonpacket_.command20.target_temp); + // TODO + target->set_water_outlet_target(nonpacket_.src, false); + // TODO + target->set_target_water_temperature(nonpacket_.src, false); + target->set_room_temperature(nonpacket_.src, nonpacket_.command20.room_temp); + target->set_power(nonpacket_.src, nonpacket_.command20.power); + // TODO + target->set_water_heater_power(nonpacket_.src, false); + 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, 0); + // TODO + target->set_swing_horizontal(nonpacket_.src, false); + target->set_swing_vertical(nonpacket_.src, false); } } else if (nonpacket_.cmd == NonNasaCommand::CmdC6) diff --git a/components/samsung_ac/samsung_ac.h b/components/samsung_ac/samsung_ac.h index 0a5bd30..1fcab17 100644 --- a/components/samsung_ac/samsung_ac.h +++ b/components/samsung_ac/samsung_ac.h @@ -39,7 +39,7 @@ namespace esphome void set_debug_log_messages(bool value) { - debug_log_packets = value; + debug_log_messages = value; } void set_debug_log_messages_raw(bool value) @@ -51,7 +51,10 @@ namespace esphome { non_nasa_keepalive = value; } - + void set_debug_log_undefined_messages(bool value) + { + debug_log_undefined_messages = value; + } void register_device(Samsung_AC_Device *device); void /*MessageTarget::*/ register_address(const std::string address) override @@ -80,13 +83,27 @@ namespace esphome dev->update_outdoor_temperature(value); } + void /*MessageTarget::*/ set_indoor_eva_in_temperature(const std::string address, float value) override + { + Samsung_AC_Device *dev = find_device(address); + if (dev != nullptr) + dev->update_indoor_eva_in_temperature(value); + } + + void /*MessageTarget::*/ set_indoor_eva_out_temperature(const std::string address, float value) override + { + Samsung_AC_Device *dev = find_device(address); + if (dev != nullptr) + dev->update_indoor_eva_out_temperature(value); + } + void /*MessageTarget::*/ set_target_temperature(const std::string address, float value) override { Samsung_AC_Device *dev = find_device(address); if (dev != nullptr) dev->update_target_temperature(value); } - + void /*MessageTarget::*/ set_water_outlet_target(const std::string address, float value) override { Samsung_AC_Device *dev = find_device(address); @@ -107,6 +124,12 @@ namespace esphome if (dev != nullptr) dev->update_power(value); } + void /*MessageTarget::*/ set_automatic_cleaning(const std::string address, bool value) override + { + Samsung_AC_Device *dev = find_device(address); + if (dev != nullptr) + dev->update_automatic_cleaning(value); + } void /*MessageTarget::*/ set_water_heater_power(const std::string address, bool value) override { Samsung_AC_Device *dev = find_device(address); diff --git a/components/samsung_ac/samsung_ac_device.h b/components/samsung_ac/samsung_ac_device.h index bc202da..409d490 100644 --- a/components/samsung_ac/samsung_ac_device.h +++ b/components/samsung_ac/samsung_ac_device.h @@ -89,10 +89,13 @@ namespace esphome std::string address; sensor::Sensor *room_temperature{nullptr}; sensor::Sensor *outdoor_temperature{nullptr}; + sensor::Sensor *indoor_eva_in_temperature{nullptr}; + sensor::Sensor *indoor_eva_out_temperature{nullptr}; Samsung_AC_Number *target_temperature{nullptr}; Samsung_AC_Number *water_outlet_target{nullptr}; Samsung_AC_Number *target_water_temperature{nullptr}; Samsung_AC_Switch *power{nullptr}; + Samsung_AC_Switch *automatic_cleaning{nullptr}; Samsung_AC_Switch *water_heater_power{nullptr}; Samsung_AC_Mode_Select *mode{nullptr}; Samsung_AC_Climate *climate{nullptr}; @@ -109,6 +112,16 @@ namespace esphome outdoor_temperature = sensor; } + void set_indoor_eva_in_temperature_sensor(sensor::Sensor *sensor) + { + indoor_eva_in_temperature = sensor; + } + + void set_indoor_eva_out_temperature_sensor(sensor::Sensor *sensor) + { + indoor_eva_out_temperature = sensor; + } + void add_custom_sensor(int message_number, sensor::Sensor *sensor) { Samsung_AC_Sensor cust_sensor; @@ -136,6 +149,17 @@ namespace esphome }; } + void set_automatic_cleaning_switch(Samsung_AC_Switch *switch_) + { + automatic_cleaning = switch_; + automatic_cleaning->write_state_ = [this](bool value) + { + ProtocolRequest request; + request.automatic_cleaning = value; + publish_request(request); + }; + } + void set_water_heater_power_switch(Samsung_AC_Switch *switch_) { water_heater_power = switch_; @@ -168,7 +192,7 @@ namespace esphome publish_request(request); }; }; - + void set_water_outlet_target_number(Samsung_AC_Number *number) { water_outlet_target = number; @@ -207,7 +231,7 @@ namespace esphome climate->publish_state(); } } - + void update_water_outlet_target(float value) { if (water_outlet_target != nullptr) @@ -221,6 +245,7 @@ namespace esphome } optional _cur_power; + optional _cur_automatic_cleaning; optional _cur_water_heater_power; optional _cur_mode; @@ -233,6 +258,15 @@ namespace esphome calc_and_publish_mode(); } + void update_automatic_cleaning(bool value) + { + _cur_automatic_cleaning = value; + if (automatic_cleaning != nullptr) + automatic_cleaning->publish_state(value); + if (climate != nullptr) + calc_and_publish_mode(); + } + void update_water_heater_power(bool value) { _cur_water_heater_power = value; @@ -333,6 +367,18 @@ namespace esphome outdoor_temperature->publish_state(value); } + void update_indoor_eva_in_temperature(float value) + { + if (indoor_eva_in_temperature != nullptr) + indoor_eva_in_temperature->publish_state(value); + } + + void update_indoor_eva_out_temperature(float value) + { + if (indoor_eva_out_temperature != nullptr) + indoor_eva_out_temperature->publish_state(value); + } + void update_custom_sensor(uint16_t message_number, float value) { for (auto &sensor : custom_sensors) diff --git a/esphome_samsung_ac b/esphome_samsung_ac new file mode 160000 index 0000000..f8e00b5 --- /dev/null +++ b/esphome_samsung_ac @@ -0,0 +1 @@ +Subproject commit f8e00b5246f27885a328bbf120798b22da5bdcba diff --git a/example.yaml b/example.yaml index 4acba9d..decfc30 100644 --- a/example.yaml +++ b/example.yaml @@ -47,7 +47,7 @@ uart: # Import custom component from GitHub external_components: - - source: github://lanwin/esphome_samsung_ac@stable # use @main if you want the latest development (possibly unstable?) + - source: github://omerfaruk-aran/esphome_samsung_ac@main # use @main if you want the latest development (possibly unstable?) components: [samsung_ac] # Configuration of AC component @@ -56,6 +56,12 @@ samsung_ac: # For NonNASA devices the following option can be enabled to prevent the device from sleeping when idle. This allows # values like internal and external temperature to continue to be tracked when the device isn't in use. non_nasa_keepalive: true + + #When enabled (set to true), this option will log the messages associated with undefined codes on the device. This is useful for debugging and identifying any unexpected or unknown codes that the device may receive during operation. + debug_log_undefined_messages: false + + #When enabled (set to true), this option logs messages associated with defined codes on the device. This helps in monitoring the behavior of the device by recording the activity related to known, expected codes. + debug_log_messages: false # Capabilities configure the features alle devices of your AC system have (all parts of this section are optional). # All capabilities are off by default, you need to enable only those your devices have. @@ -104,6 +110,12 @@ samsung_ac: name: "Kitchen power" mode: name: "Kitchen mode" + + #Add automatic_cleaning mode for Samsung AC NASA + #- Added the "automatic_cleaning" feature to the Samsung AC integration. + #- This mode ensures hygienic drying of all moisture in the indoor unit after the cooling process is completed. + automatic_cleaning: + name: "Kitchen automatic clean" # If your AC sits near or inside the ceiling, the reported room temperature is often a little bit heigher then whats # measured below. This property can be used to correct that value.