48 HonAlarmMessages,
"Outdoor module failure",
"Outdoor defrost sensor failure",
49 "Outdoor compressor exhaust sensor failure",
"Outdoor EEPROM abnormality",
"Indoor coil sensor failure",
50 "Indoor-outdoor communication failure",
"Power supply overvoltage protection",
51 "Communication failure between panel and indoor unit",
"Outdoor compressor overheat protection",
52 "Outdoor environmental sensor abnormality",
"Full water protection",
"Indoor EEPROM failure",
53 "Outdoor out air sensor failure",
"CBD and module communication failure",
"Indoor DC fan failure",
54 "Outdoor DC fan failure",
"Door switch failure",
"Dust filter needs cleaning reminder",
"Water shortage protection",
55 "Humidity sensor failure",
"Indoor temperature sensor failure",
"Manipulator limit failure",
56 "Indoor PM2.5 sensor failure",
"Outdoor PM2.5 sensor failure",
"Indoor heating overload/high load alarm",
57 "Outdoor AC current protection",
"Outdoor compressor operation abnormality",
"Outdoor DC current protection",
58 "Outdoor no-load failure",
"CT current abnormality",
"Indoor cooling freeze protection",
59 "High and low pressure protection",
"Compressor out air temperature is too high",
60 "Outdoor evaporator sensor failure",
"Outdoor cooling overload",
"Water pump drainage failure",
61 "Three-phase power supply failure",
"Four-way valve failure",
"External alarm/scraper flow switch failure",
62 "Temperature cutoff protection alarm",
"Different mode operation failure",
"Electronic expansion valve failure",
63 "Dual heat source sensor Tw failure",
"Communication failure with the wired controller",
64 "Indoor unit address duplication failure",
"50Hz zero crossing failure",
"Outdoor unit failure",
65 "Formaldehyde sensor failure",
"VOC sensor failure",
"CO2 sensor failure",
"Firewall failure",
"Unknown");
69 got_valid_outdoor_temp_(false),
70 active_alarms_{0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00} {
93 if ((this->mode != ClimateMode::CLIMATE_MODE_OFF) && (this->mode != ClimateMode::CLIMATE_MODE_FAN_ONLY)) {
127 ESP_LOGW(TAG,
"Vertical AUTO mode is not allowed for airflow position selector");
155 ESP_LOGW(TAG,
"Horizontal AUTO mode is not allowed for airflow position selector");
175 return "56°C Steri-Clean";
177 return "No cleaning";
185 ESP_LOGI(TAG,
"Sending self cleaning start request");
193 ESP_LOGI(TAG,
"Sending steri cleaning start request");
200 haier_protocol::FrameType message_type,
201 const uint8_t *data,
size_t data_size) {
203 if (message_type == haier_protocol::FrameType::INVALID) {
204 ESP_LOGW(TAG,
"It looks like your ESPHome Haier climate configuration is wrong. You should use the smartAir2 "
205 "protocol instead of hOn");
207 return haier_protocol::HandlerError::INVALID_ANSWER;
209 haier_protocol::HandlerError result =
210 this->
answer_preprocess_(request_type, haier_protocol::FrameType::GET_DEVICE_VERSION, message_type,
212 if (result == haier_protocol::HandlerError::HANDLER_OK) {
215 return haier_protocol::HandlerError::WRONG_MESSAGE_STRUCTURE;
224 info.functions_[0] = (answr->
functions[1] & 0x01) != 0;
225 info.functions_[1] = (answr->
functions[1] & 0x02) != 0;
226 info.functions_[2] = (answr->
functions[1] & 0x04) != 0;
227 info.functions_[3] = (answr->
functions[1] & 0x08) != 0;
228 info.functions_[4] = (answr->
functions[1] & 0x20) != 0;
229 this->
use_crc_ = info.functions_[2];
230#ifdef USE_TEXT_SENSOR
244 haier_protocol::FrameType message_type,
245 const uint8_t *data,
size_t data_size) {
246 haier_protocol::HandlerError result =
247 this->
answer_preprocess_(request_type, haier_protocol::FrameType::GET_DEVICE_ID, message_type,
249 if (result == haier_protocol::HandlerError::HANDLER_OK) {
259 haier_protocol::FrameType message_type,
const uint8_t *data,
261 haier_protocol::HandlerError result =
262 this->
answer_preprocess_(request_type, haier_protocol::FrameType::CONTROL, message_type,
264 if (result == haier_protocol::HandlerError::HANDLER_OK) {
266 if (result != haier_protocol::HandlerError::HANDLER_OK) {
267 ESP_LOGW(TAG,
"Error %d while parsing Status packet", (
int) result);
280 this->real_control_packet_size_);
287 ESP_LOGI(TAG,
"First HVAC status received");
322 haier_protocol::FrameType request_type, haier_protocol::FrameType message_type,
const uint8_t *data,
325 request_type, haier_protocol::FrameType::GET_MANAGEMENT_INFORMATION, message_type,
327 if (result == haier_protocol::HandlerError::HANDLER_OK) {
337 haier_protocol::FrameType message_type,
338 const uint8_t *data,
size_t data_size) {
339 if (request_type == haier_protocol::FrameType::GET_ALARM_STATUS) {
340 if (message_type != haier_protocol::FrameType::GET_ALARM_STATUS_RESPONSE) {
343 return haier_protocol::HandlerError::UNSUPPORTED_MESSAGE;
349 return haier_protocol::HandlerError::UNEXPECTED_MESSAGE;
352 return haier_protocol::HandlerError::WRONG_MESSAGE_STRUCTURE;
355 return haier_protocol::HandlerError::HANDLER_OK;
358 return haier_protocol::HandlerError::UNSUPPORTED_MESSAGE;
364 haier_protocol::HandlerError result = haier_protocol::HandlerError::HANDLER_OK;
367 result = haier_protocol::HandlerError::WRONG_MESSAGE_STRUCTURE;
370 this->
haier_protocol_.send_answer(haier_protocol::HaierMessage(haier_protocol::FrameType::CONFIRM));
378 haier_protocol::FrameType::GET_DEVICE_VERSION,
379 [
this](haier_protocol::FrameType req, haier_protocol::FrameType msg,
const uint8_t *data,
size_t size) {
383 haier_protocol::FrameType::GET_DEVICE_ID,
384 [
this](haier_protocol::FrameType req, haier_protocol::FrameType msg,
const uint8_t *data,
size_t size) {
388 haier_protocol::FrameType::CONTROL,
389 [
this](haier_protocol::FrameType req, haier_protocol::FrameType msg,
const uint8_t *data,
size_t size) {
393 haier_protocol::FrameType::GET_MANAGEMENT_INFORMATION,
394 [
this](haier_protocol::FrameType req, haier_protocol::FrameType msg,
const uint8_t *data,
size_t size) {
398 haier_protocol::FrameType::GET_ALARM_STATUS,
399 [
this](haier_protocol::FrameType req, haier_protocol::FrameType msg,
const uint8_t *data,
size_t size) {
403 haier_protocol::FrameType::REPORT_NETWORK_STATUS,
404 [
this](haier_protocol::FrameType req, haier_protocol::FrameType msg,
const uint8_t *data,
size_t size) {
407 this->
haier_protocol_.set_message_handler(haier_protocol::FrameType::ALARM_STATUS,
408 [
this](haier_protocol::FrameType
type,
const uint8_t *data,
size_t size) {
416 " Protocol version: hOn\n"
417 " Control method: %d",
421 " Device protocol version: %s\n"
422 " Device software version: %s\n"
423 " Device hardware version: %s\n"
426 this->hvac_hardware_info_.value().software_version_,
427 this->hvac_hardware_info_.value().hardware_version_, this->hvac_hardware_info_.value().device_name_);
428 ESP_LOGCONFIG(TAG,
" Device features:%s%s%s%s%s",
430 (this->
hvac_hardware_info_.value().functions_[1] ? LOG_STR_LITERAL(
" controller-device") :
""),
448 uint8_t module_capabilities[2] = {0b00000000, 0b00000111};
449 static const haier_protocol::HaierMessage DEVICE_VERSION_REQUEST(
450 haier_protocol::FrameType::GET_DEVICE_VERSION, module_capabilities,
sizeof(module_capabilities));
456 static const haier_protocol::HaierMessage DEVICEID_REQUEST(haier_protocol::FrameType::GET_DEVICE_ID);
463 static const haier_protocol::HaierMessage STATUS_REQUEST(
465 static const haier_protocol::HaierMessage BIG_DATA_REQUEST(
479 static const haier_protocol::HaierMessage UPDATE_SIGNAL_REQUEST(
480 haier_protocol::FrameType::GET_MANAGEMENT_INFORMATION);
499 static const haier_protocol::HaierMessage ALARM_STATUS_REQUEST(haier_protocol::FrameType::GET_ALARM_STATUS);
515 ESP_LOGI(TAG,
"AC control is disabled, monitor only");
519 ESP_LOGW(TAG,
"Unsupported control method for hOn protocol!");
525 ESP_LOGW(TAG,
"Control message queue is empty!");
544 ESP_LOGW(TAG,
"SENDING_ACTION_COMMAND phase without action request!");
553 ALARM_STATUS_REQUEST_INTERVAL_MS) {
559 SIGNAL_LEVEL_UPDATE_INTERVAL_MS)) {
566 ESP_LOGE(TAG,
"Wrong protocol handler state: %s (%d), resetting communication",
575 static haier_protocol::HaierMessage power_on_message(
577 std::initializer_list<uint8_t>({0x00, 0x01}).begin(), 2);
578 return power_on_message;
580 static haier_protocol::HaierMessage power_off_message(
582 std::initializer_list<uint8_t>({0x00, 0x00}).begin(), 2);
583 return power_off_message;
589 constexpr uint32_t restore_settings_version = 0x57EB59DDUL;
597 bool settings_fixed =
false;
600 settings_fixed =
true;
604 settings_fixed =
true;
606 if (settings_fixed) {
615 uint8_t control_out_buffer[haier_protocol::MAX_FRAME_SIZE];
618 control_out_buffer[4] = 0;
619 bool has_hvac_settings =
false;
621 has_hvac_settings =
true;
623 if (climate_control.
mode.has_value()) {
624 switch (climate_control.
mode.value()) {
656 ESP_LOGE(
"Control",
"Unsupported climate mode");
661 if (climate_control.
fan_mode.has_value()) {
662 switch (climate_control.
fan_mode.value()) {
677 ESP_LOGE(
"Control",
"Unsupported fan mode");
704 out_data->
set_point = ((int) target_temp) - 16;
705 out_data->
half_degree = (target_temp - ((int) target_temp) >= 0.49f) ? 1 : 0;
711 }
else if (climate_control.
preset.has_value()) {
712 switch (climate_control.
preset.value()) {
736 ESP_LOGE(
"Control",
"Unsupported preset");
746 if (!vertical_axis_is_auto(target_swing_mode)) {
749 ESP_LOGD(TAG,
"Vertical swing is on; the position is kept for when it is turned off");
754 if (!horizontal_axis_is_auto(target_swing_mode)) {
757 ESP_LOGD(TAG,
"Horizontal swing is on; the position is kept for when it is turned off");
777 return haier_protocol::HaierMessage(haier_protocol::FrameType::CONTROL,
783 constexpr size_t active_alarms_size =
sizeof(this->
active_alarms_);
784 if (size >= active_alarms_size + 2) {
786 size_t alarm_code = 0;
787 for (
int i = active_alarms_size - 1; i >= 0; i--) {
789 uint8_t alarm_bit = 1;
790 for (
int b = 0; b < 8; b++) {
791 if ((packet[2 + i] & alarm_bit) != (this->
active_alarms_[i] & alarm_bit)) {
792 bool alarm_status = (packet[2 + i] & alarm_bit) != 0;
793 int log_level = alarm_status ? ESPHOME_LOG_LEVEL_WARN : ESPHOME_LOG_LEVEL_INFO;
797 static char alarm_message[HonAlarmMessages::MAX_LENGTH + 1];
798 ESPHOME_strncpy_P(alarm_message,
799 reinterpret_cast<const char *
>(
800 HonAlarmMessages::get_progmem_str(alarm_code, HonAlarmMessages::LAST_INDEX)),
801 sizeof(alarm_message));
803 const char *alarm_message = HonAlarmMessages::get_progmem_str(alarm_code, HonAlarmMessages::LAST_INDEX);
805 esp_log_printf_(log_level, TAG, __LINE__,
"Alarm %s (%d): %s", alarm_status ?
"activated" :
"deactivated",
806 alarm_code, alarm_message);
824 float alarm_count = 0.0f;
825 static uint8_t nibble_bits_count[] = {0, 1, 1, 2, 1, 2, 2, 3, 1, 2, 2, 3, 2, 3, 3, 4};
827 alarm_count += (float) (nibble_bits_count[packet[2 + i] & 0x0F] + nibble_bits_count[packet[2 + i] >> 4]);
839 if ((this->
sub_sensors_[(
size_t) type] !=
nullptr) && (sens ==
nullptr)) {
841 }
else if ((this->
sub_sensors_[(
size_t) type] ==
nullptr) && (sens !=
nullptr)) {
851 size_t index = (size_t)
type;
859#ifdef USE_BINARY_SENSOR
873 bool converted_value = value == 1;
874 size_t index = (size_t)
type;
882#ifdef USE_TEXT_SENSOR
903 size_t index = (size_t)
type;
926template<
typename Mode,
size_t N>
927static void publish_airflow_index(
select::Select *sel,
const std::array<Mode, N> &order, Mode
mode) {
928 if (sel ==
nullptr) {
934 for (
size_t i = 0; i < N; i++) {
938 }
else if (entry == Mode::CENTER) {
946 if (active.has_value() && *active == index) {
961 size_t expected_size =
963 if (size < expected_size) {
964 ESP_LOGW(TAG,
"Unexpected message size %u (expexted >= %zu)",
size, expected_size);
965 return haier_protocol::HandlerError::WRONG_MESSAGE_STRUCTURE;
967 uint16_t subtype = (((uint16_t) packet_buffer[0]) << 8) + packet_buffer[1];
986#ifdef USE_BINARY_SENSOR
1000 memcpy(&packet.control, packet_buffer + 2 + this->status_message_header_size_,
1002 memcpy(&packet.sensors, packet_buffer + 2 + this->status_message_header_size_ + this->real_control_packet_size_,
1004 if (packet.sensors.error_status != 0) {
1005 ESP_LOGW(TAG,
"HVAC error, code=0x%02X", packet.sensors.error_status);
1018 bool should_publish =
false;
1021 optional<ClimatePreset> old_preset = this->
preset;
1022 if (packet.control.fast_mode != 0) {
1024 }
else if (packet.control.sleep_mode != 0) {
1026 }
else if (packet.control.ten_degree != 0) {
1031 should_publish = should_publish || (!old_preset.has_value()) ||
1037 this->
target_temperature = packet.control.set_point + 16.0f + ((packet.control.half_degree == 1) ? 0.5f : 0.0f);
1038 should_publish = should_publish || (old_target_temperature != this->
target_temperature);
1044 should_publish = should_publish || (old_current_temperature != this->
current_temperature);
1048 optional<ClimateFanMode> old_fan_mode = this->
fan_mode;
1056 switch (packet.control.fan_mode) {
1062 ESP_LOGI(TAG,
"Fan speed Auto is not supported in Fan only AC mode, ignoring");
1077 should_publish = should_publish || (!old_fan_mode.has_value()) ||
1082 if (packet.control.ac_power != 0) {
1084 bool disp_status = packet.control.display_status != 0;
1099 should_publish = should_publish || (old_health_mode != this->
get_health_mode());
1103 if (packet.control.steri_clean == 1) {
1106 }
else if (packet.control.self_cleaning_status == 1) {
1114 ESP_LOGD(TAG,
"Cleaning status change: %d => %d", (uint8_t) this->
cleaning_status_, (uint8_t) new_cleaning);
1120 this->cleaning_status_ = new_cleaning;
1121#ifdef USE_TEXT_SENSOR
1129 if (packet.control.ac_power == 0) {
1133 switch (packet.control.ac_mode) {
1153 should_publish = should_publish || (old_mode != this->
mode);
1160 bool new_quiet_mode = packet.control.quiet_mode != 0;
1179 if (horizontal_swing_supported &&
1181 if (vertical_swing_supported &&
1188 if (vertical_swing_supported &&
1205 if (save_vertical || save_horizontal) {
1206 if (save_vertical) {
1209 if (save_horizontal) {
1217 should_publish = should_publish || (old_swing_mode != this->
swing_mode);
1220 if (should_publish) {
1223 if (should_publish) {
1224 ESP_LOGI(TAG,
"HVAC values changed");
1226 int log_level = should_publish ? ESPHOME_LOG_LEVEL_INFO : ESPHOME_LOG_LEVEL_DEBUG;
1227 esp_log_printf_(log_level, TAG, __LINE__,
"HVAC Mode = 0x%X", packet.control.ac_mode);
1228 esp_log_printf_(log_level, TAG, __LINE__,
"Fan speed Status = 0x%X", packet.control.fan_mode);
1229 esp_log_printf_(log_level, TAG, __LINE__,
"Horizontal Swing Status = 0x%X", packet.control.horizontal_swing_mode);
1230 esp_log_printf_(log_level, TAG, __LINE__,
"Vertical Swing Status = 0x%X", packet.control.vertical_swing_mode);
1231 esp_log_printf_(log_level, TAG, __LINE__,
"Set Point Status = 0x%X", packet.control.set_point);
1232 return haier_protocol::HandlerError::HANDLER_OK;
1259 uint8_t fan_mode_buf[] = {0x00, 0xFF};
1260 uint8_t quiet_mode_buf[] = {0x00, 0xFF};
1261 if (climate_control.
mode.has_value()) {
1262 climate_mode = climate_control.
mode.value();
1263 uint8_t
buffer[2] = {0x00, 0x00};
1264 switch (climate_control.
mode.value()) {
1314 ESP_LOGE(
"Control",
"Unsupported climate mode");
1327 uint8_t fast_mode_buf[] = {0x00, 0xFF};
1328 uint8_t away_mode_buf[] = {0x00, 0xFF};
1331 fast_mode_buf[1] = 0x00;
1332 away_mode_buf[1] = 0x00;
1333 }
else if (climate_control.
preset.has_value()) {
1334 switch (climate_control.
preset.value()) {
1336 fast_mode_buf[1] = 0x00;
1337 away_mode_buf[1] = 0x00;
1342 away_mode_buf[1] = 0x00;
1345 fast_mode_buf[1] = 0x00;
1349 ESP_LOGE(
"Control",
"Unsupported preset");
1356 quiet_mode_buf[1] = 0x01;
1358 quiet_mode_buf[1] = 0x00;
1364 if (quiet_mode_buf[1] != 0xFF) {
1384 if (climate_control.
target_temperature.has_value() && (this->mode != ClimateMode::CLIMATE_MODE_FAN_ONLY)) {
1385 uint8_t
buffer[2] = {0x00, 0x00};
1394 if (climate_control.
swing_mode.has_value()) {
1395 target_swing_mode = climate_control.
swing_mode.value();
1398 switch (climate_control.
swing_mode.value()) {
1415 horizontal_swing_buf, 2);
1419 vertical_swing_buf, 2);
1422 const bool swing_sent = climate_control.
swing_mode.has_value();
1424 if (vertical_axis_is_auto(target_swing_mode)) {
1425 ESP_LOGD(TAG,
"Vertical swing is on; the position is kept for when it is turned off");
1426 }
else if (!swing_sent) {
1431 vertical_swing_buf, 2);
1436 if (horizontal_axis_is_auto(target_swing_mode)) {
1437 ESP_LOGD(TAG,
"Horizontal swing is on; the position is kept for when it is turned off");
1438 }
else if (!swing_sent) {
1443 horizontal_swing_buf, 2);
1448 if (climate_control.
fan_mode.has_value()) {
1449 switch (climate_control.
fan_mode.value()) {
1464 ESP_LOGE(
"Control",
"Unsupported fan mode");
1467 if (fan_mode_buf[1] != 0xFF) {
1483 switch (action_request.action) {
1486 uint8_t control_out_buffer[haier_protocol::MAX_FRAME_SIZE];
1497 action_request.message = haier_protocol::HaierMessage(
1502 action_request.message =
1503 haier_protocol::HaierMessage(haier_protocol::FrameType::CONTROL,
1514 uint8_t control_out_buffer[haier_protocol::MAX_FRAME_SIZE];
1525 action_request.message = haier_protocol::HaierMessage(
1543 if ((sub_sensor !=
nullptr) && sub_sensor->has_state())
1544 sub_sensor->publish_state(NAN);
BedjetMode mode
BedJet operating mode.
uint32_t IRAM_ATTR HOT get_loop_component_start_time() const
Get the cached time in milliseconds from when the current component started its loop execution.
ESPPreferenceObject make_entity_preference(uint32_t version=0)
Create a preference object for storing this entity's state/settings.
constexpr size_t count(ValueType value) const
Check if the set contains a specific value (std::set compatibility) Returns 1 if present,...
Base class for all binary_sensor-type classes.
void publish_state(bool new_state)
Publish a new state to the front-end.
ClimateMode mode
The active mode of the climate device.
optional< ClimateFanMode > fan_mode
The active fan mode of the climate device.
float target_temperature
The target temperature of the climate device.
ClimateSwingMode swing_mode
The active swing mode of the climate device.
float current_temperature
The current temperature of the climate device, as reported from the integration.
void publish_state()
Publish the state of the climate device, to be called from integrations.
optional< ClimatePreset > preset
The active preset of the climate device.
const ClimatePresetMask & get_supported_presets() const
const ClimateSwingModeMask & get_supported_swing_modes() const
ProtocolPhases protocol_phase_
SwitchState display_status_
esphome::climate::ClimateTraits traits_
bool get_health_mode() const
bool is_message_interval_exceeded_(std::chrono::steady_clock::time_point now)
CallbackManager< void(const char *, size_t)> status_message_callback_
bool forced_request_status_
bool is_protocol_initialisation_interval_exceeded_(std::chrono::steady_clock::time_point now)
bool is_status_request_interval_exceeded_(std::chrono::steady_clock::time_point now)
haier_protocol::HandlerError answer_preprocess_(haier_protocol::FrameType request_message_type, haier_protocol::FrameType expected_request_message_type, haier_protocol::FrameType answer_message_type, haier_protocol::FrameType expected_answer_message_type, ProtocolPhases expected_phase)
virtual void initialization()
haier_protocol::ProtocolHandler haier_protocol_
virtual void process_protocol_reset()
const char * phase_to_string_(ProtocolPhases phase)
@ SENDING_UPDATE_SIGNAL_REQUEST
@ SENDING_ALARM_STATUS_REQUEST
@ SENDING_FIRST_STATUS_REQUEST
@ SENDING_FIRST_ALARM_STATUS_REQUEST
std::unique_ptr< uint8_t[]> last_status_message_
void send_message_(const haier_protocol::HaierMessage &command, bool use_crc, uint8_t num_repeats=0, std::chrono::milliseconds interval=std::chrono::milliseconds::zero())
haier_protocol::HandlerError report_network_status_answer_handler_(haier_protocol::FrameType request_type, haier_protocol::FrameType message_type, const uint8_t *data, size_t data_size)
void control(const esphome::climate::ClimateCall &call) override
bool can_send_message() const
virtual bool prepare_pending_action()
bool get_display_state() const
std::chrono::steady_clock::time_point last_valid_status_timestamp_
haier_protocol::HaierMessage get_wifi_signal_message_()
bool is_control_message_interval_exceeded_(std::chrono::steady_clock::time_point now)
uint8_t other_modes_fan_speed_
esphome::optional< PendingAction > action_request_
std::chrono::steady_clock::time_point last_status_request_
HvacSettings current_hvac_settings_
void dump_config() override
virtual void set_phase(ProtocolPhases phase)
std::chrono::steady_clock::time_point last_signal_request_
void set_quiet_mode_switch(switch_::Switch *sw)
bool should_get_big_data_()
void dump_config() override
esphome::optional< hon_protocol::VerticalSwingMode > get_vertical_airflow() const
ESPPreferenceObject hon_rtc_
void set_sub_text_sensor(SubTextSensorType type, text_sensor::TextSensor *sens)
select::Select * vertical_airflow_select_
uint8_t active_alarms_[8]
haier_protocol::HandlerError status_handler_(haier_protocol::FrameType request_type, haier_protocol::FrameType message_type, const uint8_t *data, size_t data_size)
HonControlMethod control_method_
void initialization() override
haier_protocol::HandlerError get_device_id_answer_handler_(haier_protocol::FrameType request_type, haier_protocol::FrameType message_type, const uint8_t *data, size_t data_size)
int extra_control_packet_bytes_
CallbackManager< void(uint8_t, const char *)> alarm_end_callback_
esphome::optional< HardwareInfo > hvac_hardware_info_
void set_sub_sensor(SubSensorType type, sensor::Sensor *sens)
void set_handlers() override
CallbackManager< void(uint8_t, const char *)> alarm_start_callback_
void update_sub_sensor_(SubSensorType type, float value)
void set_sub_binary_sensor(SubBinarySensorType type, binary_sensor::BinarySensor *sens)
haier_protocol::HaierMessage get_power_message(bool state) override
uint32_t vertical_direction_set_time_
bool got_valid_outdoor_temp_
text_sensor::TextSensor * sub_text_sensors_[(size_t) SubTextSensorType::SUB_TEXT_SENSOR_TYPE_COUNT]
haier_protocol::HandlerError get_alarm_status_answer_handler_(haier_protocol::FrameType request_type, haier_protocol::FrameType message_type, const uint8_t *data, size_t data_size)
int status_message_header_size_
switch_::Switch * beeper_switch_
std::chrono::steady_clock::time_point last_alarm_request_
void start_steri_cleaning()
sensor::Sensor * sub_sensors_[(size_t) SubSensorType::SUB_SENSOR_TYPE_COUNT]
void set_beeper_state(bool state)
uint8_t big_data_counter_
size_t real_control_packet_size_
int real_sensors_packet_size_
void set_horizontal_airflow(hon_protocol::HorizontalSwingMode direction)
haier_protocol::HandlerError process_status_message_(const uint8_t *packet, uint8_t size)
@ SUB_BINARY_SENSOR_TYPE_COUNT
@ INDOOR_ELECTRIC_HEATING_STATUS
void start_self_cleaning()
void set_vertical_airflow(hon_protocol::VerticalSwingMode direction)
bool get_beeper_state() const
void publish_airflow_selects_()
CleaningState cleaning_status_
haier_protocol::HandlerError get_management_information_answer_handler_(haier_protocol::FrameType request_type, haier_protocol::FrameType message_type, const uint8_t *data, size_t data_size)
std::queue< haier_protocol::HaierMessage > control_messages_queue_
esphome::optional< hon_protocol::HorizontalSwingMode > current_horizontal_swing_
void set_quiet_mode_state(bool state)
uint32_t horizontal_direction_set_time_
haier_protocol::HandlerError get_device_version_answer_handler_(haier_protocol::FrameType request_type, haier_protocol::FrameType message_type, const uint8_t *data, size_t data_size)
binary_sensor::BinarySensor * sub_binary_sensors_[(size_t) SubBinarySensorType::SUB_BINARY_SENSOR_TYPE_COUNT]
haier_protocol::HandlerError alarm_status_message_handler_(haier_protocol::FrameType type, const uint8_t *buffer, size_t size)
void clear_control_messages_queue_()
float active_alarm_count_
const char * get_cleaning_status_text() const
void update_sub_binary_sensor_(SubBinarySensorType type, uint8_t value)
haier_protocol::HaierMessage get_control_message() override
void process_phase(std::chrono::steady_clock::time_point now) override
select::Select * horizontal_airflow_select_
esphome::optional< hon_protocol::HorizontalSwingMode > pending_horizontal_direction_
static constexpr size_t HARDWARE_INFO_STR_SIZE
bool get_quiet_mode_state() const
switch_::Switch * quiet_mode_switch_
void process_protocol_reset() override
int extra_sensors_packet_bytes_
CleaningState get_cleaning_status() const
esphome::optional< hon_protocol::HorizontalSwingMode > get_horizontal_airflow() const
SwitchState quiet_mode_state_
void fill_control_messages_queue_()
void set_beeper_switch(switch_::Switch *sw)
esphome::optional< hon_protocol::VerticalSwingMode > current_vertical_swing_
@ BIG_DATA_FRAME_SUB_SENSORS
@ EXPANSION_VALVE_OPEN_DEGREE
@ OUTDOOR_IN_AIR_TEMPERATURE
@ INDOOR_COIL_TEMPERATURE
@ OUTDOOR_COIL_TEMPERATURE
@ OUTDOOR_OUT_AIR_TEMPERATURE
@ OUTDOOR_DEFROST_TEMPERATURE
void update_sub_text_sensor_(SubTextSensorType type, const char *value)
void process_alarm_message_(const uint8_t *packet, uint8_t size, bool check_new)
bool prepare_pending_action() override
esphome::optional< hon_protocol::VerticalSwingMode > pending_vertical_direction_
Base-class for all selects.
optional< size_t > active_index() const
Return the (optional) index offset of the currently active option.
void publish_state(const std::string &state)
Base-class for all sensors.
void publish_state(float state)
Publish a new state to the front-end.
Base class for all switches.
void publish_state(bool state)
Publish a state to the front-end from the back-end.
void publish_state(const std::string &state)
ClimateSwingMode swing_mode
@ CLIMATE_PRESET_NONE
No preset is active.
@ CLIMATE_PRESET_AWAY
Device is in away preset.
@ CLIMATE_PRESET_BOOST
Device is in boost preset.
@ CLIMATE_PRESET_SLEEP
Device is prepared for sleep.
ClimateSwingMode
Enum for all modes a climate swing can be in NOTE: If adding values, update ClimateSwingModeMask in c...
@ CLIMATE_SWING_OFF
The swing mode is set to Off.
@ CLIMATE_SWING_HORIZONTAL
The fan mode is set to Horizontal.
@ CLIMATE_SWING_VERTICAL
The fan mode is set to Vertical.
@ CLIMATE_SWING_BOTH
The fan mode is set to Both.
ClimateMode
Enum for all modes a climate device can be in.
@ CLIMATE_MODE_DRY
The climate device is set to dry/humidity mode.
@ CLIMATE_MODE_FAN_ONLY
The climate device only has the fan enabled, no heating or cooling is taking place.
@ CLIMATE_MODE_HEAT
The climate device is set to heat to reach the target temperature.
@ CLIMATE_MODE_COOL
The climate device is set to cool to reach the target temperature.
@ CLIMATE_MODE_HEAT_COOL
The climate device is set to heat/cool to reach the target temperature.
@ CLIMATE_MODE_OFF
The climate device is off.
@ CLIMATE_FAN_MEDIUM
The fan mode is set to Medium.
@ CLIMATE_FAN_ON
The fan mode is set to On.
@ CLIMATE_FAN_AUTO
The fan mode is set to Auto.
@ CLIMATE_FAN_LOW
The fan mode is set to Low.
@ CLIMATE_FAN_HIGH
The fan mode is set to High.
Mode airflow_order_at(const std::array< Mode, N > &order, size_t index)
constexpr uint8_t CONTROL_MESSAGE_RETRIES
constexpr size_t ALARM_STATUS_REQUEST_INTERVAL_MS
constexpr std::chrono::milliseconds CONTROL_MESSAGE_RETRIES_INTERVAL
constexpr uint32_t AIRFLOW_SELECT_DEBOUNCE_MS
PROGMEM_STRING_TABLE(HonAlarmMessages, "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", "Unknown")
constexpr int PROTOCOL_OUTDOOR_TEMPERATURE_OFFSET
ESPHOME_LOG_TAG(TAG, "haier.climate")
constexpr size_t SIGNAL_LEVEL_UPDATE_INTERVAL_MS
void HOT esp_log_printf_(int level, const char *tag, int line, const char *format,...)
constexpr uint16_t encode_uint16(uint8_t msb, uint8_t lsb)
Encode a 16-bit value given the most and least significant byte.
Application App
Global storage of Application pointer - only one Application can exist.
esphome::optional< esphome::climate::ClimateFanMode > fan_mode
esphome::optional< esphome::climate::ClimateSwingMode > swing_mode
esphome::optional< esphome::climate::ClimateMode > mode
esphome::optional< esphome::climate::ClimatePreset > preset
esphome::optional< float > target_temperature
hon_protocol::HorizontalSwingMode last_horizontal_swing
hon_protocol::VerticalSwingMode last_vertiacal_swing
uint8_t compressor_status
uint8_t indoor_coil_temperature
uint8_t outdoor_coil_temperature
uint8_t compressor_frequency
uint8_t four_way_valve_status
uint8_t expansion_valve_open_degree[2]
uint8_t outdoor_defrost_temperature
uint8_t outdoor_in_air_temperature
uint8_t indoor_electric_heating_status
uint8_t outdoor_out_air_temperature
uint8_t compressor_current[2]
uint8_t outdoor_fan_status
uint8_t indoor_fan_status
uint8_t vertical_swing_mode
uint8_t self_cleaning_status
uint8_t horizontal_swing_mode