mirror of
https://github.com/GrKoR/esphome_aux_ac_component.git
synced 2025-12-11 05:57:01 +03:00
Слил/поправил.
This commit is contained in:
@@ -17,7 +17,7 @@ namespace aux_ac {
|
|||||||
|
|
||||||
protected:
|
protected:
|
||||||
AirCon *ac_;
|
AirCon *ac_;
|
||||||
};
|
};
|
||||||
|
|
||||||
template <typename... Ts>
|
template <typename... Ts>
|
||||||
class AirConDisplayOnAction : public Action<Ts...>
|
class AirConDisplayOnAction : public Action<Ts...>
|
||||||
@@ -59,7 +59,7 @@ namespace aux_ac {
|
|||||||
bool static_{false};
|
bool static_{false};
|
||||||
std::function<std::vector<uint8_t>(Ts...)> data_func_{};
|
std::function<std::vector<uint8_t>(Ts...)> data_func_{};
|
||||||
std::vector<uint8_t> data_static_{};
|
std::vector<uint8_t> data_static_{};
|
||||||
};
|
};
|
||||||
|
|
||||||
} // namespace aux_ac
|
} // namespace aux_ac
|
||||||
} // namespace esphome
|
} // namespace esphome
|
||||||
@@ -452,13 +452,13 @@ enum ac_power : uint8_t { AC_POWER_OFF = 0x00, AC_POWER_ON = 0x20, AC_POWER_UNTO
|
|||||||
enum ac_clean : uint8_t { AC_CLEAN_OFF = 0x00, AC_CLEAN_ON = 0x04, AC_CLEAN_UNTOUCHED = 0xFF };
|
enum ac_clean : uint8_t { AC_CLEAN_OFF = 0x00, AC_CLEAN_ON = 0x04, AC_CLEAN_UNTOUCHED = 0xFF };
|
||||||
|
|
||||||
// для включения ионизатора нужно установить второй бит в байте
|
// для включения ионизатора нужно установить второй бит в байте
|
||||||
// по результату этот бит останется установленным
|
// по результату этот бит останется установленным, но кондиционер еще и установит первый бит
|
||||||
#define AC_HEALTH_MASK 0b00000010
|
#define AC_HEALTH_MASK 0b00000010
|
||||||
enum ac_health : uint8_t { AC_HEALTH_OFF = 0x00, AC_HEALTH_ON = 0x02, AC_HEALTH_UNTOUCHED = 0xFF };
|
enum ac_health : uint8_t { AC_HEALTH_OFF = 0x00, AC_HEALTH_ON = 0x02, AC_HEALTH_UNTOUCHED = 0xFF };
|
||||||
|
|
||||||
// Статус ионизатора. Если бит поднят, то обнаружена ошибка ключения ионизатора
|
// Статус ионизатора. Если бит поднят, то обнаружена ошибка ключения ионизатора
|
||||||
#define AC_HEALTH_STATUS_MASK 0b00000001
|
#define AC_HEALTH_STATUS_MASK 0b00000001
|
||||||
enum ac_health_status : uint8_t { AC_HEALTH_ERROR_NO = 0x00, AC_HEALTH_ERROR_ACT = 0x01, AC_HEALTH_STATUS_UNTOUCHED = 0xFF };
|
enum ac_health_status : uint8_t { AC_HEALTH_STATUS_OFF = 0x00, AC_HEALTH_STATUS_ON = 0x01, AC_HEALTH_STATUS_UNTOUCHED = 0xFF };
|
||||||
|
|
||||||
// целевая температура
|
// целевая температура
|
||||||
#define AC_TEMP_TARGET_INT_PART_MASK 0b11111000
|
#define AC_TEMP_TARGET_INT_PART_MASK 0b11111000
|
||||||
@@ -756,7 +756,7 @@ class AirCon : public esphome::Component, public esphome::climate::Climate {
|
|||||||
// входящий и исходящий пакеты
|
// входящий и исходящий пакеты
|
||||||
packet_t _inPacket;
|
packet_t _inPacket;
|
||||||
packet_t _outPacket;
|
packet_t _outPacket;
|
||||||
|
|
||||||
// пакет для тестирования всякой фигни
|
// пакет для тестирования всякой фигни
|
||||||
packet_t _outTestPacket;
|
packet_t _outTestPacket;
|
||||||
|
|
||||||
@@ -915,7 +915,7 @@ class AirCon : public esphome::Component, public esphome::climate::Climate {
|
|||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// заполняет структуру команды нейтральными значениями
|
// заполняет структуру команды нейтральными значениями
|
||||||
void _clearCommand(ac_command_t * cmd){
|
void _clearCommand(ac_command_t * cmd){
|
||||||
cmd->clean = AC_CLEAN_UNTOUCHED;
|
cmd->clean = AC_CLEAN_UNTOUCHED;
|
||||||
@@ -944,7 +944,7 @@ class AirCon : public esphome::Component, public esphome::climate::Climate {
|
|||||||
cmd->temp_strange = 0;
|
cmd->temp_strange = 0;
|
||||||
cmd->realFanSpeed = AC_REAL_FAN_UNTOUCHED;
|
cmd->realFanSpeed = AC_REAL_FAN_UNTOUCHED;
|
||||||
};
|
};
|
||||||
|
|
||||||
// очистка буфера размером AC_BUFFER_SIZE
|
// очистка буфера размером AC_BUFFER_SIZE
|
||||||
void _clearBuffer(uint8_t * buf){
|
void _clearBuffer(uint8_t * buf){
|
||||||
memset(buf, 0, AC_BUFFER_SIZE);
|
memset(buf, 0, AC_BUFFER_SIZE);
|
||||||
@@ -1287,7 +1287,7 @@ class AirCon : public esphome::Component, public esphome::climate::Climate {
|
|||||||
stateByte = small_info_body->display_and_mildew & AC_MILDEW_MASK;
|
stateByte = small_info_body->display_and_mildew & AC_MILDEW_MASK;
|
||||||
stateChangedFlag = stateChangedFlag || (_current_ac_state.mildew != (ac_mildew)stateByte);
|
stateChangedFlag = stateChangedFlag || (_current_ac_state.mildew != (ac_mildew)stateByte);
|
||||||
_current_ac_state.mildew = (ac_mildew)stateByte;
|
_current_ac_state.mildew = (ac_mildew)stateByte;
|
||||||
|
|
||||||
// уведомляем об изменении статуса сплита
|
// уведомляем об изменении статуса сплита
|
||||||
if (stateChangedFlag) stateChanged();
|
if (stateChangedFlag) stateChanged();
|
||||||
|
|
||||||
@@ -2000,9 +2000,9 @@ class AirCon : public esphome::Component, public esphome::climate::Climate {
|
|||||||
|
|
||||||
_clearPacket(&_outTestPacket);
|
_clearPacket(&_outTestPacket);
|
||||||
_outTestPacket.header->start_byte = AC_PACKET_START_BYTE;
|
_outTestPacket.header->start_byte = AC_PACKET_START_BYTE;
|
||||||
_outTestPacket.header->wifi = AC_PACKET_ANSWER;
|
_outTestPacket.header->wifi = AC_PACKET_ANSWER;
|
||||||
|
|
||||||
_setStateMachineState(ACSM_IDLE);
|
_setStateMachineState(ACSM_IDLE);
|
||||||
_ac_serial = parent;
|
_ac_serial = parent;
|
||||||
_hw_initialized = (_ac_serial != nullptr);
|
_hw_initialized = (_ac_serial != nullptr);
|
||||||
_has_connection = false;
|
_has_connection = false;
|
||||||
@@ -2772,7 +2772,7 @@ class AirCon : public esphome::Component, public esphome::climate::Climate {
|
|||||||
cmd.sleep = AC_SLEEP_ON;
|
cmd.sleep = AC_SLEEP_ON;
|
||||||
cmd.iFeel = AC_IFEEL_OFF; // для логики пресетов
|
cmd.iFeel = AC_IFEEL_OFF; // для логики пресетов
|
||||||
cmd.health = AC_HEALTH_OFF; // для логики пресетов
|
cmd.health = AC_HEALTH_OFF; // для логики пресетов
|
||||||
cmd.health_status = AC_HEALTH_ERROR_NO;
|
cmd.health_status = AC_HEALTH_STATUS_OFF;
|
||||||
this->preset = preset;
|
this->preset = preset;
|
||||||
} else {
|
} else {
|
||||||
_debugMsg(F("SLEEP preset is suitable in COOL,HEAT and AUTO modes only."), ESPHOME_LOG_LEVEL_VERBOSE, __LINE__);
|
_debugMsg(F("SLEEP preset is suitable in COOL,HEAT and AUTO modes only."), ESPHOME_LOG_LEVEL_VERBOSE, __LINE__);
|
||||||
@@ -2782,7 +2782,7 @@ class AirCon : public esphome::Component, public esphome::climate::Climate {
|
|||||||
// выбран пустой пресет, сбрасываем все настройки
|
// выбран пустой пресет, сбрасываем все настройки
|
||||||
hasCommand = true;
|
hasCommand = true;
|
||||||
cmd.health = AC_HEALTH_OFF; // для логики пресетов
|
cmd.health = AC_HEALTH_OFF; // для логики пресетов
|
||||||
cmd.health_status = AC_HEALTH_ERROR_NO;
|
cmd.health_status = AC_HEALTH_STATUS_OFF;
|
||||||
cmd.sleep = AC_SLEEP_OFF; // для логики пресетов
|
cmd.sleep = AC_SLEEP_OFF; // для логики пресетов
|
||||||
cmd.iFeel = AC_IFEEL_OFF; // для логики пресетов
|
cmd.iFeel = AC_IFEEL_OFF; // для логики пресетов
|
||||||
this->preset = preset;
|
this->preset = preset;
|
||||||
@@ -2802,13 +2802,13 @@ class AirCon : public esphome::Component, public esphome::climate::Climate {
|
|||||||
hasCommand = true;
|
hasCommand = true;
|
||||||
cmd.iFeel = AC_IFEEL_ON;
|
cmd.iFeel = AC_IFEEL_ON;
|
||||||
cmd.health = AC_HEALTH_OFF; // для логики пресетов
|
cmd.health = AC_HEALTH_OFF; // для логики пресетов
|
||||||
cmd.health_status = AC_HEALTH_ERROR_NO;
|
cmd.health_status = AC_HEALTH_STATUS_OFF;
|
||||||
cmd.sleep = AC_SLEEP_OFF; // для логики пресетов
|
cmd.sleep = AC_SLEEP_OFF; // для логики пресетов
|
||||||
this->custom_preset = custom_preset;
|
this->custom_preset = custom_preset;
|
||||||
} else if (custom_preset == Constants::HEALTH) {
|
} else if (custom_preset == Constants::HEALTH) {
|
||||||
hasCommand = true;
|
hasCommand = true;
|
||||||
cmd.health = AC_HEALTH_ON;
|
cmd.health = AC_HEALTH_ON;
|
||||||
cmd.health_status = AC_HEALTH_ERROR_ACT;
|
cmd.health_status = AC_HEALTH_STATUS_ON;
|
||||||
cmd.iFeel = AC_IFEEL_ON; // зависимость от health
|
cmd.iFeel = AC_IFEEL_ON; // зависимость от health
|
||||||
cmd.fanTurbo = AC_FANTURBO_OFF; // зависимость от health
|
cmd.fanTurbo = AC_FANTURBO_OFF; // зависимость от health
|
||||||
cmd.fanMute = AC_FANMUTE_OFF; // зависимость от health
|
cmd.fanMute = AC_FANMUTE_OFF; // зависимость от health
|
||||||
|
|||||||
@@ -11,6 +11,7 @@ from esphome.const import (
|
|||||||
CONF_CUSTOM_FAN_MODES,
|
CONF_CUSTOM_FAN_MODES,
|
||||||
CONF_CUSTOM_PRESETS,
|
CONF_CUSTOM_PRESETS,
|
||||||
CONF_INTERNAL,
|
CONF_INTERNAL,
|
||||||
|
CONF_DATA,
|
||||||
CONF_SUPPORTED_MODES,
|
CONF_SUPPORTED_MODES,
|
||||||
CONF_SUPPORTED_SWING_MODES,
|
CONF_SUPPORTED_SWING_MODES,
|
||||||
CONF_SUPPORTED_PRESETS,
|
CONF_SUPPORTED_PRESETS,
|
||||||
@@ -66,6 +67,7 @@ Capabilities = aux_ac_ns.namespace("Constants")
|
|||||||
|
|
||||||
AirConDisplayOffAction = aux_ac_ns.class_("AirConDisplayOffAction", automation.Action)
|
AirConDisplayOffAction = aux_ac_ns.class_("AirConDisplayOffAction", automation.Action)
|
||||||
AirConDisplayOnAction = aux_ac_ns.class_("AirConDisplayOnAction", automation.Action)
|
AirConDisplayOnAction = aux_ac_ns.class_("AirConDisplayOnAction", automation.Action)
|
||||||
|
AirConSendTestPacketAction = aux_ac_ns.class_("AirConSendTestPacketAction", automation.Action)
|
||||||
|
|
||||||
ALLOWED_CLIMATE_MODES = {
|
ALLOWED_CLIMATE_MODES = {
|
||||||
"HEAT_COOL": ClimateMode.CLIMATE_MODE_HEAT_COOL,
|
"HEAT_COOL": ClimateMode.CLIMATE_MODE_HEAT_COOL,
|
||||||
@@ -102,6 +104,14 @@ CUSTOM_PRESETS = {
|
|||||||
}
|
}
|
||||||
validate_custom_presets = cv.enum(CUSTOM_PRESETS, upper=True)
|
validate_custom_presets = cv.enum(CUSTOM_PRESETS, upper=True)
|
||||||
|
|
||||||
|
def validate_raw_data(value):
|
||||||
|
if isinstance(value, list):
|
||||||
|
return cv.Schema([cv.hex_uint8_t])(value)
|
||||||
|
raise cv.Invalid(
|
||||||
|
"data must be a list of bytes"
|
||||||
|
)
|
||||||
|
|
||||||
|
|
||||||
def output_info(config):
|
def output_info(config):
|
||||||
"""_LOGGER.info(config)"""
|
"""_LOGGER.info(config)"""
|
||||||
return config
|
return config
|
||||||
@@ -283,11 +293,47 @@ DISPLAY_ACTION_SCHEMA = maybe_simple_id(
|
|||||||
)
|
)
|
||||||
|
|
||||||
@automation.register_action("aux_ac.display_off", AirConDisplayOffAction, DISPLAY_ACTION_SCHEMA)
|
@automation.register_action("aux_ac.display_off", AirConDisplayOffAction, DISPLAY_ACTION_SCHEMA)
|
||||||
async def switch_toggle_to_code(config, action_id, template_arg, args):
|
async def display_off_to_code(config, action_id, template_arg, args):
|
||||||
paren = await cg.get_variable(config[CONF_ID])
|
paren = await cg.get_variable(config[CONF_ID])
|
||||||
return cg.new_Pvariable(action_id, template_arg, paren)
|
return cg.new_Pvariable(action_id, template_arg, paren)
|
||||||
|
|
||||||
@automation.register_action("aux_ac.display_on", AirConDisplayOnAction, DISPLAY_ACTION_SCHEMA)
|
@automation.register_action("aux_ac.display_on", AirConDisplayOnAction, DISPLAY_ACTION_SCHEMA)
|
||||||
async def switch_toggle_to_code(config, action_id, template_arg, args):
|
async def display_on_to_code(config, action_id, template_arg, args):
|
||||||
paren = await cg.get_variable(config[CONF_ID])
|
paren = await cg.get_variable(config[CONF_ID])
|
||||||
return cg.new_Pvariable(action_id, template_arg, paren)
|
return cg.new_Pvariable(action_id, template_arg, paren)
|
||||||
|
|
||||||
|
|
||||||
|
SEND_TEST_PACKET_ACTION_SCHEMA = maybe_simple_id(
|
||||||
|
{
|
||||||
|
cv.Required(CONF_ID): cv.use_id(AirCon),
|
||||||
|
cv.Required(CONF_DATA): cv.templatable(validate_raw_data),
|
||||||
|
}
|
||||||
|
)
|
||||||
|
|
||||||
|
|
||||||
|
# *********************************************************************************************************
|
||||||
|
# ВАЖНО! Только для инженеров!
|
||||||
|
# Вызывайте метод aux_ac.send_packet только если понимаете, что делаете! Он не проверяет данные, а передаёт
|
||||||
|
# кондиционеру всё как есть. Какой эффект получится от передачи кондиционеру рандомных байт, никто не знает.
|
||||||
|
# Вы действуете на свой страх и риск.
|
||||||
|
# *********************************************************************************************************
|
||||||
|
@automation.register_action(
|
||||||
|
"aux_ac.send_packet",
|
||||||
|
AirConSendTestPacketAction,
|
||||||
|
SEND_TEST_PACKET_ACTION_SCHEMA
|
||||||
|
)
|
||||||
|
async def send_packet_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)
|
||||||
|
|
||||||
|
data = config[CONF_DATA]
|
||||||
|
if isinstance(data, bytes):
|
||||||
|
data = list(data)
|
||||||
|
|
||||||
|
if cg.is_template(data):
|
||||||
|
templ = await cg.templatable(data, args, cg.std_vector.template(cg.uint8))
|
||||||
|
cg.add(var.set_data_template(templ))
|
||||||
|
else:
|
||||||
|
cg.add(var.set_data_static(data))
|
||||||
|
|
||||||
|
return var
|
||||||
Reference in New Issue
Block a user