ESPHome 2026.1.5
Loading...
Searching...
No Matches
whirlpool.cpp
Go to the documentation of this file.
1#include "whirlpool.h"
2#include "esphome/core/log.h"
3
4namespace esphome {
5namespace whirlpool {
6
7static const char *const TAG = "whirlpool.climate";
8
9const uint16_t WHIRLPOOL_HEADER_MARK = 9000;
10const uint16_t WHIRLPOOL_HEADER_SPACE = 4494;
11const uint16_t WHIRLPOOL_BIT_MARK = 572;
12const uint16_t WHIRLPOOL_ONE_SPACE = 1659;
13const uint16_t WHIRLPOOL_ZERO_SPACE = 553;
14const uint32_t WHIRLPOOL_GAP = 7960;
15
16const uint32_t WHIRLPOOL_CARRIER_FREQUENCY = 38000;
17
18const uint8_t WHIRLPOOL_STATE_LENGTH = 21;
19
20const uint8_t WHIRLPOOL_HEAT = 0;
21const uint8_t WHIRLPOOL_DRY = 3;
22const uint8_t WHIRLPOOL_COOL = 2;
23const uint8_t WHIRLPOOL_FAN = 4;
24const uint8_t WHIRLPOOL_AUTO = 1;
25
26const uint8_t WHIRLPOOL_FAN_AUTO = 0;
27const uint8_t WHIRLPOOL_FAN_HIGH = 1;
28const uint8_t WHIRLPOOL_FAN_MED = 2;
29const uint8_t WHIRLPOOL_FAN_LOW = 3;
30
31const uint8_t WHIRLPOOL_SWING_MASK = 128;
32
33const uint8_t WHIRLPOOL_POWER = 0x04;
34
36 this->last_transmit_time_ = millis(); // setting the time of the last transmission.
37 uint8_t remote_state[WHIRLPOOL_STATE_LENGTH] = {0};
38 remote_state[0] = 0x83;
39 remote_state[1] = 0x06;
40 remote_state[6] = 0x80;
41 // MODEL DG11J191
42 remote_state[18] = 0x08;
43
44 auto powered_on = this->mode != climate::CLIMATE_MODE_OFF;
45 if (powered_on != this->powered_on_assumed) {
46 // Set power toggle command
47 remote_state[2] = 4;
48 remote_state[15] = 1;
49 this->powered_on_assumed = powered_on;
50 }
51 switch (this->mode) {
53 // set fan auto
54 // set temp auto temp
55 // set sleep false
56 remote_state[3] = WHIRLPOOL_AUTO;
57 remote_state[15] = 0x17;
58 break;
60 remote_state[3] = WHIRLPOOL_HEAT;
61 remote_state[15] = 6;
62 break;
64 remote_state[3] = WHIRLPOOL_COOL;
65 remote_state[15] = 6;
66 break;
68 remote_state[3] = WHIRLPOOL_DRY;
69 remote_state[15] = 6;
70 break;
72 remote_state[3] = WHIRLPOOL_FAN;
73 remote_state[15] = 6;
74 break;
76 default:
77 break;
78 }
79
80 // Temperature
81 auto temp = (uint8_t) roundf(clamp(this->target_temperature, this->temperature_min_(), this->temperature_max_()));
82 remote_state[3] |= (uint8_t) (temp - this->temperature_min_()) << 4;
83
84 // Fan speed
85 switch (this->fan_mode.value()) {
87 remote_state[2] |= WHIRLPOOL_FAN_HIGH;
88 break;
90 remote_state[2] |= WHIRLPOOL_FAN_MED;
91 break;
93 remote_state[2] |= WHIRLPOOL_FAN_LOW;
94 break;
95 default:
96 break;
97 }
98
99 // Swing
100 ESP_LOGV(TAG, "send swing %s", this->send_swing_cmd_ ? "true" : "false");
101 if (this->send_swing_cmd_) {
103 remote_state[2] |= 128;
104 remote_state[8] |= 64;
105 }
106 }
107
108 // Checksum
109 for (uint8_t i = 2; i < 13; i++)
110 remote_state[13] ^= remote_state[i];
111 for (uint8_t i = 14; i < 20; i++)
112 remote_state[20] ^= remote_state[i];
113
114 ESP_LOGV(TAG,
115 "Sending: %02X %02X %02X %02X %02X %02X %02X %02X %02X %02X %02X %02X %02X %02X %02X %02X %02X %02X "
116 "%02X %02X %02X",
117 remote_state[0], remote_state[1], remote_state[2], remote_state[3], remote_state[4], remote_state[5],
118 remote_state[6], remote_state[7], remote_state[8], remote_state[9], remote_state[10], remote_state[11],
119 remote_state[12], remote_state[13], remote_state[14], remote_state[15], remote_state[16], remote_state[17],
120 remote_state[18], remote_state[19], remote_state[20]);
121
122 // Send code
123 auto transmit = this->transmitter_->transmit();
124 auto *data = transmit.get_data();
125
126 data->set_carrier_frequency(38000);
127
128 // Header
129 data->mark(WHIRLPOOL_HEADER_MARK);
130 data->space(WHIRLPOOL_HEADER_SPACE);
131 // Data
132 auto bytes_sent = 0;
133 for (uint8_t i : remote_state) {
134 for (uint8_t j = 0; j < 8; j++) {
135 data->mark(WHIRLPOOL_BIT_MARK);
136 bool bit = i & (1 << j);
137 data->space(bit ? WHIRLPOOL_ONE_SPACE : WHIRLPOOL_ZERO_SPACE);
138 }
139 bytes_sent++;
140 if (bytes_sent == 6 || bytes_sent == 14) {
141 // Divider
142 data->mark(WHIRLPOOL_BIT_MARK);
143 data->space(WHIRLPOOL_GAP);
144 }
145 }
146 // Footer
147 data->mark(WHIRLPOOL_BIT_MARK);
148
149 transmit.perform();
150}
151
153 // Check if the esp isn't currently transmitting.
154 if (millis() - this->last_transmit_time_ < 500) {
155 ESP_LOGV(TAG, "Blocked receive because of current trasmittion");
156 return false;
157 }
158
159 // Validate header
161 ESP_LOGV(TAG, "Header fail");
162 return false;
163 }
164
165 uint8_t remote_state[WHIRLPOOL_STATE_LENGTH] = {0};
166 bool skip_footer = false;
167 // Read all bytes.
168 for (int i = 0; i < WHIRLPOOL_STATE_LENGTH; i++) {
169 // Read bit
170 if (i == 6 || i == 14) {
172 return false;
173 }
174 if (i == 14 && !data.is_valid()) {
175 // Remote control only sent 14 bytes, nothing more to read, not even the footer
176 ESP_LOGV(TAG, "Remote control only sent %d bytes", i);
177 skip_footer = true;
178 break;
179 }
180
181 for (int j = 0; j < 8; j++) {
183 remote_state[i] |= 1 << j;
184
186 ESP_LOGV(TAG, "Byte %d bit %d fail", i, j);
187 return false;
188 }
189 }
190
191 ESP_LOGVV(TAG, "Byte %d %02X", i, remote_state[i]);
192 }
193 // Validate footer
194 if (!data.expect_mark(WHIRLPOOL_BIT_MARK) && !skip_footer) {
195 ESP_LOGV(TAG, "Footer fail");
196 return false;
197 }
198
199 uint8_t checksum13 = 0;
200 uint8_t checksum20 = 0;
201 // Calculate checksum and compare with signal value.
202 for (uint8_t i = 2; i < 13; i++)
203 checksum13 ^= remote_state[i];
204 for (uint8_t i = 14; i < 20; i++)
205 checksum20 ^= remote_state[i];
206
207 if (checksum13 != remote_state[13] || (!skip_footer && checksum20 != remote_state[20])) {
208 ESP_LOGVV(TAG, "Checksum fail");
209 return false;
210 }
211
212 ESP_LOGV(
213 TAG,
214 "Received: %02X %02X %02X %02X %02X %02X %02X %02X %02X %02X %02X %02X %02X %02X %02X %02X %02X %02X "
215 "%02X %02X %02X",
216 remote_state[0], remote_state[1], remote_state[2], remote_state[3], remote_state[4], remote_state[5],
217 remote_state[6], remote_state[7], remote_state[8], remote_state[9], remote_state[10], remote_state[11],
218 remote_state[12], remote_state[13], remote_state[14], remote_state[15], remote_state[16], remote_state[17],
219 remote_state[18], remote_state[19], remote_state[20]);
220
221 // verify header remote code
222 if (remote_state[0] != 0x83 || remote_state[1] != 0x06)
223 return false;
224
225 // powr on/off button
226 ESP_LOGV(TAG, "Power: %02X", (remote_state[2] & WHIRLPOOL_POWER));
227
228 if ((remote_state[2] & WHIRLPOOL_POWER) == WHIRLPOOL_POWER) {
229 auto powered_on = this->mode != climate::CLIMATE_MODE_OFF;
230
231 if (powered_on) {
233 this->powered_on_assumed = false;
234 } else {
235 this->powered_on_assumed = true;
236 }
237 }
238
239 // Set received mode
240 if (powered_on_assumed) {
241 auto mode = remote_state[3] & 0x7;
242 ESP_LOGV(TAG, "Mode: %02X", mode);
243 switch (mode) {
244 case WHIRLPOOL_HEAT:
246 break;
247 case WHIRLPOOL_COOL:
249 break;
250 case WHIRLPOOL_DRY:
252 break;
253 case WHIRLPOOL_FAN:
255 break;
256 case WHIRLPOOL_AUTO:
258 break;
259 }
260 }
261
262 // Set received temp
263 int temp = remote_state[3] & 0xF0;
264 ESP_LOGVV(TAG, "Temperature Raw: %02X", temp);
265 temp = (uint8_t) temp >> 4;
266 temp += static_cast<int>(this->temperature_min_());
267 ESP_LOGVV(TAG, "Temperature Climate: %u", temp);
268 this->target_temperature = temp;
269
270 // Set received fan speed
271 auto fan = remote_state[2] & 0x03;
272 ESP_LOGVV(TAG, "Fan: %02X", fan);
273 switch (fan) {
276 break;
279 break;
282 break;
284 default:
286 break;
287 }
288
289 // Set received swing status
290 if ((remote_state[2] & WHIRLPOOL_SWING_MASK) == WHIRLPOOL_SWING_MASK && remote_state[8] == 0x40) {
291 ESP_LOGVV(TAG, "Swing toggle pressed ");
294 } else {
296 }
297 }
298
299 this->publish_state();
300 return true;
301}
302
303} // namespace whirlpool
304} // namespace esphome
ClimateMode mode
The active mode of the climate device.
Definition climate.h:262
optional< ClimateFanMode > fan_mode
The active fan mode of the climate device.
Definition climate.h:256
float target_temperature
The target temperature of the climate device.
Definition climate.h:243
ClimateSwingMode swing_mode
The active swing mode of the climate device.
Definition climate.h:268
void publish_state()
Publish the state of the climate device, to be called from integrations.
Definition climate.cpp:438
value_type const & value() const
Definition optional.h:94
bool expect_item(uint32_t mark, uint32_t space)
bool is_valid(uint32_t offset=0) const
Definition remote_base.h:58
void set_carrier_frequency(uint32_t carrier_frequency)
Definition remote_base.h:30
int32_t last_transmit_time_
Set the time of the last transmission.
Definition whirlpool.h:51
void transmit_state() override
Transmit via IR the state of this climate controller.
Definition whirlpool.cpp:35
bool on_receive(remote_base::RemoteReceiveData data) override
Handle received IR Buffer.
@ CLIMATE_SWING_OFF
The swing mode is set to Off.
@ CLIMATE_SWING_VERTICAL
The fan mode is set to Vertical.
@ 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_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.
const uint8_t WHIRLPOOL_COOL
Definition whirlpool.cpp:22
const uint16_t WHIRLPOOL_BIT_MARK
Definition whirlpool.cpp:11
const uint16_t WHIRLPOOL_HEADER_SPACE
Definition whirlpool.cpp:10
const uint8_t WHIRLPOOL_FAN_MED
Definition whirlpool.cpp:28
const uint8_t WHIRLPOOL_FAN_AUTO
Definition whirlpool.cpp:26
const uint8_t WHIRLPOOL_SWING_MASK
Definition whirlpool.cpp:31
const uint8_t WHIRLPOOL_STATE_LENGTH
Definition whirlpool.cpp:18
const uint32_t WHIRLPOOL_CARRIER_FREQUENCY
Definition whirlpool.cpp:16
const uint8_t WHIRLPOOL_FAN_LOW
Definition whirlpool.cpp:29
const uint16_t WHIRLPOOL_ZERO_SPACE
Definition whirlpool.cpp:13
const uint8_t WHIRLPOOL_DRY
Definition whirlpool.cpp:21
const uint16_t WHIRLPOOL_ONE_SPACE
Definition whirlpool.cpp:12
const uint16_t WHIRLPOOL_HEADER_MARK
Definition whirlpool.cpp:9
const uint8_t WHIRLPOOL_HEAT
Definition whirlpool.cpp:20
const uint8_t WHIRLPOOL_AUTO
Definition whirlpool.cpp:24
const uint8_t WHIRLPOOL_POWER
Definition whirlpool.cpp:33
const uint8_t WHIRLPOOL_FAN
Definition whirlpool.cpp:23
const uint8_t WHIRLPOOL_FAN_HIGH
Definition whirlpool.cpp:27
const uint32_t WHIRLPOOL_GAP
Definition whirlpool.cpp:14
Providing packet encoding functions for exchanging data with a remote host.
Definition a01nyub.cpp:7
uint32_t IRAM_ATTR HOT millis()
Definition core.cpp:25