From 2d4162323a81b98ba07fd278e892f004ab6a7ac7 Mon Sep 17 00:00:00 2001 From: GrKoR Date: Wed, 1 Nov 2023 18:04:16 +0300 Subject: [PATCH 1/2] Brokly's changes for power limitation --- components/aux_ac/aux_ac.h | 138 ++++++++++++++++++++++++------------- 1 file changed, 91 insertions(+), 47 deletions(-) diff --git a/components/aux_ac/aux_ac.h b/components/aux_ac/aux_ac.h index 99d4e7f..62d2175 100644 --- a/components/aux_ac/aux_ac.h +++ b/components/aux_ac/aux_ac.h @@ -626,12 +626,20 @@ namespace esphome // GK: define убрал, т.к. считаю, что сбрасывать счетчик не надо. // #define AC_MIN_COUNTER_MASK 0b00111111 -// маски ограничения мощности для инверторного кондиционера -#define AC_INVERTER_POWER_LIMITATION_ENABLE_MASK 0b10000000 -#define AC_INVERTER_POWER_LIMITATION_VALUE_MASK 0b01111111 -#define AC_INVERTER_POWER_LIMITATION_VALUE_UNTOUCHED 0xFF +// включение-выключение функции "Ограничение мощности". + enum ac_powLim_state : uint8_t + { + AC_POWLIMSTAT_OFF = 0x00, + AC_POWLIMSTAT_ON = 0x80, + AC_POWLIMSTAT_UNTOUCHED = 0xFF + }; - // положение вертикальных жалюзи для фронтенда +// маски ограничения мощности для инверторного кондиционера +#define AC_POWLIMVAL_MASK 0b01111111 +#define AC_POWLIMVAL_UNTOUCHED 0xFF + +// положение вертикальных жалюзи для фронтенда +#define AC_POWLIMSTAT_MASK 0b10000000 enum ac_vlouver_frontend : uint8_t { AC_VLOUVER_FRONTEND_SWING = 0x00, @@ -707,8 +715,8 @@ namespace esphome ac_realFan realFanSpeed; // текущая скорость вентилятора uint8_t inverter_power; // мощность инвертора bool defrost; // режим разморозки внешнего блока (накопление тепла + прогрев испарителя) - bool inverter_power_limitation_enable; // ограничение мощности инвертора - uint8_t inverter_power_limitation_value; // значение ограничения мощности инвертора + ac_powLim_state power_lim_state; // статус ограничения мощности инвертора + uint8_t power_lim_value; // значение ограничения мощности инвертора }; typedef ac_command_t ac_state_t; // текущее состояние параметров кондея можно хранить в таком же формате, как и комманды @@ -1134,8 +1142,8 @@ namespace esphome cmd->realFanSpeed = AC_REAL_FAN_UNTOUCHED; cmd->inverter_power = 0; cmd->defrost = false; - cmd->inverter_power_limitation_enable = false; - cmd->inverter_power_limitation_value = AC_INVERTER_POWER_LIMITATION_VALUE_UNTOUCHED; + cmd->power_lim_state = AC_POWLIMSTAT_UNTOUCHED; + cmd->power_lim_value = AC_POWLIMVAL_UNTOUCHED; }; // очистка буфера размером AC_BUFFER_SIZE @@ -1509,17 +1517,15 @@ namespace esphome stateByte = small_info_body->display_and_mildew & AC_MILDEW_MASK; stateChangedFlag = stateChangedFlag || (_current_ac_state.mildew != (ac_mildew)stateByte); _current_ac_state.mildew = (ac_mildew)stateByte; - - // enable flag of power limitation for inverter ACs - bool temp = small_info_body->inverter_power_limitation_enable; - stateChangedFlag = stateChangedFlag || (_current_ac_state.inverter_power_limitation_enable != temp); - _current_ac_state.inverter_power_limitation_enable = temp; - - // the limit value of power limitation for inverter ACs + + stateByte = AC_POWLIMSTAT_ON * small_info_body->inverter_power_limitation_enable; + stateChangedFlag = stateChangedFlag || (_current_ac_state.power_lim_state != (ac_powLim_state)stateByte); + _current_ac_state.power_lim_state = (ac_powLim_state)stateByte; + stateByte = small_info_body->inverter_power_limitation_value; - stateChangedFlag = stateChangedFlag || (_current_ac_state.inverter_power_limitation_value != stateByte); - _current_ac_state.inverter_power_limitation_value = stateByte; - + stateChangedFlag = stateChangedFlag || (_current_ac_state.power_lim_value != stateByte); + _current_ac_state.power_lim_value = stateByte; + // уведомляем об изменении статуса сплита if (stateChangedFlag) stateChanged(); @@ -1921,12 +1927,17 @@ namespace esphome } } - // ограничение мощности инвертора - if ((cmd->inverter_power_limitation_value != AC_INVERTER_POWER_LIMITATION_VALUE_UNTOUCHED)) + // значение ограничения мощности инвертора + if ((cmd->power_lim_value != AC_POWLIMVAL_UNTOUCHED)) { - pack->body[13] = (pack->body[13] & ~AC_INVERTER_POWER_LIMITATION_ENABLE_MASK) | (cmd->inverter_power_limitation_enable << 7); - cmd->inverter_power_limitation_value = _power_limitation_value_normalise(cmd->inverter_power_limitation_value); - pack->body[13] = (pack->body[13] & ~AC_INVERTER_POWER_LIMITATION_VALUE_MASK) | cmd->inverter_power_limitation_value; + cmd->power_lim_value = _power_limitation_value_normalise(cmd->power_lim_value); + pack->body[13] = (pack->body[13] & ~AC_POWLIMVAL_MASK) | (cmd->power_lim_value & AC_POWLIMVAL_MASK); + } + + // включение/выключение ограничения мощности инвертора + if ((cmd->power_lim_state != AC_POWLIMSTAT_UNTOUCHED)) + { + pack->body[13] = (pack->body[13] & ~AC_POWLIMSTAT_MASK) | (cmd->power_lim_state & AC_POWLIMSTAT_MASK); } // обнулить счетчик минут с последней команды @@ -2790,11 +2801,10 @@ namespace esphome sensor_vlouver_state_->publish_state((float)this->getCurrentVlouverFrontendState()); // флаг включенного ограничения мощности инвертора if (sensor_inverter_power_limit_state_ != nullptr) - sensor_inverter_power_limit_state_->publish_state(_current_ac_state.inverter_power_limitation_enable); + sensor_inverter_power_limit_state_->publish_state(_current_ac_state.power_lim_state == AC_POWLIMSTAT_ON); // значение ограничения мощности инвертора if (sensor_inverter_power_limit_value_ != nullptr) - sensor_inverter_power_limit_value_->publish_state(_current_ac_state.inverter_power_limitation_value); - + sensor_inverter_power_limit_value_->publish_state(_current_ac_state.power_lim_value); // сенсор состояния сплита if (sensor_preset_reporter_ != nullptr) { @@ -2837,11 +2847,8 @@ namespace esphome #endif ESP_LOGCONFIG(TAG, " [?] Is inverter %s", millis() > _update_period + 1000 ? YESNO(_is_inverter) : "pending..."); - LOG_SENSOR(" ", "Inverter Power", this->sensor_inverter_power_); LOG_SENSOR(" ", "Inverter Power Limit Value", this->sensor_inverter_power_limit_value_); - LOG_BINARY_SENSOR(" ", "Inverter Power Limit State", this->sensor_inverter_power_limit_state_); - LOG_SENSOR(" ", "Indoor Temperature", this->sensor_indoor_temperature_); LOG_SENSOR(" ", "Outdoor Temperature", this->sensor_outdoor_temperature_); LOG_SENSOR(" ", "Inbound Temperature", this->sensor_inbound_temperature_); @@ -2849,6 +2856,7 @@ namespace esphome LOG_SENSOR(" ", "Compressor Temperature", this->sensor_compressor_temperature_); LOG_BINARY_SENSOR(" ", "Defrost Status", this->sensor_defrost_); LOG_BINARY_SENSOR(" ", "Display", this->sensor_display_); + LOG_BINARY_SENSOR(" ", "Inverter Power Limit State", this->sensor_inverter_power_limit_state_); LOG_TEXT_SENSOR(" ", "Preset Reporter", this->sensor_preset_reporter_); this->dump_traits_(TAG); } @@ -3533,63 +3541,99 @@ namespace esphome return true; } - // выключает ограничение мощности сплита - bool powerLimitationOffSequence() + // выключает-выключает ограничение мощности сплита + bool powerLimitationOnOffSequence(bool state) { // нет смысла в последовательности, если нет коннекта с кондиционером if (!get_has_connection()) { - _debugMsg(F("powerLimitationOffSequence: no pings from HVAC. It seems like no AC connected."), ESPHOME_LOG_LEVEL_ERROR, __LINE__); + _debugMsg(F("powerLimitationOnOffSequence: no pings from HVAC. It seems like no AC connected."), ESPHOME_LOG_LEVEL_ERROR, __LINE__); return false; } if (!this->_is_inverter) + { + _debugMsg(F("powerLimitationOnSequence: unsupported for noninverter AC."), ESPHOME_LOG_LEVEL_WARN, __LINE__); return false; // если кондиционер не инверторный, то выходим - + } + // формируем команду ac_command_t cmd; _clearCommand(&cmd); // не забываем очищать, а то будет мусор - cmd.inverter_power_limitation_enable = false; - cmd.inverter_power_limitation_value = this->_current_ac_state.inverter_power_limitation_value; + if(state){ + cmd.power_lim_state = AC_POWLIMSTAT_ON; // включить ограничение мощности + } else { + cmd.power_lim_state = AC_POWLIMSTAT_OFF; // отключить ограничение мощности + } // добавляем команду в последовательность if (!commandSequence(&cmd)) return false; - _debugMsg(F("powerLimitationOffSequence: loaded (value = %02X)"), ESPHOME_LOG_LEVEL_VERBOSE, __LINE__, cmd.inverter_power_limitation_enable); + _debugMsg(F("powerLimitationOnOffSequence: loaded (state = %02X)"), ESPHOME_LOG_LEVEL_VERBOSE, __LINE__, cmd.power_lim_state); return true; } + + // выключает ограничение мощности сплита + bool powerLimitationOffSequence() + { + return powerLimitationOnOffSequence(false); + } - // включает ограничение мощности сплита на нужный уровень - bool powerLimitationOnSequence(uint8_t power_limit = Constants::AC_MIN_INVERTER_POWER_LIMIT) + // устанавливает ограничение мощности сплита на нужный уровень + bool powerLimitationSetSequence(uint8_t power_limit, bool setOn=false) { // нет смысла в последовательности, если нет коннекта с кондиционером if (!get_has_connection()) { - _debugMsg(F("powerLimitationOnSequence: no pings from HVAC. It seems like no AC connected."), ESPHOME_LOG_LEVEL_ERROR, __LINE__); + _debugMsg(F("powerLimitationSetSequence: no pings from HVAC. It seems like no AC connected."), ESPHOME_LOG_LEVEL_ERROR, __LINE__); return false; } if (!this->_is_inverter) { // если кондиционер не инверторный, то выходим - _debugMsg(F("powerLimitationOnSequence: unsupported for noninverter AC."), ESPHOME_LOG_LEVEL_WARN, __LINE__); + _debugMsg(F("powerLimitationSetSequence: unsupported for noninverter AC."), ESPHOME_LOG_LEVEL_WARN, __LINE__); return false; } - power_limit = this->_power_limitation_value_normalise(power_limit); - + if(power_limit != this->_power_limitation_value_normalise(power_limit)) + { + _debugMsg(F("powerLimitationSetSequence: incorrect power limit value."), ESPHOME_LOG_LEVEL_WARN, __LINE__); + return false; + } + // формируем команду ac_command_t cmd; _clearCommand(&cmd); // не забываем очищать, а то будет мусор - cmd.inverter_power_limitation_enable = true; - cmd.inverter_power_limitation_value = power_limit; + cmd.power_lim_value = power_limit; + if (setOn) + { + cmd.power_lim_state = AC_POWLIMSTAT_ON; + } // добавляем команду в последовательность if (!commandSequence(&cmd)) return false; - - _debugMsg(F("powerLimitationOnSequence: loaded (power limit = %02X)"), ESPHOME_LOG_LEVEL_VERBOSE, __LINE__, power_limit); + + if (setOn) + { + _debugMsg(F("powerLimitationSetSequence: loaded (state = %02X, power limit = %02X)"), ESPHOME_LOG_LEVEL_VERBOSE, __LINE__, cmd.power_lim_state, power_limit); + } else { + _debugMsg(F("powerLimitationSetSequence: loaded (power limit = %02X)"), ESPHOME_LOG_LEVEL_VERBOSE, __LINE__, power_limit); + } return true; } + // включает ограничение мощности сплита + bool powerLimitationOnSequence() + { + return powerLimitationOnOffSequence(true); + } + + // включает ограничение мощности сплита на нужный уровень + bool powerLimitationOnSequence(uint8_t power_limit) + { + return powerLimitationSetSequence(power_limit, true); + } + // конвертирует состояние жалюзи из кодов сплита в коды для фронтенда ac_vlouver_frontend AUXvlouverToVlouverFrontend(const ac_louver_V vLouver) { From 53a886f8182765ad1135344da8e5f298a1341d4e Mon Sep 17 00:00:00 2001 From: GrKoR Date: Thu, 9 Nov 2023 23:07:54 +0300 Subject: [PATCH 2/2] ref: minor fixes of Brokly's changes --- components/aux_ac/aux_ac.h | 88 +++++++++++++++++++------------------- 1 file changed, 44 insertions(+), 44 deletions(-) diff --git a/components/aux_ac/aux_ac.h b/components/aux_ac/aux_ac.h index 62d2175..3494a94 100644 --- a/components/aux_ac/aux_ac.h +++ b/components/aux_ac/aux_ac.h @@ -627,6 +627,7 @@ namespace esphome // #define AC_MIN_COUNTER_MASK 0b00111111 // включение-выключение функции "Ограничение мощности". +#define AC_POWLIMSTAT_MASK 0b10000000 enum ac_powLim_state : uint8_t { AC_POWLIMSTAT_OFF = 0x00, @@ -638,8 +639,7 @@ namespace esphome #define AC_POWLIMVAL_MASK 0b01111111 #define AC_POWLIMVAL_UNTOUCHED 0xFF -// положение вертикальных жалюзи для фронтенда -#define AC_POWLIMSTAT_MASK 0b10000000 + // положение вертикальных жалюзи для фронтенда enum ac_vlouver_frontend : uint8_t { AC_VLOUVER_FRONTEND_SWING = 0x00, @@ -2849,6 +2849,7 @@ namespace esphome ESP_LOGCONFIG(TAG, " [?] Is inverter %s", millis() > _update_period + 1000 ? YESNO(_is_inverter) : "pending..."); LOG_SENSOR(" ", "Inverter Power", this->sensor_inverter_power_); LOG_SENSOR(" ", "Inverter Power Limit Value", this->sensor_inverter_power_limit_value_); + LOG_BINARY_SENSOR(" ", "Inverter Power Limit State", this->sensor_inverter_power_limit_state_); LOG_SENSOR(" ", "Indoor Temperature", this->sensor_indoor_temperature_); LOG_SENSOR(" ", "Outdoor Temperature", this->sensor_outdoor_temperature_); LOG_SENSOR(" ", "Inbound Temperature", this->sensor_inbound_temperature_); @@ -2856,7 +2857,6 @@ namespace esphome LOG_SENSOR(" ", "Compressor Temperature", this->sensor_compressor_temperature_); LOG_BINARY_SENSOR(" ", "Defrost Status", this->sensor_defrost_); LOG_BINARY_SENSOR(" ", "Display", this->sensor_display_); - LOG_BINARY_SENSOR(" ", "Inverter Power Limit State", this->sensor_inverter_power_limit_state_); LOG_TEXT_SENSOR(" ", "Preset Reporter", this->sensor_preset_reporter_); this->dump_traits_(TAG); } @@ -3541,46 +3541,8 @@ namespace esphome return true; } - // выключает-выключает ограничение мощности сплита - bool powerLimitationOnOffSequence(bool state) - { - // нет смысла в последовательности, если нет коннекта с кондиционером - if (!get_has_connection()) - { - _debugMsg(F("powerLimitationOnOffSequence: no pings from HVAC. It seems like no AC connected."), ESPHOME_LOG_LEVEL_ERROR, __LINE__); - return false; - } - - if (!this->_is_inverter) - { - _debugMsg(F("powerLimitationOnSequence: unsupported for noninverter AC."), ESPHOME_LOG_LEVEL_WARN, __LINE__); - return false; // если кондиционер не инверторный, то выходим - } - - // формируем команду - ac_command_t cmd; - _clearCommand(&cmd); // не забываем очищать, а то будет мусор - if(state){ - cmd.power_lim_state = AC_POWLIMSTAT_ON; // включить ограничение мощности - } else { - cmd.power_lim_state = AC_POWLIMSTAT_OFF; // отключить ограничение мощности - } - // добавляем команду в последовательность - if (!commandSequence(&cmd)) - return false; - - _debugMsg(F("powerLimitationOnOffSequence: loaded (state = %02X)"), ESPHOME_LOG_LEVEL_VERBOSE, __LINE__, cmd.power_lim_state); - return true; - } - - // выключает ограничение мощности сплита - bool powerLimitationOffSequence() - { - return powerLimitationOnOffSequence(false); - } - // устанавливает ограничение мощности сплита на нужный уровень - bool powerLimitationSetSequence(uint8_t power_limit, bool setOn=false) + bool powerLimitationSetSequence(uint8_t power_limit, bool set_on=false) { // нет смысла в последовательности, если нет коннекта с кондиционером if (!get_has_connection()) @@ -3605,7 +3567,7 @@ namespace esphome ac_command_t cmd; _clearCommand(&cmd); // не забываем очищать, а то будет мусор cmd.power_lim_value = power_limit; - if (setOn) + if (set_on) { cmd.power_lim_state = AC_POWLIMSTAT_ON; } @@ -3613,7 +3575,7 @@ namespace esphome if (!commandSequence(&cmd)) return false; - if (setOn) + if (set_on) { _debugMsg(F("powerLimitationSetSequence: loaded (state = %02X, power limit = %02X)"), ESPHOME_LOG_LEVEL_VERBOSE, __LINE__, cmd.power_lim_state, power_limit); } else { @@ -3622,6 +3584,38 @@ namespace esphome return true; } + // включает/выключает ограничение мощности сплита + bool powerLimitationOnOffSequence(bool enable_limit) + { + // нет смысла в последовательности, если нет коннекта с кондиционером + if (!get_has_connection()) + { + _debugMsg(F("powerLimitationOnOffSequence: no pings from HVAC. It seems like no AC connected."), ESPHOME_LOG_LEVEL_ERROR, __LINE__); + return false; + } + + if (!this->_is_inverter) + { + _debugMsg(F("powerLimitationOnSequence: unsupported for noninverter AC."), ESPHOME_LOG_LEVEL_WARN, __LINE__); + return false; // если кондиционер не инверторный, то выходим + } + + // формируем команду + ac_command_t cmd; + _clearCommand(&cmd); // не забываем очищать, а то будет мусор + if(enable_limit){ + cmd.power_lim_state = AC_POWLIMSTAT_ON; // включить ограничение мощности + } else { + cmd.power_lim_state = AC_POWLIMSTAT_OFF; // отключить ограничение мощности + } + // добавляем команду в последовательность + if (!commandSequence(&cmd)) + return false; + + _debugMsg(F("powerLimitationOnOffSequence: loaded (state = %02X)"), ESPHOME_LOG_LEVEL_VERBOSE, __LINE__, cmd.power_lim_state); + return true; + } + // включает ограничение мощности сплита bool powerLimitationOnSequence() { @@ -3633,6 +3627,12 @@ namespace esphome { return powerLimitationSetSequence(power_limit, true); } + + // выключает ограничение мощности сплита + bool powerLimitationOffSequence() + { + return powerLimitationOnOffSequence(false); + } // конвертирует состояние жалюзи из кодов сплита в коды для фронтенда ac_vlouver_frontend AUXvlouverToVlouverFrontend(const ac_louver_V vLouver)