diff --git a/README-EN.md b/README-EN.md index b328bbc..9a639eb 100644 --- a/README-EN.md +++ b/README-EN.md @@ -36,7 +36,8 @@ The best way to report about your test results is writing a message in the [tele For correct component operation, you need hardware and firmware. The hardware description is located [in a separate file](docs/HARDWARE-EN.md). ### Firmware: Integration aux_ac to your configuration ### -You need [ESPHome](https://esphome.io) v.2025.2.0 or above. You can try esphome before 2025.2.0 but I can't guarantee error-free compilation of the examples. +You need [ESPHome](https://esphome.io) v.2026.1.0 or above. +To compile it with earlier versions of ESPHome, use the component [v.0.3.2 or older](https://github.com/GrKoR/esphome_aux_ac_component/tags). ## Installing ## 1. Declare external component. Read [the manual](https://esphome.io/components/external_components.html?highlight=external) for details. diff --git a/README.md b/README.md index 3f93387..bac7292 100644 --- a/README.md +++ b/README.md @@ -43,7 +43,8 @@ AUX - это один из нескольких OEM-производителей Для работы с кондиционером понадобится "железо" и прошивка. Описание электроники вынесено [в отдельный файл](docs/HARDWARE.md). ### Прошивка: интеграция aux_ac в вашу конфигурацию ESPHome ### -Для использования требуется [ESPHome](https://esphome.io) версией не ниже 2025.2.0. Работа с более ранними версиями возможна, но не гарантируется.
+Для использования требуется [ESPHome](https://esphome.io) версией не ниже 2026.1.0. +Для компиляции с ESPHome более ранних версий используйте компонент [v.0.3.2 или младше](https://github.com/GrKoR/esphome_aux_ac_component/tags). ## Установка ## 1. Подключите компонент. diff --git a/components/aux_ac/aux_ac.h b/components/aux_ac/aux_ac.h index c994ece..7c107a9 100644 --- a/components/aux_ac/aux_ac.h +++ b/components/aux_ac/aux_ac.h @@ -44,11 +44,9 @@ namespace esphome using climate::ClimatePreset; using climate::ClimateSwingMode; using climate::ClimateTraits; -#if ESPHOME_VERSION_CODE >= VERSION_CODE(2025, 11, 0) using climate::ClimateModeMask; using climate::ClimateSwingModeMask; using climate::ClimatePresetMask; -#endif //**************************************************************************************************************************************************** //**************************************************** Packet logger configuration ******************************************************************* @@ -858,19 +856,11 @@ namespace esphome // как "в простое" (IDLE) bool _is_inverter = false; -#if ESPHOME_VERSION_CODE >= VERSION_CODE(2025, 11, 0) ClimateModeMask _supported_modes{}; ClimateSwingModeMask _supported_swing_modes{}; ClimatePresetMask _supported_presets{}; std::vector _supported_custom_fan_modes{}; std::vector _supported_custom_presets{}; -#else - std::set _supported_modes{}; - std::set _supported_swing_modes{}; - std::set _supported_presets{}; - std::set _supported_custom_presets{}; - std::set _supported_custom_fan_modes{}; -#endif // The capabilities of the climate device // Шаблон параметров отображения виджета @@ -2404,13 +2394,8 @@ namespace esphome // первоначальная инициализация this->preset = climate::CLIMATE_PRESET_NONE; -#if ESPHOME_VERSION_CODE >= VERSION_CODE(2025, 11, 0) this->clear_custom_preset_(); this->clear_custom_fan_mode_(); -#else - this->custom_preset = (std::string) ""; - this->custom_fan_mode = (std::string) ""; -#endif this->mode = climate::CLIMATE_MODE_OFF; this->action = climate::CLIMATE_ACTION_IDLE; this->fan_mode = climate::CLIMATE_FAN_LOW; @@ -2653,24 +2638,13 @@ namespace esphome switch (_current_ac_state.fanTurbo) { case AC_FANTURBO_ON: -#if ESPHOME_VERSION_CODE >= VERSION_CODE(2025, 11, 0) this->set_custom_fan_mode_(Constants::TURBO.c_str()); -#else - this->custom_fan_mode = Constants::TURBO; -#endif break; case AC_FANTURBO_OFF: default: -#if ESPHOME_VERSION_CODE >= VERSION_CODE(2025, 11, 0) - if (this->has_custom_fan_mode()) { - if (strcmp(this->get_custom_fan_mode(), Constants::TURBO.c_str()) == 0) - this->clear_custom_fan_mode_(); - } -#else - if (this->custom_fan_mode == Constants::TURBO) - this->custom_fan_mode = (std::string) ""; -#endif + if (this->has_custom_fan_mode() && (this->get_custom_fan_mode() == Constants::TURBO)) + this->clear_custom_fan_mode_(); break; } @@ -2682,24 +2656,13 @@ namespace esphome switch (_current_ac_state.fanMute) { case AC_FANMUTE_ON: -#if ESPHOME_VERSION_CODE >= VERSION_CODE(2025, 11, 0) this->set_custom_fan_mode_(Constants::MUTE.c_str()); -#else - this->custom_fan_mode = Constants::MUTE; -#endif break; case AC_FANMUTE_OFF: default: -#if ESPHOME_VERSION_CODE >= VERSION_CODE(2025, 11, 0) - if (this->has_custom_fan_mode()) { - if (strcmp(this->get_custom_fan_mode(), Constants::MUTE.c_str()) == 0) - this->clear_custom_fan_mode_(); - } -#else - if (this->custom_fan_mode == Constants::MUTE) - this->custom_fan_mode = (std::string) ""; -#endif + if (this->has_custom_fan_mode() && (this->get_custom_fan_mode() == Constants::MUTE)) + this->clear_custom_fan_mode_(); break; } @@ -2711,25 +2674,14 @@ namespace esphome if (_current_ac_state.health == AC_HEALTH_ON && _current_ac_state.power == AC_POWER_ON) { -#if ESPHOME_VERSION_CODE >= VERSION_CODE(2025, 11, 0) this->set_custom_preset_(Constants::HEALTH.c_str()); -#else - this->custom_preset = Constants::HEALTH; -#endif } // AC_HEALTH_OFF // только в том случае, если до этого пресет был установлен -#if ESPHOME_VERSION_CODE >= VERSION_CODE(2025, 11, 0) - else if (this->has_custom_preset() && strcmp(this->get_custom_preset(), Constants::HEALTH.c_str()) == 0) + else if (this->has_custom_preset() && (this->get_custom_preset() == Constants::HEALTH)) { this->clear_custom_preset_(); } -#else - else if (this->custom_preset == Constants::HEALTH) - { - this->custom_preset = (std::string) ""; - } -#endif _debugMsg(F("Climate HEALTH preset: %i"), ESPHOME_LOG_LEVEL_VERBOSE, __LINE__, _current_ac_state.health); @@ -2757,25 +2709,14 @@ namespace esphome if (_current_ac_state.clean == AC_CLEAN_ON && _current_ac_state.power == AC_POWER_OFF) { -#if ESPHOME_VERSION_CODE >= VERSION_CODE(2025, 11, 0) this->set_custom_preset_(Constants::CLEAN.c_str()); -#else - this->custom_preset = Constants::CLEAN; -#endif } // AC_CLEAN_OFF // только в том случае, если до этого пресет был установлен -#if ESPHOME_VERSION_CODE >= VERSION_CODE(2025, 11, 0) - else if (this->has_custom_preset() && strcmp(this->get_custom_preset(), Constants::CLEAN.c_str()) == 0) + else if (this->has_custom_preset() && (this->get_custom_preset() == Constants::CLEAN)) { this->clear_custom_preset_(); } -#else - else if (this->custom_preset == Constants::CLEAN) - { - this->custom_preset = (std::string) ""; - } -#endif _debugMsg(F("Climate CLEAN preset: %i"), ESPHOME_LOG_LEVEL_VERBOSE, __LINE__, _current_ac_state.clean); @@ -2798,25 +2739,13 @@ namespace esphome switch (_current_ac_state.mildew) { case AC_MILDEW_ON: -#if ESPHOME_VERSION_CODE >= VERSION_CODE(2025, 11, 0) this->set_custom_preset_(Constants::ANTIFUNGUS.c_str()); -#else - this->custom_preset = Constants::ANTIFUNGUS; -#endif break; case AC_MILDEW_OFF: default: -#if ESPHOME_VERSION_CODE >= VERSION_CODE(2025, 11, 0) - if (this->has_custom_preset() && strcmp(this->get_custom_preset(), Constants::ANTIFUNGUS.c_str()) == 0) - { + if (this->has_custom_preset() && (this->get_custom_preset() == Constants::ANTIFUNGUS)) this->clear_custom_preset_(); - } -#else - if (this->custom_preset == Constants::ANTIFUNGUS) - this->custom_preset = (std::string) ""; - break; -#endif } _debugMsg(F("Climate ANTIFUNGUS preset: %i"), ESPHOME_LOG_LEVEL_VERBOSE, __LINE__, _current_ac_state.mildew); @@ -2902,17 +2831,10 @@ namespace esphome { state_str += "SLEEP"; } -#if ESPHOME_VERSION_CODE >= VERSION_CODE(2025, 11, 0) else if (this->has_custom_preset()) { state_str += this->get_custom_preset(); } -#else - else if (this->custom_preset.has_value() && this->custom_preset.value().length() > 0) - { - state_str += this->custom_preset.value().c_str(); - } -#endif else { state_str += "NONE"; @@ -3102,21 +3024,19 @@ namespace esphome break; } } -#if ESPHOME_VERSION_CODE >= VERSION_CODE(2025, 11, 0) else if (call.has_custom_fan_mode()) { - const char *customfanmode = call.get_custom_fan_mode(); - - if (strcmp(customfanmode, Constants::TURBO.c_str()) == 0) + auto custom_fan_mode = call.get_custom_fan_mode(); + if (custom_fan_mode == Constants::TURBO) { // TURBO fan mode is suitable in COOL and HEAT modes. // Other modes don't accept TURBO fan mode. hasCommand = true; cmd.fanTurbo = AC_FANTURBO_ON; cmd.fanMute = AC_FANMUTE_OFF; - this->set_custom_fan_mode_(customfanmode); + this->set_custom_fan_mode_(custom_fan_mode); } - else if (strcmp(customfanmode, Constants::MUTE.c_str()) == 0) + else if (custom_fan_mode == Constants::MUTE) { // MUTE fan mode is suitable in FAN mode only for Rovex air conditioner. // In COOL mode AC receives command without any changes. @@ -3124,52 +3044,9 @@ namespace esphome hasCommand = true; cmd.fanMute = AC_FANMUTE_ON; cmd.fanTurbo = AC_FANTURBO_OFF; - this->set_custom_fan_mode_(customfanmode); + this->set_custom_fan_mode_(custom_fan_mode); } } -#else - else if (call.get_custom_fan_mode().has_value()) - { - std::string customfanmode = *call.get_custom_fan_mode(); - - if (customfanmode == Constants::TURBO) - { - // TURBO fan mode is suitable in COOL and HEAT modes. - // Other modes don't accept TURBO fan mode. - /* - if ( cmd.mode == AC_MODE_COOL - or cmd.mode == AC_MODE_HEAT - or _current_ac_state.mode == AC_MODE_COOL - or _current_ac_state.mode == AC_MODE_HEAT) { - */ - hasCommand = true; - cmd.fanTurbo = AC_FANTURBO_ON; - cmd.fanMute = AC_FANMUTE_OFF; // зависимость от fanturbo - this->custom_fan_mode = customfanmode; - /* - } else { - _debugMsg(F("TURBO fan mode is suitable in COOL and HEAT modes only."), ESPHOME_LOG_LEVEL_WARN, __LINE__); - } - */ - } - else if (customfanmode == Constants::MUTE) - { - // MUTE fan mode is suitable in FAN mode only for Rovex air conditioner. - // In COOL mode AC receives command without any changes. - // May be other AUX-based air conditioners do the same. - // if ( cmd.mode == AC_MODE_FAN - // or _current_ac_state.mode == AC_MODE_FAN) { - - hasCommand = true; - cmd.fanMute = AC_FANMUTE_ON; - cmd.fanTurbo = AC_FANTURBO_OFF; // зависимость от fanmute - this->custom_fan_mode = customfanmode; - //} else { - // _debugMsg(F("MUTE fan mode is suitable in FAN mode only."), ESPHOME_LOG_LEVEL_WARN, __LINE__); - //} - } - } -#endif // Пользователь выбрал пресет if (call.get_preset().has_value()) @@ -3220,28 +3097,25 @@ namespace esphome break; } } -#if ESPHOME_VERSION_CODE >= VERSION_CODE(2025, 11, 0) else if (call.has_custom_preset()) { - const char *custom_preset = call.get_custom_preset(); - - if (strcmp(custom_preset, Constants::CLEAN.c_str()) == 0) + auto custom_preset = call.get_custom_preset(); + if (custom_preset == Constants::CLEAN) { // режим очистки кондиционера, включается (или должен включаться) при AC_POWER_OFF - // TODO: надо отдебажить выключение этого режима if (cmd.power == AC_POWER_OFF or _current_ac_state.power == AC_POWER_OFF) { hasCommand = true; cmd.clean = AC_CLEAN_ON; cmd.mildew = AC_MILDEW_OFF; - this->set_custom_preset_(custom_preset); + this->set_custom_preset_(Constants::CLEAN.c_str()); } else { _debugMsg(F("CLEAN preset is suitable in POWER_OFF mode only."), ESPHOME_LOG_LEVEL_WARN, __LINE__); } } - else if (strcmp(custom_preset, Constants::HEALTH.c_str()) == 0) + else if (custom_preset == Constants::HEALTH) { if (cmd.power == AC_POWER_ON || _current_ac_state.power == AC_POWER_ON) @@ -3266,81 +3140,7 @@ namespace esphome { cmd.fanSpeed = AC_FANSPEED_MEDIUM; // зависимость от health } - this->set_custom_preset_(custom_preset); - } - else - { - _debugMsg(F("HEALTH preset is suitable in POWER_ON mode only."), ESPHOME_LOG_LEVEL_WARN, __LINE__); - } - } - else if (strcmp(custom_preset, Constants::ANTIFUNGUS.c_str()) == 0) - { - // включение-выключение функции "Антиплесень". - // По факту: после выключения сплита он оставляет минут на 5 открытые жалюзи и глушит вентилятор. - // Уличный блок при этом гудит и тарахтит. Возможно, прогревается теплообменник для высыхания. - // Через некоторое время внешний блок замолкает и сплит закрывает жалюзи. - - // Brokly: - // включение-выключение функции "Антиплесень". - // у меня пульт отправляет 5 посылок и на включение и на выключение, но реагирует на эту кнопку - // только в режиме POWER_OFF - - // TODO: надо уточнить, в каких режимах штатно включается этот режим у кондиционера - cmd.mildew = AC_MILDEW_ON; - cmd.clean = AC_CLEAN_OFF; // для логики пресетов - - hasCommand = true; - this->set_custom_preset_(custom_preset); - } - } -#else - else if (call.get_custom_preset().has_value()) - { - std::string custom_preset = *call.get_custom_preset(); - - if (custom_preset == Constants::CLEAN) - { - // режим очистки кондиционера, включается (или должен включаться) при AC_POWER_OFF - // TODO: надо отдебажить выключение этого режима - if (cmd.power == AC_POWER_OFF or _current_ac_state.power == AC_POWER_OFF) - { - hasCommand = true; - cmd.clean = AC_CLEAN_ON; - cmd.mildew = AC_MILDEW_OFF; // для логики пресетов - this->custom_preset = custom_preset; - } - else - { - _debugMsg(F("CLEAN preset is suitable in POWER_OFF mode only."), ESPHOME_LOG_LEVEL_WARN, __LINE__); - } - } - else if (custom_preset == Constants::HEALTH) - { - if (cmd.power == AC_POWER_ON || - _current_ac_state.power == AC_POWER_ON) - { - hasCommand = true; - cmd.health = AC_HEALTH_ON; - // cmd.health_status = AC_HEALTH_STATUS_ON; // GK: статус кондей сам поднимает - cmd.fanTurbo = AC_FANTURBO_OFF; // зависимость от health - cmd.fanMute = AC_FANMUTE_OFF; // зависимость от health - cmd.sleep = AC_SLEEP_OFF; // для логики пресетов - - if (cmd.mode == AC_MODE_COOL || - cmd.mode == AC_MODE_HEAT || - cmd.mode == AC_MODE_AUTO || - _current_ac_state.mode == AC_MODE_COOL || - _current_ac_state.mode == AC_MODE_HEAT || - _current_ac_state.mode == AC_MODE_AUTO) - { - cmd.fanSpeed = AC_FANSPEED_AUTO; // зависимость от health - } - else if (cmd.mode == AC_MODE_FAN || - _current_ac_state.mode == AC_MODE_FAN) - { - cmd.fanSpeed = AC_FANSPEED_MEDIUM; // зависимость от health - } - this->custom_preset = custom_preset; + this->set_custom_preset_(Constants::HEALTH.c_str()); } else { @@ -3359,15 +3159,13 @@ namespace esphome // у меня пульт отправляет 5 посылок и на включение и на выключение, но реагирует на эту кнопку // только в режиме POWER_OFF - // TODO: надо уточнить, в каких режимах штатно включается этот режим у кондиционера cmd.mildew = AC_MILDEW_ON; cmd.clean = AC_CLEAN_OFF; // для логики пресетов hasCommand = true; - this->custom_preset = custom_preset; + this->set_custom_preset_(Constants::ANTIFUNGUS.c_str()); } } -#endif // User requested swing_mode change if (call.get_swing_mode().has_value()) @@ -3984,28 +3782,11 @@ namespace esphome void set_optimistic(bool optimistic) { this->_optimistic = optimistic; } bool get_optimistic() { return this->_optimistic; } -#if ESPHOME_VERSION_CODE >= VERSION_CODE(2025, 11, 0) void set_supported_modes(ClimateModeMask modes) { this->_supported_modes = modes; } void set_supported_swing_modes(ClimateSwingModeMask modes) { this->_supported_swing_modes = modes; } void set_supported_presets(ClimatePresetMask presets) { this->_supported_presets = presets; } void set_custom_presets(std::initializer_list presets) { this->_supported_custom_presets = presets; } void set_custom_fan_modes(std::initializer_list modes) { this->_supported_custom_fan_modes = modes; } -#else - void set_supported_modes(const std::set &modes) { this->_supported_modes = modes; } - std::set get_supported_modes() { return this->_supported_modes; } - - void set_supported_swing_modes(const std::set &modes) { this->_supported_swing_modes = modes; } - std::set get_supported_swing_modes() { return this->_supported_swing_modes; } - - void set_supported_presets(const std::set &presets) { this->_supported_presets = presets; } - const std::set &get_supported_presets() { return this->_supported_presets; } - - void set_custom_presets(const std::set &presets) { this->_supported_custom_presets = presets; } - const std::set &get_supported_custom_presets() { return this->_supported_custom_presets; } - - void set_custom_fan_modes(const std::set &modes) { this->_supported_custom_fan_modes = modes; } - const std::set &get_supported_custom_fan_modes() { return this->_supported_custom_fan_modes; } -#endif #if defined(PRESETS_SAVING) void set_store_settings(bool store_settings) { this->_store_settings = store_settings; } @@ -4023,13 +3804,7 @@ namespace esphome // заполнение шаблона параметров отображения виджета // GK: всё же похоже правильнее это делать тут, а не в initAC() // initAC() в формируемом питоном коде вызывается до вызова aux_ac.set_supported_***() с установленными пользователем в конфиге параметрами -#if ESPHOME_VERSION_CODE >= VERSION_CODE(2025, 11, 0) _traits.add_feature_flags(climate::CLIMATE_SUPPORTS_CURRENT_TEMPERATURE); - // NOT setting CLIMATE_REQUIRES_TWO_POINT_TARGET_TEMPERATURE - this device uses single target temperature -#else - _traits.set_supports_current_temperature(true); - _traits.set_supports_two_point_target_temperature(false); // if the climate device's target temperature should be split in target_temperature_low and target_temperature_high instead of just the single target_temperature -#endif _traits.set_supported_modes(this->_supported_modes); _traits.set_supported_swing_modes(this->_supported_swing_modes); @@ -4058,14 +3833,10 @@ namespace esphome //_traits.add_supported_preset(ClimatePreset::CLIMATE_PRESET_SLEEP); // if the climate device supports reporting the active current action of the device with the action property. -#if ESPHOME_VERSION_CODE >= VERSION_CODE(2025, 11, 0) if (this->_show_action) { _traits.add_feature_flags(climate::CLIMATE_SUPPORTS_ACTION); } -#else - _traits.set_supports_action(this->_show_action); -#endif }; void loop() override diff --git a/components/aux_ac/climate.py b/components/aux_ac/climate.py index 15a81ea..bf81dbd 100644 --- a/components/aux_ac/climate.py +++ b/components/aux_ac/climate.py @@ -34,7 +34,7 @@ from esphome.components.climate import ( ClimateSwingMode, ) -AUX_AC_FIRMWARE_VERSION = '0.3.2' +AUX_AC_FIRMWARE_VERSION = '0.3.3' AC_PACKET_TIMEOUT_MIN = 150 AC_PACKET_TIMEOUT_MAX = 600 AC_POWER_LIMIT_MIN = 30