Additional sensors and binary sensors support for Haier Climate (#6257)

Co-authored-by: Jesse Hills <3060199+jesserockz@users.noreply.github.com>
Co-authored-by: Pavlo Dudnytskyi <pdudnytskyi@astrata.eu>
This commit is contained in:
Pavlo Dudnytskyi 2024-03-04 22:54:01 +01:00 committed by GitHub
parent de2d5a65b5
commit 81b8451b8a
No known key found for this signature in database
GPG key ID: B5690EEEBB952194
13 changed files with 1054 additions and 61 deletions

View file

@ -0,0 +1,70 @@
import esphome.codegen as cg
import esphome.config_validation as cv
from esphome.components import binary_sensor
from esphome.const import (
ENTITY_CATEGORY_DIAGNOSTIC,
ICON_FAN,
ICON_RADIATOR,
)
from ..climate import (
CONF_HAIER_ID,
HonClimate,
)
BinarySensorTypeEnum = HonClimate.enum("SubBinarySensorType", True)
# Haier sensors
CONF_OUTDOOR_FAN_STATUS = "outdoor_fan_status"
CONF_DEFROST_STATUS = "defrost_status"
CONF_COMPRESSOR_STATUS = "compressor_status"
CONF_INDOOR_FAN_STATUS = "indoor_fan_status"
CONF_FOUR_WAY_VALVE_STATUS = "four_way_valve_status"
CONF_INDOOR_ELECTRIC_HEATING_STATUS = "indoor_electric_heating_status"
# Additional icons
ICON_SNOWFLAKE_THERMOMETER = "mdi:snowflake-thermometer"
ICON_HVAC = "mdi:hvac"
ICON_VALVE = "mdi:valve"
SENSOR_TYPES = {
CONF_OUTDOOR_FAN_STATUS: binary_sensor.binary_sensor_schema(
icon=ICON_FAN,
entity_category=ENTITY_CATEGORY_DIAGNOSTIC,
),
CONF_DEFROST_STATUS: binary_sensor.binary_sensor_schema(
icon=ICON_SNOWFLAKE_THERMOMETER,
entity_category=ENTITY_CATEGORY_DIAGNOSTIC,
),
CONF_COMPRESSOR_STATUS: binary_sensor.binary_sensor_schema(
icon=ICON_HVAC,
entity_category=ENTITY_CATEGORY_DIAGNOSTIC,
),
CONF_INDOOR_FAN_STATUS: binary_sensor.binary_sensor_schema(
icon=ICON_FAN,
entity_category=ENTITY_CATEGORY_DIAGNOSTIC,
),
CONF_FOUR_WAY_VALVE_STATUS: binary_sensor.binary_sensor_schema(
icon=ICON_VALVE,
entity_category=ENTITY_CATEGORY_DIAGNOSTIC,
),
CONF_INDOOR_ELECTRIC_HEATING_STATUS: binary_sensor.binary_sensor_schema(
icon=ICON_RADIATOR,
entity_category=ENTITY_CATEGORY_DIAGNOSTIC,
),
}
CONFIG_SCHEMA = cv.Schema(
{
cv.Required(CONF_HAIER_ID): cv.use_id(HonClimate),
}
).extend({cv.Optional(type): schema for type, schema in SENSOR_TYPES.items()})
async def to_code(config):
paren = await cg.get_variable(config[CONF_HAIER_ID])
for type, _ in SENSOR_TYPES.items():
if conf := config.get(type):
sens = await binary_sensor.new_binary_sensor(conf)
binary_sensor_type = getattr(BinarySensorTypeEnum, type.upper())
cg.add(paren.set_sub_binary_sensor(binary_sensor_type, sens))

View file

@ -2,7 +2,7 @@
import esphome.codegen as cg
import esphome.config_validation as cv
import esphome.final_validate as fv
from esphome.components import uart, sensor, climate, logger
from esphome.components import uart, climate, logger
from esphome import automation
from esphome.const import (
CONF_BEEPER,
@ -21,10 +21,6 @@ from esphome.const import (
CONF_TRIGGER_ID,
CONF_VISUAL,
CONF_WIFI,
DEVICE_CLASS_TEMPERATURE,
ICON_THERMOMETER,
STATE_CLASS_MEASUREMENT,
UNIT_CELSIUS,
)
from esphome.components.climate import (
ClimateMode,
@ -42,7 +38,6 @@ PROTOCOL_CURRENT_TEMPERATURE_STEP = 0.5
PROTOCOL_CONTROL_PACKET_SIZE = 10
CODEOWNERS = ["@paveldn"]
AUTO_LOAD = ["sensor"]
DEPENDENCIES = ["climate", "uart"]
CONF_ALTERNATIVE_SWING_CONTROL = "alternative_swing_control"
CONF_ANSWER_TIMEOUT = "answer_timeout"
@ -58,7 +53,6 @@ CONF_WIFI_SIGNAL = "wifi_signal"
PROTOCOL_HON = "HON"
PROTOCOL_SMARTAIR2 = "SMARTAIR2"
PROTOCOLS_SUPPORTED = [PROTOCOL_HON, PROTOCOL_SMARTAIR2]
haier_ns = cg.esphome_ns.namespace("haier")
HaierClimateBase = haier_ns.class_(
@ -67,6 +61,7 @@ HaierClimateBase = haier_ns.class_(
HonClimate = haier_ns.class_("HonClimate", HaierClimateBase)
Smartair2Climate = haier_ns.class_("Smartair2Climate", HaierClimateBase)
CONF_HAIER_ID = "haier_id"
AirflowVerticalDirection = haier_ns.enum("AirflowVerticalDirection", True)
AIRFLOW_VERTICAL_DIRECTION_OPTIONS = {
@ -239,12 +234,8 @@ CONFIG_SCHEMA = cv.All(
): cv.ensure_list(
cv.enum(SUPPORTED_CLIMATE_PRESETS_HON_OPTIONS, upper=True)
),
cv.Optional(CONF_OUTDOOR_TEMPERATURE): sensor.sensor_schema(
unit_of_measurement=UNIT_CELSIUS,
icon=ICON_THERMOMETER,
accuracy_decimals=0,
device_class=DEVICE_CLASS_TEMPERATURE,
state_class=STATE_CLASS_MEASUREMENT,
cv.Optional(CONF_OUTDOOR_TEMPERATURE): cv.invalid(
f"The {CONF_OUTDOOR_TEMPERATURE} option is deprecated, use a sensor for a haier platform instead"
),
cv.Optional(CONF_ON_ALARM_START): automation.validate_automation(
{
@ -463,9 +454,6 @@ async def to_code(config):
cg.add(var.set_beeper_state(config[CONF_BEEPER]))
if CONF_DISPLAY in config:
cg.add(var.set_display_state(config[CONF_DISPLAY]))
if CONF_OUTDOOR_TEMPERATURE in config:
sens = await sensor.new_sensor(config[CONF_OUTDOOR_TEMPERATURE])
cg.add(var.set_outdoor_temperature_sensor(sens))
if CONF_SUPPORTED_MODES in config:
cg.add(var.set_supported_modes(config[CONF_SUPPORTED_MODES]))
if CONF_SUPPORTED_SWING_MODES in config:

View file

@ -2,6 +2,7 @@
#include <string>
#include "esphome/components/climate/climate.h"
#include "esphome/components/uart/uart.h"
#include "esphome/core/helpers.h"
#include "hon_climate.h"
#include "hon_packet.h"
@ -51,10 +52,9 @@ hon_protocol::HorizontalSwingMode get_horizontal_swing_mode(AirflowHorizontalDir
}
HonClimate::HonClimate()
: cleaning_status_(CleaningState::NO_CLEANING),
got_valid_outdoor_temp_(false),
active_alarms_{0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00},
outdoor_sensor_(nullptr) {
: cleaning_status_(CleaningState::NO_CLEANING), got_valid_outdoor_temp_(false), active_alarms_{0x00, 0x00, 0x00,
0x00, 0x00, 0x00,
0x00, 0x00} {
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;
@ -66,8 +66,6 @@ void HonClimate::set_beeper_state(bool state) { this->beeper_status_ = state; }
bool HonClimate::get_beeper_state() const { return this->beeper_status_; }
void HonClimate::set_outdoor_temperature_sensor(esphome::sensor::Sensor *sensor) { this->outdoor_sensor_ = sensor; }
AirflowVerticalDirection HonClimate::get_vertical_airflow() const { return this->vertical_direction_; };
void HonClimate::set_vertical_airflow(AirflowVerticalDirection direction) {
@ -368,7 +366,14 @@ void HonClimate::process_phase(std::chrono::steady_clock::time_point now) {
if (this->can_send_message() && this->is_message_interval_exceeded_(now)) {
static const haier_protocol::HaierMessage STATUS_REQUEST(
haier_protocol::FrameType::CONTROL, (uint16_t) hon_protocol::SubcommandsControl::GET_USER_DATA);
static const haier_protocol::HaierMessage BIG_DATA_REQUEST(
haier_protocol::FrameType::CONTROL, (uint16_t) hon_protocol::SubcommandsControl::GET_BIG_DATA);
if ((this->protocol_phase_ == ProtocolPhases::SENDING_FIRST_STATUS_REQUEST) ||
(!this->should_get_big_data_())) {
this->send_message_(STATUS_REQUEST, this->use_crc_);
} else {
this->send_message_(BIG_DATA_REQUEST, this->use_crc_);
}
this->last_status_request_ = now;
}
break;
@ -685,9 +690,87 @@ void HonClimate::process_alarm_message_(const uint8_t *packet, uint8_t size, boo
}
}
#ifdef USE_SENSOR
void HonClimate::set_sub_sensor(SubSensorType type, sensor::Sensor *sens) {
if (type < SubSensorType::SUB_SENSOR_TYPE_COUNT) {
if (type >= SubSensorType::BIG_DATA_FRAME_SUB_SENSORS) {
if ((this->sub_sensors_[(size_t) type] != nullptr) && (sens == nullptr)) {
this->big_data_sensors_--;
} else if ((this->sub_sensors_[(size_t) type] == nullptr) && (sens != nullptr)) {
this->big_data_sensors_++;
}
}
this->sub_sensors_[(size_t) type] = sens;
}
}
void HonClimate::update_sub_sensor_(SubSensorType type, float value) {
if (type < SubSensorType::SUB_SENSOR_TYPE_COUNT) {
size_t index = (size_t) type;
if ((this->sub_sensors_[index] != nullptr) &&
((!this->sub_sensors_[index]->has_state()) || (this->sub_sensors_[index]->raw_state != value)))
this->sub_sensors_[index]->publish_state(value);
}
}
#endif // USE_SENSOR
#ifdef USE_BINARY_SENSOR
void HonClimate::set_sub_binary_sensor(SubBinarySensorType type, binary_sensor::BinarySensor *sens) {
if (type < SubBinarySensorType::SUB_BINARY_SENSOR_TYPE_COUNT) {
if ((this->sub_binary_sensors_[(size_t) type] != nullptr) && (sens == nullptr)) {
this->big_data_sensors_--;
} else if ((this->sub_binary_sensors_[(size_t) type] == nullptr) && (sens != nullptr)) {
this->big_data_sensors_++;
}
this->sub_binary_sensors_[(size_t) type] = sens;
}
}
void HonClimate::update_sub_binary_sensor_(SubBinarySensorType type, uint8_t value) {
if (value < 2) {
bool converted_value = value == 1;
size_t index = (size_t) type;
if ((this->sub_binary_sensors_[index] != nullptr) && ((!this->sub_binary_sensors_[index]->has_state()) ||
(this->sub_binary_sensors_[index]->state != converted_value)))
this->sub_binary_sensors_[index]->publish_state(converted_value);
}
}
#endif // USE_BINARY_SENSOR
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_)
size_t expected_size = 2 + sizeof(hon_protocol::HaierPacketControl) + sizeof(hon_protocol::HaierPacketSensors) +
this->extra_control_packet_bytes_;
if (size < expected_size)
return haier_protocol::HandlerError::WRONG_MESSAGE_STRUCTURE;
uint16_t subtype = (((uint16_t) packet_buffer[0]) << 8) + packet_buffer[1];
if ((subtype == 0x7D01) && (size >= expected_size + 4 + sizeof(hon_protocol::HaierPacketBigData))) {
// Got BigData packet
const hon_protocol::HaierPacketBigData *bd_packet =
(const hon_protocol::HaierPacketBigData *) (&packet_buffer[expected_size + 4]);
#ifdef USE_SENSOR
this->update_sub_sensor_(SubSensorType::INDOOR_COIL_TEMPERATURE, bd_packet->indoor_coil_temperature / 2.0 - 20);
this->update_sub_sensor_(SubSensorType::OUTDOOR_COIL_TEMPERATURE, bd_packet->outdoor_coil_temperature - 64);
this->update_sub_sensor_(SubSensorType::OUTDOOR_DEFROST_TEMPERATURE, bd_packet->outdoor_coil_temperature - 64);
this->update_sub_sensor_(SubSensorType::OUTDOOR_IN_AIR_TEMPERATURE, bd_packet->outdoor_in_air_temperature - 64);
this->update_sub_sensor_(SubSensorType::OUTDOOR_OUT_AIR_TEMPERATURE, bd_packet->outdoor_out_air_temperature - 64);
this->update_sub_sensor_(SubSensorType::POWER, encode_uint16(bd_packet->power[0], bd_packet->power[1]));
this->update_sub_sensor_(SubSensorType::COMPRESSOR_FREQUENCY, bd_packet->compressor_frequency);
this->update_sub_sensor_(SubSensorType::COMPRESSOR_CURRENT,
encode_uint16(bd_packet->compressor_current[0], bd_packet->compressor_current[1]) / 10.0);
this->update_sub_sensor_(
SubSensorType::EXPANSION_VALVE_OPEN_DEGREE,
encode_uint16(bd_packet->expansion_valve_open_degree[0], bd_packet->expansion_valve_open_degree[1]) / 4095.0);
#endif // USE_SENSOR
#ifdef USE_BINARY_SENSOR
this->update_sub_binary_sensor_(SubBinarySensorType::OUTDOOR_FAN_STATUS, bd_packet->outdoor_fan_status);
this->update_sub_binary_sensor_(SubBinarySensorType::DEFROST_STATUS, bd_packet->defrost_status);
this->update_sub_binary_sensor_(SubBinarySensorType::COMPRESSOR_STATUS, bd_packet->compressor_status);
this->update_sub_binary_sensor_(SubBinarySensorType::INDOOR_FAN_STATUS, bd_packet->indoor_fan_status);
this->update_sub_binary_sensor_(SubBinarySensorType::FOUR_WAY_VALVE_STATUS, bd_packet->four_way_valve_status);
this->update_sub_binary_sensor_(SubBinarySensorType::INDOOR_ELECTRIC_HEATING_STATUS,
bd_packet->indoor_electric_heating_status);
#endif // USE_BINARY_SENSOR
}
struct {
hon_protocol::HaierPacketControl control;
hon_protocol::HaierPacketSensors sensors;
@ -699,13 +782,17 @@ haier_protocol::HandlerError HonClimate::process_status_message_(const uint8_t *
if (packet.sensors.error_status != 0) {
ESP_LOGW(TAG, "HVAC error, code=0x%02X", packet.sensors.error_status);
}
if ((this->outdoor_sensor_ != nullptr) &&
#ifdef USE_SENSOR
if ((this->sub_sensors_[(size_t) SubSensorType::OUTDOOR_TEMPERATURE] != nullptr) &&
(this->got_valid_outdoor_temp_ || (packet.sensors.outdoor_temperature > 0))) {
this->got_valid_outdoor_temp_ = true;
float otemp = (float) (packet.sensors.outdoor_temperature + PROTOCOL_OUTDOOR_TEMPERATURE_OFFSET);
if ((!this->outdoor_sensor_->has_state()) || (this->outdoor_sensor_->get_raw_state() != otemp))
this->outdoor_sensor_->publish_state(otemp);
this->update_sub_sensor_(SubSensorType::OUTDOOR_TEMPERATURE,
(float) (packet.sensors.outdoor_temperature + PROTOCOL_OUTDOOR_TEMPERATURE_OFFSET));
}
if ((this->sub_sensors_[(size_t) SubSensorType::HUMIDITY] != nullptr) && (packet.sensors.room_humidity <= 100)) {
this->update_sub_sensor_(SubSensorType::HUMIDITY, (float) packet.sensors.room_humidity);
}
#endif // USE_SENSOR
bool should_publish = false;
{
// Extra modes/presets
@ -1009,21 +1096,22 @@ void HonClimate::fill_control_messages_queue_() {
break;
}
}
if (quiet_mode_buf[1] != 0xFF) {
auto presets = this->traits_.get_supported_presets();
if ((quiet_mode_buf[1] != 0xFF) && ((presets.find(climate::ClimatePreset::CLIMATE_PRESET_ECO) != presets.end()))) {
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::QUIET_MODE,
quiet_mode_buf, 2));
}
if (fast_mode_buf[1] != 0xFF) {
if ((fast_mode_buf[1] != 0xFF) && ((presets.find(climate::ClimatePreset::CLIMATE_PRESET_BOOST) != presets.end()))) {
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::FAST_MODE,
fast_mode_buf, 2));
}
if (away_mode_buf[1] != 0xFF) {
if ((away_mode_buf[1] != 0xFF) && ((presets.find(climate::ClimatePreset::CLIMATE_PRESET_AWAY) != presets.end()))) {
this->control_messages_queue_.push(
haier_protocol::HaierMessage(haier_protocol::FrameType::CONTROL,
(uint16_t) hon_protocol::SubcommandsControl::SET_SINGLE_PARAMETER +
@ -1032,7 +1120,7 @@ void HonClimate::fill_control_messages_queue_() {
}
}
// Target temperature
if (climate_control.target_temperature.has_value()) {
if (climate_control.target_temperature.has_value() && (this->mode != ClimateMode::CLIMATE_MODE_FAN_ONLY)) {
uint8_t buffer[2] = {0x00, 0x00};
buffer[1] = ((uint8_t) climate_control.target_temperature.value()) - 16;
this->control_messages_queue_.push(
@ -1119,12 +1207,24 @@ bool HonClimate::prepare_pending_action() {
void HonClimate::process_protocol_reset() {
HaierClimateBase::process_protocol_reset();
if (this->outdoor_sensor_ != nullptr) {
this->outdoor_sensor_->publish_state(NAN);
#ifdef USE_SENSOR
for (auto &sub_sensor : this->sub_sensors_) {
if ((sub_sensor != nullptr) && sub_sensor->has_state())
sub_sensor->publish_state(NAN);
}
#endif // USE_SENSOR
this->got_valid_outdoor_temp_ = false;
this->hvac_hardware_info_.reset();
}
bool HonClimate::should_get_big_data_() {
if (this->big_data_sensors_ > 0) {
static uint8_t counter = 0;
counter = (counter + 1) % 3;
return counter == 1;
}
return false;
}
} // namespace haier
} // namespace esphome

View file

@ -1,7 +1,12 @@
#pragma once
#include <chrono>
#ifdef USE_SENSOR
#include "esphome/components/sensor/sensor.h"
#endif
#ifdef USE_BINARY_SENSOR
#include "esphome/components/binary_sensor/binary_sensor.h"
#endif
#include "esphome/core/automation.h"
#include "haier_base.h"
@ -34,6 +39,48 @@ enum class CleaningState : uint8_t {
enum class HonControlMethod { MONITOR_ONLY = 0, SET_GROUP_PARAMETERS, SET_SINGLE_PARAMETER };
class HonClimate : public HaierClimateBase {
#ifdef USE_SENSOR
public:
enum class SubSensorType {
// Used data based sensors
OUTDOOR_TEMPERATURE = 0,
HUMIDITY,
// Big data based sensors
INDOOR_COIL_TEMPERATURE,
OUTDOOR_COIL_TEMPERATURE,
OUTDOOR_DEFROST_TEMPERATURE,
OUTDOOR_IN_AIR_TEMPERATURE,
OUTDOOR_OUT_AIR_TEMPERATURE,
POWER,
COMPRESSOR_FREQUENCY,
COMPRESSOR_CURRENT,
EXPANSION_VALVE_OPEN_DEGREE,
SUB_SENSOR_TYPE_COUNT,
BIG_DATA_FRAME_SUB_SENSORS = INDOOR_COIL_TEMPERATURE,
};
void set_sub_sensor(SubSensorType type, sensor::Sensor *sens);
protected:
void update_sub_sensor_(SubSensorType type, float value);
sensor::Sensor *sub_sensors_[(size_t) SubSensorType::SUB_SENSOR_TYPE_COUNT]{nullptr};
#endif
#ifdef USE_BINARY_SENSOR
public:
enum class SubBinarySensorType {
OUTDOOR_FAN_STATUS = 0,
DEFROST_STATUS,
COMPRESSOR_STATUS,
INDOOR_FAN_STATUS,
FOUR_WAY_VALVE_STATUS,
INDOOR_ELECTRIC_HEATING_STATUS,
SUB_BINARY_SENSOR_TYPE_COUNT,
};
void set_sub_binary_sensor(SubBinarySensorType type, binary_sensor::BinarySensor *sens);
protected:
void update_sub_binary_sensor_(SubBinarySensorType type, uint8_t value);
binary_sensor::BinarySensor *sub_binary_sensors_[(size_t) SubBinarySensorType::SUB_BINARY_SENSOR_TYPE_COUNT]{nullptr};
#endif
public:
HonClimate();
HonClimate(const HonClimate &) = delete;
@ -42,7 +89,6 @@ class HonClimate : public HaierClimateBase {
void dump_config() override;
void set_beeper_state(bool state);
bool get_beeper_state() const;
void set_outdoor_temperature_sensor(esphome::sensor::Sensor *sensor);
AirflowVerticalDirection get_vertical_airflow() const;
void set_vertical_airflow(AirflowVerticalDirection direction);
AirflowHorizontalDirection get_horizontal_airflow() const;
@ -64,6 +110,7 @@ class HonClimate : public HaierClimateBase {
haier_protocol::HaierMessage get_power_message(bool state) override;
bool prepare_pending_action() override;
void process_protocol_reset() override;
bool should_get_big_data_();
// Answers handlers
haier_protocol::HandlerError get_device_version_answer_handler_(haier_protocol::FrameType request_type,
@ -106,12 +153,12 @@ class HonClimate : public HaierClimateBase {
uint8_t active_alarms_[8];
int extra_control_packet_bytes_;
HonControlMethod control_method_;
esphome::sensor::Sensor *outdoor_sensor_;
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_;
int big_data_sensors_{0};
};
class HaierAlarmStartTrigger : public Trigger<uint8_t, const char *> {

View file

@ -55,18 +55,18 @@ enum class FanMode : uint8_t { FAN_HIGH = 0x01, FAN_MID = 0x02, FAN_LOW = 0x03,
struct HaierPacketControl {
// Control bytes starts here
// 10
// 1
uint8_t set_point; // Target temperature with 16°C offset (0x00 = 16°C)
// 11
// 2
uint8_t vertical_swing_mode : 4; // See enum VerticalSwingMode
uint8_t : 0;
// 12
// 3
uint8_t fan_mode : 3; // See enum FanMode
uint8_t special_mode : 2; // See enum SpecialMode
uint8_t ac_mode : 3; // See enum ConditioningMode
// 13
// 4
uint8_t : 8;
// 14
// 5
uint8_t ten_degree : 1; // 10 degree status
uint8_t display_status : 1; // If 0 disables AC's display
uint8_t half_degree : 1; // Use half degree
@ -75,7 +75,7 @@ struct HaierPacketControl {
uint8_t use_fahrenheit : 1; // Use Fahrenheit instead of Celsius
uint8_t : 1;
uint8_t steri_clean : 1;
// 15
// 6
uint8_t ac_power : 1; // Is ac on or off
uint8_t health_mode : 1; // Health mode (negative ions) on or off
uint8_t electric_heating_status : 1; // Electric heating status
@ -84,16 +84,16 @@ struct HaierPacketControl {
uint8_t sleep_mode : 1; // Sleep mode
uint8_t lock_remote : 1; // Disable remote
uint8_t beeper_status : 1; // If 1 disables AC's command feedback beeper (need to be set on every control command)
// 16
// 7
uint8_t target_humidity; // Target humidity (0=30% .. 3C=90%, step = 1%)
// 17
// 8
uint8_t horizontal_swing_mode : 3; // See enum HorizontalSwingMode
uint8_t : 3;
uint8_t human_sensing_status : 2; // Human sensing status
// 18
// 9
uint8_t change_filter : 1; // Filter need replacement
uint8_t : 0;
// 19
// 10
uint8_t fresh_air_status : 1; // Fresh air status
uint8_t humidification_status : 1; // Humidification status
uint8_t pm2p5_cleaning_status : 1; // PM2.5 cleaning status
@ -105,40 +105,68 @@ struct HaierPacketControl {
};
struct HaierPacketSensors {
// 20
// 11
uint8_t room_temperature; // 0.5°C step
// 21
// 12
uint8_t room_humidity; // 0%-100% with 1% step
// 22
// 13
uint8_t outdoor_temperature; // 1°C step, -64°C offset (0=-64°C)
// 23
// 14
uint8_t pm2p5_level : 2; // Indoor PM2.5 grade (00: Excellent, 01: good, 02: Medium, 03: Bad)
uint8_t air_quality : 2; // Air quality grade (00: Excellent, 01: good, 02: Medium, 03: Bad)
uint8_t human_sensing : 2; // Human presence result (00: N/A, 01: not detected, 02: One, 03: Multiple)
uint8_t : 1;
uint8_t ac_type : 1; // 00 - Heat and cool, 01 - Cool only)
// 24
// 15
uint8_t error_status; // See enum ErrorStatus
// 25
// 16
uint8_t operation_source : 2; // who is controlling AC (00: Other, 01: Remote control, 02: Button, 03: ESP)
uint8_t operation_mode_hk : 2; // Homekit only, operation mode (00: Cool, 01: Dry, 02: Heat, 03: Fan)
uint8_t : 3;
uint8_t err_confirmation : 1; // If 1 clear error status
// 26
// 17
uint16_t total_cleaning_time; // Cleaning cumulative time (1h step)
// 28
// 19
uint16_t indoor_pm2p5_value; // Indoor PM2.5 value (0 ug/m3 - 4095 ug/m3, 1 ug/m3 step)
// 30
// 21
uint16_t outdoor_pm2p5_value; // Outdoor PM2.5 value (0 ug/m3 - 4095 ug/m3, 1 ug/m3 step)
// 32
// 23
uint16_t ch2o_value; // Formaldehyde value (0 ug/m3 - 10000 ug/m3, 1 ug/m3 step)
// 34
// 25
uint16_t voc_value; // VOC value (Volatile Organic Compounds) (0 ug/m3 - 1023 ug/m3, 1 ug/m3 step)
// 36
// 27
uint16_t co2_value; // CO2 value (0 PPM - 10000 PPM, 1 PPM step)
};
constexpr size_t HAIER_STATUS_FRAME_SIZE = 2 + sizeof(HaierPacketControl) + sizeof(HaierPacketSensors);
struct HaierPacketBigData {
// 29
uint8_t power[2]; // AC power consumption (0W - 65535W, 1W step)
// 31
uint8_t indoor_coil_temperature; // 0.5°C step, -20°C offset (0=-20°C)
// 32
uint8_t outdoor_out_air_temperature; // 1°C step, -64°C offset (0=-64°C)
// 33
uint8_t outdoor_coil_temperature; // 1°C step, -64°C offset (0=-64°C)
// 34
uint8_t outdoor_in_air_temperature; // 1°C step, -64°C offset (0=-64°C)
// 35
uint8_t outdoor_defrost_temperature; // 1°C step, -64°C offset (0=-64°C)
// 36
uint8_t compressor_frequency; // 1Hz step, 0Hz - 127Hz
// 37
uint8_t compressor_current[2]; // 0.1A step, 0.0A - 51.1A (0x0000 - 0x01FF)
// 39
uint8_t outdoor_fan_status : 2; // 0 - off, 1 - on, 2 - information not available
uint8_t defrost_status : 2; // 0 - off, 1 - on, 2 - information not available
uint8_t : 0;
// 40
uint8_t compressor_status : 2; // 0 - off, 1 - on, 2 - information not available
uint8_t indoor_fan_status : 2; // 0 - off, 1 - on, 2 - information not available
uint8_t four_way_valve_status : 2; // 0 - off, 1 - on, 2 - information not available
uint8_t indoor_electric_heating_status : 2; // 0 - off, 1 - on, 2 - information not available
// 41
uint8_t expansion_valve_open_degree[2]; // 0 - 4095
};
struct DeviceVersionAnswer {
char protocol_version[8];

View file

@ -0,0 +1,151 @@
import esphome.codegen as cg
import esphome.config_validation as cv
from esphome.components import sensor
from esphome.const import (
CONF_POWER,
CONF_HUMIDITY,
DEVICE_CLASS_CURRENT,
DEVICE_CLASS_FREQUENCY,
DEVICE_CLASS_HUMIDITY,
DEVICE_CLASS_POWER,
DEVICE_CLASS_TEMPERATURE,
ENTITY_CATEGORY_DIAGNOSTIC,
ICON_CURRENT_AC,
ICON_FLASH,
ICON_GAUGE,
ICON_HEATING_COIL,
ICON_PULSE,
ICON_THERMOMETER,
ICON_WATER_PERCENT,
ICON_WEATHER_WINDY,
STATE_CLASS_MEASUREMENT,
UNIT_AMPERE,
UNIT_CELSIUS,
UNIT_HERTZ,
UNIT_PERCENT,
UNIT_WATT,
)
from ..climate import (
CONF_HAIER_ID,
HonClimate,
)
SensorTypeEnum = HonClimate.enum("SubSensorType", True)
# Haier sensors
CONF_COMPRESSOR_CURRENT = "compressor_current"
CONF_COMPRESSOR_FREQUENCY = "compressor_frequency"
CONF_EXPANSION_VALVE_OPEN_DEGREE = "expansion_valve_open_degree"
CONF_INDOOR_COIL_TEMPERATURE = "indoor_coil_temperature"
CONF_OUTDOOR_COIL_TEMPERATURE = "outdoor_coil_temperature"
CONF_OUTDOOR_DEFROST_TEMPERATURE = "outdoor_defrost_temperature"
CONF_OUTDOOR_IN_AIR_TEMPERATURE = "outdoor_in_air_temperature"
CONF_OUTDOOR_OUT_AIR_TEMPERATURE = "outdoor_out_air_temperature"
CONF_OUTDOOR_TEMPERATURE = "outdoor_temperature"
# Additional icons
ICON_SNOWFLAKE_THERMOMETER = "mdi:snowflake-thermometer"
SENSOR_TYPES = {
CONF_COMPRESSOR_CURRENT: sensor.sensor_schema(
unit_of_measurement=UNIT_AMPERE,
icon=ICON_CURRENT_AC,
accuracy_decimals=1,
device_class=DEVICE_CLASS_CURRENT,
state_class=STATE_CLASS_MEASUREMENT,
entity_category=ENTITY_CATEGORY_DIAGNOSTIC,
),
CONF_COMPRESSOR_FREQUENCY: sensor.sensor_schema(
unit_of_measurement=UNIT_HERTZ,
icon=ICON_PULSE,
accuracy_decimals=0,
device_class=DEVICE_CLASS_FREQUENCY,
state_class=STATE_CLASS_MEASUREMENT,
entity_category=ENTITY_CATEGORY_DIAGNOSTIC,
),
CONF_EXPANSION_VALVE_OPEN_DEGREE: sensor.sensor_schema(
unit_of_measurement=UNIT_PERCENT,
icon=ICON_GAUGE,
accuracy_decimals=2,
state_class=STATE_CLASS_MEASUREMENT,
entity_category=ENTITY_CATEGORY_DIAGNOSTIC,
),
CONF_HUMIDITY: sensor.sensor_schema(
unit_of_measurement=UNIT_PERCENT,
icon=ICON_WATER_PERCENT,
accuracy_decimals=0,
device_class=DEVICE_CLASS_HUMIDITY,
state_class=STATE_CLASS_MEASUREMENT,
),
CONF_INDOOR_COIL_TEMPERATURE: sensor.sensor_schema(
unit_of_measurement=UNIT_CELSIUS,
icon=ICON_HEATING_COIL,
accuracy_decimals=0,
device_class=DEVICE_CLASS_TEMPERATURE,
state_class=STATE_CLASS_MEASUREMENT,
entity_category=ENTITY_CATEGORY_DIAGNOSTIC,
),
CONF_OUTDOOR_COIL_TEMPERATURE: sensor.sensor_schema(
unit_of_measurement=UNIT_CELSIUS,
icon=ICON_HEATING_COIL,
accuracy_decimals=0,
device_class=DEVICE_CLASS_TEMPERATURE,
state_class=STATE_CLASS_MEASUREMENT,
entity_category=ENTITY_CATEGORY_DIAGNOSTIC,
),
CONF_OUTDOOR_DEFROST_TEMPERATURE: sensor.sensor_schema(
unit_of_measurement=UNIT_CELSIUS,
icon=ICON_SNOWFLAKE_THERMOMETER,
accuracy_decimals=0,
device_class=DEVICE_CLASS_TEMPERATURE,
state_class=STATE_CLASS_MEASUREMENT,
entity_category=ENTITY_CATEGORY_DIAGNOSTIC,
),
CONF_OUTDOOR_IN_AIR_TEMPERATURE: sensor.sensor_schema(
unit_of_measurement=UNIT_CELSIUS,
icon=ICON_WEATHER_WINDY,
accuracy_decimals=0,
device_class=DEVICE_CLASS_TEMPERATURE,
state_class=STATE_CLASS_MEASUREMENT,
entity_category=ENTITY_CATEGORY_DIAGNOSTIC,
),
CONF_OUTDOOR_OUT_AIR_TEMPERATURE: sensor.sensor_schema(
unit_of_measurement=UNIT_CELSIUS,
icon=ICON_WEATHER_WINDY,
accuracy_decimals=0,
device_class=DEVICE_CLASS_TEMPERATURE,
state_class=STATE_CLASS_MEASUREMENT,
entity_category=ENTITY_CATEGORY_DIAGNOSTIC,
),
CONF_OUTDOOR_TEMPERATURE: sensor.sensor_schema(
unit_of_measurement=UNIT_CELSIUS,
icon=ICON_THERMOMETER,
accuracy_decimals=0,
device_class=DEVICE_CLASS_TEMPERATURE,
state_class=STATE_CLASS_MEASUREMENT,
),
CONF_POWER: sensor.sensor_schema(
unit_of_measurement=UNIT_WATT,
icon=ICON_FLASH,
accuracy_decimals=0,
device_class=DEVICE_CLASS_POWER,
state_class=STATE_CLASS_MEASUREMENT,
entity_category=ENTITY_CATEGORY_DIAGNOSTIC,
),
}
CONFIG_SCHEMA = cv.Schema(
{
cv.Required(CONF_HAIER_ID): cv.use_id(HonClimate),
}
).extend({cv.Optional(type): schema for type, schema in SENSOR_TYPES.items()})
async def to_code(config):
paren = await cg.get_variable(config[CONF_HAIER_ID])
for type, _ in SENSOR_TYPES.items():
if conf := config.get(type):
sens = await sensor.new_sensor(conf)
sensor_type = getattr(SensorTypeEnum, type.upper())
cg.add(paren.set_sub_sensor(sensor_type, sens))

View file

@ -0,0 +1,95 @@
wifi:
ssid: MySSID
password: password1
uart:
- id: uart_haier
tx_pin: 4
rx_pin: 5
baud_rate: 9600
climate:
- platform: haier
id: haier_ac
protocol: hOn
name: Haier AC
wifi_signal: true
answer_timeout: 200ms
beeper: true
visual:
min_temperature: 16 °C
max_temperature: 30 °C
temperature_step:
target_temperature: 1
current_temperature: 0.5
supported_modes:
- 'OFF'
- HEAT_COOL
- COOL
- HEAT
- DRY
- FAN_ONLY
supported_swing_modes:
- 'OFF'
- VERTICAL
- HORIZONTAL
- 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]
sensor:
- platform: haier
haier_id: haier_ac
outdoor_temperature:
name: Haier outdoor temperature
humidity:
name: Haier Indoor Humidity
compressor_current:
name: Haier Compressor Current
compressor_frequency:
name: Haier Compressor Frequency
expansion_valve_open_degree:
name: Haier Expansion Valve Open Degree
indoor_coil_temperature:
name: Haier Indoor Coil Temperature
outdoor_coil_temperature:
name: Haier Outdoor Coil Temperature
outdoor_defrost_temperature:
name: Haier Outdoor Defrost Temperature
outdoor_in_air_temperature:
name: Haier Outdoor In Air Temperature
outdoor_out_air_temperature:
name: Haier Outdoor Out Air Temperature
power:
name: Haier Power
binary_sensor:
- platform: haier
haier_id: haier_ac
compressor_status:
name: Haier Outdoor Compressor Status
defrost_status:
name: Haier Defrost Status
four_way_valve_status:
name: Haier Four Way Valve Status
indoor_electric_heating_status:
name: Haier Indoor Electric Heating Status
indoor_fan_status:
name: Haier Indoor Fan Status
outdoor_fan_status:
name: Haier Outdoor Fan Status

View file

@ -0,0 +1,95 @@
wifi:
ssid: MySSID
password: password1
uart:
- id: uart_haier
tx_pin: 4
rx_pin: 5
baud_rate: 9600
climate:
- platform: haier
id: haier_ac
protocol: hOn
name: Haier AC
wifi_signal: true
answer_timeout: 200ms
beeper: true
visual:
min_temperature: 16 °C
max_temperature: 30 °C
temperature_step:
target_temperature: 1
current_temperature: 0.5
supported_modes:
- 'OFF'
- HEAT_COOL
- COOL
- HEAT
- DRY
- FAN_ONLY
supported_swing_modes:
- 'OFF'
- VERTICAL
- HORIZONTAL
- 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]
sensor:
- platform: haier
haier_id: haier_ac
outdoor_temperature:
name: Haier outdoor temperature
humidity:
name: Haier Indoor Humidity
compressor_current:
name: Haier Compressor Current
compressor_frequency:
name: Haier Compressor Frequency
expansion_valve_open_degree:
name: Haier Expansion Valve Open Degree
indoor_coil_temperature:
name: Haier Indoor Coil Temperature
outdoor_coil_temperature:
name: Haier Outdoor Coil Temperature
outdoor_defrost_temperature:
name: Haier Outdoor Defrost Temperature
outdoor_in_air_temperature:
name: Haier Outdoor In Air Temperature
outdoor_out_air_temperature:
name: Haier Outdoor Out Air Temperature
power:
name: Haier Power
binary_sensor:
- platform: haier
haier_id: haier_ac
compressor_status:
name: Haier Outdoor Compressor Status
defrost_status:
name: Haier Defrost Status
four_way_valve_status:
name: Haier Four Way Valve Status
indoor_electric_heating_status:
name: Haier Indoor Electric Heating Status
indoor_fan_status:
name: Haier Indoor Fan Status
outdoor_fan_status:
name: Haier Outdoor Fan Status

View file

@ -0,0 +1,95 @@
wifi:
ssid: MySSID
password: password1
uart:
- id: uart_haier
tx_pin: 17
rx_pin: 16
baud_rate: 9600
climate:
- platform: haier
id: haier_ac
protocol: hOn
name: Haier AC
wifi_signal: true
answer_timeout: 200ms
beeper: true
visual:
min_temperature: 16 °C
max_temperature: 30 °C
temperature_step:
target_temperature: 1
current_temperature: 0.5
supported_modes:
- 'OFF'
- HEAT_COOL
- COOL
- HEAT
- DRY
- FAN_ONLY
supported_swing_modes:
- 'OFF'
- VERTICAL
- HORIZONTAL
- 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]
sensor:
- platform: haier
haier_id: haier_ac
outdoor_temperature:
name: Haier outdoor temperature
humidity:
name: Haier Indoor Humidity
compressor_current:
name: Haier Compressor Current
compressor_frequency:
name: Haier Compressor Frequency
expansion_valve_open_degree:
name: Haier Expansion Valve Open Degree
indoor_coil_temperature:
name: Haier Indoor Coil Temperature
outdoor_coil_temperature:
name: Haier Outdoor Coil Temperature
outdoor_defrost_temperature:
name: Haier Outdoor Defrost Temperature
outdoor_in_air_temperature:
name: Haier Outdoor In Air Temperature
outdoor_out_air_temperature:
name: Haier Outdoor Out Air Temperature
power:
name: Haier Power
binary_sensor:
- platform: haier
haier_id: haier_ac
compressor_status:
name: Haier Outdoor Compressor Status
defrost_status:
name: Haier Defrost Status
four_way_valve_status:
name: Haier Four Way Valve Status
indoor_electric_heating_status:
name: Haier Indoor Electric Heating Status
indoor_fan_status:
name: Haier Indoor Fan Status
outdoor_fan_status:
name: Haier Outdoor Fan Status

View file

@ -0,0 +1,95 @@
wifi:
ssid: MySSID
password: password1
uart:
- id: uart_haier
tx_pin: 17
rx_pin: 16
baud_rate: 9600
climate:
- platform: haier
id: haier_ac
protocol: hOn
name: Haier AC
wifi_signal: true
answer_timeout: 200ms
beeper: true
visual:
min_temperature: 16 °C
max_temperature: 30 °C
temperature_step:
target_temperature: 1
current_temperature: 0.5
supported_modes:
- 'OFF'
- HEAT_COOL
- COOL
- HEAT
- DRY
- FAN_ONLY
supported_swing_modes:
- 'OFF'
- VERTICAL
- HORIZONTAL
- 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]
sensor:
- platform: haier
haier_id: haier_ac
outdoor_temperature:
name: Haier outdoor temperature
humidity:
name: Haier Indoor Humidity
compressor_current:
name: Haier Compressor Current
compressor_frequency:
name: Haier Compressor Frequency
expansion_valve_open_degree:
name: Haier Expansion Valve Open Degree
indoor_coil_temperature:
name: Haier Indoor Coil Temperature
outdoor_coil_temperature:
name: Haier Outdoor Coil Temperature
outdoor_defrost_temperature:
name: Haier Outdoor Defrost Temperature
outdoor_in_air_temperature:
name: Haier Outdoor In Air Temperature
outdoor_out_air_temperature:
name: Haier Outdoor Out Air Temperature
power:
name: Haier Power
binary_sensor:
- platform: haier
haier_id: haier_ac
compressor_status:
name: Haier Outdoor Compressor Status
defrost_status:
name: Haier Defrost Status
four_way_valve_status:
name: Haier Four Way Valve Status
indoor_electric_heating_status:
name: Haier Indoor Electric Heating Status
indoor_fan_status:
name: Haier Indoor Fan Status
outdoor_fan_status:
name: Haier Outdoor Fan Status

View file

@ -0,0 +1,95 @@
wifi:
ssid: MySSID
password: password1
uart:
- id: uart_haier
tx_pin: 4
rx_pin: 5
baud_rate: 9600
climate:
- platform: haier
id: haier_ac
protocol: hOn
name: Haier AC
wifi_signal: true
answer_timeout: 200ms
beeper: true
visual:
min_temperature: 16 °C
max_temperature: 30 °C
temperature_step:
target_temperature: 1
current_temperature: 0.5
supported_modes:
- 'OFF'
- HEAT_COOL
- COOL
- HEAT
- DRY
- FAN_ONLY
supported_swing_modes:
- 'OFF'
- VERTICAL
- HORIZONTAL
- 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]
sensor:
- platform: haier
haier_id: haier_ac
outdoor_temperature:
name: Haier outdoor temperature
humidity:
name: Haier Indoor Humidity
compressor_current:
name: Haier Compressor Current
compressor_frequency:
name: Haier Compressor Frequency
expansion_valve_open_degree:
name: Haier Expansion Valve Open Degree
indoor_coil_temperature:
name: Haier Indoor Coil Temperature
outdoor_coil_temperature:
name: Haier Outdoor Coil Temperature
outdoor_defrost_temperature:
name: Haier Outdoor Defrost Temperature
outdoor_in_air_temperature:
name: Haier Outdoor In Air Temperature
outdoor_out_air_temperature:
name: Haier Outdoor Out Air Temperature
power:
name: Haier Power
binary_sensor:
- platform: haier
haier_id: haier_ac
compressor_status:
name: Haier Outdoor Compressor Status
defrost_status:
name: Haier Defrost Status
four_way_valve_status:
name: Haier Four Way Valve Status
indoor_electric_heating_status:
name: Haier Indoor Electric Heating Status
indoor_fan_status:
name: Haier Indoor Fan Status
outdoor_fan_status:
name: Haier Outdoor Fan Status

View file

@ -0,0 +1,95 @@
wifi:
ssid: MySSID
password: password1
uart:
- id: uart_haier
tx_pin: 4
rx_pin: 5
baud_rate: 9600
climate:
- platform: haier
id: haier_ac
protocol: hOn
name: Haier AC
wifi_signal: true
answer_timeout: 200ms
beeper: true
visual:
min_temperature: 16 °C
max_temperature: 30 °C
temperature_step:
target_temperature: 1
current_temperature: 0.5
supported_modes:
- 'OFF'
- HEAT_COOL
- COOL
- HEAT
- DRY
- FAN_ONLY
supported_swing_modes:
- 'OFF'
- VERTICAL
- HORIZONTAL
- 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]
sensor:
- platform: haier
haier_id: haier_ac
outdoor_temperature:
name: Haier outdoor temperature
humidity:
name: Haier Indoor Humidity
compressor_current:
name: Haier Compressor Current
compressor_frequency:
name: Haier Compressor Frequency
expansion_valve_open_degree:
name: Haier Expansion Valve Open Degree
indoor_coil_temperature:
name: Haier Indoor Coil Temperature
outdoor_coil_temperature:
name: Haier Outdoor Coil Temperature
outdoor_defrost_temperature:
name: Haier Outdoor Defrost Temperature
outdoor_in_air_temperature:
name: Haier Outdoor In Air Temperature
outdoor_out_air_temperature:
name: Haier Outdoor Out Air Temperature
power:
name: Haier Power
binary_sensor:
- platform: haier
haier_id: haier_ac
compressor_status:
name: Haier Outdoor Compressor Status
defrost_status:
name: Haier Defrost Status
four_way_valve_status:
name: Haier Four Way Valve Status
indoor_electric_heating_status:
name: Haier Indoor Electric Heating Status
indoor_fan_status:
name: Haier Indoor Fan Status
outdoor_fan_status:
name: Haier Outdoor Fan Status

View file

@ -747,6 +747,31 @@ sensor:
temperature:
name: Kuntze temperature
- platform: haier
haier_id: haier_climate
compressor_current:
name: Haier AC compressor current
compressor_frequency:
name: Haier AC compressor frequency
expansion_valve_open_degree:
name: Haier AC expansion valve open degree
humidity:
name: Haier AC indoor humidity
indoor_coil_temperature:
name: Haier AC indoor coil temperature
outdoor_coil_temperature:
name: Haier AC outdoor coil temperature
outdoor_defrost_temperature:
name: Haier AC outdoor defrost temperature
outdoor_in_air_temperature:
name: Haier AC outdoor in air temperature
outdoor_out_air_temperature:
name: Haier AC outdoor out air temperature
outdoor_temperature:
name: Haier AC outdoor temperature
power:
name: Haier AC power
time:
- platform: homeassistant
@ -813,6 +838,21 @@ binary_sensor:
allow_other_uses: true
number: 3
- platform: haier
haier_id: haier_climate
compressor_status:
name: Haier AC compressor status
defrost_status:
name: Haier AC defrost status
four_way_valve_status:
name: Haier AC four-way valve status
indoor_electric_heating_status:
name: Haier AC indoor electric heating status
indoor_fan_status:
name: Haier AC indoor fan status
outdoor_fan_status:
name: Haier AC outdoor fan status
globals:
- id: my_global_string
type: std::string
@ -1024,14 +1064,13 @@ climate:
kd_multiplier: 0.0
deadband_output_averaging_samples: 1
- platform: haier
id: haier_climate
protocol: hOn
name: Haier AC
uart_id: uart_12
wifi_signal: true
answer_timeout: 200ms
beeper: true
outdoor_temperature:
name: Haier AC outdoor temperature
visual:
min_temperature: 16 °C
max_temperature: 30 °C