Skip to content

Commit

Permalink
Refactoring stage 2. Moving common code to HaierBase class
Browse files Browse the repository at this point in the history
  • Loading branch information
paveldn committed Oct 11, 2023
1 parent 641e6ee commit 4332b96
Show file tree
Hide file tree
Showing 6 changed files with 72 additions and 65 deletions.
10 changes: 7 additions & 3 deletions components/haier/haier_base.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -18,6 +18,7 @@ constexpr size_t COMMUNICATION_TIMEOUT_MS = 60000;
constexpr size_t STATUS_REQUEST_INTERVAL_MS = 5000;
constexpr size_t PROTOCOL_INITIALIZATION_INTERVAL = 10000;
constexpr size_t DEFAULT_MESSAGES_INTERVAL_MS = 2000;
constexpr size_t CONTROL_MESSAGES_INTERVAL_MS = 400;

#if (HAIER_LOG_LEVEL > 4)
// To reduce size of binary this function only available when log level is Verbose
Expand Down Expand Up @@ -61,10 +62,10 @@ HaierClimateBase::HaierClimateBase()
display_status_(true),
health_mode_(false),
force_send_control_(false),
forced_publish_(false),
forced_request_status_(false),
reset_protocol_request_(false),
send_wifi_signal_(true) {
send_wifi_signal_(true),
use_crc_(false) {
this->traits_ = climate::ClimateTraits();
this->traits_.set_supported_modes({climate::CLIMATE_MODE_OFF, climate::CLIMATE_MODE_COOL, climate::CLIMATE_MODE_HEAT,
climate::CLIMATE_MODE_FAN_ONLY, climate::CLIMATE_MODE_DRY,
Expand Down Expand Up @@ -94,7 +95,6 @@ void HaierClimateBase::reset_to_idle_() {
if (this->current_hvac_settings_.valid)
this->current_hvac_settings_.reset();
this->forced_request_status_ = true;
this->forced_publish_ = false;
this->set_phase(ProtocolPhases::IDLE);
this->action_request_ = ActionRequest::NO_ACTION;
}
Expand All @@ -112,6 +112,10 @@ bool HaierClimateBase::is_status_request_interval_exceeded_(std::chrono::steady_
return this->check_timeout_(now, this->last_status_request_, STATUS_REQUEST_INTERVAL_MS);
}

bool HaierClimateBase::is_control_message_interval_exceeded_(std::chrono::steady_clock::time_point now) {
return this->check_timeout_(now, this->last_request_timestamp_, CONTROL_MESSAGES_INTERVAL_MS);
}

bool HaierClimateBase::is_protocol_initialisation_interval_exceeded_(std::chrono::steady_clock::time_point now) {
return this->check_timeout_(now, this->last_request_timestamp_, PROTOCOL_INITIALIZATION_INTERVAL);
}
Expand Down
11 changes: 8 additions & 3 deletions components/haier/haier_base.h
Original file line number Diff line number Diff line change
Expand Up @@ -107,6 +107,7 @@ class HaierClimateBase : public esphome::Component,
size_t timeout);
bool is_message_interval_exceeded_(std::chrono::steady_clock::time_point now);
bool is_status_request_interval_exceeded_(std::chrono::steady_clock::time_point now);
bool is_control_message_interval_exceeded_(std::chrono::steady_clock::time_point now);
bool is_protocol_initialisation_interval_exceeded_(std::chrono::steady_clock::time_point now);
#ifdef USE_WIFI
haier_protocol::HaierMessage get_wifi_signal_message_(haier_protocol::FrameType message_type);
Expand All @@ -118,7 +119,10 @@ class HaierClimateBase : public esphome::Component,
esphome::optional<esphome::climate::ClimateSwingMode> swing_mode;
esphome::optional<float> target_temperature;
esphome::optional<esphome::climate::ClimatePreset> preset;
esphome::optional<bool> display;
esphome::optional<bool> health;
bool valid;
bool force_update;
HvacSettings() : valid(false){};
HvacSettings(const HvacSettings&) = default;
HvacSettings& operator=(const HvacSettings&) = default;
Expand All @@ -132,16 +136,17 @@ class HaierClimateBase : public esphome::Component,
bool display_status_;
bool health_mode_;
bool force_send_control_;
bool forced_publish_;
bool forced_request_status_;
bool reset_protocol_request_;
bool send_wifi_signal_;
bool use_crc_;
esphome::climate::ClimateTraits traits_;
HvacSettings current_hvac_settings_;
HvacSettings next_hvac_settings_;
HvacSettings next_hvac_settings_;
std::unique_ptr<uint8_t[]> last_status_message_;
std::chrono::steady_clock::time_point last_request_timestamp_; // For interval between messages
std::chrono::steady_clock::time_point last_valid_status_timestamp_; // For protocol timeout
std::chrono::steady_clock::time_point last_status_request_; // To request AC status
bool send_wifi_signal_;
std::chrono::steady_clock::time_point last_signal_request_; // To send WiFI signal level
};

Expand Down
88 changes: 43 additions & 45 deletions components/haier/hon_climate.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -50,14 +50,11 @@ hon_protocol::HorizontalSwingMode get_horizontal_swing_mode(AirflowHorizontalDir
}

HonClimate::HonClimate()
: last_status_message_(new uint8_t[sizeof(hon_protocol::HaierPacketControl)]),
cleaning_status_(CleaningState::NO_CLEANING),
: cleaning_status_(CleaningState::NO_CLEANING),
got_valid_outdoor_temp_(false),
hvac_hardware_info_available_(false),
hvac_functions_{false, false, false, false, false},
use_crc_(hvac_functions_[2]),
active_alarms_{0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00},
outdoor_sensor_(nullptr) {
last_status_message_ = std::unique_ptr<uint8_t[]>(new uint8_t[sizeof(hon_protocol::HaierPacketControl)]);
this->fan_mode_speed_ = (uint8_t) hon_protocol::FanMode::FAN_MID;
this->other_modes_fan_speed_ = (uint8_t) hon_protocol::FanMode::FAN_AUTO;
}
Expand Down Expand Up @@ -136,19 +133,20 @@ haier_protocol::HandlerError HonClimate::get_device_version_answer_handler_(haie
char tmp[9];
tmp[8] = 0;
strncpy(tmp, answr->protocol_version, 8);
this->hvac_protocol_version_ = std::string(tmp);
this->hvac_hardware_info_ = HardwareInfo();
this->hvac_hardware_info_.value().protocol_version_ = std::string(tmp);
strncpy(tmp, answr->software_version, 8);
this->hvac_software_version_ = std::string(tmp);
this->hvac_hardware_info_.value().software_version_ = std::string(tmp);
strncpy(tmp, answr->hardware_version, 8);
this->hvac_hardware_version_ = std::string(tmp);
this->hvac_hardware_info_.value().hardware_version_ = std::string(tmp);
strncpy(tmp, answr->device_name, 8);
this->hvac_device_name_ = std::string(tmp);
this->hvac_functions_[0] = (answr->functions[1] & 0x01) != 0; // interactive mode support
this->hvac_functions_[1] = (answr->functions[1] & 0x02) != 0; // controller-device mode support
this->hvac_functions_[2] = (answr->functions[1] & 0x04) != 0; // crc support
this->hvac_functions_[3] = (answr->functions[1] & 0x08) != 0; // multiple AC support
this->hvac_functions_[4] = (answr->functions[1] & 0x20) != 0; // roles support
this->hvac_hardware_info_available_ = true;
this->hvac_hardware_info_.value().device_name_ = std::string(tmp);
this->hvac_hardware_info_.value().functions_[0] = (answr->functions[1] & 0x01) != 0; // interactive mode support
this->hvac_hardware_info_.value().functions_[1] = (answr->functions[1] & 0x02) != 0; // controller-device mode support
this->hvac_hardware_info_.value().functions_[2] = (answr->functions[1] & 0x04) != 0; // crc support
this->hvac_hardware_info_.value().functions_[3] = (answr->functions[1] & 0x08) != 0; // multiple AC support
this->hvac_hardware_info_.value().functions_[4] = (answr->functions[1] & 0x20) != 0; // roles support
this->use_crc_ = this->hvac_hardware_info_.value().functions_[2];
this->set_phase(ProtocolPhases::SENDING_INIT_2);
return result;
} else {
Expand Down Expand Up @@ -304,14 +302,14 @@ void HonClimate::dump_config() {
HaierClimateBase::dump_config();
ESP_LOGCONFIG(TAG, " Protocol version: hOn");
ESP_LOGCONFIG(TAG, " Control method: %d", (uint8_t)this->control_method_);
if (this->hvac_hardware_info_available_) {
ESP_LOGCONFIG(TAG, " Device protocol version: %s", this->hvac_protocol_version_.c_str());
ESP_LOGCONFIG(TAG, " Device software version: %s", this->hvac_software_version_.c_str());
ESP_LOGCONFIG(TAG, " Device hardware version: %s", this->hvac_hardware_version_.c_str());
ESP_LOGCONFIG(TAG, " Device name: %s", this->hvac_device_name_.c_str());
ESP_LOGCONFIG(TAG, " Device features:%s%s%s%s%s", (this->hvac_functions_[0] ? " interactive" : ""),
(this->hvac_functions_[1] ? " controller-device" : ""), (this->hvac_functions_[2] ? " crc" : ""),
(this->hvac_functions_[3] ? " multinode" : ""), (this->hvac_functions_[4] ? " role" : ""));
if (this->hvac_hardware_info_.has_value()) {
ESP_LOGCONFIG(TAG, " Device protocol version: %s", this->hvac_hardware_info_.value().protocol_version_.c_str());
ESP_LOGCONFIG(TAG, " Device software version: %s", this->hvac_hardware_info_.value().software_version_.c_str());
ESP_LOGCONFIG(TAG, " Device hardware version: %s", this->hvac_hardware_info_.value().hardware_version_.c_str());
ESP_LOGCONFIG(TAG, " Device name: %s", this->hvac_hardware_info_.value().device_name_.c_str());
ESP_LOGCONFIG(TAG, " Device features:%s%s%s%s%s", (this->hvac_hardware_info_.value().functions_[0] ? " interactive" : ""),
(this->hvac_hardware_info_.value().functions_[1] ? " controller-device" : ""), (this->hvac_hardware_info_.value().functions_[2] ? " crc" : ""),
(this->hvac_hardware_info_.value().functions_[3] ? " multinode" : ""), (this->hvac_hardware_info_.value().functions_[4] ? " role" : ""));
ESP_LOGCONFIG(TAG, " Active alarms: %s", buf_to_hex(this->active_alarms_, sizeof(this->active_alarms_)).c_str());
}
}
Expand All @@ -320,7 +318,7 @@ void HonClimate::process_phase(std::chrono::steady_clock::time_point now) {
switch (this->protocol_phase_) {
case ProtocolPhases::SENDING_INIT_1:
if (this->can_send_message() && this->is_protocol_initialisation_interval_exceeded_(now)) {
this->hvac_hardware_info_available_ = false;
this->hvac_hardware_info_.reset();
// Indicate device capabilities:
// bit 0 - if 1 module support interactive mode
// bit 1 - if 1 module support controller-device mode
Expand Down Expand Up @@ -388,29 +386,30 @@ void HonClimate::process_phase(std::chrono::steady_clock::time_point now) {
}
break;
case ProtocolPhases::SENDING_CONTROL:
switch (this->control_method_) {
case HonControlMethod::SET_GROUP_PARAMETERS: {
haier_protocol::HaierMessage control_message = this->get_control_message();
this->clear_control_messages_queue_();
this->control_messages_queue_.push(control_message);
}
break;
case HonControlMethod::SET_SINGLE_PARAMETER:
this->fill_control_messages_queue_();
break;
case HonControlMethod::MONITOR_ONLY:
ESP_LOGI(TAG, "AC control is disabled, monitor only");
this->reset_to_idle_();
return;
default:
ESP_LOGW(TAG, "Unsupported control method for hOn protocol!");
this->reset_to_idle_();
return;
if (this->control_messages_queue_.empty()) {
switch (this->control_method_) {
case HonControlMethod::SET_GROUP_PARAMETERS: {
haier_protocol::HaierMessage control_message = this->get_control_message();
this->control_messages_queue_.push(control_message);
}
break;
case HonControlMethod::SET_SINGLE_PARAMETER:
this->fill_control_messages_queue_();
break;
case HonControlMethod::MONITOR_ONLY:
ESP_LOGI(TAG, "AC control is disabled, monitor only");
this->reset_to_idle_();
return;
default:
ESP_LOGW(TAG, "Unsupported control method for hOn protocol!");
this->reset_to_idle_();
return;
}
}
if (this->control_messages_queue_.empty()) {
ESP_LOGW(TAG, "Control message queue is empty!");
this->reset_to_idle_();
} else if (this->can_send_message() && this->is_message_interval_exceeded_(now)) {
} else if (this->can_send_message() && this->is_control_message_interval_exceeded_(now)) {
ESP_LOGI(TAG, "Sending control packet, queue size %d", this->control_messages_queue_.size());
this->send_message_(this->control_messages_queue_.front(), this->use_crc_, CONTROL_MESSAGE_RETRIES, CONTROL_MESSAGE_RETRIES_INTERVAL);
this->set_phase(ProtocolPhases::WAITING_CONTROL_ANSWER);
Expand Down Expand Up @@ -807,7 +806,7 @@ haier_protocol::HandlerError HonClimate::process_status_message_(const uint8_t *
should_publish = should_publish || (old_swing_mode != this->swing_mode);
}
this->last_valid_status_timestamp_ = std::chrono::steady_clock::now();
if (this->forced_publish_ || should_publish) {
if (should_publish) {
#if (HAIER_LOG_LEVEL > 4)
std::chrono::high_resolution_clock::time_point _publish_start = std::chrono::high_resolution_clock::now();
#endif
Expand All @@ -818,7 +817,6 @@ haier_protocol::HandlerError HonClimate::process_status_message_(const uint8_t *
_publish_start)
.count());
#endif
this->forced_publish_ = false;
}
if (should_publish) {
ESP_LOGI(TAG, "HVAC values changed");
Expand Down
17 changes: 9 additions & 8 deletions components/haier/hon_climate.h
Original file line number Diff line number Diff line change
Expand Up @@ -81,19 +81,20 @@ class HonClimate : public HaierClimateBase {
void fill_control_messages_queue_();
void clear_control_messages_queue_();

std::unique_ptr<uint8_t[]> last_status_message_;
struct HardwareInfo {
std::string protocol_version_;
std::string software_version_;
std::string hardware_version_;
std::string device_name_;
bool functions_[5];
};

bool beeper_status_;
CleaningState cleaning_status_;
bool got_valid_outdoor_temp_;
AirflowVerticalDirection vertical_direction_;
AirflowHorizontalDirection horizontal_direction_;
bool hvac_hardware_info_available_;
std::string hvac_protocol_version_;
std::string hvac_software_version_;
std::string hvac_hardware_version_;
std::string hvac_device_name_;
bool hvac_functions_[5];
bool &use_crc_;
esphome::optional<HardwareInfo> hvac_hardware_info_;
uint8_t active_alarms_[8];
int extra_control_packet_bytes_;
HonControlMethod control_method_;
Expand Down
10 changes: 5 additions & 5 deletions components/haier/smartair2_climate.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -15,8 +15,9 @@ constexpr size_t SIGNAL_LEVEL_UPDATE_INTERVAL_MS = 10000;
constexpr uint8_t CONTROL_MESSAGE_RETRIES = 5;
constexpr std::chrono::milliseconds CONTROL_MESSAGE_RETRIES_INTERVAL = std::chrono::milliseconds(500);

Smartair2Climate::Smartair2Climate()
: last_status_message_(new uint8_t[sizeof(smartair2_protocol::HaierPacketControl)]), timeouts_counter_(0) {}
Smartair2Climate::Smartair2Climate(): timeouts_counter_(0) {
last_status_message_ = std::unique_ptr<uint8_t[]>(new uint8_t[sizeof(smartair2_protocol::HaierPacketControl)]);
}

haier_protocol::HandlerError Smartair2Climate::status_handler_(haier_protocol::FrameType request_type, haier_protocol::FrameType message_type,
const uint8_t *data, size_t data_size) {
Expand Down Expand Up @@ -193,7 +194,7 @@ void Smartair2Climate::process_phase(std::chrono::steady_clock::time_point now)
this->set_phase(ProtocolPhases::SENDING_INIT_1);
break;
case ProtocolPhases::SENDING_CONTROL:
if (this->can_send_message() && this->is_message_interval_exceeded_(now))
if (this->can_send_message() && this->is_control_message_interval_exceeded_(now))
{
haier_protocol::HaierMessage control_message = get_control_message();
this->send_message_(control_message, false, CONTROL_MESSAGE_RETRIES, CONTROL_MESSAGE_RETRIES_INTERVAL);
Expand Down Expand Up @@ -538,7 +539,7 @@ haier_protocol::HandlerError Smartair2Climate::process_status_message_(const uin
should_publish = should_publish || (old_swing_mode != this->swing_mode);
}
this->last_valid_status_timestamp_ = std::chrono::steady_clock::now();
if (this->forced_publish_ || should_publish) {
if (should_publish) {
#if (HAIER_LOG_LEVEL > 4)
std::chrono::high_resolution_clock::time_point _publish_start = std::chrono::high_resolution_clock::now();
#endif
Expand All @@ -549,7 +550,6 @@ haier_protocol::HandlerError Smartair2Climate::process_status_message_(const uin
_publish_start)
.count());
#endif
this->forced_publish_ = false;
}
if (should_publish) {
ESP_LOGI(TAG, "HVAC values changed");
Expand Down
1 change: 0 additions & 1 deletion components/haier/smartair2_climate.h
Original file line number Diff line number Diff line change
Expand Up @@ -32,7 +32,6 @@ class Smartair2Climate : public HaierClimateBase {
haier_protocol::HandlerError initial_messages_timeout_handler_(haier_protocol::FrameType message_type);
// Helper functions
haier_protocol::HandlerError process_status_message_(const uint8_t *packet, uint8_t size);
std::unique_ptr<uint8_t[]> last_status_message_;
unsigned int timeouts_counter_;
bool use_alternative_swing_control_;
};
Expand Down

0 comments on commit 4332b96

Please sign in to comment.