diff --git a/components/samsung_ac/__init__.py b/components/samsung_ac/__init__.py index 7bf08cd..862c99b 100644 --- a/components/samsung_ac/__init__.py +++ b/components/samsung_ac/__init__.py @@ -8,10 +8,14 @@ DEVICE_CLASS_HUMIDITY, CONF_UNIT_OF_MEASUREMENT, CONF_DEVICE_CLASS, + CONF_FILTERS, UNIT_CELSIUS, UNIT_PERCENT, ) -from esphome.core import CORE +from esphome.core import ( + CORE, + Lambda +) CODEOWNERS = ["matthias882", "lanwin"] DEPENDENCIES = ["uart"] @@ -54,6 +58,47 @@ CONF_DEVICE_POWER = "power" CONF_DEVICE_MODE = "mode" CONF_DEVICE_CLIMATE = "climate" +CONF_DEVICE_CUSTOM = "custom_sensor" +CONF_RAW_FILTERS = "raw_filters" +CONF_DEVICE_MESSAGE = "message" +CUSTOM_SENSOR_SCHEMA = sensor.sensor_schema().extend({ + cv.Required(CONF_DEVICE_MESSAGE): cv.hex_int, +}) + +def custom_sensor_schema( + message: int, + unit_of_measurement: str = sensor._UNDEF, + icon: str = sensor._UNDEF, + accuracy_decimals: int = sensor._UNDEF, + device_class: str = sensor._UNDEF, + state_class: str = sensor._UNDEF, + entity_category: str = sensor._UNDEF, + raw_filters = [] +): + return sensor.sensor_schema( + unit_of_measurement=unit_of_measurement, + icon=icon, + accuracy_decimals=accuracy_decimals, + device_class=device_class, + state_class=state_class, + entity_category=entity_category, + ).extend({ + cv.Optional(CONF_DEVICE_MESSAGE, default=message): cv.hex_int, + cv.Optional(CONF_RAW_FILTERS, default=raw_filters): sensor.validate_filters + }) + +def temperature_sensor_schema(message: int): + return custom_sensor_schema( + message=message, + unit_of_measurement=UNIT_CELSIUS, + accuracy_decimals=1, + device_class=DEVICE_CLASS_TEMPERATURE, + state_class=STATE_CLASS_MEASUREMENT, + raw_filters=[ + { "lambda": Lambda("return (int16_t)x;") }, + { "multiply": 0.1 } + ], + ) DEVICE_SCHEMA = ( cv.Schema( @@ -88,6 +133,7 @@ cv.Optional(CONF_DEVICE_POWER): switch.switch_schema(Samsung_AC_Switch), cv.Optional(CONF_DEVICE_MODE): SELECT_MODE_SCHEMA, cv.Optional(CONF_DEVICE_CLIMATE): CLIMATE_SCHEMA, + cv.Optional(CONF_DEVICE_CUSTOM, default=[]): cv.ensure_list(CUSTOM_SENSOR_SCHEMA), } ) ) @@ -177,6 +223,11 @@ async def to_code(config): var_cli = cg.new_Pvariable(conf[CONF_ID]) await climate.register_climate(var_cli, conf) cg.add(var_dev.set_climate(var_cli)) + + 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_MESSAGE], sens)) cg.add(var.register_device(var_dev)) diff --git a/components/samsung_ac/protocol.h b/components/samsung_ac/protocol.h index 7f38675..265d5e9 100644 --- a/components/samsung_ac/protocol.h +++ b/components/samsung_ac/protocol.h @@ -1,5 +1,6 @@ #pragma once +#include #include "esphome/core/optional.h" #include "util.h" @@ -77,6 +78,8 @@ namespace esphome 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; + virtual optional> get_custom_sensors(const std::string address) = 0; + virtual void set_custom_sensor(const std::string address, uint16_t message_number, float value) = 0; }; struct ProtocolRequest diff --git a/components/samsung_ac/protocol_nasa.cpp b/components/samsung_ac/protocol_nasa.cpp index 36eefd5..9d9fe92 100644 --- a/components/samsung_ac/protocol_nasa.cpp +++ b/components/samsung_ac/protocol_nasa.cpp @@ -1,5 +1,6 @@ #include #include +#include #include "esphome/core/log.h" #include "esphome/core/util.h" #include "esphome/core/hal.h" @@ -521,7 +522,7 @@ namespace esphome } } - void process_messageset(std::string source, std::string dest, MessageSet &message, MessageTarget *target) + void process_messageset(std::string source, std::string dest, MessageSet &message, optional> &custom, MessageTarget *target) { if (debug_mqtt_connected()) { @@ -539,6 +540,11 @@ namespace esphome } } + if (custom.has_value() && custom.value().find((uint16_t) message.messageNumber) != custom.value().end()) + { + target->set_custom_sensor(source, (uint16_t) message.messageNumber, (float) message.value); + } + switch (message.messageNumber) { case MessageNumber::VAR_in_temp_room_f: // unit = 'Celsius' from XML @@ -770,9 +776,10 @@ namespace esphome if (packet_.commad.dataType != DataType::Notification) return; + optional> custom = target->get_custom_sensors(source); for (auto &message : packet_.messages) { - process_messageset(source, dest, message, target); + process_messageset(source, dest, message, custom, target); } } diff --git a/components/samsung_ac/samsung_ac.h b/components/samsung_ac/samsung_ac.h index 4ac9770..ceb3e1c 100644 --- a/components/samsung_ac/samsung_ac.h +++ b/components/samsung_ac/samsung_ac.h @@ -138,6 +138,21 @@ namespace esphome dev->update_swing_horizontal(horizontal); } + optional> /*MessageTarget::*/ get_custom_sensors(const std::string address) override + { + Samsung_AC_Device *dev = find_device(address); + if (dev != nullptr) + return optional>(dev->get_custom_sensors()); + return optional>(); + } + + void /*MessageTarget::*/ 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); + } + 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 fb03c82..df725c8 100644 --- a/components/samsung_ac/samsung_ac_device.cpp +++ b/components/samsung_ac/samsung_ac_device.cpp @@ -3,6 +3,7 @@ #include "util.h" #include "conversions.h" #include +#include namespace esphome { diff --git a/components/samsung_ac/samsung_ac_device.h b/components/samsung_ac/samsung_ac_device.h index acdf456..3764750 100644 --- a/components/samsung_ac/samsung_ac_device.h +++ b/components/samsung_ac/samsung_ac_device.h @@ -65,6 +65,12 @@ namespace esphome } }; + struct Samsung_AC_Sensor + { + uint16_t message_number; + sensor::Sensor *sensor; + }; + class Samsung_AC_Device { public: @@ -84,6 +90,7 @@ namespace esphome Samsung_AC_Switch *power{nullptr}; Samsung_AC_Mode_Select *mode{nullptr}; Samsung_AC_Climate *climate{nullptr}; + std::vector custom_sensors; void set_room_temperature_sensor(sensor::Sensor *sensor) { @@ -105,6 +112,22 @@ namespace esphome room_humidity = sensor; } + 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)); + } + + std::set get_custom_sensors() + { + std::set numbers; + for (auto &sensor: custom_sensors) + numbers.insert(sensor.message_number); + return numbers; + } + void set_power_switch(Samsung_AC_Switch *switch_) { power = switch_; @@ -263,6 +286,13 @@ namespace esphome room_humidity->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);