ESPHome 2026.11.0-dev
Loading...
Searching...
No Matches
zhlt01.cpp
Go to the documentation of this file.
1#include "zhlt01.h"
2#include "esphome/core/log.h"
3
4namespace esphome::zhlt01 {
5
6ESPHOME_LOG_TAG(TAG, "zhlt01.climate");
7
8static constexpr uint8_t ZHLT01_MESSAGE_LENGTH = 12;
9
11 uint8_t ir_message[ZHLT01_MESSAGE_LENGTH] = {0};
12
13 // Byte 1 : Timer
14 ir_message[1] = 0x00; // Timer off
15
16 // Byte 3 : Turbo mode
18 ir_message[3] = AC1_FAN_TURBO;
19 }
20
21 // Byte 5 : Last pressed button
22 ir_message[5] = 0x00; // fixed as power button
23
24 // Byte 7 : Power | Swing | Fan
25 // -- Power
26 if (this->mode == climate::CLIMATE_MODE_OFF) {
27 ir_message[7] = AC1_POWER_OFF;
28 } else {
29 ir_message[7] = AC1_POWER_ON;
30 }
31
32 // -- Swing
33 switch (this->swing_mode) {
35 ir_message[7] |= AC1_HDIR_FIXED | AC1_VDIR_FIXED;
36 break;
38 ir_message[7] |= AC1_HDIR_SWING | AC1_VDIR_FIXED;
39 break;
41 ir_message[7] |= AC1_HDIR_FIXED | AC1_VDIR_SWING;
42 break;
44 ir_message[7] |= AC1_HDIR_SWING | AC1_VDIR_SWING;
45 break;
46 default:
47 break;
48 }
49
50 // -- Fan
51 switch (this->preset.value_or(climate::CLIMATE_PRESET_NONE)) {
53 ir_message[7] |= AC1_FAN3;
54 break;
56 ir_message[7] |= AC1_FAN_SILENT;
57 break;
58 default:
59 switch (this->fan_mode.value_or(climate::CLIMATE_FAN_ON)) {
61 ir_message[7] |= AC1_FAN1;
62 break;
64 ir_message[7] |= AC1_FAN2;
65 break;
67 ir_message[7] |= AC1_FAN3;
68 break;
70 ir_message[7] |= AC1_FAN_AUTO;
71 break;
72 default:
73 break;
74 }
75 }
76
77 // Byte 9 : AC Mode | Temperature
78 // -- AC Mode
79 switch (this->mode) {
82 ir_message[9] = AC1_MODE_AUTO;
83 break;
85 ir_message[9] = AC1_MODE_COOL;
86 break;
88 ir_message[9] = AC1_MODE_HEAT;
89 break;
91 ir_message[9] = AC1_MODE_DRY;
92 break;
94 ir_message[9] = AC1_MODE_FAN;
95 break;
96 default:
97 break;
98 }
99
100 // -- Temperature
101 ir_message[9] |= (uint8_t) (this->target_temperature - 16.0f);
102
103 // Byte 11 : Remote control ID
104 ir_message[11] = 0xD5;
105
106 // Set checksum bytes
107 for (int i = 0; i < ZHLT01_MESSAGE_LENGTH; i += 2) {
108 ir_message[i] = ~ir_message[i + 1];
109 }
110
111 // Send the code
112 auto transmit = this->transmitter_->transmit();
113 auto *data = transmit.get_data();
114
115 data->set_carrier_frequency(38000); // 38 kHz PWM
116
117 // Header
118 data->mark(AC1_HDR_MARK);
119 data->space(AC1_HDR_SPACE);
120
121 // Data
122 data->item_bytes<AC1_BIT_TIMINGS>(ir_message, sizeof(ir_message));
123
124 // Footer
125 data->mark(AC1_BIT_MARK);
126 data->space(0);
127
128 transmit.perform();
129}
130
132 // Validate header
133 if (!data.expect_item(AC1_HDR_MARK, AC1_HDR_SPACE)) {
134 ESP_LOGV(TAG, "Header fail");
135 return false;
136 }
137
138 // Decode IR message
139 uint8_t ir_message[ZHLT01_MESSAGE_LENGTH];
140 if (!data.expect_bytes<AC1_BIT_TIMINGS>(ir_message, sizeof(ir_message))) {
141 ESP_LOGV(TAG, "Data fail");
142 return false;
143 }
144
145 // Validate footer
146 if (!data.expect_mark(AC1_BIT_MARK)) {
147 ESP_LOGV(TAG, "Footer fail");
148 return false;
149 }
150
151 // Validate checksum
152 for (int i = 0; i < ZHLT01_MESSAGE_LENGTH; i += 2) {
153 if (ir_message[i] != (uint8_t) (~ir_message[i + 1])) {
154 ESP_LOGV(TAG, "Byte %d checksum incorrect (%02X != %02X)", i, ir_message[i], (uint8_t) (~ir_message[i + 1]));
155 return false;
156 }
157 }
158
159 // Validate remote control ID
160 if (ir_message[11] != 0xD5) {
161 ESP_LOGV(TAG, "Invalid remote control ID");
162 return false;
163 }
164
165 // All is good to go
166
167 if ((ir_message[7] & AC1_POWER_ON) == 0) {
169 } else {
170 // Vertical swing
171 if ((ir_message[7] & 0x0C) == AC1_VDIR_FIXED) {
172 if ((ir_message[7] & 0x10) == AC1_HDIR_FIXED) {
174 } else {
176 }
177 } else {
178 if ((ir_message[7] & 0x10) == AC1_HDIR_FIXED) {
180 } else {
182 }
183 }
184
185 // Preset + Fan speed
186 if ((ir_message[3] & AC1_FAN_TURBO) == AC1_FAN_TURBO) {
189 } else if ((ir_message[7] & 0xE1) == AC1_FAN_SILENT) {
192 } else if ((ir_message[7] & 0xE1) == AC1_FAN_AUTO) {
194 } else if ((ir_message[7] & 0xE1) == AC1_FAN1) {
196 } else if ((ir_message[7] & 0xE1) == AC1_FAN2) {
198 } else if ((ir_message[7] & 0xE1) == AC1_FAN3) {
200 }
201
202 // AC Mode
203 if ((ir_message[9] & 0xE0) == AC1_MODE_COOL) {
205 } else if ((ir_message[9] & 0xE0) == AC1_MODE_HEAT) {
207 } else if ((ir_message[9] & 0xE0) == AC1_MODE_DRY) {
209 } else if ((ir_message[9] & 0xE0) == AC1_MODE_FAN) {
211 } else {
213 }
214
215 // Taregt Temperature
216 this->target_temperature = (ir_message[9] & 0x1F) + 16.0f;
217 }
218
219 this->publish_state();
220 return true;
221}
222
223} // namespace esphome::zhlt01
ClimateMode mode
The active mode of the climate device.
Definition climate.h:317
optional< ClimateFanMode > fan_mode
The active fan mode of the climate device.
Definition climate.h:311
float target_temperature
The target temperature of the climate device.
Definition climate.h:298
ClimateSwingMode swing_mode
The active swing mode of the climate device.
Definition climate.h:323
void publish_state()
Publish the state of the climate device, to be called from integrations.
Definition climate.cpp:432
optional< ClimatePreset > preset
The active preset of the climate device.
Definition climate.h:314
bool on_receive(remote_base::RemoteReceiveData data) override
Handle received IR Buffer.
Definition zhlt01.cpp:131
void transmit_state() override
Transmit via IR the state of this climate controller.
Definition zhlt01.cpp:10
@ CLIMATE_PRESET_NONE
No preset is active.
@ CLIMATE_PRESET_BOOST
Device is in boost preset.
@ CLIMATE_PRESET_SLEEP
Device is prepared for sleep.
@ 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.
@ 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_MODE_AUTO
The climate device is adjusting the temperature dynamically.
@ 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.
ESPHOME_LOG_TAG(TAG, "zhlt01.climate")