mirror of
https://github.com/GrKoR/esphome_aux_ac_component.git
synced 2025-12-10 05:26:56 +03:00
Add files via upload
This commit is contained in:
@@ -17,6 +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...>
|
||||||
@@ -30,5 +31,35 @@ namespace aux_ac {
|
|||||||
AirCon *ac_;
|
AirCon *ac_;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
template <typename... Ts>
|
||||||
|
class AirConSendTestPacketAction : public Action<Ts...>
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
explicit AirConSendTestPacketAction(AirCon *ac) : ac_(ac) {}
|
||||||
|
void set_data_template(std::function<std::vector<uint8_t>(Ts...)> func) {
|
||||||
|
this->data_func_ = func;
|
||||||
|
this->static_ = false;
|
||||||
|
}
|
||||||
|
void set_data_static(const std::vector<uint8_t> &data) {
|
||||||
|
this->data_static_ = data;
|
||||||
|
this->static_ = true;
|
||||||
|
}
|
||||||
|
|
||||||
|
void play(Ts... x) override {
|
||||||
|
if (this->static_) {
|
||||||
|
this->ac_->sendTestPacket(this->data_static_);
|
||||||
|
} else {
|
||||||
|
auto val = this->data_func_(x...);
|
||||||
|
this->ac_->sendTestPacket(val);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
protected:
|
||||||
|
AirCon *ac_;
|
||||||
|
bool static_{false};
|
||||||
|
std::function<std::vector<uint8_t>(Ts...)> data_func_{};
|
||||||
|
std::vector<uint8_t> data_static_{};
|
||||||
|
};
|
||||||
|
|
||||||
} // namespace aux_ac
|
} // namespace aux_ac
|
||||||
} // namespace esphome
|
} // namespace esphome
|
||||||
@@ -410,7 +410,7 @@ struct packet_small_info_body_t {
|
|||||||
// биты 0..5 растут на 1 каждую минуту, возможно внутренний таймер для включения/выключения по времени
|
// биты 0..5 растут на 1 каждую минуту, возможно внутренний таймер для включения/выключения по времени
|
||||||
uint8_t fan_speed; // три старших бита - скорость вентилятора, остальные биты не известны
|
uint8_t fan_speed; // три старших бита - скорость вентилятора, остальные биты не известны
|
||||||
// AUTO = 0xA0, LOW = 0x60, MEDIUM = 0x40, HIGH = 0x20
|
// AUTO = 0xA0, LOW = 0x60, MEDIUM = 0x40, HIGH = 0x20
|
||||||
uint8_t fan_turbo_and_mute; // бит 7 = режим TURBO, бит 6 - режим MUTE; остальные не известны
|
uint8_t fan_turbo_and_mute; // бит 7 = режим MUTE, бит 6 - режим TURBO; остальные не известны
|
||||||
uint8_t mode; // режим работы сплита:
|
uint8_t mode; // режим работы сплита:
|
||||||
// AUTO : bits[7, 6, 5] = [0, 0, 0]
|
// AUTO : bits[7, 6, 5] = [0, 0, 0]
|
||||||
// COOL : bits[7, 6, 5] = [0, 0, 1]
|
// COOL : bits[7, 6, 5] = [0, 0, 1]
|
||||||
@@ -757,6 +757,9 @@ class AirCon : public esphome::Component, public esphome::climate::Climate {
|
|||||||
packet_t _inPacket;
|
packet_t _inPacket;
|
||||||
packet_t _outPacket;
|
packet_t _outPacket;
|
||||||
|
|
||||||
|
// пакет для тестирования всякой фигни
|
||||||
|
packet_t _outTestPacket;
|
||||||
|
|
||||||
// последовательность пакетов текущий шаг в последовательности
|
// последовательность пакетов текущий шаг в последовательности
|
||||||
sequence_item_t _sequence[AC_SEQUENCE_MAX_LEN];
|
sequence_item_t _sequence[AC_SEQUENCE_MAX_LEN];
|
||||||
uint8_t _sequence_current_step;
|
uint8_t _sequence_current_step;
|
||||||
@@ -921,7 +924,7 @@ class AirCon : public esphome::Component, public esphome::climate::Climate {
|
|||||||
cmd->fanSpeed = AC_FANSPEED_UNTOUCHED;
|
cmd->fanSpeed = AC_FANSPEED_UNTOUCHED;
|
||||||
cmd->fanTurbo = AC_FANTURBO_UNTOUCHED;
|
cmd->fanTurbo = AC_FANTURBO_UNTOUCHED;
|
||||||
cmd->health = AC_HEALTH_UNTOUCHED;
|
cmd->health = AC_HEALTH_UNTOUCHED;
|
||||||
cmd->health_error = AC_HEALTH_ERROR_UNTOUCHED;
|
cmd->health_status = AC_HEALTH_STATUS_UNTOUCHED;
|
||||||
cmd->iFeel = AC_IFEEL_UNTOUCHED;
|
cmd->iFeel = AC_IFEEL_UNTOUCHED;
|
||||||
cmd->louver.louver_h = AC_LOUVERH_UNTOUCHED;
|
cmd->louver.louver_h = AC_LOUVERH_UNTOUCHED;
|
||||||
cmd->louver.louver_v = AC_LOUVERV_UNTOUCHED;
|
cmd->louver.louver_v = AC_LOUVERV_UNTOUCHED;
|
||||||
@@ -1269,9 +1272,9 @@ class AirCon : public esphome::Component, public esphome::climate::Climate {
|
|||||||
stateChangedFlag = stateChangedFlag || (_current_ac_state.health != (ac_health)stateByte);
|
stateChangedFlag = stateChangedFlag || (_current_ac_state.health != (ac_health)stateByte);
|
||||||
_current_ac_state.health = (ac_health)stateByte;
|
_current_ac_state.health = (ac_health)stateByte;
|
||||||
|
|
||||||
stateByte = small_info_body->status & AC_HEALTH_ERROR_MASK;
|
stateByte = small_info_body->status & AC_HEALTH_STATUS_MASK;
|
||||||
stateChangedFlag = stateChangedFlag || (_current_ac_state.health_error != (ac_health_error)stateByte);
|
stateChangedFlag = stateChangedFlag || (_current_ac_state.health_status != (ac_health_status)stateByte);
|
||||||
_current_ac_state.health_error = (ac_health_error)stateByte;
|
_current_ac_state.health_status = (ac_health_status)stateByte;
|
||||||
|
|
||||||
stateByte = small_info_body->status & AC_CLEAN_MASK;
|
stateByte = small_info_body->status & AC_CLEAN_MASK;
|
||||||
stateChangedFlag = stateChangedFlag || (_current_ac_state.clean != (ac_clean)stateByte);
|
stateChangedFlag = stateChangedFlag || (_current_ac_state.clean != (ac_clean)stateByte);
|
||||||
@@ -1995,6 +1998,10 @@ class AirCon : public esphome::Component, public esphome::climate::Climate {
|
|||||||
_clearInPacket();
|
_clearInPacket();
|
||||||
_clearOutPacket();
|
_clearOutPacket();
|
||||||
|
|
||||||
|
_clearPacket(&_outTestPacket);
|
||||||
|
_outTestPacket.header->start_byte = AC_PACKET_START_BYTE;
|
||||||
|
_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);
|
||||||
@@ -2802,7 +2809,7 @@ class AirCon : public esphome::Component, public esphome::climate::Climate {
|
|||||||
hasCommand = true;
|
hasCommand = true;
|
||||||
cmd.health = AC_HEALTH_ON;
|
cmd.health = AC_HEALTH_ON;
|
||||||
cmd.health_status = AC_HEALTH_STATUS_ON;
|
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
|
||||||
cmd.sleep = AC_SLEEP_OFF; // для логики пресетов
|
cmd.sleep = AC_SLEEP_OFF; // для логики пресетов
|
||||||
@@ -3110,6 +3117,67 @@ class AirCon : public esphome::Component, public esphome::climate::Climate {
|
|||||||
return _displaySequence(dsp);
|
return _displaySequence(dsp);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// отправляет сплиту заданный набор байт
|
||||||
|
// Перед отправкой проверяет пакет на корректность структуры. CRC16 рассчитывает самостоятельно и перезаписывает.
|
||||||
|
bool sendTestPacket(const std::vector<uint8_t> &data){
|
||||||
|
//bool sendTestPacket(uint8_t *data = nullptr, uitn8_t data_length = 0){
|
||||||
|
//if (data == nullptr) return false;
|
||||||
|
//if (data_length == 0) return false;
|
||||||
|
if (data.size() == 0) return false;
|
||||||
|
//if (data_length > AC_BUFFER_SIZE) return false;
|
||||||
|
if (data.size() > AC_BUFFER_SIZE) return false;
|
||||||
|
|
||||||
|
// нет смысла в отправке, если нет коннекта с кондиционером
|
||||||
|
if (!get_has_connection()) {
|
||||||
|
_debugMsg(F("sendTestPacket: no pings from HVAC. It seems like no AC connected."), ESPHOME_LOG_LEVEL_ERROR, __LINE__);
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
// очищаем пакет
|
||||||
|
_clearPacket(&_outTestPacket);
|
||||||
|
|
||||||
|
// копируем данные в пакет
|
||||||
|
//memcpy(_outTestPacket.data, data, data_length);
|
||||||
|
uint8_t i = 0;
|
||||||
|
for (uint8_t n : data) {
|
||||||
|
_outTestPacket.data[i] = n;
|
||||||
|
i++;
|
||||||
|
}
|
||||||
|
|
||||||
|
// на всякий случай указываем правильные некоторые байты
|
||||||
|
_outTestPacket.header->start_byte = AC_PACKET_START_BYTE;
|
||||||
|
//_outTestPacket.header->wifi = AC_PACKET_ANSWER;
|
||||||
|
|
||||||
|
_outTestPacket.msec = millis();
|
||||||
|
_outTestPacket.body = &(_outTestPacket.data[AC_HEADER_SIZE]);
|
||||||
|
_outTestPacket.bytesLoaded = AC_HEADER_SIZE + _outTestPacket.header->body_length + 2;
|
||||||
|
|
||||||
|
// рассчитываем и записываем в пакет CRC
|
||||||
|
_outTestPacket.crc = (packet_crc_t *) &(_outTestPacket.data[AC_HEADER_SIZE + _outTestPacket.header->body_length]);
|
||||||
|
_setCRC16(&_outTestPacket);
|
||||||
|
|
||||||
|
_debugMsg(F("sendTestPacket: test packet loaded."), ESPHOME_LOG_LEVEL_WARN, __LINE__);
|
||||||
|
_debugPrintPacket(&_outTestPacket, ESPHOME_LOG_LEVEL_WARN, __LINE__);
|
||||||
|
|
||||||
|
// ниже блок добавления отправки пакета в последовательность команд
|
||||||
|
//*****************************************************************
|
||||||
|
// есть ли место на запрос в последовательности команд?
|
||||||
|
if (_getFreeSequenceSpace() < 1) {
|
||||||
|
_debugMsg(F("sendTestPacket: not enough space in command sequence. Sequence steps doesn't loaded."), ESPHOME_LOG_LEVEL_WARN, __LINE__);
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
/*************************************** sendTestPacket request ***********************************************/
|
||||||
|
if (!_addSequenceFuncStep(&AirCon::sq_requestTestPacket)) {
|
||||||
|
_debugMsg(F("sendTestPacket: sendTestPacket request sequence step fail."), ESPHOME_LOG_LEVEL_WARN, __LINE__);
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
/**************************************************************************************/
|
||||||
|
|
||||||
|
_debugMsg(F("sendTestPacket: loaded to sequence"), ESPHOME_LOG_LEVEL_VERBOSE, __LINE__);
|
||||||
|
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
void set_period(uint32_t ms) { this->_update_period = ms; }
|
void set_period(uint32_t ms) { this->_update_period = ms; }
|
||||||
uint32_t get_period() { return this->_update_period; }
|
uint32_t get_period() { return this->_update_period; }
|
||||||
|
|
||||||
|
|||||||
@@ -39,6 +39,9 @@ CODEOWNERS = ["@GrKoR"]
|
|||||||
DEPENDENCIES = ["climate", "uart"]
|
DEPENDENCIES = ["climate", "uart"]
|
||||||
AUTO_LOAD = ["sensor", "binary_sensor"]
|
AUTO_LOAD = ["sensor", "binary_sensor"]
|
||||||
|
|
||||||
|
CONF_SUPPORTED_MODES = 'supported_modes'
|
||||||
|
CONF_SUPPORTED_SWING_MODES = 'supported_swing_modes'
|
||||||
|
CONF_SUPPORTED_PRESETS = 'supported_presets'
|
||||||
CONF_SHOW_ACTION = 'show_action'
|
CONF_SHOW_ACTION = 'show_action'
|
||||||
CONF_INDOOR_TEMPERATURE = 'indoor_temperature'
|
CONF_INDOOR_TEMPERATURE = 'indoor_temperature'
|
||||||
CONF_OUTDOOR_TEMPERATURE = 'outdoor_temperature'
|
CONF_OUTDOOR_TEMPERATURE = 'outdoor_temperature'
|
||||||
@@ -57,6 +60,7 @@ CONF_DISPLAY_INVERTED = 'display_inverted'
|
|||||||
ICON_DISPLAY = "mdi:clock-digital"
|
ICON_DISPLAY = "mdi:clock-digital"
|
||||||
CONF_STORE_SETTINGS = 'store_settings'
|
CONF_STORE_SETTINGS = 'store_settings'
|
||||||
|
|
||||||
|
|
||||||
aux_ac_ns = cg.esphome_ns.namespace("aux_ac")
|
aux_ac_ns = cg.esphome_ns.namespace("aux_ac")
|
||||||
AirCon = aux_ac_ns.class_("AirCon", climate.Climate, cg.Component)
|
AirCon = aux_ac_ns.class_("AirCon", climate.Climate, cg.Component)
|
||||||
Capabilities = aux_ac_ns.namespace("Constants")
|
Capabilities = aux_ac_ns.namespace("Constants")
|
||||||
@@ -100,6 +104,7 @@ 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):
|
def validate_raw_data(value):
|
||||||
if isinstance(value, list):
|
if isinstance(value, list):
|
||||||
return cv.Schema([cv.hex_uint8_t])(value)
|
return cv.Schema([cv.hex_uint8_t])(value)
|
||||||
@@ -282,6 +287,8 @@ async def to_code(config):
|
|||||||
if CONF_CUSTOM_FAN_MODES in config:
|
if CONF_CUSTOM_FAN_MODES in config:
|
||||||
cg.add(var.set_custom_fan_modes(config[CONF_CUSTOM_FAN_MODES]))
|
cg.add(var.set_custom_fan_modes(config[CONF_CUSTOM_FAN_MODES]))
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
DISPLAY_ACTION_SCHEMA = maybe_simple_id(
|
DISPLAY_ACTION_SCHEMA = maybe_simple_id(
|
||||||
{
|
{
|
||||||
cv.Required(CONF_ID): cv.use_id(AirCon),
|
cv.Required(CONF_ID): cv.use_id(AirCon),
|
||||||
@@ -299,7 +306,6 @@ async def display_on_to_code(config, action_id, template_arg, args):
|
|||||||
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(
|
SEND_TEST_PACKET_ACTION_SCHEMA = maybe_simple_id(
|
||||||
{
|
{
|
||||||
cv.Required(CONF_ID): cv.use_id(AirCon),
|
cv.Required(CONF_ID): cv.use_id(AirCon),
|
||||||
|
|||||||
Reference in New Issue
Block a user