ESPHome 2025.5.0
Loading...
Searching...
No Matches
toshiba.cpp
Go to the documentation of this file.
1#include "toshiba.h"
2
3#include <vector>
4
5namespace esphome {
6namespace toshiba {
7
8struct RacPt1411hwruFanSpeed {
9 uint8_t code1;
10 uint8_t code2;
11};
12
13static const char *const TAG = "toshiba.climate";
14// Timings for IR bits/data
15const uint16_t TOSHIBA_HEADER_MARK = 4380;
16const uint16_t TOSHIBA_HEADER_SPACE = 4370;
17const uint16_t TOSHIBA_GAP_SPACE = 5480;
18const uint16_t TOSHIBA_PACKET_SPACE = 10500;
19const uint16_t TOSHIBA_BIT_MARK = 540;
20const uint16_t TOSHIBA_ZERO_SPACE = 540;
21const uint16_t TOSHIBA_ONE_SPACE = 1620;
22const uint16_t TOSHIBA_CARRIER_FREQUENCY = 38000;
23const uint8_t TOSHIBA_HEADER_LENGTH = 4;
24// Generic Toshiba commands/flags
25const uint8_t TOSHIBA_COMMAND_DEFAULT = 0x01;
26const uint8_t TOSHIBA_COMMAND_TIMER = 0x02;
27const uint8_t TOSHIBA_COMMAND_POWER = 0x08;
28const uint8_t TOSHIBA_COMMAND_MOTION = 0x02;
29
30const uint8_t TOSHIBA_MODE_AUTO = 0x00;
31const uint8_t TOSHIBA_MODE_COOL = 0x01;
32const uint8_t TOSHIBA_MODE_DRY = 0x02;
33const uint8_t TOSHIBA_MODE_HEAT = 0x03;
34const uint8_t TOSHIBA_MODE_FAN_ONLY = 0x04;
35const uint8_t TOSHIBA_MODE_OFF = 0x07;
36
37const uint8_t TOSHIBA_FAN_SPEED_AUTO = 0x00;
38const uint8_t TOSHIBA_FAN_SPEED_QUIET = 0x20;
39const uint8_t TOSHIBA_FAN_SPEED_1 = 0x40;
40const uint8_t TOSHIBA_FAN_SPEED_2 = 0x60;
41const uint8_t TOSHIBA_FAN_SPEED_3 = 0x80;
42const uint8_t TOSHIBA_FAN_SPEED_4 = 0xa0;
43const uint8_t TOSHIBA_FAN_SPEED_5 = 0xc0;
44
45const uint8_t TOSHIBA_POWER_HIGH = 0x01;
46const uint8_t TOSHIBA_POWER_ECO = 0x03;
47
48const uint8_t TOSHIBA_MOTION_SWING = 0x04;
49const uint8_t TOSHIBA_MOTION_FIX = 0x00;
50
51// RAC-PT1411HWRU temperature code flag bits
52const uint8_t RAC_PT1411HWRU_FLAG_FAH = 0x01;
53const uint8_t RAC_PT1411HWRU_FLAG_FRAC = 0x20;
54const uint8_t RAC_PT1411HWRU_FLAG_NEG = 0x10;
55// RAC-PT1411HWRU temperature short code flags mask
56const uint8_t RAC_PT1411HWRU_FLAG_MASK = 0x0F;
57// RAC-PT1411HWRU Headers, Footers and such
58const uint8_t RAC_PT1411HWRU_MESSAGE_HEADER0 = 0xB2;
59const uint8_t RAC_PT1411HWRU_MESSAGE_HEADER1 = 0xD5;
61// RAC-PT1411HWRU "Comfort Sense" feature bits
62const uint8_t RAC_PT1411HWRU_CS_ENABLED = 0x40;
63const uint8_t RAC_PT1411HWRU_CS_DATA = 0x80;
64const uint8_t RAC_PT1411HWRU_CS_HEADER = 0xBA;
65const uint8_t RAC_PT1411HWRU_CS_FOOTER_AUTO = 0x7A;
66const uint8_t RAC_PT1411HWRU_CS_FOOTER_COOL = 0x72;
67const uint8_t RAC_PT1411HWRU_CS_FOOTER_HEAT = 0x7E;
68// RAC-PT1411HWRU Swing
69const uint8_t RAC_PT1411HWRU_SWING_HEADER = 0xB9;
70const std::vector<uint8_t> RAC_PT1411HWRU_SWING_VERTICAL{0xB9, 0x46, 0xF5, 0x0A, 0x04, 0xFB};
71const std::vector<uint8_t> RAC_PT1411HWRU_SWING_OFF{0xB9, 0x46, 0xF5, 0x0A, 0x05, 0xFA};
72// RAC-PT1411HWRU Fan speeds
73const uint8_t RAC_PT1411HWRU_FAN_OFF = 0x7B;
74constexpr RacPt1411hwruFanSpeed RAC_PT1411HWRU_FAN_AUTO{0xBF, 0x66};
75constexpr RacPt1411hwruFanSpeed RAC_PT1411HWRU_FAN_LOW{0x9F, 0x28};
76constexpr RacPt1411hwruFanSpeed RAC_PT1411HWRU_FAN_MED{0x5F, 0x3C};
77constexpr RacPt1411hwruFanSpeed RAC_PT1411HWRU_FAN_HIGH{0x3F, 0x64};
78// RAC-PT1411HWRU Fan speed for Auto and Dry climate modes
79const RacPt1411hwruFanSpeed RAC_PT1411HWRU_NO_FAN{0x1F, 0x65};
80// RAC-PT1411HWRU Modes
81const uint8_t RAC_PT1411HWRU_MODE_AUTO = 0x08;
82const uint8_t RAC_PT1411HWRU_MODE_COOL = 0x00;
83const uint8_t RAC_PT1411HWRU_MODE_DRY = 0x04;
84const uint8_t RAC_PT1411HWRU_MODE_FAN = 0x04;
85const uint8_t RAC_PT1411HWRU_MODE_HEAT = 0x0C;
86const uint8_t RAC_PT1411HWRU_MODE_OFF = 0x00;
87// RAC-PT1411HWRU Fan-only "temperature"/system off
89// RAC-PT1411HWRU temperature codes are not sequential; they instead follow a modified Gray code.
90// Hence these look-up tables. In addition, the upper nibble is used here for additional
91// "negative" and "fractional value" flags as required for some temperatures.
92// RAC-PT1411HWRU °C Temperatures (short codes)
93const std::vector<uint8_t> RAC_PT1411HWRU_TEMPERATURE_C{0x10, 0x00, 0x01, 0x03, 0x02, 0x06, 0x07, 0x05,
94 0x04, 0x0C, 0x0D, 0x09, 0x08, 0x0A, 0x0B};
95// RAC-PT1411HWRU °F Temperatures (short codes)
96const std::vector<uint8_t> RAC_PT1411HWRU_TEMPERATURE_F{0x10, 0x30, 0x00, 0x20, 0x01, 0x21, 0x03, 0x23, 0x02,
97 0x22, 0x06, 0x26, 0x07, 0x05, 0x25, 0x04, 0x24, 0x0C,
98 0x2C, 0x0D, 0x2D, 0x09, 0x08, 0x28, 0x0A, 0x2A, 0x0B};
99
101 if (this->sensor_) {
102 this->sensor_->add_on_state_callback([this](float state) {
105 // current temperature changed, publish state
106 this->publish_state();
107 });
108 this->current_temperature = this->sensor_->state;
109 } else {
110 this->current_temperature = NAN;
111 }
112 // restore set points
113 auto restore = this->restore_state_();
114 if (restore.has_value()) {
115 restore->apply(this);
116 } else {
117 // restore from defaults
119 // initialize target temperature to some value so that it's not NAN
120 this->target_temperature =
121 roundf(clamp<float>(this->current_temperature, this->minimum_temperature_, this->maximum_temperature_));
124 }
125 // Set supported modes & temperatures based on model
128 this->swing_modes_ = this->toshiba_swing_modes_();
129 // Never send nan to HA
130 if (std::isnan(this->target_temperature))
131 this->target_temperature = 24;
132}
133
141
143 uint8_t message[16] = {0};
144 uint8_t message_length = 9;
145
146 // Header
147 message[0] = 0xf2;
148 message[1] = 0x0d;
149
150 // Message length
151 message[2] = message_length - 6;
152
153 // First checksum
154 message[3] = message[0] ^ message[1] ^ message[2];
155
156 // Command
157 message[4] = TOSHIBA_COMMAND_DEFAULT;
158
159 // Temperature
160 uint8_t temperature = static_cast<uint8_t>(
162 message[5] = (temperature - static_cast<uint8_t>(TOSHIBA_GENERIC_TEMP_C_MIN)) << 4;
163
164 // Mode and fan
165 uint8_t mode;
166 switch (this->mode) {
169 break;
170
173 break;
174
177 break;
178
181 break;
182
185 break;
186
188 default:
190 }
191
192 uint8_t fan;
193 switch (this->fan_mode.value()) {
196 break;
197
200 break;
201
204 break;
205
208 break;
209
211 default:
213 break;
214 }
215 message[6] = fan | mode;
216
217 // Zero
218 message[7] = 0x00;
219
220 // If timers bit in the command is set, two extra bytes are added here
221
222 // If power bit is set in the command, one extra byte is added here
223
224 // The last byte is the xor of all bytes from [4]
225 for (uint8_t i = 4; i < 8; i++) {
226 message[8] ^= message[i];
227 }
228
229 // Transmit
230 auto transmit = this->transmitter_->transmit();
231 auto *data = transmit.get_data();
232
233 encode_(data, message, message_length, 1);
234
235 transmit.perform();
236}
237
239 uint8_t code = 0, index = 0, message[RAC_PT1411HWRU_MESSAGE_LENGTH * 2] = {0};
240 float temperature =
243 auto transmit = this->transmitter_->transmit();
244 auto *data = transmit.get_data();
245
246 // Byte 0: Header upper (0xB2)
248 // Byte 1: Header lower (0x4D)
249 message[1] = ~message[0];
250 // Byte 2u: Fan speed
251 // Byte 2l: 1111 (on) or 1011 (off)
252 if (this->mode == climate::CLIMATE_MODE_OFF) {
253 message[2] = RAC_PT1411HWRU_FAN_OFF;
254 } else if ((this->mode == climate::CLIMATE_MODE_HEAT_COOL) || (this->mode == climate::CLIMATE_MODE_DRY)) {
255 message[2] = RAC_PT1411HWRU_NO_FAN.code1;
256 message[7] = RAC_PT1411HWRU_NO_FAN.code2;
257 } else {
258 switch (this->fan_mode.value()) {
260 message[2] = RAC_PT1411HWRU_FAN_LOW.code1;
261 message[7] = RAC_PT1411HWRU_FAN_LOW.code2;
262 break;
263
265 message[2] = RAC_PT1411HWRU_FAN_MED.code1;
266 message[7] = RAC_PT1411HWRU_FAN_MED.code2;
267 break;
268
270 message[2] = RAC_PT1411HWRU_FAN_HIGH.code1;
271 message[7] = RAC_PT1411HWRU_FAN_HIGH.code2;
272 break;
273
275 default:
276 message[2] = RAC_PT1411HWRU_FAN_AUTO.code1;
277 message[7] = RAC_PT1411HWRU_FAN_AUTO.code2;
278 }
279 }
280 // Byte 3u: ~Fan speed
281 // Byte 3l: 0000 (on) or 0100 (off)
282 message[3] = ~message[2];
283 // Byte 4u: Temp
284 if (this->model_ == MODEL_RAC_PT1411HWRU_F) {
285 temperature = (temperature * 1.8) + 32;
287 }
288
289 index = static_cast<uint8_t>(roundf(temp_adjd));
290
291 if (this->model_ == MODEL_RAC_PT1411HWRU_F) {
292 code = RAC_PT1411HWRU_TEMPERATURE_F[index];
293 message[9] |= RAC_PT1411HWRU_FLAG_FAH;
294 } else {
295 code = RAC_PT1411HWRU_TEMPERATURE_C[index];
296 }
299 }
300
301 if (code & RAC_PT1411HWRU_FLAG_FRAC) {
302 message[8] |= RAC_PT1411HWRU_FLAG_FRAC;
303 }
304 if (code & RAC_PT1411HWRU_FLAG_NEG) {
305 message[9] |= RAC_PT1411HWRU_FLAG_NEG;
306 }
307 message[4] = (code & RAC_PT1411HWRU_FLAG_MASK) << 4;
308 // Byte 4l: Mode
309 switch (this->mode) {
311 // zerooooo
312 break;
313
315 message[4] |= RAC_PT1411HWRU_MODE_HEAT;
316 break;
317
319 message[4] |= RAC_PT1411HWRU_MODE_COOL;
320 break;
321
323 message[4] |= RAC_PT1411HWRU_MODE_DRY;
324 break;
325
327 message[4] |= RAC_PT1411HWRU_MODE_FAN;
328 break;
329
331 default:
332 message[4] |= RAC_PT1411HWRU_MODE_AUTO;
333 }
334
335 // Byte 5u: ~Temp
336 // Byte 5l: ~Mode
337 message[5] = ~message[4];
338
339 if (this->mode != climate::CLIMATE_MODE_OFF) {
340 // Byte 6: Header (0xD5)
342 // Byte 7: Fan speed part 2 (done above)
343 // Byte 8: 0x20 for °F frac, else 0 (done above)
344 // Byte 9: 0x10=NEG, 0x01=°F (done above)
345 // Byte 10: 0
346 // Byte 11: Checksum (bytes 6 through 10)
347 for (index = 6; index <= 10; index++) {
348 message[11] += message[index];
349 }
350 }
351 ESP_LOGV(TAG, "*** Generated codes: 0x%.2X%.2X%.2X%.2X%.2X%.2X 0x%.2X%.2X%.2X%.2X%.2X%.2X", message[0], message[1],
352 message[2], message[3], message[4], message[5], message[6], message[7], message[8], message[9], message[10],
353 message[11]);
354
355 // load first block of IR code and repeat it once
356 encode_(data, &message[0], RAC_PT1411HWRU_MESSAGE_LENGTH, 1);
357 // load second block of IR code, if present
358 if (message[6] != 0) {
359 encode_(data, &message[6], RAC_PT1411HWRU_MESSAGE_LENGTH, 0);
360 }
361
362 transmit.perform();
363
364 // Swing Mode
365 data->reset();
366 data->space(TOSHIBA_PACKET_SPACE);
367 switch (this->swing_mode) {
370 break;
371
373 default:
375 }
376
377 data->space(TOSHIBA_PACKET_SPACE);
378 transmit.perform();
379
380 if (this->sensor_) {
382 }
383}
384
385void ToshibaClimate::transmit_rac_pt1411hwru_temp_(const bool cs_state, const bool cs_send_update) {
386 if ((this->mode == climate::CLIMATE_MODE_HEAT) || (this->mode == climate::CLIMATE_MODE_COOL) ||
388 uint8_t message[RAC_PT1411HWRU_MESSAGE_LENGTH] = {0};
390 auto transmit = this->transmitter_->transmit();
391 auto *data = transmit.get_data();
392 // "Comfort Sense" feature notes
393 // IR Code: 0xBA45 xxXX yyYY
394 // xx: Temperature in °C
395 // Bit 6: feature state (on/off)
396 // Bit 7: message contains temperature data for feature (bit 6 must also be set)
397 // XX: Bitwise complement of xx
398 // yy: Mode: Auto=0x7A, Cool=0x72, Heat=0x7E
399 // YY: Bitwise complement of yy
400 //
401 // Byte 0: Header upper (0xBA)
402 message[0] = RAC_PT1411HWRU_CS_HEADER;
403 // Byte 1: Header lower (0x45)
404 message[1] = ~message[0];
405 // Byte 2: Temperature in °C
406 message[2] = static_cast<uint8_t>(roundf(temperature));
407 if (cs_send_update) {
409 } else if (cs_state) {
410 message[2] |= RAC_PT1411HWRU_CS_ENABLED;
411 }
412 // Byte 3: Bitwise complement of byte 2
413 message[3] = ~message[2];
414 // Byte 4: Footer upper
415 switch (this->mode) {
418 break;
419
422 break;
423
426
427 default:
428 break;
429 }
430 // Byte 5: Footer lower/bitwise complement of byte 4
431 message[5] = ~message[4];
432
433 ESP_LOGV(TAG, "*** Generated code: 0x%.2X%.2X%.2X%.2X%.2X%.2X", message[0], message[1], message[2], message[3],
434 message[4], message[5]);
435 // load IR code and repeat it once
436 encode_(data, message, RAC_PT1411HWRU_MESSAGE_LENGTH, 1);
437
438 transmit.perform();
439 }
440}
441
442uint8_t ToshibaClimate::is_valid_rac_pt1411hwru_header_(const uint8_t *message) {
443 const std::vector<uint8_t> header{RAC_PT1411HWRU_MESSAGE_HEADER0, RAC_PT1411HWRU_CS_HEADER,
445
446 for (auto i : header) {
447 if ((message[0] == i) && (message[1] == static_cast<uint8_t>(~i)))
448 return i;
449 }
450 if (message[0] == RAC_PT1411HWRU_MESSAGE_HEADER1)
452
453 return 0;
454}
455
456bool ToshibaClimate::compare_rac_pt1411hwru_packets_(const uint8_t *message1, const uint8_t *message2) {
457 for (uint8_t i = 0; i < RAC_PT1411HWRU_MESSAGE_LENGTH; i++) {
458 if (message1[i] != message2[i])
459 return false;
460 }
461 return true;
462}
463
465 uint8_t checksum = 0;
466
467 switch (is_valid_rac_pt1411hwru_header_(message)) {
471 if (is_valid_rac_pt1411hwru_header_(message) && (message[2] == static_cast<uint8_t>(~message[3])) &&
472 (message[4] == static_cast<uint8_t>(~message[5]))) {
473 return true;
474 }
475 break;
476
478 for (uint8_t i = 0; i < RAC_PT1411HWRU_MESSAGE_LENGTH - 1; i++) {
479 checksum += message[i];
480 }
481 if (checksum == message[RAC_PT1411HWRU_MESSAGE_LENGTH - 1]) {
482 return true;
483 }
484 break;
485
486 default:
487 return false;
488 }
489
490 return false;
491}
492
494 uint8_t message[18] = {0};
495 uint8_t message_length = TOSHIBA_HEADER_LENGTH, temperature_code = 0;
496
497 // Validate header
499 return false;
500 }
501 // Read incoming bits into buffer
502 if (!decode_(&data, message, message_length)) {
503 return false;
504 }
505 // Determine incoming message protocol version and/or length
506 if (is_valid_rac_pt1411hwru_header_(message)) {
507 // We already received four bytes
508 message_length = RAC_PT1411HWRU_MESSAGE_LENGTH - 4;
509 } else if ((message[0] ^ message[1] ^ message[2]) != message[3]) {
510 // Return false if first checksum was not valid
511 return false;
512 } else {
513 // First checksum was valid so continue receiving the remaining bits
514 message_length = message[2] + 2;
515 }
516 // Decode the remaining bytes
517 if (!decode_(&data, &message[4], message_length)) {
518 return false;
519 }
520 // If this is a RAC-PT1411HWRU message, we expect the first packet a second time and also possibly a third packet
521 if (is_valid_rac_pt1411hwru_header_(message)) {
522 // There is always a space between packets
524 return false;
525 }
526 // Validate header 2
528 return false;
529 }
530 if (!decode_(&data, &message[6], RAC_PT1411HWRU_MESSAGE_LENGTH)) {
531 return false;
532 }
533 // If this is a RAC-PT1411HWRU message, there may also be a third packet.
534 // We do not fail the receive if we don't get this; it isn't always present
536 // Validate header 3
538 if (decode_(&data, &message[12], RAC_PT1411HWRU_MESSAGE_LENGTH)) {
539 if (!is_valid_rac_pt1411hwru_message_(&message[12])) {
540 // If a third packet was received but the checksum is not valid, fail
541 return false;
542 }
543 }
544 }
545 if (!compare_rac_pt1411hwru_packets_(&message[0], &message[6])) {
546 // If the first two packets don't match each other, fail
547 return false;
548 }
549 if (!is_valid_rac_pt1411hwru_message_(&message[0])) {
550 // If the first packet isn't valid, fail
551 return false;
552 }
553 }
554
555 // Header has been verified, now determine protocol version and set the climate component properties
556 switch (is_valid_rac_pt1411hwru_header_(message)) {
557 // Power, temperature, mode, fan speed
559 // Get the mode
560 switch (message[4] & 0x0F) {
563 break;
564
565 // case RAC_PT1411HWRU_MODE_OFF:
567 if (((message[4] >> 4) == RAC_PT1411HWRU_TEMPERATURE_FAN_ONLY) && (message[2] == RAC_PT1411HWRU_FAN_OFF)) {
569 } else {
571 }
572 break;
573
574 // case RAC_PT1411HWRU_MODE_DRY:
576 if ((message[4] >> 4) == RAC_PT1411HWRU_TEMPERATURE_FAN_ONLY) {
578 } else {
580 }
581 break;
582
585 break;
586
587 default:
589 break;
590 }
591 // Get the fan speed/mode
592 switch (message[2]) {
593 case RAC_PT1411HWRU_FAN_LOW.code1:
595 break;
596
597 case RAC_PT1411HWRU_FAN_MED.code1:
599 break;
600
601 case RAC_PT1411HWRU_FAN_HIGH.code1:
603 break;
604
605 case RAC_PT1411HWRU_FAN_AUTO.code1:
606 default:
608 break;
609 }
610 // Get the target temperature
611 if (is_valid_rac_pt1411hwru_message_(&message[12])) {
612 temperature_code =
613 (message[4] >> 4) | (message[14] & RAC_PT1411HWRU_FLAG_FRAC) | (message[15] & RAC_PT1411HWRU_FLAG_NEG);
614 if (message[15] & RAC_PT1411HWRU_FLAG_FAH) {
615 for (size_t i = 0; i < RAC_PT1411HWRU_TEMPERATURE_F.size(); i++) {
616 if (RAC_PT1411HWRU_TEMPERATURE_F[i] == temperature_code) {
617 this->target_temperature = static_cast<float>((i + TOSHIBA_RAC_PT1411HWRU_TEMP_F_MIN - 32) * 5) / 9;
618 }
619 }
620 } else {
621 for (size_t i = 0; i < RAC_PT1411HWRU_TEMPERATURE_C.size(); i++) {
622 if (RAC_PT1411HWRU_TEMPERATURE_C[i] == temperature_code) {
624 }
625 }
626 }
627 }
628 break;
629 // "Comfort Sense" temperature packet
631 // "Comfort Sense" feature notes
632 // IR Code: 0xBA45 xxXX yyYY
633 // xx: Temperature in °C
634 // Bit 6: feature state (on/off)
635 // Bit 7: message contains temperature data for feature (bit 6 must also be set)
636 // XX: Bitwise complement of xx
637 // yy: Mode: Auto: 7A
638 // Cool: 72
639 // Heat: 7E
640 // YY: Bitwise complement of yy
641 if ((message[2] & RAC_PT1411HWRU_CS_ENABLED) && (message[2] & RAC_PT1411HWRU_CS_DATA)) {
642 // Setting current_temperature this way allows the unit's remote to provide the temperature to HA
644 }
645 break;
646 // Swing mode
648 if (message[4] == RAC_PT1411HWRU_SWING_VERTICAL[4]) {
650 } else {
652 }
653 break;
654 // Generic (old) Toshiba packet
655 default:
656 uint8_t checksum = 0;
657 // Add back the length of the header (we pruned it above)
658 message_length += TOSHIBA_HEADER_LENGTH;
659 // Validate the second checksum before trusting any more of the message
660 for (uint8_t i = TOSHIBA_HEADER_LENGTH; i < message_length - 1; i++) {
661 checksum ^= message[i];
662 }
663 // Did our computed checksum and the provided checksum match?
664 if (checksum != message[message_length - 1]) {
665 return false;
666 }
667 // Check if this is a short swing/fix message
668 if (message[4] & TOSHIBA_COMMAND_MOTION) {
669 // Not supported yet
670 return false;
671 }
672
673 // Get the mode
674 switch (message[6] & 0x0F) {
675 case TOSHIBA_MODE_OFF:
677 break;
678
681 break;
682
683 case TOSHIBA_MODE_DRY:
685 break;
686
689 break;
690
693 break;
694
696 default:
698 }
699
700 // Get the fan mode
701 switch (message[6] & 0xF0) {
704 break;
705
708 break;
709
712 break;
713
716 break;
717
719 default:
721 break;
722 }
723
724 // Get the target temperature
725 this->target_temperature = (message[5] >> 4) + TOSHIBA_GENERIC_TEMP_C_MIN;
726 }
727
728 this->publish_state();
729 return true;
730}
731
732void ToshibaClimate::encode_(remote_base::RemoteTransmitData *data, const uint8_t *message, const uint8_t nbytes,
733 const uint8_t repeat) {
735
736 for (uint8_t copy = 0; copy <= repeat; copy++) {
738
739 for (uint8_t byte = 0; byte < nbytes; byte++) {
740 for (uint8_t bit = 0; bit < 8; bit++) {
741 data->mark(TOSHIBA_BIT_MARK);
742 if (message[byte] & (1 << (7 - bit))) {
744 } else {
746 }
747 }
748 }
750 }
751}
752
753bool ToshibaClimate::decode_(remote_base::RemoteReceiveData *data, uint8_t *message, const uint8_t nbytes) {
754 for (uint8_t byte = 0; byte < nbytes; byte++) {
755 for (uint8_t bit = 0; bit < 8; bit++) {
757 message[byte] |= 1 << (7 - bit);
759 message[byte] &= static_cast<uint8_t>(~(1 << (7 - bit)));
760 } else {
761 return false;
762 }
763 }
764 }
765 return true;
766}
767
768} // namespace toshiba
769} // namespace esphome
uint8_t checksum
Definition bl0906.h:3
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
float current_temperature
The current temperature of the climate device, as reported from the integration.
Definition climate.h:179
void publish_state()
Publish the state of the climate device, to be called from integrations.
Definition climate.cpp:395
optional< ClimateDeviceRestoreState > restore_state_()
Restore the state of the climate device, call this from your setup() method.
Definition climate.cpp:329
std::set< climate::ClimateSwingMode > swing_modes_
Definition climate_ir.h:64
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
void item(uint32_t mark, uint32_t space)
Definition remote_base.h:29
void add_on_state_callback(std::function< void(float)> &&callback)
Add a callback that will be called every time a filtered value arrives.
Definition sensor.cpp:52
float state
This member variable stores the last state that has passed through all filters.
Definition sensor.h:131
void encode_(remote_base::RemoteTransmitData *data, const uint8_t *message, uint8_t nbytes, uint8_t repeat)
Definition toshiba.cpp:732
bool compare_rac_pt1411hwru_packets_(const uint8_t *message1, const uint8_t *message2)
Definition toshiba.cpp:456
bool is_valid_rac_pt1411hwru_message_(const uint8_t *message)
Definition toshiba.cpp:464
uint8_t is_valid_rac_pt1411hwru_header_(const uint8_t *message)
Definition toshiba.cpp:442
bool decode_(remote_base::RemoteReceiveData *data, uint8_t *message, uint8_t nbytes)
Definition toshiba.cpp:753
std::set< climate::ClimateSwingMode > toshiba_swing_modes_()
Definition toshiba.h:52
void transmit_rac_pt1411hwru_temp_(bool cs_state=true, bool cs_send_update=true)
Definition toshiba.cpp:385
bool on_receive(remote_base::RemoteReceiveData data) override
Definition toshiba.cpp:493
bool state
Definition fan.h:0
@ 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_QUIET
The fan mode is set to Quiet.
@ CLIMATE_FAN_HIGH
The fan mode is set to High.
const uint8_t TOSHIBA_HEADER_LENGTH
Definition toshiba.cpp:23
const uint8_t RAC_PT1411HWRU_MODE_HEAT
Definition toshiba.cpp:85
const uint16_t TOSHIBA_HEADER_MARK
Definition toshiba.cpp:15
const uint8_t TOSHIBA_MODE_HEAT
Definition toshiba.cpp:33
const uint8_t RAC_PT1411HWRU_MODE_FAN
Definition toshiba.cpp:84
const uint8_t RAC_PT1411HWRU_CS_ENABLED
Definition toshiba.cpp:62
const uint16_t TOSHIBA_CARRIER_FREQUENCY
Definition toshiba.cpp:22
const uint8_t TOSHIBA_FAN_SPEED_2
Definition toshiba.cpp:40
@ MODEL_RAC_PT1411HWRU_C
Definition toshiba.h:11
@ MODEL_RAC_PT1411HWRU_F
Definition toshiba.h:12
const uint8_t RAC_PT1411HWRU_MODE_AUTO
Definition toshiba.cpp:81
const RacPt1411hwruFanSpeed RAC_PT1411HWRU_NO_FAN
Definition toshiba.cpp:79
const uint8_t RAC_PT1411HWRU_MODE_COOL
Definition toshiba.cpp:82
const uint8_t RAC_PT1411HWRU_TEMPERATURE_FAN_ONLY
Definition toshiba.cpp:88
const uint8_t TOSHIBA_COMMAND_MOTION
Definition toshiba.cpp:28
const uint8_t RAC_PT1411HWRU_FLAG_FAH
Definition toshiba.cpp:52
const uint8_t RAC_PT1411HWRU_CS_FOOTER_COOL
Definition toshiba.cpp:66
const uint8_t RAC_PT1411HWRU_CS_DATA
Definition toshiba.cpp:63
const uint8_t TOSHIBA_MODE_DRY
Definition toshiba.cpp:32
const uint8_t RAC_PT1411HWRU_FAN_OFF
Definition toshiba.cpp:73
const uint8_t TOSHIBA_FAN_SPEED_QUIET
Definition toshiba.cpp:38
const uint16_t TOSHIBA_BIT_MARK
Definition toshiba.cpp:19
const uint8_t RAC_PT1411HWRU_FLAG_NEG
Definition toshiba.cpp:54
const float TOSHIBA_RAC_PT1411HWRU_TEMP_F_MIN
Definition toshiba.h:20
const uint8_t TOSHIBA_POWER_HIGH
Definition toshiba.cpp:45
const uint8_t TOSHIBA_MODE_FAN_ONLY
Definition toshiba.cpp:34
const uint8_t TOSHIBA_POWER_ECO
Definition toshiba.cpp:46
const float TOSHIBA_GENERIC_TEMP_C_MAX
Definition toshiba.h:17
const uint8_t TOSHIBA_MODE_COOL
Definition toshiba.cpp:31
const float TOSHIBA_GENERIC_TEMP_C_MIN
Definition toshiba.h:16
const uint16_t TOSHIBA_ZERO_SPACE
Definition toshiba.cpp:20
const uint8_t TOSHIBA_FAN_SPEED_3
Definition toshiba.cpp:41
constexpr RacPt1411hwruFanSpeed RAC_PT1411HWRU_FAN_LOW
Definition toshiba.cpp:75
const uint16_t TOSHIBA_GAP_SPACE
Definition toshiba.cpp:17
const uint8_t RAC_PT1411HWRU_MESSAGE_HEADER1
Definition toshiba.cpp:59
const float TOSHIBA_RAC_PT1411HWRU_TEMP_C_MAX
Definition toshiba.h:19
const uint8_t RAC_PT1411HWRU_CS_HEADER
Definition toshiba.cpp:64
const uint8_t TOSHIBA_COMMAND_POWER
Definition toshiba.cpp:27
constexpr RacPt1411hwruFanSpeed RAC_PT1411HWRU_FAN_AUTO
Definition toshiba.cpp:74
const std::vector< uint8_t > RAC_PT1411HWRU_TEMPERATURE_F
Definition toshiba.cpp:96
const uint8_t TOSHIBA_COMMAND_TIMER
Definition toshiba.cpp:26
const uint8_t TOSHIBA_FAN_SPEED_4
Definition toshiba.cpp:42
const uint8_t TOSHIBA_COMMAND_DEFAULT
Definition toshiba.cpp:25
const uint8_t TOSHIBA_FAN_SPEED_1
Definition toshiba.cpp:39
const std::vector< uint8_t > RAC_PT1411HWRU_SWING_VERTICAL
Definition toshiba.cpp:70
const uint8_t RAC_PT1411HWRU_CS_FOOTER_AUTO
Definition toshiba.cpp:65
const uint8_t TOSHIBA_MOTION_SWING
Definition toshiba.cpp:48
const uint8_t TOSHIBA_MODE_AUTO
Definition toshiba.cpp:30
const uint8_t RAC_PT1411HWRU_MODE_DRY
Definition toshiba.cpp:83
const uint16_t TOSHIBA_ONE_SPACE
Definition toshiba.cpp:21
constexpr RacPt1411hwruFanSpeed RAC_PT1411HWRU_FAN_HIGH
Definition toshiba.cpp:77
const uint8_t TOSHIBA_FAN_SPEED_5
Definition toshiba.cpp:43
const uint8_t RAC_PT1411HWRU_MESSAGE_HEADER0
Definition toshiba.cpp:58
constexpr RacPt1411hwruFanSpeed RAC_PT1411HWRU_FAN_MED
Definition toshiba.cpp:76
const uint8_t RAC_PT1411HWRU_FLAG_FRAC
Definition toshiba.cpp:53
const uint16_t TOSHIBA_HEADER_SPACE
Definition toshiba.cpp:16
const uint8_t TOSHIBA_MODE_OFF
Definition toshiba.cpp:35
const uint8_t RAC_PT1411HWRU_CS_FOOTER_HEAT
Definition toshiba.cpp:67
const uint16_t TOSHIBA_PACKET_SPACE
Definition toshiba.cpp:18
const uint8_t RAC_PT1411HWRU_MODE_OFF
Definition toshiba.cpp:86
const float TOSHIBA_RAC_PT1411HWRU_TEMP_C_MIN
Definition toshiba.h:18
const uint8_t RAC_PT1411HWRU_MESSAGE_LENGTH
Definition toshiba.cpp:60
const uint8_t RAC_PT1411HWRU_FLAG_MASK
Definition toshiba.cpp:56
const uint8_t TOSHIBA_MOTION_FIX
Definition toshiba.cpp:49
const std::vector< uint8_t > RAC_PT1411HWRU_TEMPERATURE_C
Definition toshiba.cpp:93
const uint8_t RAC_PT1411HWRU_SWING_HEADER
Definition toshiba.cpp:69
const uint8_t TOSHIBA_FAN_SPEED_AUTO
Definition toshiba.cpp:37
const std::vector< uint8_t > RAC_PT1411HWRU_SWING_OFF
Definition toshiba.cpp:71
Providing packet encoding functions for exchanging data with a remote host.
Definition a01nyub.cpp:7
constexpr const T & clamp(const T &v, const T &lo, const T &hi, Compare comp)
Definition helpers.h:101
uint16_t temperature
Definition sun_gtil2.cpp:12