ESPHome 2025.5.0
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 // Read all bytes.
167 for (int i = 0; i < WHIRLPOOL_STATE_LENGTH; i++) {
168 // Read bit
169 if (i == 6 || i == 14) {
171 return false;
172 }
173 for (int j = 0; j < 8; j++) {
175 remote_state[i] |= 1 << j;
176
178 ESP_LOGV(TAG, "Byte %d bit %d fail", i, j);
179 return false;
180 }
181 }
182
183 ESP_LOGVV(TAG, "Byte %d %02X", i, remote_state[i]);
184 }
185 // Validate footer
186 if (!data.expect_mark(WHIRLPOOL_BIT_MARK)) {
187 ESP_LOGV(TAG, "Footer fail");
188 return false;
189 }
190
191 uint8_t checksum13 = 0;
192 uint8_t checksum20 = 0;
193 // Calculate checksum and compare with signal value.
194 for (uint8_t i = 2; i < 13; i++)
195 checksum13 ^= remote_state[i];
196 for (uint8_t i = 14; i < 20; i++)
197 checksum20 ^= remote_state[i];
198
199 if (checksum13 != remote_state[13] || checksum20 != remote_state[20]) {
200 ESP_LOGVV(TAG, "Checksum fail");
201 return false;
202 }
203
204 ESP_LOGV(
205 TAG,
206 "Received: %02X %02X %02X %02X %02X %02X %02X %02X %02X %02X %02X %02X %02X %02X %02X %02X %02X %02X "
207 "%02X %02X %02X",
208 remote_state[0], remote_state[1], remote_state[2], remote_state[3], remote_state[4], remote_state[5],
209 remote_state[6], remote_state[7], remote_state[8], remote_state[9], remote_state[10], remote_state[11],
210 remote_state[12], remote_state[13], remote_state[14], remote_state[15], remote_state[16], remote_state[17],
211 remote_state[18], remote_state[19], remote_state[20]);
212
213 // verify header remote code
214 if (remote_state[0] != 0x83 || remote_state[1] != 0x06)
215 return false;
216
217 // powr on/off button
218 ESP_LOGV(TAG, "Power: %02X", (remote_state[2] & WHIRLPOOL_POWER));
219
220 if ((remote_state[2] & WHIRLPOOL_POWER) == WHIRLPOOL_POWER) {
221 auto powered_on = this->mode != climate::CLIMATE_MODE_OFF;
222
223 if (powered_on) {
225 this->powered_on_assumed = false;
226 } else {
227 this->powered_on_assumed = true;
228 }
229 }
230
231 // Set received mode
232 if (powered_on_assumed) {
233 auto mode = remote_state[3] & 0x7;
234 ESP_LOGV(TAG, "Mode: %02X", mode);
235 switch (mode) {
236 case WHIRLPOOL_HEAT:
238 break;
239 case WHIRLPOOL_COOL:
241 break;
242 case WHIRLPOOL_DRY:
244 break;
245 case WHIRLPOOL_FAN:
247 break;
248 case WHIRLPOOL_AUTO:
250 break;
251 }
252 }
253
254 // Set received temp
255 int temp = remote_state[3] & 0xF0;
256 ESP_LOGVV(TAG, "Temperature Raw: %02X", temp);
257 temp = (uint8_t) temp >> 4;
258 temp += static_cast<int>(this->temperature_min_());
259 ESP_LOGVV(TAG, "Temperature Climate: %u", temp);
260 this->target_temperature = temp;
261
262 // Set received fan speed
263 auto fan = remote_state[2] & 0x03;
264 ESP_LOGVV(TAG, "Fan: %02X", fan);
265 switch (fan) {
268 break;
271 break;
274 break;
276 default:
278 break;
279 }
280
281 // Set received swing status
282 if ((remote_state[2] & WHIRLPOOL_SWING_MASK) == WHIRLPOOL_SWING_MASK && remote_state[8] == 0x40) {
283 ESP_LOGVV(TAG, "Swing toggle pressed ");
286 } else {
288 }
289 }
290
291 this->publish_state();
292 return true;
293}
294
295} // namespace whirlpool
296} // namespace esphome
ClimateMode mode
The active mode of the climate device.
Definition climate.h:173
optional< ClimateFanMode > fan_mode
The active fan mode of the climate device.
Definition climate.h:199
float target_temperature
The target temperature of the climate device.
Definition climate.h:186
ClimateSwingMode swing_mode
The active swing mode of the climate device.
Definition climate.h:202
void publish_state()
Publish the state of the climate device, to be called from integrations.
Definition climate.cpp:395
value_type const & value() const
Definition optional.h:89
bool expect_item(uint32_t mark, uint32_t space)
void set_carrier_frequency(uint32_t carrier_frequency)
Definition remote_base.h:34
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:27
constexpr const T & clamp(const T &v, const T &lo, const T &hi, Compare comp)
Definition helpers.h:101