ESPHome 2026.5.1
Loading...
Searching...
No Matches
daikin.cpp
Go to the documentation of this file.
1#include "daikin.h"
3
4namespace esphome::daikin {
5
6static const char *const TAG = "daikin.climate";
7
9 uint8_t remote_state[35] = {0x11, 0xDA, 0x27, 0x00, 0xC5, 0x00, 0x00, 0xD7, 0x11, 0xDA, 0x27, 0x00,
10 0x42, 0x49, 0x05, 0xA2, 0x11, 0xDA, 0x27, 0x00, 0x00, 0x00, 0x00, 0x00,
11 0x00, 0x00, 0x00, 0x06, 0x60, 0x00, 0x00, 0xC0, 0x00, 0x00, 0x00};
12
13 remote_state[21] = this->operation_mode_();
14 remote_state[22] = this->temperature_();
15 uint16_t fan_speed = this->fan_speed_();
16 remote_state[24] = fan_speed >> 8;
17 remote_state[25] = fan_speed & 0xff;
18
19 // Calculate checksum
20 for (int i = 16; i < 34; i++) {
21 remote_state[34] += remote_state[i];
22 }
23
24 auto transmit = this->transmitter_->transmit();
25 auto *data = transmit.get_data();
26 data->set_carrier_frequency(DAIKIN_IR_FREQUENCY);
27
28 data->mark(DAIKIN_HEADER_MARK);
29 data->space(DAIKIN_HEADER_SPACE);
30 for (int i = 0; i < 8; i++) {
31 for (uint8_t mask = 1; mask > 0; mask <<= 1) { // iterate through bit mask
32 data->mark(DAIKIN_BIT_MARK);
33 bool bit = remote_state[i] & mask;
34 data->space(bit ? DAIKIN_ONE_SPACE : DAIKIN_ZERO_SPACE);
35 }
36 }
37 data->mark(DAIKIN_BIT_MARK);
38 data->space(DAIKIN_MESSAGE_SPACE);
39 data->mark(DAIKIN_HEADER_MARK);
40 data->space(DAIKIN_HEADER_SPACE);
41
42 for (int i = 8; i < 16; i++) {
43 for (uint8_t mask = 1; mask > 0; mask <<= 1) { // iterate through bit mask
44 data->mark(DAIKIN_BIT_MARK);
45 bool bit = remote_state[i] & mask;
46 data->space(bit ? DAIKIN_ONE_SPACE : DAIKIN_ZERO_SPACE);
47 }
48 }
49 data->mark(DAIKIN_BIT_MARK);
50 data->space(DAIKIN_MESSAGE_SPACE);
51 data->mark(DAIKIN_HEADER_MARK);
52 data->space(DAIKIN_HEADER_SPACE);
53
54 for (int i = 16; i < 35; i++) {
55 for (uint8_t mask = 1; mask > 0; mask <<= 1) { // iterate through bit mask
56 data->mark(DAIKIN_BIT_MARK);
57 bool bit = remote_state[i] & mask;
58 data->space(bit ? DAIKIN_ONE_SPACE : DAIKIN_ZERO_SPACE);
59 }
60 }
61 data->mark(DAIKIN_BIT_MARK);
62 data->space(0);
63
64 transmit.perform();
65}
66
68 uint8_t operating_mode = DAIKIN_MODE_ON;
69 switch (this->mode) {
71 operating_mode |= DAIKIN_MODE_COOL;
72 break;
74 operating_mode |= DAIKIN_MODE_DRY;
75 break;
77 operating_mode |= DAIKIN_MODE_HEAT;
78 break;
80 operating_mode |= DAIKIN_MODE_AUTO;
81 break;
83 operating_mode |= DAIKIN_MODE_FAN;
84 break;
86 default:
87 operating_mode = DAIKIN_MODE_OFF;
88 break;
89 }
90
91 return operating_mode;
92}
93
94uint16_t DaikinClimate::fan_speed_() const {
95 uint16_t fan_speed;
96 switch (this->fan_mode.value_or(climate::CLIMATE_FAN_ON)) {
98 fan_speed = DAIKIN_FAN_SILENT << 8;
99 break;
101 fan_speed = DAIKIN_FAN_1 << 8;
102 break;
104 fan_speed = DAIKIN_FAN_3 << 8;
105 break;
107 fan_speed = DAIKIN_FAN_5 << 8;
108 break;
110 default:
111 fan_speed = DAIKIN_FAN_AUTO << 8;
112 }
113
114 // If swing is enabled switch first 4 bits to 1111
115 switch (this->swing_mode) {
117 fan_speed |= 0x0F00;
118 break;
120 fan_speed |= 0x000F;
121 break;
123 fan_speed |= 0x0F0F;
124 break;
125 default:
126 break;
127 }
128 return fan_speed;
129}
130
132 // Force special temperatures depending on the mode
133 switch (this->mode) {
135 return 0x32;
137 return 0xc0;
138 default:
139 uint8_t temperature = (uint8_t) roundf(clamp<float>(this->target_temperature, DAIKIN_TEMP_MIN, DAIKIN_TEMP_MAX));
140 return temperature << 1;
141 }
142}
143
144bool DaikinClimate::parse_state_frame_(const uint8_t frame[]) {
145 uint8_t checksum = 0;
146 for (int i = 0; i < (DAIKIN_STATE_FRAME_SIZE - 1); i++) {
147 checksum += frame[i];
148 }
149 if (frame[DAIKIN_STATE_FRAME_SIZE - 1] != checksum)
150 return false;
151 uint8_t mode = frame[5];
152 // Temperature is given in degrees celcius * 2
153 // only update for states that use the temperature
154 uint8_t temperature = frame[6];
155 if (mode & DAIKIN_MODE_ON) {
156 switch (mode & 0xF0) {
157 case DAIKIN_MODE_COOL:
158 this->mode = climate::CLIMATE_MODE_COOL;
159 this->target_temperature = static_cast<float>(temperature * 0.5f);
160 break;
161 case DAIKIN_MODE_DRY:
162 this->mode = climate::CLIMATE_MODE_DRY;
163 break;
164 case DAIKIN_MODE_HEAT:
165 this->mode = climate::CLIMATE_MODE_HEAT;
166 this->target_temperature = static_cast<float>(temperature * 0.5f);
167 break;
168 case DAIKIN_MODE_AUTO:
170 this->target_temperature = static_cast<float>(temperature * 0.5f);
171 break;
172 case DAIKIN_MODE_FAN:
174 break;
175 }
176 } else {
177 this->mode = climate::CLIMATE_MODE_OFF;
178 }
179 uint8_t fan_mode = frame[8];
180 uint8_t swing_mode = frame[9];
181 if (fan_mode & 0xF && swing_mode & 0xF) {
182 this->swing_mode = climate::CLIMATE_SWING_BOTH;
183 } else if (fan_mode & 0xF) {
184 this->swing_mode = climate::CLIMATE_SWING_VERTICAL;
185 } else if (swing_mode & 0xF) {
186 this->swing_mode = climate::CLIMATE_SWING_HORIZONTAL;
187 } else {
188 this->swing_mode = climate::CLIMATE_SWING_OFF;
189 }
190 switch (fan_mode & 0xF0) {
191 case DAIKIN_FAN_1:
192 case DAIKIN_FAN_2:
193 this->fan_mode = climate::CLIMATE_FAN_LOW;
194 break;
195 case DAIKIN_FAN_3:
196 this->fan_mode = climate::CLIMATE_FAN_MEDIUM;
197 break;
198 case DAIKIN_FAN_4:
199 case DAIKIN_FAN_5:
200 this->fan_mode = climate::CLIMATE_FAN_HIGH;
201 break;
202 case DAIKIN_FAN_AUTO:
203 this->fan_mode = climate::CLIMATE_FAN_AUTO;
204 break;
206 this->fan_mode = climate::CLIMATE_FAN_QUIET;
207 break;
208 }
209 this->publish_state();
210 return true;
211}
212
214 uint8_t state_frame[DAIKIN_STATE_FRAME_SIZE] = {};
215 if (!data.expect_item(DAIKIN_HEADER_MARK, DAIKIN_HEADER_SPACE)) {
216 return false;
217 }
218 for (uint8_t pos = 0; pos < DAIKIN_STATE_FRAME_SIZE; pos++) {
219 uint8_t byte = 0;
220 for (int8_t bit = 0; bit < 8; bit++) {
221 if (data.expect_item(DAIKIN_BIT_MARK, DAIKIN_ONE_SPACE)) {
222 byte |= 1 << bit;
223 } else if (!data.expect_item(DAIKIN_BIT_MARK, DAIKIN_ZERO_SPACE)) {
224 return false;
225 }
226 }
227 state_frame[pos] = byte;
228 if (pos == 0) {
229 // frame header
230 if (byte != 0x11)
231 return false;
232 } else if (pos == 1) {
233 // frame header
234 if (byte != 0xDA)
235 return false;
236 } else if (pos == 2) {
237 // frame header
238 if (byte != 0x27)
239 return false;
240 } else if (pos == 3) { // NOLINT(bugprone-branch-clone)
241 // frame header
242 if (byte != 0x00)
243 return false;
244 } else if (pos == 4) {
245 // frame type
246 if (byte != 0x00)
247 return false;
248 }
249 }
250 return this->parse_state_frame_(state_frame);
251}
252
253} // namespace esphome::daikin
uint8_t checksum
Definition bl0906.h:3
ClimateMode mode
The active mode of the climate device.
Definition climate.h:293
optional< ClimateFanMode > fan_mode
The active fan mode of the climate device.
Definition climate.h:287
float target_temperature
The target temperature of the climate device.
Definition climate.h:274
ClimateSwingMode swing_mode
The active swing mode of the climate device.
Definition climate.h:299
void publish_state()
Publish the state of the climate device, to be called from integrations.
Definition climate.cpp:437
bool parse_state_frame_(const uint8_t frame[])
Definition daikin.cpp:144
uint8_t temperature_() const
Definition daikin.cpp:131
uint8_t operation_mode_() const
Definition daikin.cpp:67
uint16_t fan_speed_() const
Definition daikin.cpp:94
void transmit_state() override
Definition daikin.cpp:8
bool on_receive(remote_base::RemoteReceiveData data) override
Definition daikin.cpp:213
@ 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_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_QUIET
The fan mode is set to Quiet.
@ CLIMATE_FAN_HIGH
The fan mode is set to High.
const uint8_t DAIKIN_MODE_AUTO
Definition daikin.h:13
const uint8_t DAIKIN_MODE_OFF
Definition daikin.h:18
const uint8_t DAIKIN_STATE_FRAME_SIZE
Definition daikin.h:40
const uint32_t DAIKIN_BIT_MARK
Definition daikin.h:34
const uint8_t DAIKIN_TEMP_MIN
Definition daikin.h:9
const uint32_t DAIKIN_IR_FREQUENCY
Definition daikin.h:31
const uint8_t DAIKIN_FAN_4
Definition daikin.h:27
const uint32_t DAIKIN_HEADER_MARK
Definition daikin.h:32
const uint8_t DAIKIN_MODE_COOL
Definition daikin.h:14
const uint8_t DAIKIN_FAN_5
Definition daikin.h:28
const uint32_t DAIKIN_MESSAGE_SPACE
Definition daikin.h:37
const uint32_t DAIKIN_HEADER_SPACE
Definition daikin.h:33
const uint8_t DAIKIN_FAN_SILENT
Definition daikin.h:23
const uint32_t DAIKIN_ZERO_SPACE
Definition daikin.h:36
const uint8_t DAIKIN_MODE_DRY
Definition daikin.h:16
const uint32_t DAIKIN_ONE_SPACE
Definition daikin.h:35
const uint8_t DAIKIN_FAN_2
Definition daikin.h:25
const uint8_t DAIKIN_MODE_ON
Definition daikin.h:19
const uint8_t DAIKIN_FAN_1
Definition daikin.h:24
const uint8_t DAIKIN_FAN_AUTO
Definition daikin.h:22
const uint8_t DAIKIN_FAN_3
Definition daikin.h:26
const uint8_t DAIKIN_TEMP_MAX
Definition daikin.h:10
const uint8_t DAIKIN_MODE_HEAT
Definition daikin.h:15
const uint8_t DAIKIN_MODE_FAN
Definition daikin.h:17
size_t size_t pos
Definition helpers.h:1038
uint16_t temperature
Definition sun_gtil2.cpp:12