diff --git a/.gitignore b/.gitignore index 1bcb836..04d9cda 100644 --- a/.gitignore +++ b/.gitignore @@ -2,3 +2,12 @@ __pycache__ .esphome test.exe +.pio/ +.vscode/ +src/ +platformio.ini +sdkconfig.m5stack-atom +CMakeLists.txt +.gitignore +esp.yaml +secrets.yaml \ No newline at end of file diff --git a/.vscode/settings.json b/.vscode/settings.json index 55851a9..933b423 100644 --- a/.vscode/settings.json +++ b/.vscode/settings.json @@ -71,7 +71,7 @@ "stop_token": "cpp" }, "[python]": { - "editor.defaultFormatter": "ms-python.autopep8" + "editor.defaultFormatter": "ms-python.black-formatter" }, "python.formatting.provider": "none" } \ No newline at end of file diff --git a/components/samsung_ac/__init__.py b/components/samsung_ac/__init__.py index 89a7d1b..0affde4 100644 --- a/components/samsung_ac/__init__.py +++ b/components/samsung_ac/__init__.py @@ -5,19 +5,24 @@ CONF_ID, DEVICE_CLASS_TEMPERATURE, STATE_CLASS_MEASUREMENT, + STATE_CLASS_TOTAL_INCREASING, + DEVICE_CLASS_ENERGY, + DEVICE_CLASS_POWER, DEVICE_CLASS_HUMIDITY, + DEVICE_CLASS_VOLTAGE, + DEVICE_CLASS_CURRENT, + UNIT_CELSIUS, + UNIT_PERCENT, + UNIT_WATT, + UNIT_VOLT, + UNIT_AMPERE, CONF_UNIT_OF_MEASUREMENT, CONF_DEVICE_CLASS, CONF_FILTERS, - UNIT_CELSIUS, - UNIT_PERCENT, -) -from esphome.core import ( - CORE, - Lambda ) +from esphome.core import CORE, Lambda -CODEOWNERS = ["matthias882", "lanwin"] +CODEOWNERS = ["matthias882", "lanwin", "omerfaruk-aran"] DEPENDENCIES = ["uart"] AUTO_LOAD = ["sensor", "switch", "select", "number", "climate"] MULTI_CONF = False @@ -25,30 +30,28 @@ CONF_SAMSUNG_AC_ID = "samsung_ac_id" samsung_ac = cg.esphome_ns.namespace("samsung_ac") -Samsung_AC = samsung_ac.class_( - "Samsung_AC", cg.PollingComponent, uart.UARTDevice -) +Samsung_AC = samsung_ac.class_("Samsung_AC", cg.PollingComponent, uart.UARTDevice) Samsung_AC_Device = samsung_ac.class_("Samsung_AC_Device") Samsung_AC_Switch = samsung_ac.class_("Samsung_AC_Switch", switch.Switch) -Samsung_AC_Mode_Select = samsung_ac.class_( - "Samsung_AC_Mode_Select", select.Select) +Samsung_AC_Mode_Select = samsung_ac.class_("Samsung_AC_Mode_Select", select.Select) Samsung_AC_Water_Heater_Mode_Select = samsung_ac.class_( - "Samsung_AC_Water_Heater_Mode_Select", select.Select) + "Samsung_AC_Water_Heater_Mode_Select", select.Select +) Samsung_AC_Number = samsung_ac.class_("Samsung_AC_Number", number.Number) Samsung_AC_Climate = samsung_ac.class_("Samsung_AC_Climate", climate.Climate) # not sure why select.select_schema did not work yet SELECT_MODE_SCHEMA = select.select_schema(Samsung_AC_Mode_Select) -SELECT_WATER_HEATER_MODE_SCHEMA = select.select_schema(Samsung_AC_Water_Heater_Mode_Select) +SELECT_WATER_HEATER_MODE_SCHEMA = select.select_schema( + Samsung_AC_Water_Heater_Mode_Select +) -NUMBER_SCHEMA = ( - number.NUMBER_SCHEMA.extend( - {cv.GenerateID(): cv.declare_id(Samsung_AC_Number)}) +NUMBER_SCHEMA = number.NUMBER_SCHEMA.extend( + {cv.GenerateID(): cv.declare_id(Samsung_AC_Number)} ) -CLIMATE_SCHEMA = ( - climate.CLIMATE_SCHEMA.extend( - {cv.GenerateID(): cv.declare_id(Samsung_AC_Climate)}) +CLIMATE_SCHEMA = climate.CLIMATE_SCHEMA.extend( + {cv.GenerateID(): cv.declare_id(Samsung_AC_Climate)} ) CONF_DEVICE_ID = "samsung_ac_device_id" @@ -73,7 +76,10 @@ CONF_DEVICE_CUSTOM_MESSAGE = "message" CONF_DEVICE_CUSTOM_RAW_FILTERS = "raw_filters" CONF_DEVICE_ERROR_CODE = "error_code" - +CONF_DEVICE_OUT_CONTROL_WATTMETER_ALL_UNIT_ACCUM = "outdoor_instantaneous_power" +CONF_DEVICE_OUT_CONTROL_WATTMETER_1W_1MIN_SUM = "outdoor_cumulative_energy" +CONF_DEVICE_OUT_SENSOR_CT1 = "outdoor_current" +CONF_DEVICE_OUT_SENSOR_VOLTAGE = "outdoor_voltage" CONF_CAPABILITIES = "capabilities" @@ -86,17 +92,20 @@ CONF_PRESET_VALUE = "value" -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_ - })) -) +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 = { @@ -108,20 +117,28 @@ def preset_entry( "windfree": {"value": 9, "displayName": "WindFree"}, } -CAPABILITIES_SCHEMA = ( - cv.Schema({ +CAPABILITIES_SCHEMA = cv.Schema( + { cv.Optional(CONF_CAPABILITIES_HORIZONTAL_SWING, default=False): cv.boolean, cv.Optional(CONF_CAPABILITIES_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] - )) - }) + 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_CUSTOM_MESSAGE): cv.hex_int, -}) +CUSTOM_SENSOR_SCHEMA = sensor.sensor_schema().extend( + { + cv.Required(CONF_DEVICE_CUSTOM_MESSAGE): cv.hex_int, + } +) def custom_sensor_schema( @@ -132,7 +149,7 @@ def custom_sensor_schema( device_class: str = sensor._UNDEF, state_class: str = sensor._UNDEF, entity_category: str = sensor._UNDEF, - raw_filters=[] + raw_filters=[], ): return sensor.sensor_schema( unit_of_measurement=unit_of_measurement, @@ -141,10 +158,14 @@ def custom_sensor_schema( device_class=device_class, state_class=state_class, entity_category=entity_category, - ).extend({ - cv.Optional(CONF_DEVICE_CUSTOM_MESSAGE, default=message): cv.hex_int, - cv.Optional(CONF_DEVICE_CUSTOM_RAW_FILTERS, default=raw_filters): sensor.validate_filters - }) + ).extend( + { + cv.Optional(CONF_DEVICE_CUSTOM_MESSAGE, default=message): cv.hex_int, + cv.Optional( + CONF_DEVICE_CUSTOM_RAW_FILTERS, default=raw_filters + ): sensor.validate_filters, + } + ) def temperature_sensor_schema(message: int): @@ -154,10 +175,7 @@ def temperature_sensor_schema(message: int): accuracy_decimals=1, device_class=DEVICE_CLASS_TEMPERATURE, state_class=STATE_CLASS_MEASUREMENT, - raw_filters=[ - {"lambda": Lambda("return (int16_t)x;")}, - {"multiply": 0.1} - ], + raw_filters=[{"lambda": Lambda("return (int16_t)x;")}, {"multiply": 0.1}], ) @@ -170,6 +188,7 @@ def humidity_sensor_schema(message: int): state_class=STATE_CLASS_MEASUREMENT, ) + def error_code_sensor_schema(message: int): return custom_sensor_schema( message=message, @@ -177,55 +196,108 @@ def error_code_sensor_schema(message: int): accuracy_decimals=0, icon="mdi:alert", ) - -DEVICE_SCHEMA = ( - 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, - accuracy_decimals=1, - device_class=DEVICE_CLASS_TEMPERATURE, - state_class=STATE_CLASS_MEASUREMENT, - ), - cv.Optional(CONF_DEVICE_ROOM_TEMPERATURE_OFFSET): cv.float_, - cv.Optional(CONF_DEVICE_OUTDOOR_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_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_ERROR_CODE): error_code_sensor_schema(0x8235), - 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_WATER_HEATER_MODE): SELECT_WATER_HEATER_MODE_SCHEMA, - cv.Optional(CONF_DEVICE_CLIMATE): CLIMATE_SCHEMA, - cv.Optional(CONF_DEVICE_CUSTOM, default=[]): cv.ensure_list(CUSTOM_SENSOR_SCHEMA), - - # keep CUSTOM_SENSOR_KEYS in sync with these - cv.Optional(CONF_DEVICE_WATER_TEMPERATURE): temperature_sensor_schema(0x4237), - cv.Optional(CONF_DEVICE_ROOM_HUMIDITY): humidity_sensor_schema(0x4038), - } - ) + + +DEVICE_SCHEMA = 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, + accuracy_decimals=1, + device_class=DEVICE_CLASS_TEMPERATURE, + state_class=STATE_CLASS_MEASUREMENT, + ), + cv.Optional(CONF_DEVICE_ROOM_TEMPERATURE_OFFSET): cv.float_, + cv.Optional(CONF_DEVICE_OUTDOOR_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_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_ERROR_CODE): error_code_sensor_schema(0x8235), + 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_WATER_HEATER_MODE): SELECT_WATER_HEATER_MODE_SCHEMA, + cv.Optional(CONF_DEVICE_CLIMATE): CLIMATE_SCHEMA, + cv.Optional(CONF_DEVICE_CUSTOM, default=[]): cv.ensure_list( + CUSTOM_SENSOR_SCHEMA + ), + # keep CUSTOM_SENSOR_KEYS in sync with these + cv.Optional(CONF_DEVICE_WATER_TEMPERATURE): temperature_sensor_schema(0x4237), + cv.Optional(CONF_DEVICE_ROOM_HUMIDITY): humidity_sensor_schema(0x4038), + cv.Optional( + CONF_DEVICE_OUT_CONTROL_WATTMETER_ALL_UNIT_ACCUM + ): sensor.sensor_schema( + unit_of_measurement=UNIT_WATT, + accuracy_decimals=1, + device_class=DEVICE_CLASS_POWER, + state_class=STATE_CLASS_MEASUREMENT, + icon="mdi:flash", + ), + cv.Optional( + CONF_DEVICE_OUT_CONTROL_WATTMETER_1W_1MIN_SUM + ): sensor.sensor_schema( + unit_of_measurement="kWh", + accuracy_decimals=3, + device_class=DEVICE_CLASS_ENERGY, + state_class=STATE_CLASS_TOTAL_INCREASING, + icon="mdi:counter", + ).extend( + { + cv.Optional( + CONF_FILTERS, default=[{"multiply": 0.001}] + ): sensor.validate_filters + } + ), + cv.Optional(CONF_DEVICE_OUT_SENSOR_CT1): sensor.sensor_schema( + unit_of_measurement=UNIT_AMPERE, + accuracy_decimals=2, + device_class=DEVICE_CLASS_CURRENT, + state_class=STATE_CLASS_MEASUREMENT, + icon="mdi:current-ac", + ).extend( + { + cv.Optional(CONF_DEVICE_CUSTOM_MESSAGE, default=0x8217): cv.hex_int, + cv.Optional( + CONF_FILTERS, default=[{"multiply": 0.1}] + ): sensor.validate_filters, + } + ), + cv.Optional(CONF_DEVICE_OUT_SENSOR_VOLTAGE): sensor.sensor_schema( + unit_of_measurement=UNIT_VOLT, + accuracy_decimals=1, + device_class=DEVICE_CLASS_VOLTAGE, + state_class=STATE_CLASS_MEASUREMENT, + icon="mdi:flash", + ).extend( + { + cv.Optional(CONF_DEVICE_CUSTOM_MESSAGE, default=0x24FC): cv.hex_int, + } + ), + } ) CUSTOM_SENSOR_KEYS = [ @@ -278,16 +350,25 @@ async def to_code(config): var = cg.new_Pvariable(config[CONF_ID]) for device_index, device in enumerate(config[CONF_DEVICES]): var_dev = cg.new_Pvariable( - device[CONF_DEVICE_ID], device[CONF_DEVICE_ADDRESS], var) + device[CONF_DEVICE_ID], device[CONF_DEVICE_ADDRESS], var + ) # setup capabilities capabilities = device.get(CONF_CAPABILITIES, config.get(CONF_CAPABILITIES, {})) if CONF_CAPABILITIES_VERTICAL_SWING in capabilities: - cg.add(var_dev.set_supports_vertical_swing(capabilities[CONF_CAPABILITIES_VERTICAL_SWING])) + cg.add( + var_dev.set_supports_vertical_swing( + capabilities[CONF_CAPABILITIES_VERTICAL_SWING] + ) + ) if CONF_CAPABILITIES_HORIZONTAL_SWING in capabilities: - cg.add(var_dev.set_supports_horizontal_swing(capabilities[CONF_CAPABILITIES_HORIZONTAL_SWING])) + cg.add( + var_dev.set_supports_horizontal_swing( + capabilities[CONF_CAPABILITIES_HORIZONTAL_SWING] + ) + ) none_added = False presets = capabilities.get(CONF_PRESETS, {}) @@ -300,39 +381,82 @@ async def to_code(config): none_added = True cg.add(var_dev.add_alt_mode("None", 0)) - cg.add(var_dev.add_alt_mode( - preset_info["displayName"], - preset_info["value"] - )) - elif isinstance(preset_conf, dict) and preset_conf.get(CONF_PRESET_ENABLED, False): + cg.add( + var_dev.add_alt_mode( + preset_info["displayName"], preset_info["value"] + ) + ) + elif isinstance(preset_conf, dict) and preset_conf.get( + CONF_PRESET_ENABLED, False + ): 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.get(CONF_PRESET_NAME, preset_info["displayName"]), # Kullanıcı tarafından sağlanan adı kullan - preset_conf.get(CONF_PRESET_VALUE, preset_info["value"]) # Kullanıcı tarafından sağlanan değeri kullan - )) - -# 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])) + cg.add( + var_dev.add_alt_mode( + preset_conf.get( + CONF_PRESET_NAME, preset_info["displayName"] + ), # Kullanıcı tarafından sağlanan adı kullan + preset_conf.get( + CONF_PRESET_VALUE, preset_info["value"] + ), # Kullanıcı tarafından sağlanan değeri kullan + ) + ) + + # 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])) # Mapping of config keys to their corresponding methods and types device_actions = { CONF_DEVICE_POWER: (switch.new_switch, var_dev.set_power_switch), - CONF_DEVICE_AUTOMATIC_CLEANING: (switch.new_switch, var_dev.set_automatic_cleaning_switch), - CONF_DEVICE_WATER_HEATER_POWER: (switch.new_switch, var_dev.set_water_heater_power_switch), - CONF_DEVICE_ROOM_TEMPERATURE: (sensor.new_sensor, var_dev.set_room_temperature_sensor), - CONF_DEVICE_OUTDOOR_TEMPERATURE: (sensor.new_sensor, var_dev.set_outdoor_temperature_sensor), - CONF_DEVICE_INDOOR_EVA_IN_TEMPERATURE: (sensor.new_sensor, var_dev.set_indoor_eva_in_temperature_sensor), - CONF_DEVICE_INDOOR_EVA_OUT_TEMPERATURE: (sensor.new_sensor, var_dev.set_indoor_eva_out_temperature_sensor), + CONF_DEVICE_AUTOMATIC_CLEANING: ( + switch.new_switch, + var_dev.set_automatic_cleaning_switch, + ), + CONF_DEVICE_WATER_HEATER_POWER: ( + switch.new_switch, + var_dev.set_water_heater_power_switch, + ), + CONF_DEVICE_ROOM_TEMPERATURE: ( + sensor.new_sensor, + var_dev.set_room_temperature_sensor, + ), + CONF_DEVICE_OUTDOOR_TEMPERATURE: ( + sensor.new_sensor, + var_dev.set_outdoor_temperature_sensor, + ), + CONF_DEVICE_INDOOR_EVA_IN_TEMPERATURE: ( + sensor.new_sensor, + var_dev.set_indoor_eva_in_temperature_sensor, + ), + CONF_DEVICE_INDOOR_EVA_OUT_TEMPERATURE: ( + sensor.new_sensor, + var_dev.set_indoor_eva_out_temperature_sensor, + ), CONF_DEVICE_ERROR_CODE: (sensor.new_sensor, var_dev.set_error_code_sensor), + CONF_DEVICE_OUT_CONTROL_WATTMETER_ALL_UNIT_ACCUM: ( + sensor.new_sensor, + var_dev.set_outdoor_instantaneous_power_sensor, + ), + CONF_DEVICE_OUT_CONTROL_WATTMETER_1W_1MIN_SUM: ( + sensor.new_sensor, + var_dev.set_outdoor_cumulative_energy_sensor, + ), + CONF_DEVICE_OUT_SENSOR_CT1: ( + sensor.new_sensor, + var_dev.set_outdoor_current_sensor, + ), + CONF_DEVICE_OUT_SENSOR_VOLTAGE: ( + sensor.new_sensor, + var_dev.set_outdoor_voltage_sensor, + ), } # Iterate over the actions @@ -343,37 +467,37 @@ async def to_code(config): cg.add(method(sens)) if CONF_DEVICE_ROOM_TEMPERATURE_OFFSET in device: - cg.add(var_dev.set_room_temperature_offset( - device[CONF_DEVICE_ROOM_TEMPERATURE_OFFSET])) - + cg.add( + var_dev.set_room_temperature_offset( + device[CONF_DEVICE_ROOM_TEMPERATURE_OFFSET] + ) + ) + if CONF_DEVICE_WATER_TARGET_TEMPERATURE in device: conf = device[CONF_DEVICE_WATER_TARGET_TEMPERATURE] conf[CONF_UNIT_OF_MEASUREMENT] = UNIT_CELSIUS conf[CONF_DEVICE_CLASS] = DEVICE_CLASS_TEMPERATURE - num = await number.new_number(conf, - min_value=30.0, - max_value=70.0, - step=0.5) + num = await number.new_number( + conf, min_value=30.0, max_value=70.0, step=0.5 + ) cg.add(var_dev.set_target_water_temperature_number(num)) if CONF_DEVICE_TARGET_TEMPERATURE in device: conf = device[CONF_DEVICE_TARGET_TEMPERATURE] conf[CONF_UNIT_OF_MEASUREMENT] = UNIT_CELSIUS conf[CONF_DEVICE_CLASS] = DEVICE_CLASS_TEMPERATURE - num = await number.new_number(conf, - min_value=16.0, - max_value=30.0, - step=1.0) + num = await number.new_number( + conf, min_value=16.0, max_value=30.0, step=1.0 + ) cg.add(var_dev.set_target_temperature_number(num)) - + if CONF_DEVICE_WATER_OUTLET_TARGET in device: conf = device[CONF_DEVICE_WATER_OUTLET_TARGET] conf[CONF_UNIT_OF_MEASUREMENT] = UNIT_CELSIUS conf[CONF_DEVICE_CLASS] = DEVICE_CLASS_TEMPERATURE - num = await number.new_number(conf, - min_value=15.0, - max_value=55.0, - step=0.1) + num = await number.new_number( + conf, min_value=15.0, max_value=55.0, step=0.1 + ) cg.add(var_dev.set_water_outlet_target_number(num)) if CONF_DEVICE_MODE in device: @@ -381,7 +505,7 @@ async def to_code(config): values = ["Auto", "Cool", "Dry", "Fan", "Heat"] sel = await select.new_select(conf, options=values) cg.add(var_dev.set_mode_select(sel)) - + if CONF_DEVICE_WATER_HEATER_MODE in device: conf = device[CONF_DEVICE_WATER_HEATER_MODE] values = ["Eco", "Standard", "Power", "Force"] @@ -397,38 +521,54 @@ async def to_code(config): if CONF_DEVICE_CUSTOM in device: for cust_sens in device[CONF_DEVICE_CUSTOM]: sens = await sensor.new_sensor(cust_sens) - cg.add(var_dev.add_custom_sensor( - cust_sens[CONF_DEVICE_CUSTOM_MESSAGE], sens)) + cg.add( + var_dev.add_custom_sensor( + cust_sens[CONF_DEVICE_CUSTOM_MESSAGE], sens + ) + ) for key in CUSTOM_SENSOR_KEYS: if key in device: conf = device[key] # combine raw filters with any user-defined filters conf_copy = conf.copy() - conf_copy[CONF_FILTERS] = (conf[CONF_DEVICE_CUSTOM_RAW_FILTERS] if CONF_DEVICE_CUSTOM_RAW_FILTERS in conf else [ - ]) + (conf[CONF_FILTERS] if CONF_FILTERS in conf else []) + conf_copy[CONF_FILTERS] = ( + conf[CONF_DEVICE_CUSTOM_RAW_FILTERS] + if CONF_DEVICE_CUSTOM_RAW_FILTERS in conf + else [] + ) + (conf[CONF_FILTERS] if CONF_FILTERS in conf else []) sens = await sensor.new_sensor(conf_copy) - cg.add(var_dev.add_custom_sensor( - conf[CONF_DEVICE_CUSTOM_MESSAGE], sens)) + cg.add( + var_dev.add_custom_sensor(conf[CONF_DEVICE_CUSTOM_MESSAGE], sens) + ) cg.add(var.register_device(var_dev)) - cg.add(var.set_debug_mqtt(config[CONF_DEBUG_MQTT_HOST], config[CONF_DEBUG_MQTT_PORT], - config[CONF_DEBUG_MQTT_USERNAME], config[CONF_DEBUG_MQTT_PASSWORD])) + cg.add( + var.set_debug_mqtt( + config[CONF_DEBUG_MQTT_HOST], + config[CONF_DEBUG_MQTT_PORT], + config[CONF_DEBUG_MQTT_USERNAME], + config[CONF_DEBUG_MQTT_PASSWORD], + ) + ) - if (CONF_DEBUG_LOG_MESSAGES in config): + if CONF_DEBUG_LOG_MESSAGES in config: cg.add(var.set_debug_log_messages(config[CONF_DEBUG_LOG_MESSAGES])) - if (CONF_DEBUG_LOG_MESSAGES_RAW in config): - cg.add(var.set_debug_log_messages_raw( - config[CONF_DEBUG_LOG_MESSAGES_RAW])) - - if (CONF_NON_NASA_KEEPALIVE in config): + if CONF_DEBUG_LOG_MESSAGES_RAW in config: + cg.add(var.set_debug_log_messages_raw(config[CONF_DEBUG_LOG_MESSAGES_RAW])) + + 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])) - + + if CONF_DEBUG_LOG_UNDEFINED_MESSAGES in config: + cg.add( + var.set_debug_log_undefined_messages( + config[CONF_DEBUG_LOG_UNDEFINED_MESSAGES] + ) + ) + # Mapping of config keys to their corresponding methods config_actions = { CONF_DEBUG_LOG_MESSAGES: var.set_debug_log_messages, @@ -441,6 +581,6 @@ async def to_code(config): for key, method in config_actions.items(): if key in config: cg.add(method(config[key])) - + await cg.register_component(var, config) await uart.register_uart_device(var, config) diff --git a/components/samsung_ac/device_state_tracker.h b/components/samsung_ac/device_state_tracker.h index 394d492..98ef3b6 100644 --- a/components/samsung_ac/device_state_tracker.h +++ b/components/samsung_ac/device_state_tracker.h @@ -6,50 +6,62 @@ #include #include -namespace esphome { - -template -class DeviceStateTracker { - public: - DeviceStateTracker(unsigned long timeout_period) - : TIMEOUT_PERIOD(timeout_period) {} - - void update(const std::string &address, const T ¤t_value) { - unsigned long now = millis(); - - if (pending_changes_.find(address) != pending_changes_.end()) { - if (current_value == pending_changes_[address]) { - pending_changes_.erase(address); - } else { - ESP_LOGI("device_state_tracker", "Stale value received for device: %s, ignoring.", address.c_str()); - return; - } - } +namespace esphome +{ - if (last_values_.find(address) == last_values_.end() || last_values_[address] != current_value) { - pending_changes_[address] = current_value; - last_values_[address] = current_value; - last_update_time_[address] = now; + template + class DeviceStateTracker + { + public: + DeviceStateTracker(unsigned long timeout_period) + : TIMEOUT_PERIOD(timeout_period) {} - ESP_LOGI("device_state_tracker", "Value changed for device: %s", address.c_str()); - } else { - ESP_LOGD("device_state_tracker", "No change in value for device: %s", address.c_str()); + void update(const std::string &address, const T ¤t_value) + { + unsigned long now = millis(); - if (now - last_update_time_[address] > TIMEOUT_PERIOD) { - if (pending_changes_.find(address) != pending_changes_.end()) { - ESP_LOGW("device_state_tracker", "Timeout for device: %s, forcing update.", address.c_str()); + if (pending_changes_.find(address) != pending_changes_.end()) + { + if (current_value == pending_changes_[address]) + { pending_changes_.erase(address); } + else + { + ESP_LOGI("device_state_tracker", "Stale value received for device: %s, ignoring.", address.c_str()); + return; + } + } + + if (last_values_.find(address) == last_values_.end() || last_values_[address] != current_value) + { + pending_changes_[address] = current_value; + last_values_[address] = current_value; + last_update_time_[address] = now; + + ESP_LOGI("device_state_tracker", "Value changed for device: %s", address.c_str()); + } + else + { + ESP_LOGD("device_state_tracker", "No change in value for device: %s", address.c_str()); + + if ((now - last_update_time_[address]) % TIMEOUT_PERIOD == 0) + { + if (pending_changes_.find(address) != pending_changes_.end()) + { + ESP_LOGW("device_state_tracker", "Timeout for device: %s, forcing update.", address.c_str()); + pending_changes_.erase(address); + } + } } } - } - - private: - std::map last_values_; - std::map last_update_time_; - std::map pending_changes_; - const unsigned long TIMEOUT_PERIOD; -}; + + private: + std::map last_values_; + std::map last_update_time_; + std::map pending_changes_; + const unsigned long TIMEOUT_PERIOD; + }; } // namespace esphome diff --git a/components/samsung_ac/protocol.h b/components/samsung_ac/protocol.h index 1c951c1..43f0a19 100644 --- a/components/samsung_ac/protocol.h +++ b/components/samsung_ac/protocol.h @@ -94,6 +94,10 @@ namespace esphome virtual void set_swing_horizontal(const std::string address, bool horizontal) = 0; virtual void set_custom_sensor(const std::string address, uint16_t message_number, float value) = 0; virtual void set_error_code(const std::string address, int error_code) = 0; + virtual void set_outdoor_instantaneous_power(const std::string &address, float value) = 0; + virtual void set_outdoor_cumulative_energy(const std::string &address, float value) = 0; + virtual void set_outdoor_current(const std::string &address, float value) = 0; + virtual void set_outdoor_voltage(const std::string &address, float value) = 0; }; struct ProtocolRequest diff --git a/components/samsung_ac/protocol_nasa.cpp b/components/samsung_ac/protocol_nasa.cpp index 0b5774f..4c45c95 100644 --- a/components/samsung_ac/protocol_nasa.cpp +++ b/components/samsung_ac/protocol_nasa.cpp @@ -727,7 +727,34 @@ namespace esphome target->set_error_code(source, code); break; } - + case MessageNumber::LVAR_OUT_CONTROL_WATTMETER_1W_1MIN_SUM: + { + double value = static_cast(message.value); + LOG_MESSAGE(LVAR_OUT_CONTROL_WATTMETER_1W_1MIN_SUM, value, source, dest); + target->set_outdoor_instantaneous_power(source, value); + break; + } + case MessageNumber::LVAR_OUT_CONTROL_WATTMETER_ALL_UNIT_ACCUM: + { + double value = static_cast(message.value); + LOG_MESSAGE(LVAR_OUT_CONTROL_WATTMETER_ALL_UNIT_ACCUM, value, source, dest); + target->set_outdoor_cumulative_energy(source, value); + break; + } + case MessageNumber::VAR_OUT_SENSOR_CT1: + { + double value = static_cast(message.value); + LOG_MESSAGE(VAR_OUT_SENSOR_CT1, value, source, dest); + target->set_outdoor_current(source, value); + break; + } + case MessageNumber::LVAR_NM_OUT_SENSOR_VOLTAGE: + { + double value = static_cast(message.value); + LOG_MESSAGE(LVAR_NM_OUT_SENSOR_VOLTAGE, value, source, dest); + target->set_outdoor_voltage(source, value); + break; + } default: { double value = 0; @@ -748,16 +775,6 @@ namespace esphome LOG_MESSAGE(VAR_IN_FSV_3023, value, source, dest); break; - case 0x8414: - value = (double)message.value / 1000.0; - LOG_MESSAGE(LVAR_OUT_CONTROL_WATTMETER_ALL_UNIT_ACCUM, value, source, dest); - break; - - case 0x8413: - value = (double)message.value; - LOG_MESSAGE(LVAR_OUT_CONTROL_WATTMETER_1W_1MIN_SUM, value, source, dest); - break; - case 0x8411: value = (double)message.value; LOG_MESSAGE(NASA_OUTDOOR_CONTROL_WATTMETER_1UNIT, value, source, dest); @@ -880,6 +897,10 @@ namespace esphome target->publish_data(data); ESP_LOGW(TAG, "Resending packet %d number of attempts: %d", info.packet.command.packetNumber, info.retry_count); } + else if (info.retry_count >= 3) + { + ESP_LOGW(TAG, "Packet %d failed after 3 attempts.", info.packet.command.packetNumber); + } } } @@ -1071,7 +1092,6 @@ namespace esphome case 0x80af: case 0x8204: case 0x820a: - case 0x8217: case 0x8218: case 0x821a: case 0x8223: @@ -1132,9 +1152,6 @@ namespace esphome case 0x82a1: case 0x82b5: case 0x82b6: - case 0x8411: - case 0x8413: - case 0x8414: case 0x8608: case 0x860c: case 0x860d: @@ -1151,12 +1168,6 @@ namespace esphome case 0x8260: case 0x2400: case 0x2401: - case 0x24fc: - { - // ESP_LOGW(TAG, "s:%s d:%s Todo %s %li", source.c_str(), dest.c_str(), long_to_hex((int)message.messageNumber).c_str(), message.value); - break; // Todo - } - case 0x8601: // STR_out_install_inverter_and_bootloader_info case 0x608: // STR_ad_dbcode_micom_main case 0x603: // STR_ad_option_cycle diff --git a/components/samsung_ac/protocol_nasa.h b/components/samsung_ac/protocol_nasa.h index 499d407..df50e74 100644 --- a/components/samsung_ac/protocol_nasa.h +++ b/components/samsung_ac/protocol_nasa.h @@ -89,6 +89,10 @@ namespace esphome VAR_in_temp_eva_in_f = 0x4205, VAR_in_temp_eva_out_f = 0x4206, VAR_out_error_code = 0x8235, + LVAR_OUT_CONTROL_WATTMETER_1W_1MIN_SUM = 0x8413, + LVAR_OUT_CONTROL_WATTMETER_ALL_UNIT_ACCUM = 0x8414, + VAR_OUT_SENSOR_CT1 = 0x8217, + LVAR_NM_OUT_SENSOR_VOLTAGE = 0x24fc, }; struct Address diff --git a/components/samsung_ac/samsung_ac.h b/components/samsung_ac/samsung_ac.h index 2891bb7..60928d0 100644 --- a/components/samsung_ac/samsung_ac.h +++ b/components/samsung_ac/samsung_ac.h @@ -30,6 +30,26 @@ namespace esphome void loop() override; void dump_config() override; + template + void update_device_sensor(const std::string &address, SensorType Samsung_AC_Device::*sensor_ptr, ValueType value) + { + Samsung_AC_Device *dev = find_device(address); + if (dev != nullptr && dev->*sensor_ptr != nullptr) + { + dev->update_sensor_state(dev->*sensor_ptr, value); + } + } + + template + void execute_if_device_exists(const std::string &address, Func func) + { + Samsung_AC_Device *dev = find_device(address); + if (dev != nullptr) + { + func(dev); + } + } + void set_debug_mqtt(std::string host, int port, std::string username, std::string password) { debug_mqtt_host = host; @@ -56,146 +76,150 @@ namespace esphome { debug_log_undefined_messages = value; } + void register_device(Samsung_AC_Device *device); - void /*MessageTarget::*/ register_address(const std::string address) override + void register_address(const std::string address) override { addresses_.insert(address); } - uint32_t /*MessageTarget::*/ get_miliseconds() + uint32_t get_miliseconds() { return millis(); } - void /*MessageTarget::*/ publish_data(std::vector &data); + void publish_data(std::vector &data); - void /*MessageTarget::*/ set_room_temperature(const std::string address, float value) override + void set_room_temperature(const std::string address, float value) override { - Samsung_AC_Device *dev = find_device(address); - if (dev != nullptr) - dev->update_room_temperature(value); + execute_if_device_exists(address, [value](Samsung_AC_Device *dev) + { dev->update_room_temperature(value); }); } - void /*MessageTarget::*/ set_outdoor_temperature(const std::string address, float value) override + void set_outdoor_temperature(const std::string address, float value) override { - Samsung_AC_Device *dev = find_device(address); - if (dev != nullptr) - dev->update_outdoor_temperature(value); + execute_if_device_exists(address, [value](Samsung_AC_Device *dev) + { dev->update_sensor_state(dev->outdoor_temperature, value); }); } - void /*MessageTarget::*/ set_indoor_eva_in_temperature(const std::string address, float value) override + void 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); + execute_if_device_exists(address, [value](Samsung_AC_Device *dev) + { dev->update_sensor_state(dev->indoor_eva_in_temperature, value); }); } - void /*MessageTarget::*/ set_indoor_eva_out_temperature(const std::string address, float value) override + void 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); + execute_if_device_exists(address, [value](Samsung_AC_Device *dev) + { dev->update_sensor_state(dev->indoor_eva_out_temperature, value); }); } - void /*MessageTarget::*/ set_target_temperature(const std::string address, float value) override + void 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); + execute_if_device_exists(address, [value](Samsung_AC_Device *dev) + { dev->update_target_temperature(value); }); } - void /*MessageTarget::*/ set_water_outlet_target(const std::string address, float value) override + void set_water_outlet_target(const std::string address, float value) override { - Samsung_AC_Device *dev = find_device(address); - if (dev != nullptr) - dev->update_water_outlet_target(value); + execute_if_device_exists(address, [value](Samsung_AC_Device *dev) + { dev->update_water_outlet_target(value); }); } - void /*MessageTarget::*/ set_target_water_temperature(const std::string address, float value) override + void set_target_water_temperature(const std::string address, float value) override { - Samsung_AC_Device *dev = find_device(address); - if (dev != nullptr) - dev->update_target_water_temperature(value); + execute_if_device_exists(address, [value](Samsung_AC_Device *dev) + { dev->update_target_water_temperature(value); }); } - void /*MessageTarget::*/ set_power(const std::string address, bool value) override + void set_power(const std::string address, bool value) override { - Samsung_AC_Device *dev = find_device(address); - if (dev != nullptr) - dev->update_power(value); + execute_if_device_exists(address, [value](Samsung_AC_Device *dev) + { dev->update_power(value); }); } - void /*MessageTarget::*/ set_automatic_cleaning(const std::string address, bool value) override + void 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); + execute_if_device_exists(address, [value](Samsung_AC_Device *dev) + { dev->update_automatic_cleaning(value); }); } - void /*MessageTarget::*/ set_water_heater_power(const std::string address, bool value) override + + void set_water_heater_power(const std::string address, bool value) override { - Samsung_AC_Device *dev = find_device(address); - if (dev != nullptr) - dev->update_water_heater_power(value); + execute_if_device_exists(address, [value](Samsung_AC_Device *dev) + { dev->update_water_heater_power(value); }); } - void /*MessageTarget::*/ set_mode(const std::string address, Mode mode) override + void set_mode(const std::string address, Mode mode) override { - Samsung_AC_Device *dev = find_device(address); - if (dev != nullptr) - dev->update_mode(mode); + execute_if_device_exists(address, [mode](Samsung_AC_Device *dev) + { dev->update_mode(mode); }); } - void /*MessageTarget::*/ set_water_heater_mode(const std::string address, WaterHeaterMode waterheatermode) override + void set_water_heater_mode(const std::string address, WaterHeaterMode waterheatermode) override { - Samsung_AC_Device *dev = find_device(address); - if (dev != nullptr) - dev->update_water_heater_mode(waterheatermode); + execute_if_device_exists(address, [waterheatermode](Samsung_AC_Device *dev) + { dev->update_water_heater_mode(waterheatermode); }); } - void /*MessageTarget::*/ set_fanmode(const std::string address, FanMode fanmode) override + void set_fanmode(const std::string address, FanMode fanmode) override { - Samsung_AC_Device *dev = find_device(address); - if (dev != nullptr) - dev->update_fanmode(fanmode); + execute_if_device_exists(address, [fanmode](Samsung_AC_Device *dev) + { dev->update_fanmode(fanmode); }); } - void /*MessageTarget::*/ set_altmode(const std::string address, AltMode altmode) override + void set_altmode(const std::string address, AltMode altmode) override { - Samsung_AC_Device *dev = find_device(address); - if (dev != nullptr) - dev->update_altmode(altmode); + execute_if_device_exists(address, [altmode](Samsung_AC_Device *dev) + { dev->update_altmode(altmode); }); } - void /*MessageTarget::*/ set_swing_vertical(const std::string address, bool vertical) override + void set_swing_vertical(const std::string address, bool vertical) override { - Samsung_AC_Device *dev = find_device(address); - if (dev != nullptr) - dev->update_swing_vertical(vertical); + execute_if_device_exists(address, [vertical](Samsung_AC_Device *dev) + { dev->update_swing_vertical(vertical); }); } - void /*MessageTarget::*/ set_swing_horizontal(const std::string address, bool horizontal) override + void set_swing_horizontal(const std::string address, bool horizontal) override { - Samsung_AC_Device *dev = find_device(address); - if (dev != nullptr) - dev->update_swing_horizontal(horizontal); + execute_if_device_exists(address, [horizontal](Samsung_AC_Device *dev) + { dev->update_swing_horizontal(horizontal); }); } - void /*MessageTarget::*/ set_custom_sensor(const std::string address, uint16_t message_number, float value) override + void set_custom_sensor(const std::string address, uint16_t message_number, float value) override { - Samsung_AC_Device *dev = find_device(address); - if (dev != nullptr) - dev->update_custom_sensor(message_number, value); + execute_if_device_exists(address, [message_number, value](Samsung_AC_Device *dev) + { dev->update_custom_sensor(message_number, value); }); } - void /*MessageTarget::*/ set_error_code(const std::string address, int value) override + void set_error_code(const std::string address, int value) override { - Samsung_AC_Device *dev = find_device(address); - if (dev != nullptr) - dev->update_error_code(value); + execute_if_device_exists(address, [value](Samsung_AC_Device *dev) + { dev->update_error_code(value); }); + } + + void set_outdoor_instantaneous_power(const std::string &address, float value) + { + update_device_sensor(address, &Samsung_AC_Device::outdoor_instantaneous_power, value); + } + + void set_outdoor_cumulative_energy(const std::string &address, float value) + { + update_device_sensor(address, &Samsung_AC_Device::outdoor_cumulative_energy, value); + } + + void set_outdoor_current(const std::string &address, float value) + { + update_device_sensor(address, &Samsung_AC_Device::outdoor_current, value); + } + + void set_outdoor_voltage(const std::string &address, float value) + { + update_device_sensor(address, &Samsung_AC_Device::outdoor_voltage, value); } protected: - Samsung_AC_Device *find_device(const std::string address) + Samsung_AC_Device *find_device(const std::string &address) { auto it = devices_.find(address); if (it != devices_.end()) diff --git a/components/samsung_ac/samsung_ac_device.h b/components/samsung_ac/samsung_ac_device.h index ec487e7..eec979c 100644 --- a/components/samsung_ac/samsung_ac_device.h +++ b/components/samsung_ac/samsung_ac_device.h @@ -108,6 +108,10 @@ namespace esphome sensor::Sensor *indoor_eva_in_temperature{nullptr}; sensor::Sensor *indoor_eva_out_temperature{nullptr}; sensor::Sensor *error_code{nullptr}; + sensor::Sensor *outdoor_instantaneous_power{nullptr}; + sensor::Sensor *outdoor_cumulative_energy{nullptr}; + sensor::Sensor *outdoor_current{nullptr}; + sensor::Sensor *outdoor_voltage{nullptr}; Samsung_AC_Number *target_temperature{nullptr}; Samsung_AC_Number *water_outlet_target{nullptr}; Samsung_AC_Number *target_water_temperature{nullptr}; @@ -117,12 +121,53 @@ namespace esphome Samsung_AC_Mode_Select *mode{nullptr}; Samsung_AC_Water_Heater_Mode_Select *waterheatermode{nullptr}; Samsung_AC_Climate *climate{nullptr}; - std::vector custom_sensors; + std::map custom_sensor_map; float room_temperature_offset{0}; - void set_room_temperature_sensor(sensor::Sensor *sensor) + template + void update_swing(SwingType &swing_variable, uint8_t mask, bool value) { - room_temperature = sensor; + swing_variable = combine(swing_variable, mask, value); + climate->publish_state(); + } + + void update_sensor_state(sensor::Sensor *target_sensor, float value) + { + if (target_sensor != nullptr) + { + target_sensor->publish_state(value); + } + } + + void set_error_code_sensor(sensor::Sensor *sensor) + { + error_code = sensor; + } + + void update_error_code(int value) + { + if (error_code != nullptr) + error_code->publish_state(value); + } + + void set_outdoor_instantaneous_power_sensor(sensor::Sensor *sensor) + { + outdoor_instantaneous_power = sensor; + } + + void set_outdoor_cumulative_energy_sensor(sensor::Sensor *sensor) + { + outdoor_cumulative_energy = sensor; + } + + void set_outdoor_current_sensor(sensor::Sensor *sensor) + { + outdoor_current = sensor; + } + + void set_outdoor_voltage_sensor(sensor::Sensor *sensor) + { + outdoor_voltage = sensor; } void set_outdoor_temperature_sensor(sensor::Sensor *sensor) @@ -140,17 +185,34 @@ namespace esphome indoor_eva_out_temperature = sensor; } - void set_error_code_sensor(sensor::Sensor *sensor) + void update_custom_sensor(uint16_t message_number, float value) { - error_code = sensor; + auto it = custom_sensor_map.find(message_number); + if (it != custom_sensor_map.end()) + { + it->second->publish_state(value); + } + } + + void set_room_temperature_sensor(sensor::Sensor *sensor) + { + room_temperature = sensor; + } + + void update_room_temperature(float value) + { + if (room_temperature != nullptr) + room_temperature->publish_state(value + room_temperature_offset); + if (climate != nullptr) + { + climate->current_temperature = value + room_temperature_offset; + climate->publish_state(); + } } void add_custom_sensor(int message_number, sensor::Sensor *sensor) { - Samsung_AC_Sensor cust_sensor; - cust_sensor.message_number = (uint16_t)message_number; - cust_sensor.sensor = sensor; - custom_sensors.push_back(std::move(cust_sensor)); + custom_sensor_map[(uint16_t)message_number] = sensor; } void set_power_switch(Samsung_AC_Switch *switch_) @@ -370,8 +432,7 @@ namespace esphome { if (climate != nullptr) { - climate->swing_mode = combine(climate->swing_mode, 1, value); - climate->publish_state(); + update_swing(climate->swing_mode, 1, value); } } @@ -379,53 +440,10 @@ namespace esphome { if (climate != nullptr) { - climate->swing_mode = combine(climate->swing_mode, 2, value); - climate->publish_state(); - } - } - - void update_room_temperature(float value) - { - if (room_temperature != nullptr) - room_temperature->publish_state(value + room_temperature_offset); - if (climate != nullptr) - { - climate->current_temperature = value + room_temperature_offset; - climate->publish_state(); + update_swing(climate->swing_mode, 2, value); } } - void update_outdoor_temperature(float value) - { - if (outdoor_temperature != nullptr) - 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_error_code(int value) - { - if (error_code != nullptr) - error_code->publish_state(value); - } - - void update_custom_sensor(uint16_t message_number, float value) - { - for (auto &sensor : custom_sensors) - if (sensor.message_number == message_number) - sensor.sensor->publish_state(value); - } - void publish_request(ProtocolRequest &request) { protocol->publish_request(target, address, request); diff --git a/example.yaml b/example.yaml index 0d0c32a..51365e4 100644 --- a/example.yaml +++ b/example.yaml @@ -131,7 +131,27 @@ samsung_ac: # Additionally, by using the blueprint available at https://github.com/omerfaruk-aran/esphome_samsung_ac_blueprint, # you can automatically send detailed error messages to your mobile devices based on the captured error codes. error_code: - name: "Error Code" + name: error_code + + # This sensor measures the instantaneous power consumption of the outdoor unit in Watts. + # The captured value represents the current power draw of the outdoor HVAC components, helping track energy usage patterns. + outdoor_instantaneous_power: + name: "Outdoor Instantaneous Power" + + # This sensor records the cumulative energy consumption of the outdoor unit in kWh. + # It calculates the total energy consumed over time, allowing users to monitor and analyze energy efficiency. + outdoor_cumulative_energy: + name: "Outdoor Cumulative Energy" + + # This sensor measures the current drawn by the outdoor unit in Amperes. + # Monitoring current values helps identify electrical irregularities and ensure safe power levels in the system. + outdoor_current: + name: "Outdoor Current" + + # This sensor tracks the voltage supplied to the outdoor unit in Volts. + # Consistent voltage readings indicate stable power delivery, while deviations can help detect electrical issues in the system. + outdoor_voltage: + name: "Outdoor Voltage" # Only supported on NASA based heatpumps water_temperature: