diff --git a/components/tclac/climate.py b/components/tclac/climate.py index 75f7bde..0aca9c9 100644 --- a/components/tclac/climate.py +++ b/components/tclac/climate.py @@ -9,7 +9,7 @@ from esphome.const import ( CONF_MAX_TEMPERATURE, CONF_MIN_TEMPERATURE, CONF_SUPPORTED_MODES, - CONF_SUPPORTED_PRESETS, + CONF_SUPPORTED_FAN_MODES, CONF_SUPPORTED_SWING_MODES, ) @@ -17,7 +17,6 @@ from esphome.components.climate import ( ClimateMode, ClimatePreset, ClimateSwingMode, - CONF_CURRENT_TEMPERATURE, ) AUTO_LOAD = ["climate"] @@ -26,7 +25,6 @@ DEPENDENCIES = ["climate", "uart"] CONF_RX_LED = "rx_led" CONF_TX_LED = "tx_led" CONF_DISPLAY = "show_display" -CONF_USE_OLED = "use_oled_display" CONF_MODULE_DISPLAY = "show_module_display" CONF_VERTICAL_AIRFLOW = "vertical_airflow" CONF_HORIZONTAL_AIRFLOW = "horizontal_airflow" @@ -36,6 +34,48 @@ CONF_HORIZONTAL_SWING_MODE = "horizontal_swing_mode" tclac_ns = cg.esphome_ns.namespace("tclac") tclacClimate = tclac_ns.class_("tclacClimate", uart.UARTDevice, climate.Climate, cg.PollingComponent) +SUPPORTED_FAN_MODES_OPTIONS = { + "AUTO": ClimateMode.CLIMATE_FAN_AUTO, # Доступен всегда + "QUIET": ClimateMode.CLIMATE_FAN_QUIET, + "LOW": ClimateMode.CLIMATE_FAN_LOW, + "MIDDLE": ClimateMode.CLIMATE_FAN_MIDDLE, + "MEDIUM": ClimateMode.CLIMATE_FAN_MEDIUM, + "HIGH": ClimateMode.CLIMATE_FAN_HIGH, + "FOCUS": ClimateMode.CLIMATE_FAN_FOCUS, + "DIFFUSE": ClimateMode.CLIMATE_FAN_DIFFUSE, +} + +SUPPORTED_SWING_MODES_OPTIONS = { + "OFF": ClimateSwingMode.CLIMATE_SWING_OFF, # Доступен всегда + "VERTICAL": ClimateSwingMode.CLIMATE_SWING_VERTICAL, + "HORIZONTAL": ClimateSwingMode.CLIMATE_SWING_HORIZONTAL, + "BOTH": ClimateSwingMode.CLIMATE_SWING_BOTH, +} + +SUPPORTED_CLIMATE_MODES_OPTIONS = { + "OFF": ClimateMode.CLIMATE_MODE_OFF, # Доступен всегда + "AUTO": ClimateMode.CLIMATE_MODE_AUTO, # Доступен всегда + "COOL": ClimateMode.CLIMATE_MODE_COOL, + "HEAT": ClimateMode.CLIMATE_MODE_HEAT, + "DRY": ClimateMode.CLIMATE_MODE_DRY, + "FAN_ONLY": ClimateMode.CLIMATE_MODE_FAN_ONLY, +} + +VerticalSwingDirection = tclac_ns.enum("VerticalSwingDirection", True) +VERTICAL_SWING_DIRECTION_OPTIONS = { + "UP_DOWN": VerticalSwingDirection.UPDOWN, + "UPSIDE": VerticalSwingDirection.UPSIDE, + "DOWNSIDE": VerticalSwingDirection.DOWNSIDE, +} + +HorizontalSwingDirection = tclac_ns.enum("HorizontalSwingDirection", True) +HORIZONTAL_SWING_DIRECTION_OPTIONS = { + "LEFT_RIGHT": HorizontalSwingDirection.LEFT_RIGHT, + "LEFTSIDE": HorizontalSwingDirection.LEFTSIDE, + "CENTER": HorizontalSwingDirection.CENTER, + "RIGHTSIDE": HorizontalSwingDirection.RIGHTSIDE, +} + AirflowVerticalDirection = tclac_ns.enum("AirflowVerticalDirection", True) AIRFLOW_VERTICAL_DIRECTION_OPTIONS = { "LAST": AirflowVerticalDirection.LAST, @@ -56,40 +96,6 @@ AIRFLOW_HORIZONTAL_DIRECTION_OPTIONS = { "MAX_RIGHT": AirflowHorizontalDirection.MAX_RIGHT, } -VerticalSwingDirection = tclac_ns.enum("VerticalSwingDirection", True) -VERTICAL_SWING_DIRECTION_OPTIONS = { - "UP_DOWN": VerticalSwingDirection.UPDOWN, - "UPSIDE": VerticalSwingDirection.UPSIDE, - "DOWNSIDE": VerticalSwingDirection.DOWNSIDE, -} - -HorizontalSwingDirection = tclac_ns.enum("HorizontalSwingDirection", True) -HORIZONTAL_SWING_DIRECTION_OPTIONS = { - "LEFT_RIGHT": HorizontalSwingDirection.LEFT_RIGHT, - "LEFTSIDE": HorizontalSwingDirection.LEFTSIDE, - "CENTER": HorizontalSwingDirection.CENTER, - "RIGHTSIDE": HorizontalSwingDirection.RIGHTSIDE, -} - -SUPPORTED_SWING_MODES_OPTIONS = { - "OFF": ClimateSwingMode.CLIMATE_SWING_OFF, - "VERTICAL": ClimateSwingMode.CLIMATE_SWING_VERTICAL, - "HORIZONTAL": ClimateSwingMode.CLIMATE_SWING_HORIZONTAL, - "BOTH": ClimateSwingMode.CLIMATE_SWING_BOTH, -} - -SUPPORTED_CLIMATE_MODES_OPTIONS = { - "OFF": ClimateMode.CLIMATE_MODE_OFF, # always available - "AUTO": ClimateMode.CLIMATE_MODE_AUTO, # always available - "COOL": ClimateMode.CLIMATE_MODE_COOL, - "HEAT": ClimateMode.CLIMATE_MODE_HEAT, - "DRY": ClimateMode.CLIMATE_MODE_DRY, - "FAN_ONLY": ClimateMode.CLIMATE_MODE_FAN_ONLY, -} - -# Упрощаем себе житзнь и даем спискам названия покороче -validate_presets = cv.enum(AIRFLOW_HORIZONTAL_DIRECTION_OPTIONS, upper=True) - CONFIG_SCHEMA = cv.All( climate.CLIMATE_SCHEMA.extend( { @@ -99,8 +105,9 @@ CONFIG_SCHEMA = cv.All( cv.Optional(CONF_RX_LED): pins.gpio_output_pin_schema, cv.Optional(CONF_TX_LED): pins.gpio_output_pin_schema, cv.Optional(CONF_MODULE_DISPLAY, default=True): cv.boolean, - cv.Optional(CONF_SUPPORTED_MODES): cv.ensure_list(cv.enum(SUPPORTED_CLIMATE_MODES_OPTIONS, upper=True)), - cv.Optional(CONF_SUPPORTED_SWING_MODES,default=["OFF","VERTICAL","HORIZONTAL","BOTH",],): cv.ensure_list(cv.enum(SUPPORTED_SWING_MODES_OPTIONS, upper=True)), + cv.Optional(CONF_SUPPORTED_SWING_MODES,default=["OFF","VERTICAL","HORIZONTAL","BOTH",],): cv.ensure_list(cv.enum(SUPPORTED_SWING_MODES_OPTIONS, upper=True)), + cv.Optional(CONF_SUPPORTED_MODES,default=["OFF","AUTO","COOL","HEAT","DRY","FAN_ONLY",],): cv.ensure_list(cv.enum(SUPPORTED_CLIMATE_MODES_OPTIONS, upper=True)), + cv.Optional(CONF_SUPPORTED_FAN_MODES,default=["AUTO","QUIET","LOW","MIDDLE","MEDIUM","HIGH","FOCUS","DIFFUSE",],): cv.ensure_list(cv.enum(SUPPORTED_FAN_MODES_OPTIONS, upper=True)), } ) .extend(uart.UART_DEVICE_SCHEMA) @@ -119,9 +126,9 @@ HorizontalAirflowAction = tclac_ns.class_("HorizontalAirflowAction", automation. VerticalSwingDirectionAction = tclac_ns.class_("VerticalSwingDirectionAction", automation.Action) HorizontalSwingDirectionAction = tclac_ns.class_("HorizontalSwingDirectionAction", automation.Action) -# TCLAC_ACTION_BASE_SCHEMA = cv.Schema( TCLAC_ACTION_BASE_SCHEMA = automation.maybe_simple_id({cv.GenerateID(CONF_ID): cv.use_id(tclacClimate),}) +# Регистрация событий включения и отключения дисплея кондиционера @automation.register_action( "climate.tclac.display_on", DisplayOnAction, cv.Schema ) @@ -133,7 +140,7 @@ async def display_action_to_code(config, action_id, template_arg, args): var = cg.new_Pvariable(action_id, template_arg, paren) return var - +# Регистрация событий включения и отключения пищалки кондиционера @automation.register_action( "climate.tclac.beeper_on", BeeperOnAction, cv.Schema ) @@ -144,8 +151,8 @@ async def beeper_action_to_code(config, action_id, template_arg, args): paren = await cg.get_variable(config[CONF_ID]) var = cg.new_Pvariable(action_id, template_arg, paren) return var - +# Регистрация событий включения и отключения светодиодов связи модуля @automation.register_action( "climate.tclac.module_display_on", ModuleDisplayOnAction, cv.Schema ) @@ -157,8 +164,7 @@ async def module_display_action_to_code(config, action_id, template_arg, args): var = cg.new_Pvariable(action_id, template_arg, paren) return var - -# Set vertical airflow direction action +# Регистрация события установки вертикальной фиксации заслонки @automation.register_action( "climate.tclac.set_vertical_airflow", VerticalAirflowAction, @@ -179,7 +185,7 @@ async def tclac_set_vertical_airflow_to_code(config, action_id, template_arg, ar return var -# Set horizontal airflow direction action +# Регистрация события установки горизонтальной фиксации заслонок @automation.register_action( "climate.tclac.set_horizontal_airflow", HorizontalAirflowAction, @@ -236,30 +242,33 @@ async def tclac_set_horizontal_swing_direction_to_code(config, action_id, templa return var - +# Добавление конфигурации в код def to_code(config): var = cg.new_Pvariable(config[CONF_ID]) yield cg.register_component(var, config) yield uart.register_uart_device(var, config) yield climate.register_climate(var, config) - - if CONF_SUPPORTED_MODES in config: - cg.add(var.set_supported_modes(config[CONF_SUPPORTED_MODES])) - if CONF_SUPPORTED_SWING_MODES in config: - cg.add(var.set_supported_swing_modes(config[CONF_SUPPORTED_SWING_MODES])) + + if CONF_USE_OLED in config: + cg.add_define("USE_OLED_DISPLAY") if CONF_BEEPER in config: cg.add(var.set_beeper_state(config[CONF_BEEPER])) if CONF_DISPLAY in config: cg.add(var.set_display_state(config[CONF_DISPLAY])) + if CONF_SUPPORTED_MODES in config: + cg.add(var.set_supported_modes(config[CONF_SUPPORTED_MODES])) if CONF_MODULE_DISPLAY in config: cg.add(var.set_module_display_state(config[CONF_MODULE_DISPLAY])) - if CONF_USE_OLED in config: - cg.add_define("USE_OLED_DISPLAY") - if CONF_RX_LED in config: - cg.add_define("CONF_RX_LED") - rx_led_pin = yield cg.gpio_pin_expression(config[CONF_RX_LED]) - cg.add(var.set_rx_led_pin(rx_led_pin)) + if CONF_SUPPORTED_FAN_MODES in config: + cg.add(var.set_supported_fan_modes(config[CONF_SUPPORTED_FAN_MODES])) + if CONF_SUPPORTED_SWING_MODES in config: + cg.add(var.set_supported_swing_modes(config[CONF_SUPPORTED_SWING_MODES])) + if CONF_TX_LED in config: cg.add_define("CONF_TX_LED") tx_led_pin = yield cg.gpio_pin_expression(config[CONF_TX_LED]) - cg.add(var.set_tx_led_pin(tx_led_pin)) \ No newline at end of file + cg.add(var.set_tx_led_pin(tx_led_pin)) + if CONF_RX_LED in config: + cg.add_define("CONF_RX_LED") + rx_led_pin = yield cg.gpio_pin_expression(config[CONF_RX_LED]) + cg.add(var.set_rx_led_pin(rx_led_pin)) \ No newline at end of file diff --git a/components/tclac/tclac.cpp b/components/tclac/tclac.cpp index 2573b3a..5cfd712 100644 --- a/components/tclac/tclac.cpp +++ b/components/tclac/tclac.cpp @@ -11,34 +11,29 @@ ClimateTraits tclacClimate::traits() { traits.set_supports_action(false); - traits.set_supported_modes( - { - climate::CLIMATE_MODE_AUTO, - climate::CLIMATE_MODE_COOL, - climate::CLIMATE_MODE_DRY, - climate::CLIMATE_MODE_FAN_ONLY, - climate::CLIMATE_MODE_HEAT, - climate::CLIMATE_MODE_OFF - }); +// traits.set_supported_modes( +// { +// climate::CLIMATE_MODE_AUTO, +// climate::CLIMATE_MODE_COOL, +// climate::CLIMATE_MODE_DRY, +// climate::CLIMATE_MODE_FAN_ONLY, +// climate::CLIMATE_MODE_HEAT, +// climate::CLIMATE_MODE_OFF +// }); - traits.set_supported_fan_modes( - { - climate::CLIMATE_FAN_AUTO, // auto - climate::CLIMATE_FAN_QUIET, // silent - climate::CLIMATE_FAN_LOW, // | - climate::CLIMATE_FAN_MIDDLE, // || - climate::CLIMATE_FAN_MEDIUM, // ||| - climate::CLIMATE_FAN_HIGH, // |||| - climate::CLIMATE_FAN_FOCUS, // ||||| - climate::CLIMATE_FAN_DIFFUSE // POWER [7] - }); - - //traits.set_supported_swing_modes({climate::CLIMATE_SWING_OFF,climate::CLIMATE_SWING_BOTH,climate::CLIMATE_SWING_VERTICAL,climate::CLIMATE_SWING_HORIZONTAL}); - traits.set_supported_swing_modes(this->supported_swing_modes_); +// traits.set_supported_fan_modes( +// { +// climate::CLIMATE_FAN_AUTO, // auto +// climate::CLIMATE_FAN_QUIET, // silent +// climate::CLIMATE_FAN_LOW, // | +// climate::CLIMATE_FAN_MIDDLE, // || +// climate::CLIMATE_FAN_MEDIUM, // ||| +// climate::CLIMATE_FAN_HIGH, // |||| +// climate::CLIMATE_FAN_FOCUS, // ||||| +// climate::CLIMATE_FAN_DIFFUSE // POWER [7] +// }); + - if (!traits.get_supported_swing_modes().empty()) - traits.add_supported_swing_mode(ClimateSwingMode::CLIMATE_SWING_OFF); - traits.set_visual_min_temperature(MIN_SET_TEMPERATURE); traits.set_visual_max_temperature(MAX_SET_TEMPERATURE); traits.set_visual_temperature_step(STEP_TEMPERATURE); @@ -51,8 +46,6 @@ ClimateTraits tclacClimate::traits() { void tclacClimate::setup() { -// Serial.begin(9600); -// ESP_LOGD("TCL" , "Started Serial"); #ifdef CONF_RX_LED this->rx_led_pin_->setup(); this->rx_led_pin_->digital_write(false); @@ -213,7 +206,7 @@ void tclacClimate::control(const ClimateCall &call) { dataTX[8] = 0b00000000;//mute,0,turbo,health,mode(4) 0=cool 1=fan 2=dry 3=heat 4=auto dataTX[9] = 0b00000000;//[9] = 0,0,0,0,temp(4) 31 - value dataTX[10] = 0b00000000;//[10] = 0,timerindicator,swingv(3),fan(3) 0=auto 1=low 2=med 3=high - // {0,2,3,5,0}; + // {0,2,3,5,0}; dataTX[11] = 0b00000000; dataTX[32] = 0b00000000; dataTX[33] = 0b00000000; @@ -380,7 +373,7 @@ void tclacClimate::control(const ClimateCall &call) { // А если в переключателе пусто- заполняем значением из последнего опроса состояния. Типа, ничего не поменялось. switchvar = swing_mode; } - + // Устанавливаем режим качания заслонок switch(switchvar) { case climate::CLIMATE_SWING_OFF: dataTX[10] += 0b00000000; @@ -399,7 +392,7 @@ void tclacClimate::control(const ClimateCall &call) { dataTX[11] += 0b00001000; break; } - //Выбираем режим для качания вертикальной заслонки + // Устанавливаем режим для качания вертикальной заслонки switch(vertical_swing_direction_) { case VerticalSwingDirection::UP_DOWN: dataTX[32] += 0b00001000; @@ -414,7 +407,7 @@ void tclacClimate::control(const ClimateCall &call) { ESP_LOGD("TCL", "Vertical swing: downer"); break; } - //Выбираем режим для качания горизонтальных заслонок + // Устанавливаем режим для качания горизонтальных заслонок switch(horizontal_swing_direction_) { case HorizontalSwingDirection::LEFT_RIGHT: dataTX[33] += 0b00001000; @@ -433,7 +426,7 @@ void tclacClimate::control(const ClimateCall &call) { ESP_LOGD("TCL", "Horizontal swing: righter"); break; } - //Выбираем положение фиксации вертикальной заслонки + // Устанавливаем положение фиксации вертикальной заслонки switch(this->vertical_direction_) { case AirflowVerticalDirection::LAST: dataTX[32] += 0b00000000; @@ -460,7 +453,7 @@ void tclacClimate::control(const ClimateCall &call) { ESP_LOGD("TCL", "Vertical fix: down"); break; } - //Выбираем положение фиксации горизонтальных заслонок + // Устанавливаем положение фиксации горизонтальных заслонок switch(this->horizontal_direction_) { case AirflowHorizontalDirection::LAST: dataTX[33] += 0b00000000; @@ -537,7 +530,7 @@ void tclacClimate::control(const ClimateCall &call) { tclacClimate::sendData(dataTX, sizeof(dataTX)); } - +// Отправка данных в кондиционер void tclacClimate::sendData(byte * message, byte size) { tclacClimate::dataShow(1,1); //Serial.write(message, size); @@ -546,7 +539,7 @@ void tclacClimate::sendData(byte * message, byte size) { ESP_LOGD("TCL", "Message to TCL sended..."); tclacClimate::dataShow(1,0); } - +// Преобразование байта в читабельнывй формат String tclacClimate::getHex(byte *message, byte size) { String raw; for (int i = 0; i < size; i++) { @@ -555,7 +548,7 @@ String tclacClimate::getHex(byte *message, byte size) { raw.toUpperCase(); return raw; } - +// Вычисление контрольной суммы byte tclacClimate::getChecksum(const byte * message, size_t size) { byte position = size - 1; byte crc = 0; @@ -563,7 +556,7 @@ byte tclacClimate::getChecksum(const byte * message, size_t size) { crc ^= message[i]; return crc; } - +// Мигаем светодиодами void tclacClimate::dataShow(bool flow, bool shine) { if (module_display_status_){ if (flow == 0){ @@ -593,11 +586,6 @@ void tclacClimate::dataShow(bool flow, bool shine) { // Действия с данными из конфига -//void tclacClimate::set_supported_modes(const std::set &modes) { -// this->traits.set_supported_modes(modes); -// this->traits.add_supported_mode(climate::CLIMATE_MODE_OFF); // Always available -// this->traits.add_supported_mode(climate::CLIMATE_MODE_HEAT_COOL); // Always available -//} void tclacClimate::set_beeper_state(bool state) { this->beeper_status_ = state; @@ -635,14 +623,27 @@ void tclacClimate::set_vertical_swing_direction(VerticalSwingDirection direction this->vertical_swing_direction_ = direction; } +void tclacClimate::set_supported_modes(const std::set &modes) { + this->traits.set_supported_modes(modes); + this->traits.add_supported_mode(climate::CLIMATE_MODE_OFF); // Выключенный режим доступен всегда + this->traits.add_supported_mode(climate::CLIMATE_MODE_AUTO); // Автоматический режим тоже +} + void tclacClimate::set_horizontal_swing_direction(HorizontalSwingDirection direction) { this->horizontal_swing_direction_ = direction; } -void tclacClimate::set_supported_swing_modes(const std::set &modes) { - this->supported_swing_modes_ = modes; +void tclacClimate::set_supported_fan_modes(const std::set &modes){ + this->traits.set_supported_fan_modes(modes); + this->traits.add_supported_fan_mode(climate::CLIMATE_FAN_AUTO); // Автоматический режим доступен всегда } +void tclacClimate::set_supported_swing_modes(const std::set &modes) { + this->traits.set_supported_swing_modes(modes); + this->traits.add_supported_swing_mode(climate::CLIMATE_SWING_OFF); // Выключенный режим доступен всегда +} + + // Заготовки функций запроса состояния, может пригодиться в будущем, если делать обратную связь. Очень не хочется, будет очень костыльно. diff --git a/components/tclac/tclac.h b/components/tclac/tclac.h index 26d7593..5147f1f 100644 --- a/components/tclac/tclac.h +++ b/components/tclac/tclac.h @@ -1,7 +1,8 @@ /** * Create by Miguel Ángel López on 20/07/19 * and modify by xaxexa -* and finally made it by Solovey 13.08.2023 +* Refactoring & component making +* Соловей с паяльником 15.03.2024 **/ #ifndef TCL_ESP_TCL_H @@ -138,6 +139,7 @@ class tclacClimate : public climate::Climate, public esphome::uart::UARTDevice, void set_vertical_swing_direction(VerticalSwingDirection direction); void set_horizontal_swing_direction(HorizontalSwingDirection direction); void set_supported_modes(const std::set &modes); + void set_supported_fan_modes(const std::set &modes); void set_supported_swing_modes(const std::set &modes); @@ -145,10 +147,11 @@ class tclacClimate : public climate::Climate, public esphome::uart::UARTDevice, GPIOPin *rx_led_pin_; GPIOPin *tx_led_pin_; ClimateTraits traits() override; +// std::set supported_modes_{}; AirflowVerticalDirection vertical_direction_; AirflowHorizontalDirection horizontal_direction_; VerticalSwingDirection vertical_swing_direction_; - std::set supported_swing_modes_{}; +// std::set supported_swing_modes_{}; HorizontalSwingDirection horizontal_swing_direction_; };