mirror of
https://github.com/esphome/esphome.git
synced 2024-11-22 11:47:30 +01:00
Added alarm processing for Haier component (hOn protocol) (#5965)
This commit is contained in:
parent
c6a37da9da
commit
b5932940ee
@ -18,6 +18,7 @@ from esphome.const import (
|
|||||||
CONF_SUPPORTED_SWING_MODES,
|
CONF_SUPPORTED_SWING_MODES,
|
||||||
CONF_TARGET_TEMPERATURE,
|
CONF_TARGET_TEMPERATURE,
|
||||||
CONF_TEMPERATURE_STEP,
|
CONF_TEMPERATURE_STEP,
|
||||||
|
CONF_TRIGGER_ID,
|
||||||
CONF_VISUAL,
|
CONF_VISUAL,
|
||||||
CONF_WIFI,
|
CONF_WIFI,
|
||||||
DEVICE_CLASS_TEMPERATURE,
|
DEVICE_CLASS_TEMPERATURE,
|
||||||
@ -49,6 +50,8 @@ CONF_CONTROL_METHOD = "control_method"
|
|||||||
CONF_CONTROL_PACKET_SIZE = "control_packet_size"
|
CONF_CONTROL_PACKET_SIZE = "control_packet_size"
|
||||||
CONF_DISPLAY = "display"
|
CONF_DISPLAY = "display"
|
||||||
CONF_HORIZONTAL_AIRFLOW = "horizontal_airflow"
|
CONF_HORIZONTAL_AIRFLOW = "horizontal_airflow"
|
||||||
|
CONF_ON_ALARM_START = "on_alarm_start"
|
||||||
|
CONF_ON_ALARM_END = "on_alarm_end"
|
||||||
CONF_OUTDOOR_TEMPERATURE = "outdoor_temperature"
|
CONF_OUTDOOR_TEMPERATURE = "outdoor_temperature"
|
||||||
CONF_VERTICAL_AIRFLOW = "vertical_airflow"
|
CONF_VERTICAL_AIRFLOW = "vertical_airflow"
|
||||||
CONF_WIFI_SIGNAL = "wifi_signal"
|
CONF_WIFI_SIGNAL = "wifi_signal"
|
||||||
@ -85,8 +88,8 @@ AIRFLOW_HORIZONTAL_DIRECTION_OPTIONS = {
|
|||||||
}
|
}
|
||||||
|
|
||||||
SUPPORTED_SWING_MODES_OPTIONS = {
|
SUPPORTED_SWING_MODES_OPTIONS = {
|
||||||
"OFF": ClimateSwingMode.CLIMATE_SWING_OFF, # always available
|
"OFF": ClimateSwingMode.CLIMATE_SWING_OFF,
|
||||||
"VERTICAL": ClimateSwingMode.CLIMATE_SWING_VERTICAL, # always available
|
"VERTICAL": ClimateSwingMode.CLIMATE_SWING_VERTICAL,
|
||||||
"HORIZONTAL": ClimateSwingMode.CLIMATE_SWING_HORIZONTAL,
|
"HORIZONTAL": ClimateSwingMode.CLIMATE_SWING_HORIZONTAL,
|
||||||
"BOTH": ClimateSwingMode.CLIMATE_SWING_BOTH,
|
"BOTH": ClimateSwingMode.CLIMATE_SWING_BOTH,
|
||||||
}
|
}
|
||||||
@ -101,13 +104,15 @@ SUPPORTED_CLIMATE_MODES_OPTIONS = {
|
|||||||
}
|
}
|
||||||
|
|
||||||
SUPPORTED_CLIMATE_PRESETS_SMARTAIR2_OPTIONS = {
|
SUPPORTED_CLIMATE_PRESETS_SMARTAIR2_OPTIONS = {
|
||||||
|
"AWAY": ClimatePreset.CLIMATE_PRESET_AWAY,
|
||||||
"BOOST": ClimatePreset.CLIMATE_PRESET_BOOST,
|
"BOOST": ClimatePreset.CLIMATE_PRESET_BOOST,
|
||||||
"COMFORT": ClimatePreset.CLIMATE_PRESET_COMFORT,
|
"COMFORT": ClimatePreset.CLIMATE_PRESET_COMFORT,
|
||||||
}
|
}
|
||||||
|
|
||||||
SUPPORTED_CLIMATE_PRESETS_HON_OPTIONS = {
|
SUPPORTED_CLIMATE_PRESETS_HON_OPTIONS = {
|
||||||
"ECO": ClimatePreset.CLIMATE_PRESET_ECO,
|
"AWAY": ClimatePreset.CLIMATE_PRESET_AWAY,
|
||||||
"BOOST": ClimatePreset.CLIMATE_PRESET_BOOST,
|
"BOOST": ClimatePreset.CLIMATE_PRESET_BOOST,
|
||||||
|
"ECO": ClimatePreset.CLIMATE_PRESET_ECO,
|
||||||
"SLEEP": ClimatePreset.CLIMATE_PRESET_SLEEP,
|
"SLEEP": ClimatePreset.CLIMATE_PRESET_SLEEP,
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -118,6 +123,16 @@ SUPPORTED_HON_CONTROL_METHODS = {
|
|||||||
"SET_SINGLE_PARAMETER": HonControlMethod.SET_SINGLE_PARAMETER,
|
"SET_SINGLE_PARAMETER": HonControlMethod.SET_SINGLE_PARAMETER,
|
||||||
}
|
}
|
||||||
|
|
||||||
|
HaierAlarmStartTrigger = haier_ns.class_(
|
||||||
|
"HaierAlarmStartTrigger",
|
||||||
|
automation.Trigger.template(cg.uint8, cg.const_char_ptr),
|
||||||
|
)
|
||||||
|
|
||||||
|
HaierAlarmEndTrigger = haier_ns.class_(
|
||||||
|
"HaierAlarmEndTrigger",
|
||||||
|
automation.Trigger.template(cg.uint8, cg.const_char_ptr),
|
||||||
|
)
|
||||||
|
|
||||||
|
|
||||||
def validate_visual(config):
|
def validate_visual(config):
|
||||||
if CONF_VISUAL in config:
|
if CONF_VISUAL in config:
|
||||||
@ -200,9 +215,7 @@ CONFIG_SCHEMA = cv.All(
|
|||||||
): cv.boolean,
|
): cv.boolean,
|
||||||
cv.Optional(
|
cv.Optional(
|
||||||
CONF_SUPPORTED_PRESETS,
|
CONF_SUPPORTED_PRESETS,
|
||||||
default=list(
|
default=list(["BOOST", "COMFORT"]), # No AWAY by default
|
||||||
SUPPORTED_CLIMATE_PRESETS_SMARTAIR2_OPTIONS.keys()
|
|
||||||
),
|
|
||||||
): cv.ensure_list(
|
): cv.ensure_list(
|
||||||
cv.enum(SUPPORTED_CLIMATE_PRESETS_SMARTAIR2_OPTIONS, upper=True)
|
cv.enum(SUPPORTED_CLIMATE_PRESETS_SMARTAIR2_OPTIONS, upper=True)
|
||||||
),
|
),
|
||||||
@ -222,7 +235,7 @@ CONFIG_SCHEMA = cv.All(
|
|||||||
): cv.int_range(min=PROTOCOL_CONTROL_PACKET_SIZE, max=50),
|
): cv.int_range(min=PROTOCOL_CONTROL_PACKET_SIZE, max=50),
|
||||||
cv.Optional(
|
cv.Optional(
|
||||||
CONF_SUPPORTED_PRESETS,
|
CONF_SUPPORTED_PRESETS,
|
||||||
default=list(SUPPORTED_CLIMATE_PRESETS_HON_OPTIONS.keys()),
|
default=list(["BOOST", "ECO", "SLEEP"]), # No AWAY by default
|
||||||
): cv.ensure_list(
|
): cv.ensure_list(
|
||||||
cv.enum(SUPPORTED_CLIMATE_PRESETS_HON_OPTIONS, upper=True)
|
cv.enum(SUPPORTED_CLIMATE_PRESETS_HON_OPTIONS, upper=True)
|
||||||
),
|
),
|
||||||
@ -233,6 +246,20 @@ CONFIG_SCHEMA = cv.All(
|
|||||||
device_class=DEVICE_CLASS_TEMPERATURE,
|
device_class=DEVICE_CLASS_TEMPERATURE,
|
||||||
state_class=STATE_CLASS_MEASUREMENT,
|
state_class=STATE_CLASS_MEASUREMENT,
|
||||||
),
|
),
|
||||||
|
cv.Optional(CONF_ON_ALARM_START): automation.validate_automation(
|
||||||
|
{
|
||||||
|
cv.GenerateID(CONF_TRIGGER_ID): cv.declare_id(
|
||||||
|
HaierAlarmStartTrigger
|
||||||
|
),
|
||||||
|
}
|
||||||
|
),
|
||||||
|
cv.Optional(CONF_ON_ALARM_END): automation.validate_automation(
|
||||||
|
{
|
||||||
|
cv.GenerateID(CONF_TRIGGER_ID): cv.declare_id(
|
||||||
|
HaierAlarmEndTrigger
|
||||||
|
),
|
||||||
|
}
|
||||||
|
),
|
||||||
}
|
}
|
||||||
),
|
),
|
||||||
},
|
},
|
||||||
@ -457,5 +484,15 @@ async def to_code(config):
|
|||||||
config[CONF_CONTROL_PACKET_SIZE] - PROTOCOL_CONTROL_PACKET_SIZE
|
config[CONF_CONTROL_PACKET_SIZE] - PROTOCOL_CONTROL_PACKET_SIZE
|
||||||
)
|
)
|
||||||
)
|
)
|
||||||
|
for conf in config.get(CONF_ON_ALARM_START, []):
|
||||||
|
trigger = cg.new_Pvariable(conf[CONF_TRIGGER_ID], var)
|
||||||
|
await automation.build_automation(
|
||||||
|
trigger, [(cg.uint8, "code"), (cg.const_char_ptr, "message")], conf
|
||||||
|
)
|
||||||
|
for conf in config.get(CONF_ON_ALARM_END, []):
|
||||||
|
trigger = cg.new_Pvariable(conf[CONF_TRIGGER_ID], var)
|
||||||
|
await automation.build_automation(
|
||||||
|
trigger, [(cg.uint8, "code"), (cg.const_char_ptr, "message")], conf
|
||||||
|
)
|
||||||
# https://github.com/paveldn/HaierProtocol
|
# https://github.com/paveldn/HaierProtocol
|
||||||
cg.add_library("pavlodn/HaierProtocol", "0.9.24")
|
cg.add_library("pavlodn/HaierProtocol", "0.9.24")
|
||||||
|
@ -25,13 +25,14 @@ const char *HaierClimateBase::phase_to_string_(ProtocolPhases phase) {
|
|||||||
"SENDING_INIT_1",
|
"SENDING_INIT_1",
|
||||||
"SENDING_INIT_2",
|
"SENDING_INIT_2",
|
||||||
"SENDING_FIRST_STATUS_REQUEST",
|
"SENDING_FIRST_STATUS_REQUEST",
|
||||||
"SENDING_ALARM_STATUS_REQUEST",
|
"SENDING_FIRST_ALARM_STATUS_REQUEST",
|
||||||
"IDLE",
|
"IDLE",
|
||||||
"SENDING_STATUS_REQUEST",
|
"SENDING_STATUS_REQUEST",
|
||||||
"SENDING_UPDATE_SIGNAL_REQUEST",
|
"SENDING_UPDATE_SIGNAL_REQUEST",
|
||||||
"SENDING_SIGNAL_LEVEL",
|
"SENDING_SIGNAL_LEVEL",
|
||||||
"SENDING_CONTROL",
|
"SENDING_CONTROL",
|
||||||
"SENDING_ACTION_COMMAND",
|
"SENDING_ACTION_COMMAND",
|
||||||
|
"SENDING_ALARM_STATUS_REQUEST",
|
||||||
"UNKNOWN" // Should be the last!
|
"UNKNOWN" // Should be the last!
|
||||||
};
|
};
|
||||||
static_assert(
|
static_assert(
|
||||||
|
@ -64,7 +64,7 @@ class HaierClimateBase : public esphome::Component,
|
|||||||
SENDING_INIT_1 = 0,
|
SENDING_INIT_1 = 0,
|
||||||
SENDING_INIT_2,
|
SENDING_INIT_2,
|
||||||
SENDING_FIRST_STATUS_REQUEST,
|
SENDING_FIRST_STATUS_REQUEST,
|
||||||
SENDING_ALARM_STATUS_REQUEST,
|
SENDING_FIRST_ALARM_STATUS_REQUEST,
|
||||||
// FUNCTIONAL STATE
|
// FUNCTIONAL STATE
|
||||||
IDLE,
|
IDLE,
|
||||||
SENDING_STATUS_REQUEST,
|
SENDING_STATUS_REQUEST,
|
||||||
@ -72,6 +72,7 @@ class HaierClimateBase : public esphome::Component,
|
|||||||
SENDING_SIGNAL_LEVEL,
|
SENDING_SIGNAL_LEVEL,
|
||||||
SENDING_CONTROL,
|
SENDING_CONTROL,
|
||||||
SENDING_ACTION_COMMAND,
|
SENDING_ACTION_COMMAND,
|
||||||
|
SENDING_ALARM_STATUS_REQUEST,
|
||||||
NUM_PROTOCOL_PHASES
|
NUM_PROTOCOL_PHASES
|
||||||
};
|
};
|
||||||
const char *phase_to_string_(ProtocolPhases phase);
|
const char *phase_to_string_(ProtocolPhases phase);
|
||||||
|
@ -16,6 +16,7 @@ constexpr size_t SIGNAL_LEVEL_UPDATE_INTERVAL_MS = 10000;
|
|||||||
constexpr int PROTOCOL_OUTDOOR_TEMPERATURE_OFFSET = -64;
|
constexpr int PROTOCOL_OUTDOOR_TEMPERATURE_OFFSET = -64;
|
||||||
constexpr uint8_t CONTROL_MESSAGE_RETRIES = 5;
|
constexpr uint8_t CONTROL_MESSAGE_RETRIES = 5;
|
||||||
constexpr std::chrono::milliseconds CONTROL_MESSAGE_RETRIES_INTERVAL = std::chrono::milliseconds(500);
|
constexpr std::chrono::milliseconds CONTROL_MESSAGE_RETRIES_INTERVAL = std::chrono::milliseconds(500);
|
||||||
|
constexpr size_t ALARM_STATUS_REQUEST_INTERVAL_MS = 600000;
|
||||||
|
|
||||||
hon_protocol::VerticalSwingMode get_vertical_swing_mode(AirflowVerticalDirection direction) {
|
hon_protocol::VerticalSwingMode get_vertical_swing_mode(AirflowVerticalDirection direction) {
|
||||||
switch (direction) {
|
switch (direction) {
|
||||||
@ -110,6 +111,14 @@ void HonClimate::start_steri_cleaning() {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void HonClimate::add_alarm_start_callback(std::function<void(uint8_t, const char *)> &&callback) {
|
||||||
|
this->alarm_start_callback_.add(std::move(callback));
|
||||||
|
}
|
||||||
|
|
||||||
|
void HonClimate::add_alarm_end_callback(std::function<void(uint8_t, const char *)> &&callback) {
|
||||||
|
this->alarm_end_callback_.add(std::move(callback));
|
||||||
|
}
|
||||||
|
|
||||||
haier_protocol::HandlerError HonClimate::get_device_version_answer_handler_(haier_protocol::FrameType request_type,
|
haier_protocol::HandlerError HonClimate::get_device_version_answer_handler_(haier_protocol::FrameType request_type,
|
||||||
haier_protocol::FrameType message_type,
|
haier_protocol::FrameType message_type,
|
||||||
const uint8_t *data, size_t data_size) {
|
const uint8_t *data, size_t data_size) {
|
||||||
@ -194,7 +203,7 @@ haier_protocol::HandlerError HonClimate::status_handler_(haier_protocol::FrameTy
|
|||||||
switch (this->protocol_phase_) {
|
switch (this->protocol_phase_) {
|
||||||
case ProtocolPhases::SENDING_FIRST_STATUS_REQUEST:
|
case ProtocolPhases::SENDING_FIRST_STATUS_REQUEST:
|
||||||
ESP_LOGI(TAG, "First HVAC status received");
|
ESP_LOGI(TAG, "First HVAC status received");
|
||||||
this->set_phase(ProtocolPhases::SENDING_ALARM_STATUS_REQUEST);
|
this->set_phase(ProtocolPhases::SENDING_FIRST_ALARM_STATUS_REQUEST);
|
||||||
break;
|
break;
|
||||||
case ProtocolPhases::SENDING_ACTION_COMMAND:
|
case ProtocolPhases::SENDING_ACTION_COMMAND:
|
||||||
// Do nothing, phase will be changed in process_phase
|
// Do nothing, phase will be changed in process_phase
|
||||||
@ -251,12 +260,15 @@ haier_protocol::HandlerError HonClimate::get_alarm_status_answer_handler_(haier_
|
|||||||
this->set_phase(ProtocolPhases::IDLE);
|
this->set_phase(ProtocolPhases::IDLE);
|
||||||
return haier_protocol::HandlerError::UNSUPPORTED_MESSAGE;
|
return haier_protocol::HandlerError::UNSUPPORTED_MESSAGE;
|
||||||
}
|
}
|
||||||
if (this->protocol_phase_ != ProtocolPhases::SENDING_ALARM_STATUS_REQUEST) {
|
if ((this->protocol_phase_ != ProtocolPhases::SENDING_FIRST_ALARM_STATUS_REQUEST) &&
|
||||||
|
(this->protocol_phase_ != ProtocolPhases::SENDING_ALARM_STATUS_REQUEST)) {
|
||||||
// Don't expect this answer now
|
// Don't expect this answer now
|
||||||
this->set_phase(ProtocolPhases::IDLE);
|
this->set_phase(ProtocolPhases::IDLE);
|
||||||
return haier_protocol::HandlerError::UNEXPECTED_MESSAGE;
|
return haier_protocol::HandlerError::UNEXPECTED_MESSAGE;
|
||||||
}
|
}
|
||||||
memcpy(this->active_alarms_, data + 2, 8);
|
if (data_size < sizeof(active_alarms_) + 2)
|
||||||
|
return haier_protocol::HandlerError::WRONG_MESSAGE_STRUCTURE;
|
||||||
|
this->process_alarm_message_(data, data_size, this->protocol_phase_ >= ProtocolPhases::IDLE);
|
||||||
this->set_phase(ProtocolPhases::IDLE);
|
this->set_phase(ProtocolPhases::IDLE);
|
||||||
return haier_protocol::HandlerError::HANDLER_OK;
|
return haier_protocol::HandlerError::HANDLER_OK;
|
||||||
} else {
|
} else {
|
||||||
@ -265,6 +277,19 @@ haier_protocol::HandlerError HonClimate::get_alarm_status_answer_handler_(haier_
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
haier_protocol::HandlerError HonClimate::alarm_status_message_handler_(haier_protocol::FrameType type,
|
||||||
|
const uint8_t *buffer, size_t size) {
|
||||||
|
haier_protocol::HandlerError result = haier_protocol::HandlerError::HANDLER_OK;
|
||||||
|
if (size < sizeof(this->active_alarms_) + 2) {
|
||||||
|
// Log error but confirm anyway to avoid to many messages
|
||||||
|
result = haier_protocol::HandlerError::WRONG_MESSAGE_STRUCTURE;
|
||||||
|
}
|
||||||
|
this->process_alarm_message_(buffer, size, true);
|
||||||
|
this->haier_protocol_.send_answer(haier_protocol::HaierMessage(haier_protocol::FrameType::CONFIRM));
|
||||||
|
this->last_alarm_request_ = std::chrono::steady_clock::now();
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
|
||||||
void HonClimate::set_handlers() {
|
void HonClimate::set_handlers() {
|
||||||
// Set handlers
|
// Set handlers
|
||||||
this->haier_protocol_.set_answer_handler(
|
this->haier_protocol_.set_answer_handler(
|
||||||
@ -291,6 +316,10 @@ void HonClimate::set_handlers() {
|
|||||||
haier_protocol::FrameType::REPORT_NETWORK_STATUS,
|
haier_protocol::FrameType::REPORT_NETWORK_STATUS,
|
||||||
std::bind(&HonClimate::report_network_status_answer_handler_, this, std::placeholders::_1, std::placeholders::_2,
|
std::bind(&HonClimate::report_network_status_answer_handler_, this, std::placeholders::_1, std::placeholders::_2,
|
||||||
std::placeholders::_3, std::placeholders::_4));
|
std::placeholders::_3, std::placeholders::_4));
|
||||||
|
this->haier_protocol_.set_message_handler(
|
||||||
|
haier_protocol::FrameType::ALARM_STATUS,
|
||||||
|
std::bind(&HonClimate::alarm_status_message_handler_, this, std::placeholders::_1, std::placeholders::_2,
|
||||||
|
std::placeholders::_3));
|
||||||
}
|
}
|
||||||
|
|
||||||
void HonClimate::dump_config() {
|
void HonClimate::dump_config() {
|
||||||
@ -363,10 +392,12 @@ void HonClimate::process_phase(std::chrono::steady_clock::time_point now) {
|
|||||||
this->set_phase(ProtocolPhases::IDLE);
|
this->set_phase(ProtocolPhases::IDLE);
|
||||||
break;
|
break;
|
||||||
#endif
|
#endif
|
||||||
|
case ProtocolPhases::SENDING_FIRST_ALARM_STATUS_REQUEST:
|
||||||
case ProtocolPhases::SENDING_ALARM_STATUS_REQUEST:
|
case ProtocolPhases::SENDING_ALARM_STATUS_REQUEST:
|
||||||
if (this->can_send_message() && this->is_message_interval_exceeded_(now)) {
|
if (this->can_send_message() && this->is_message_interval_exceeded_(now)) {
|
||||||
static const haier_protocol::HaierMessage ALARM_STATUS_REQUEST(haier_protocol::FrameType::GET_ALARM_STATUS);
|
static const haier_protocol::HaierMessage ALARM_STATUS_REQUEST(haier_protocol::FrameType::GET_ALARM_STATUS);
|
||||||
this->send_message_(ALARM_STATUS_REQUEST, this->use_crc_);
|
this->send_message_(ALARM_STATUS_REQUEST, this->use_crc_);
|
||||||
|
this->last_alarm_request_ = now;
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
case ProtocolPhases::SENDING_CONTROL:
|
case ProtocolPhases::SENDING_CONTROL:
|
||||||
@ -417,12 +448,16 @@ void HonClimate::process_phase(std::chrono::steady_clock::time_point now) {
|
|||||||
if (this->forced_request_status_ || this->is_status_request_interval_exceeded_(now)) {
|
if (this->forced_request_status_ || this->is_status_request_interval_exceeded_(now)) {
|
||||||
this->set_phase(ProtocolPhases::SENDING_STATUS_REQUEST);
|
this->set_phase(ProtocolPhases::SENDING_STATUS_REQUEST);
|
||||||
this->forced_request_status_ = false;
|
this->forced_request_status_ = false;
|
||||||
|
} else if (std::chrono::duration_cast<std::chrono::milliseconds>(now - this->last_alarm_request_).count() >
|
||||||
|
ALARM_STATUS_REQUEST_INTERVAL_MS) {
|
||||||
|
this->set_phase(ProtocolPhases::SENDING_ALARM_STATUS_REQUEST);
|
||||||
}
|
}
|
||||||
#ifdef USE_WIFI
|
#ifdef USE_WIFI
|
||||||
else if (this->send_wifi_signal_ &&
|
else if (this->send_wifi_signal_ &&
|
||||||
(std::chrono::duration_cast<std::chrono::milliseconds>(now - this->last_signal_request_).count() >
|
(std::chrono::duration_cast<std::chrono::milliseconds>(now - this->last_signal_request_).count() >
|
||||||
SIGNAL_LEVEL_UPDATE_INTERVAL_MS))
|
SIGNAL_LEVEL_UPDATE_INTERVAL_MS)) {
|
||||||
this->set_phase(ProtocolPhases::SENDING_UPDATE_SIGNAL_REQUEST);
|
this->set_phase(ProtocolPhases::SENDING_UPDATE_SIGNAL_REQUEST);
|
||||||
|
}
|
||||||
#endif
|
#endif
|
||||||
} break;
|
} break;
|
||||||
default:
|
default:
|
||||||
@ -452,6 +487,7 @@ haier_protocol::HaierMessage HonClimate::get_control_message() {
|
|||||||
uint8_t control_out_buffer[sizeof(hon_protocol::HaierPacketControl)];
|
uint8_t control_out_buffer[sizeof(hon_protocol::HaierPacketControl)];
|
||||||
memcpy(control_out_buffer, this->last_status_message_.get(), sizeof(hon_protocol::HaierPacketControl));
|
memcpy(control_out_buffer, this->last_status_message_.get(), sizeof(hon_protocol::HaierPacketControl));
|
||||||
hon_protocol::HaierPacketControl *out_data = (hon_protocol::HaierPacketControl *) control_out_buffer;
|
hon_protocol::HaierPacketControl *out_data = (hon_protocol::HaierPacketControl *) control_out_buffer;
|
||||||
|
control_out_buffer[4] = 0; // This byte should be cleared before setting values
|
||||||
bool has_hvac_settings = false;
|
bool has_hvac_settings = false;
|
||||||
if (this->current_hvac_settings_.valid) {
|
if (this->current_hvac_settings_.valid) {
|
||||||
has_hvac_settings = true;
|
has_hvac_settings = true;
|
||||||
@ -552,31 +588,41 @@ haier_protocol::HaierMessage HonClimate::get_control_message() {
|
|||||||
out_data->quiet_mode = 0;
|
out_data->quiet_mode = 0;
|
||||||
out_data->fast_mode = 0;
|
out_data->fast_mode = 0;
|
||||||
out_data->sleep_mode = 0;
|
out_data->sleep_mode = 0;
|
||||||
|
out_data->ten_degree = 0;
|
||||||
break;
|
break;
|
||||||
case CLIMATE_PRESET_ECO:
|
case CLIMATE_PRESET_ECO:
|
||||||
// Eco is not supported in Fan only mode
|
// Eco is not supported in Fan only mode
|
||||||
out_data->quiet_mode = (this->mode != CLIMATE_MODE_FAN_ONLY) ? 1 : 0;
|
out_data->quiet_mode = (this->mode != CLIMATE_MODE_FAN_ONLY) ? 1 : 0;
|
||||||
out_data->fast_mode = 0;
|
out_data->fast_mode = 0;
|
||||||
out_data->sleep_mode = 0;
|
out_data->sleep_mode = 0;
|
||||||
|
out_data->ten_degree = 0;
|
||||||
break;
|
break;
|
||||||
case CLIMATE_PRESET_BOOST:
|
case CLIMATE_PRESET_BOOST:
|
||||||
out_data->quiet_mode = 0;
|
out_data->quiet_mode = 0;
|
||||||
// Boost is not supported in Fan only mode
|
// Boost is not supported in Fan only mode
|
||||||
out_data->fast_mode = (this->mode != CLIMATE_MODE_FAN_ONLY) ? 1 : 0;
|
out_data->fast_mode = (this->mode != CLIMATE_MODE_FAN_ONLY) ? 1 : 0;
|
||||||
out_data->sleep_mode = 0;
|
out_data->sleep_mode = 0;
|
||||||
|
out_data->ten_degree = 0;
|
||||||
break;
|
break;
|
||||||
case CLIMATE_PRESET_AWAY:
|
case CLIMATE_PRESET_AWAY:
|
||||||
out_data->quiet_mode = 0;
|
out_data->quiet_mode = 0;
|
||||||
out_data->fast_mode = 0;
|
out_data->fast_mode = 0;
|
||||||
out_data->sleep_mode = 0;
|
out_data->sleep_mode = 0;
|
||||||
|
// 10 degrees allowed only in heat mode
|
||||||
|
out_data->ten_degree = (this->mode == CLIMATE_MODE_HEAT) ? 1 : 0;
|
||||||
break;
|
break;
|
||||||
case CLIMATE_PRESET_SLEEP:
|
case CLIMATE_PRESET_SLEEP:
|
||||||
out_data->quiet_mode = 0;
|
out_data->quiet_mode = 0;
|
||||||
out_data->fast_mode = 0;
|
out_data->fast_mode = 0;
|
||||||
out_data->sleep_mode = 1;
|
out_data->sleep_mode = 1;
|
||||||
|
out_data->ten_degree = 0;
|
||||||
break;
|
break;
|
||||||
default:
|
default:
|
||||||
ESP_LOGE("Control", "Unsupported preset");
|
ESP_LOGE("Control", "Unsupported preset");
|
||||||
|
out_data->quiet_mode = 0;
|
||||||
|
out_data->fast_mode = 0;
|
||||||
|
out_data->sleep_mode = 0;
|
||||||
|
out_data->ten_degree = 0;
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -595,6 +641,50 @@ haier_protocol::HaierMessage HonClimate::get_control_message() {
|
|||||||
control_out_buffer, sizeof(hon_protocol::HaierPacketControl));
|
control_out_buffer, sizeof(hon_protocol::HaierPacketControl));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void HonClimate::process_alarm_message_(const uint8_t *packet, uint8_t size, bool check_new) {
|
||||||
|
constexpr size_t active_alarms_size = sizeof(this->active_alarms_);
|
||||||
|
if (size >= active_alarms_size + 2) {
|
||||||
|
if (check_new) {
|
||||||
|
size_t alarm_code = 0;
|
||||||
|
for (int i = active_alarms_size - 1; i >= 0; i--) {
|
||||||
|
if (packet[2 + i] != active_alarms_[i]) {
|
||||||
|
uint8_t alarm_bit = 1;
|
||||||
|
for (int b = 0; b < 8; b++) {
|
||||||
|
if ((packet[2 + i] & alarm_bit) != (this->active_alarms_[i] & alarm_bit)) {
|
||||||
|
bool alarm_status = (packet[2 + i] & alarm_bit) != 0;
|
||||||
|
int log_level = alarm_status ? ESPHOME_LOG_LEVEL_WARN : ESPHOME_LOG_LEVEL_INFO;
|
||||||
|
const char *alarm_message = alarm_code < esphome::haier::hon_protocol::HON_ALARM_COUNT
|
||||||
|
? esphome::haier::hon_protocol::HON_ALARM_MESSAGES[alarm_code].c_str()
|
||||||
|
: "Unknown";
|
||||||
|
esp_log_printf_(log_level, TAG, __LINE__, "Alarm %s (%d): %s", alarm_status ? "activated" : "deactivated",
|
||||||
|
alarm_code, alarm_message);
|
||||||
|
if (alarm_status) {
|
||||||
|
this->alarm_start_callback_.call(alarm_code, alarm_message);
|
||||||
|
this->active_alarm_count_ += 1.0f;
|
||||||
|
} else {
|
||||||
|
this->alarm_end_callback_.call(alarm_code, alarm_message);
|
||||||
|
this->active_alarm_count_ -= 1.0f;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
alarm_bit <<= 1;
|
||||||
|
alarm_code++;
|
||||||
|
}
|
||||||
|
active_alarms_[i] = packet[2 + i];
|
||||||
|
} else
|
||||||
|
alarm_code += 8;
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
float alarm_count = 0.0f;
|
||||||
|
static uint8_t nibble_bits_count[] = {0, 1, 1, 2, 1, 2, 2, 3, 1, 2, 2, 3, 2, 3, 3, 4};
|
||||||
|
for (size_t i = 0; i < sizeof(this->active_alarms_); i++) {
|
||||||
|
alarm_count += (float) (nibble_bits_count[packet[2 + i] & 0x0F] + nibble_bits_count[packet[2 + i] >> 4]);
|
||||||
|
}
|
||||||
|
this->active_alarm_count_ = alarm_count;
|
||||||
|
memcpy(this->active_alarms_, packet + 2, sizeof(this->active_alarms_));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
haier_protocol::HandlerError HonClimate::process_status_message_(const uint8_t *packet_buffer, uint8_t size) {
|
haier_protocol::HandlerError HonClimate::process_status_message_(const uint8_t *packet_buffer, uint8_t size) {
|
||||||
if (size < hon_protocol::HAIER_STATUS_FRAME_SIZE + this->extra_control_packet_bytes_)
|
if (size < hon_protocol::HAIER_STATUS_FRAME_SIZE + this->extra_control_packet_bytes_)
|
||||||
return haier_protocol::HandlerError::WRONG_MESSAGE_STRUCTURE;
|
return haier_protocol::HandlerError::WRONG_MESSAGE_STRUCTURE;
|
||||||
@ -626,6 +716,8 @@ haier_protocol::HandlerError HonClimate::process_status_message_(const uint8_t *
|
|||||||
this->preset = CLIMATE_PRESET_BOOST;
|
this->preset = CLIMATE_PRESET_BOOST;
|
||||||
} else if (packet.control.sleep_mode != 0) {
|
} else if (packet.control.sleep_mode != 0) {
|
||||||
this->preset = CLIMATE_PRESET_SLEEP;
|
this->preset = CLIMATE_PRESET_SLEEP;
|
||||||
|
} else if (packet.control.ten_degree != 0) {
|
||||||
|
this->preset = CLIMATE_PRESET_AWAY;
|
||||||
} else {
|
} else {
|
||||||
this->preset = CLIMATE_PRESET_NONE;
|
this->preset = CLIMATE_PRESET_NONE;
|
||||||
}
|
}
|
||||||
@ -882,25 +974,35 @@ void HonClimate::fill_control_messages_queue_() {
|
|||||||
// CLimate preset
|
// CLimate preset
|
||||||
{
|
{
|
||||||
uint8_t fast_mode_buf[] = {0x00, 0xFF};
|
uint8_t fast_mode_buf[] = {0x00, 0xFF};
|
||||||
|
uint8_t away_mode_buf[] = {0x00, 0xFF};
|
||||||
if (!new_power) {
|
if (!new_power) {
|
||||||
// If AC is off - no presets allowed
|
// If AC is off - no presets allowed
|
||||||
quiet_mode_buf[1] = 0x00;
|
quiet_mode_buf[1] = 0x00;
|
||||||
fast_mode_buf[1] = 0x00;
|
fast_mode_buf[1] = 0x00;
|
||||||
|
away_mode_buf[1] = 0x00;
|
||||||
} else if (climate_control.preset.has_value()) {
|
} else if (climate_control.preset.has_value()) {
|
||||||
switch (climate_control.preset.value()) {
|
switch (climate_control.preset.value()) {
|
||||||
case CLIMATE_PRESET_NONE:
|
case CLIMATE_PRESET_NONE:
|
||||||
quiet_mode_buf[1] = 0x00;
|
quiet_mode_buf[1] = 0x00;
|
||||||
fast_mode_buf[1] = 0x00;
|
fast_mode_buf[1] = 0x00;
|
||||||
|
away_mode_buf[1] = 0x00;
|
||||||
break;
|
break;
|
||||||
case CLIMATE_PRESET_ECO:
|
case CLIMATE_PRESET_ECO:
|
||||||
// Eco is not supported in Fan only mode
|
// Eco is not supported in Fan only mode
|
||||||
quiet_mode_buf[1] = (this->mode != CLIMATE_MODE_FAN_ONLY) ? 0x01 : 0x00;
|
quiet_mode_buf[1] = (this->mode != CLIMATE_MODE_FAN_ONLY) ? 0x01 : 0x00;
|
||||||
fast_mode_buf[1] = 0x00;
|
fast_mode_buf[1] = 0x00;
|
||||||
|
away_mode_buf[1] = 0x00;
|
||||||
break;
|
break;
|
||||||
case CLIMATE_PRESET_BOOST:
|
case CLIMATE_PRESET_BOOST:
|
||||||
quiet_mode_buf[1] = 0x00;
|
quiet_mode_buf[1] = 0x00;
|
||||||
// Boost is not supported in Fan only mode
|
// Boost is not supported in Fan only mode
|
||||||
fast_mode_buf[1] = (this->mode != CLIMATE_MODE_FAN_ONLY) ? 0x01 : 0x00;
|
fast_mode_buf[1] = (this->mode != CLIMATE_MODE_FAN_ONLY) ? 0x01 : 0x00;
|
||||||
|
away_mode_buf[1] = 0x00;
|
||||||
|
break;
|
||||||
|
case CLIMATE_PRESET_AWAY:
|
||||||
|
quiet_mode_buf[1] = 0x00;
|
||||||
|
fast_mode_buf[1] = 0x00;
|
||||||
|
away_mode_buf[1] = (this->mode == CLIMATE_MODE_HEAT) ? 0x01 : 0x00;
|
||||||
break;
|
break;
|
||||||
default:
|
default:
|
||||||
ESP_LOGE("Control", "Unsupported preset");
|
ESP_LOGE("Control", "Unsupported preset");
|
||||||
@ -921,6 +1023,13 @@ void HonClimate::fill_control_messages_queue_() {
|
|||||||
(uint8_t) hon_protocol::DataParameters::FAST_MODE,
|
(uint8_t) hon_protocol::DataParameters::FAST_MODE,
|
||||||
fast_mode_buf, 2));
|
fast_mode_buf, 2));
|
||||||
}
|
}
|
||||||
|
if (away_mode_buf[1] != 0xFF) {
|
||||||
|
this->control_messages_queue_.push(
|
||||||
|
haier_protocol::HaierMessage(haier_protocol::FrameType::CONTROL,
|
||||||
|
(uint16_t) hon_protocol::SubcommandsControl::SET_SINGLE_PARAMETER +
|
||||||
|
(uint8_t) hon_protocol::DataParameters::TEN_DEGREE,
|
||||||
|
away_mode_buf, 2));
|
||||||
|
}
|
||||||
}
|
}
|
||||||
// Target temperature
|
// Target temperature
|
||||||
if (climate_control.target_temperature.has_value()) {
|
if (climate_control.target_temperature.has_value()) {
|
||||||
|
@ -2,6 +2,7 @@
|
|||||||
|
|
||||||
#include <chrono>
|
#include <chrono>
|
||||||
#include "esphome/components/sensor/sensor.h"
|
#include "esphome/components/sensor/sensor.h"
|
||||||
|
#include "esphome/core/automation.h"
|
||||||
#include "haier_base.h"
|
#include "haier_base.h"
|
||||||
|
|
||||||
namespace esphome {
|
namespace esphome {
|
||||||
@ -52,6 +53,9 @@ class HonClimate : public HaierClimateBase {
|
|||||||
void start_steri_cleaning();
|
void start_steri_cleaning();
|
||||||
void set_extra_control_packet_bytes_size(size_t size) { this->extra_control_packet_bytes_ = size; };
|
void set_extra_control_packet_bytes_size(size_t size) { this->extra_control_packet_bytes_ = size; };
|
||||||
void set_control_method(HonControlMethod method) { this->control_method_ = method; };
|
void set_control_method(HonControlMethod method) { this->control_method_ = method; };
|
||||||
|
void add_alarm_start_callback(std::function<void(uint8_t, const char *)> &&callback);
|
||||||
|
void add_alarm_end_callback(std::function<void(uint8_t, const char *)> &&callback);
|
||||||
|
float get_active_alarm_count() const { return this->active_alarm_count_; }
|
||||||
|
|
||||||
protected:
|
protected:
|
||||||
void set_handlers() override;
|
void set_handlers() override;
|
||||||
@ -77,8 +81,11 @@ class HonClimate : public HaierClimateBase {
|
|||||||
haier_protocol::HandlerError get_alarm_status_answer_handler_(haier_protocol::FrameType request_type,
|
haier_protocol::HandlerError get_alarm_status_answer_handler_(haier_protocol::FrameType request_type,
|
||||||
haier_protocol::FrameType message_type,
|
haier_protocol::FrameType message_type,
|
||||||
const uint8_t *data, size_t data_size);
|
const uint8_t *data, size_t data_size);
|
||||||
|
haier_protocol::HandlerError alarm_status_message_handler_(haier_protocol::FrameType type, const uint8_t *buffer,
|
||||||
|
size_t size);
|
||||||
// Helper functions
|
// Helper functions
|
||||||
haier_protocol::HandlerError process_status_message_(const uint8_t *packet, uint8_t size);
|
haier_protocol::HandlerError process_status_message_(const uint8_t *packet, uint8_t size);
|
||||||
|
void process_alarm_message_(const uint8_t *packet, uint8_t size, bool check_new);
|
||||||
void fill_control_messages_queue_();
|
void fill_control_messages_queue_();
|
||||||
void clear_control_messages_queue_();
|
void clear_control_messages_queue_();
|
||||||
|
|
||||||
@ -101,6 +108,26 @@ class HonClimate : public HaierClimateBase {
|
|||||||
HonControlMethod control_method_;
|
HonControlMethod control_method_;
|
||||||
esphome::sensor::Sensor *outdoor_sensor_;
|
esphome::sensor::Sensor *outdoor_sensor_;
|
||||||
std::queue<haier_protocol::HaierMessage> control_messages_queue_;
|
std::queue<haier_protocol::HaierMessage> control_messages_queue_;
|
||||||
|
CallbackManager<void(uint8_t, const char *)> alarm_start_callback_{};
|
||||||
|
CallbackManager<void(uint8_t, const char *)> alarm_end_callback_{};
|
||||||
|
float active_alarm_count_{NAN};
|
||||||
|
std::chrono::steady_clock::time_point last_alarm_request_;
|
||||||
|
};
|
||||||
|
|
||||||
|
class HaierAlarmStartTrigger : public Trigger<uint8_t, const char *> {
|
||||||
|
public:
|
||||||
|
explicit HaierAlarmStartTrigger(HonClimate *parent) {
|
||||||
|
parent->add_alarm_start_callback(
|
||||||
|
[this](uint8_t alarm_code, const char *alarm_message) { this->trigger(alarm_code, alarm_message); });
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
class HaierAlarmEndTrigger : public Trigger<uint8_t, const char *> {
|
||||||
|
public:
|
||||||
|
explicit HaierAlarmEndTrigger(HonClimate *parent) {
|
||||||
|
parent->add_alarm_end_callback(
|
||||||
|
[this](uint8_t alarm_code, const char *alarm_message) { this->trigger(alarm_code, alarm_message); });
|
||||||
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
} // namespace haier
|
} // namespace haier
|
||||||
|
@ -163,6 +163,62 @@ enum class SubcommandsControl : uint16_t {
|
|||||||
// content: all values like in status packet)
|
// content: all values like in status packet)
|
||||||
};
|
};
|
||||||
|
|
||||||
|
const std::string HON_ALARM_MESSAGES[] = {
|
||||||
|
"Outdoor module failure",
|
||||||
|
"Outdoor defrost sensor failure",
|
||||||
|
"Outdoor compressor exhaust sensor failure",
|
||||||
|
"Outdoor EEPROM abnormality",
|
||||||
|
"Indoor coil sensor failure",
|
||||||
|
"Indoor-outdoor communication failure",
|
||||||
|
"Power supply overvoltage protection",
|
||||||
|
"Communication failure between panel and indoor unit",
|
||||||
|
"Outdoor compressor overheat protection",
|
||||||
|
"Outdoor environmental sensor abnormality",
|
||||||
|
"Full water protection",
|
||||||
|
"Indoor EEPROM failure",
|
||||||
|
"Outdoor out air sensor failure",
|
||||||
|
"CBD and module communication failure",
|
||||||
|
"Indoor DC fan failure",
|
||||||
|
"Outdoor DC fan failure",
|
||||||
|
"Door switch failure",
|
||||||
|
"Dust filter needs cleaning reminder",
|
||||||
|
"Water shortage protection",
|
||||||
|
"Humidity sensor failure",
|
||||||
|
"Indoor temperature sensor failure",
|
||||||
|
"Manipulator limit failure",
|
||||||
|
"Indoor PM2.5 sensor failure",
|
||||||
|
"Outdoor PM2.5 sensor failure",
|
||||||
|
"Indoor heating overload/high load alarm",
|
||||||
|
"Outdoor AC current protection",
|
||||||
|
"Outdoor compressor operation abnormality",
|
||||||
|
"Outdoor DC current protection",
|
||||||
|
"Outdoor no-load failure",
|
||||||
|
"CT current abnormality",
|
||||||
|
"Indoor cooling freeze protection",
|
||||||
|
"High and low pressure protection",
|
||||||
|
"Compressor out air temperature is too high",
|
||||||
|
"Outdoor evaporator sensor failure",
|
||||||
|
"Outdoor cooling overload",
|
||||||
|
"Water pump drainage failure",
|
||||||
|
"Three-phase power supply failure",
|
||||||
|
"Four-way valve failure",
|
||||||
|
"External alarm/scraper flow switch failure",
|
||||||
|
"Temperature cutoff protection alarm",
|
||||||
|
"Different mode operation failure",
|
||||||
|
"Electronic expansion valve failure",
|
||||||
|
"Dual heat source sensor Tw failure",
|
||||||
|
"Communication failure with the wired controller",
|
||||||
|
"Indoor unit address duplication failure",
|
||||||
|
"50Hz zero crossing failure",
|
||||||
|
"Outdoor unit failure",
|
||||||
|
"Formaldehyde sensor failure",
|
||||||
|
"VOC sensor failure",
|
||||||
|
"CO2 sensor failure",
|
||||||
|
"Firewall failure",
|
||||||
|
};
|
||||||
|
|
||||||
|
constexpr size_t HON_ALARM_COUNT = sizeof(HON_ALARM_MESSAGES) / sizeof(HON_ALARM_MESSAGES[0]);
|
||||||
|
|
||||||
} // namespace hon_protocol
|
} // namespace hon_protocol
|
||||||
} // namespace haier
|
} // namespace haier
|
||||||
} // namespace esphome
|
} // namespace esphome
|
||||||
|
@ -95,7 +95,7 @@ haier_protocol::HandlerError Smartair2Climate::messages_timeout_handler_with_cyc
|
|||||||
ESP_LOGI(TAG, "Answer timeout for command %02X, phase %s", (uint8_t) message_type,
|
ESP_LOGI(TAG, "Answer timeout for command %02X, phase %s", (uint8_t) message_type,
|
||||||
phase_to_string_(this->protocol_phase_));
|
phase_to_string_(this->protocol_phase_));
|
||||||
ProtocolPhases new_phase = (ProtocolPhases) ((int) this->protocol_phase_ + 1);
|
ProtocolPhases new_phase = (ProtocolPhases) ((int) this->protocol_phase_ + 1);
|
||||||
if (new_phase >= ProtocolPhases::SENDING_ALARM_STATUS_REQUEST)
|
if (new_phase >= ProtocolPhases::SENDING_FIRST_ALARM_STATUS_REQUEST)
|
||||||
new_phase = ProtocolPhases::SENDING_INIT_1;
|
new_phase = ProtocolPhases::SENDING_INIT_1;
|
||||||
this->set_phase(new_phase);
|
this->set_phase(new_phase);
|
||||||
return haier_protocol::HandlerError::HANDLER_OK;
|
return haier_protocol::HandlerError::HANDLER_OK;
|
||||||
@ -170,9 +170,12 @@ void Smartair2Climate::process_phase(std::chrono::steady_clock::time_point now)
|
|||||||
case ProtocolPhases::SENDING_UPDATE_SIGNAL_REQUEST:
|
case ProtocolPhases::SENDING_UPDATE_SIGNAL_REQUEST:
|
||||||
this->set_phase(ProtocolPhases::SENDING_SIGNAL_LEVEL);
|
this->set_phase(ProtocolPhases::SENDING_SIGNAL_LEVEL);
|
||||||
break;
|
break;
|
||||||
case ProtocolPhases::SENDING_ALARM_STATUS_REQUEST:
|
case ProtocolPhases::SENDING_FIRST_ALARM_STATUS_REQUEST:
|
||||||
this->set_phase(ProtocolPhases::SENDING_INIT_1);
|
this->set_phase(ProtocolPhases::SENDING_INIT_1);
|
||||||
break;
|
break;
|
||||||
|
case ProtocolPhases::SENDING_ALARM_STATUS_REQUEST:
|
||||||
|
this->set_phase(ProtocolPhases::IDLE);
|
||||||
|
break;
|
||||||
case ProtocolPhases::SENDING_CONTROL:
|
case ProtocolPhases::SENDING_CONTROL:
|
||||||
if (this->can_send_message() && this->is_control_message_interval_exceeded_(now)) {
|
if (this->can_send_message() && this->is_control_message_interval_exceeded_(now)) {
|
||||||
ESP_LOGI(TAG, "Sending control packet");
|
ESP_LOGI(TAG, "Sending control packet");
|
||||||
@ -343,19 +346,29 @@ haier_protocol::HaierMessage Smartair2Climate::get_control_message() {
|
|||||||
} else if (climate_control.preset.has_value()) {
|
} else if (climate_control.preset.has_value()) {
|
||||||
switch (climate_control.preset.value()) {
|
switch (climate_control.preset.value()) {
|
||||||
case CLIMATE_PRESET_NONE:
|
case CLIMATE_PRESET_NONE:
|
||||||
|
out_data->ten_degree = 0;
|
||||||
out_data->turbo_mode = 0;
|
out_data->turbo_mode = 0;
|
||||||
out_data->quiet_mode = 0;
|
out_data->quiet_mode = 0;
|
||||||
break;
|
break;
|
||||||
case CLIMATE_PRESET_BOOST:
|
case CLIMATE_PRESET_BOOST:
|
||||||
|
out_data->ten_degree = 0;
|
||||||
out_data->turbo_mode = 1;
|
out_data->turbo_mode = 1;
|
||||||
out_data->quiet_mode = 0;
|
out_data->quiet_mode = 0;
|
||||||
break;
|
break;
|
||||||
case CLIMATE_PRESET_COMFORT:
|
case CLIMATE_PRESET_COMFORT:
|
||||||
|
out_data->ten_degree = 0;
|
||||||
out_data->turbo_mode = 0;
|
out_data->turbo_mode = 0;
|
||||||
out_data->quiet_mode = 1;
|
out_data->quiet_mode = 1;
|
||||||
break;
|
break;
|
||||||
|
case CLIMATE_PRESET_AWAY:
|
||||||
|
// Only allowed in heat mode
|
||||||
|
out_data->ten_degree = (this->mode == CLIMATE_MODE_HEAT) ? 1 : 0;
|
||||||
|
out_data->turbo_mode = 0;
|
||||||
|
out_data->quiet_mode = 0;
|
||||||
|
break;
|
||||||
default:
|
default:
|
||||||
ESP_LOGE("Control", "Unsupported preset");
|
ESP_LOGE("Control", "Unsupported preset");
|
||||||
|
out_data->ten_degree = 0;
|
||||||
out_data->turbo_mode = 0;
|
out_data->turbo_mode = 0;
|
||||||
out_data->quiet_mode = 0;
|
out_data->quiet_mode = 0;
|
||||||
break;
|
break;
|
||||||
@ -381,6 +394,8 @@ haier_protocol::HandlerError Smartair2Climate::process_status_message_(const uin
|
|||||||
this->preset = CLIMATE_PRESET_BOOST;
|
this->preset = CLIMATE_PRESET_BOOST;
|
||||||
} else if (packet.control.quiet_mode != 0) {
|
} else if (packet.control.quiet_mode != 0) {
|
||||||
this->preset = CLIMATE_PRESET_COMFORT;
|
this->preset = CLIMATE_PRESET_COMFORT;
|
||||||
|
} else if (packet.control.ten_degree != 0) {
|
||||||
|
this->preset = CLIMATE_PRESET_AWAY;
|
||||||
} else {
|
} else {
|
||||||
this->preset = CLIMATE_PRESET_NONE;
|
this->preset = CLIMATE_PRESET_NONE;
|
||||||
}
|
}
|
||||||
|
@ -1026,11 +1026,13 @@ climate:
|
|||||||
wifi_signal: true
|
wifi_signal: true
|
||||||
beeper: true
|
beeper: true
|
||||||
outdoor_temperature:
|
outdoor_temperature:
|
||||||
name: Haier AC outdoor temperature
|
name: Haier AC outdoor temperature
|
||||||
visual:
|
visual:
|
||||||
min_temperature: 16 °C
|
min_temperature: 16 °C
|
||||||
max_temperature: 30 °C
|
max_temperature: 30 °C
|
||||||
temperature_step: 1 °C
|
temperature_step:
|
||||||
|
target_temperature: 1
|
||||||
|
current_temperature: 0.5
|
||||||
supported_modes:
|
supported_modes:
|
||||||
- 'OFF'
|
- 'OFF'
|
||||||
- HEAT_COOL
|
- HEAT_COOL
|
||||||
@ -1043,6 +1045,23 @@ climate:
|
|||||||
- VERTICAL
|
- VERTICAL
|
||||||
- HORIZONTAL
|
- HORIZONTAL
|
||||||
- BOTH
|
- BOTH
|
||||||
|
supported_presets:
|
||||||
|
- AWAY
|
||||||
|
- BOOST
|
||||||
|
- ECO
|
||||||
|
- SLEEP
|
||||||
|
on_alarm_start:
|
||||||
|
then:
|
||||||
|
- logger.log:
|
||||||
|
level: DEBUG
|
||||||
|
format: "Alarm activated. Code: %d. Message: \"%s\""
|
||||||
|
args: [ code, message]
|
||||||
|
on_alarm_end:
|
||||||
|
then:
|
||||||
|
- logger.log:
|
||||||
|
level: DEBUG
|
||||||
|
format: "Alarm deactivated. Code: %d. Message: \"%s\""
|
||||||
|
args: [ code, message]
|
||||||
|
|
||||||
sprinkler:
|
sprinkler:
|
||||||
- id: yard_sprinkler_ctrlr
|
- id: yard_sprinkler_ctrlr
|
||||||
|
Loading…
Reference in New Issue
Block a user