ESPHome 2026.11.0-dev
Loading...
Searching...
No Matches
receiver_mitsubishi_heavy.cpp
Go to the documentation of this file.
2#include "heatpumpir.h"
3
4#if defined(USE_ARDUINO) || defined(USE_ESP32)
5
6#include <HeatpumpIRFactory.h>
7
8namespace esphome::heatpumpir {
9
10static constexpr uint8_t FRAME_PREFIX[5] = {0x52, 0xAE, 0xC3, 0x26, 0xD9};
11static constexpr uint8_t XOR_CHECKSUM_EXPECTED = 0xFF;
12static constexpr uint8_t PREFIX_LENGTH = 5;
13static constexpr uint8_t MODE_TEMP_BYTE = 9;
14static constexpr uint8_t MODE_MASK = 0x07;
15static constexpr uint8_t TEMP_MASK = 0x0F;
16static constexpr uint8_t TEMPERATURE_BASE = 17;
17static constexpr uint8_t TEMPERATURE_SHIFT = 4;
18
19static bool read_raw_bytes(remote_base::RemoteReceiveData &data, uint8_t frame[MITSUBISHI_HEAVY_FRAME_LENGTH]) {
20 if (!data.expect_item(MITSUBISHI_HEAVY_HDR_MARK, MITSUBISHI_HEAVY_HDR_SPACE))
21 return false;
22
23 for (uint8_t i = 0; i < MITSUBISHI_HEAVY_FRAME_LENGTH; i++) {
24 uint8_t byte = 0;
25 for (uint8_t bit = 0; bit < 8; bit++) {
26 if (data.expect_item(MITSUBISHI_HEAVY_BIT_MARK, MITSUBISHI_HEAVY_ONE_SPACE)) {
27 byte |= 1 << bit;
28 } else if (!data.expect_item(MITSUBISHI_HEAVY_BIT_MARK, MITSUBISHI_HEAVY_ZERO_SPACE)) {
29 return false;
30 }
31 }
32 frame[i] = byte;
33 }
34
35 return true;
36}
37
38static bool validate_prefix(const uint8_t frame[MITSUBISHI_HEAVY_FRAME_LENGTH]) {
39 for (uint8_t i = 0; i < PREFIX_LENGTH; i++) {
40 if (frame[i] != FRAME_PREFIX[i])
41 return false;
42 }
43 return true;
44}
45
46static bool validate_checksums(const uint8_t frame[MITSUBISHI_HEAVY_FRAME_LENGTH]) {
47 for (uint8_t i = PREFIX_LENGTH; i < MITSUBISHI_HEAVY_FRAME_LENGTH; i += 2) {
48 if ((uint8_t) (frame[i] ^ frame[i + 1]) != XOR_CHECKSUM_EXPECTED)
49 return false;
50 }
51 return true;
52}
53
54static bool decode_mode_field(const uint8_t frame[MITSUBISHI_HEAVY_FRAME_LENGTH], climate::ClimateMode &mode) {
55 if (frame[MODE_TEMP_BYTE] & MITSUBISHI_HEAVY_MODE_OFF) {
57 return true;
58 }
59 switch (frame[MODE_TEMP_BYTE] & MODE_MASK) {
60 case MITSUBISHI_HEAVY_MODE_AUTO:
62 return true;
63 case MITSUBISHI_HEAVY_MODE_HEAT:
65 return true;
66 case MITSUBISHI_HEAVY_MODE_COOL:
68 return true;
69 case MITSUBISHI_HEAVY_MODE_DRY:
71 return true;
72 case MITSUBISHI_HEAVY_MODE_FAN:
74 return true;
75 default:
76 return false;
77 }
78}
79
80static float decode_temperature_field(const uint8_t frame[MITSUBISHI_HEAVY_FRAME_LENGTH]) {
81 uint8_t temp_nibble = frame[MODE_TEMP_BYTE] >> TEMPERATURE_SHIFT;
82 uint8_t inverted_nibble = ~temp_nibble;
83 uint8_t temp_offset = inverted_nibble & TEMP_MASK;
84 return TEMPERATURE_BASE + temp_offset;
85}
86
87static bool apply_climate_state(const uint8_t frame[MITSUBISHI_HEAVY_FRAME_LENGTH], HeatpumpIRClimate &climate) {
89 if (!decode_mode_field(frame, mode))
90 return false;
91 climate.mode = mode;
92 climate.target_temperature = decode_temperature_field(frame);
93 return true;
94}
95
97 HeatpumpIRClimate &climate) {
98 if (!read_raw_bytes(data, frame))
99 return false;
100 if (!validate_prefix(frame))
101 return false;
102 if (!validate_checksums(frame))
103 return false;
104 return apply_climate_state(frame, climate);
105}
106
107} // namespace esphome::heatpumpir
108
109#endif
BedjetMode mode
BedJet operating mode.
ClimateMode
Enum for all modes a climate device can be in.
@ 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.
bool decode_mitsubishi_heavy_frame(remote_base::RemoteReceiveData &data, uint8_t frame[MITSUBISHI_HEAVY_FRAME_LENGTH], HeatpumpIRClimate &climate)
Read a Mitsubishi Heavy frame into frame, check its prefix and inverted byte pairs,...
constexpr uint8_t MITSUBISHI_HEAVY_FRAME_LENGTH
Bytes in a Mitsubishi Heavy IR frame, prefix included.
std::span< const uint8_t > data