ESPHome  2024.4.1
daikin.cpp
Go to the documentation of this file.
1 #include "daikin.h"
3 
4 namespace esphome {
5 namespace daikin {
6 
7 static const char *const TAG = "daikin.climate";
8 
10  uint8_t remote_state[35] = {0x11, 0xDA, 0x27, 0x00, 0xC5, 0x00, 0x00, 0xD7, 0x11, 0xDA, 0x27, 0x00,
11  0x42, 0x49, 0x05, 0xA2, 0x11, 0xDA, 0x27, 0x00, 0x00, 0x00, 0x00, 0x00,
12  0x00, 0x00, 0x00, 0x06, 0x60, 0x00, 0x00, 0xC0, 0x00, 0x00, 0x00};
13 
14  remote_state[21] = this->operation_mode_();
15  remote_state[22] = this->temperature_();
16  uint16_t fan_speed = this->fan_speed_();
17  remote_state[24] = fan_speed >> 8;
18  remote_state[25] = fan_speed & 0xff;
19 
20  // Calculate checksum
21  for (int i = 16; i < 34; i++) {
22  remote_state[34] += remote_state[i];
23  }
24 
25  auto transmit = this->transmitter_->transmit();
26  auto *data = transmit.get_data();
28 
29  data->mark(DAIKIN_HEADER_MARK);
30  data->space(DAIKIN_HEADER_SPACE);
31  for (int i = 0; i < 8; i++) {
32  for (uint8_t mask = 1; mask > 0; mask <<= 1) { // iterate through bit mask
33  data->mark(DAIKIN_BIT_MARK);
34  bool bit = remote_state[i] & mask;
35  data->space(bit ? DAIKIN_ONE_SPACE : DAIKIN_ZERO_SPACE);
36  }
37  }
38  data->mark(DAIKIN_BIT_MARK);
39  data->space(DAIKIN_MESSAGE_SPACE);
40  data->mark(DAIKIN_HEADER_MARK);
41  data->space(DAIKIN_HEADER_SPACE);
42 
43  for (int i = 8; i < 16; i++) {
44  for (uint8_t mask = 1; mask > 0; mask <<= 1) { // iterate through bit mask
45  data->mark(DAIKIN_BIT_MARK);
46  bool bit = remote_state[i] & mask;
47  data->space(bit ? DAIKIN_ONE_SPACE : DAIKIN_ZERO_SPACE);
48  }
49  }
50  data->mark(DAIKIN_BIT_MARK);
51  data->space(DAIKIN_MESSAGE_SPACE);
52  data->mark(DAIKIN_HEADER_MARK);
53  data->space(DAIKIN_HEADER_SPACE);
54 
55  for (int i = 16; i < 35; i++) {
56  for (uint8_t mask = 1; mask > 0; mask <<= 1) { // iterate through bit mask
57  data->mark(DAIKIN_BIT_MARK);
58  bool bit = remote_state[i] & mask;
59  data->space(bit ? DAIKIN_ONE_SPACE : DAIKIN_ZERO_SPACE);
60  }
61  }
62  data->mark(DAIKIN_BIT_MARK);
63  data->space(0);
64 
65  transmit.perform();
66 }
67 
69  uint8_t operating_mode = DAIKIN_MODE_ON;
70  switch (this->mode) {
72  operating_mode |= DAIKIN_MODE_COOL;
73  break;
75  operating_mode |= DAIKIN_MODE_DRY;
76  break;
78  operating_mode |= DAIKIN_MODE_HEAT;
79  break;
81  operating_mode |= DAIKIN_MODE_AUTO;
82  break;
84  operating_mode |= DAIKIN_MODE_FAN;
85  break;
87  default:
88  operating_mode = DAIKIN_MODE_OFF;
89  break;
90  }
91 
92  return operating_mode;
93 }
94 
96  uint16_t fan_speed;
97  switch (this->fan_mode.value()) {
99  fan_speed = DAIKIN_FAN_1 << 8;
100  break;
102  fan_speed = DAIKIN_FAN_3 << 8;
103  break;
105  fan_speed = DAIKIN_FAN_5 << 8;
106  break;
108  default:
109  fan_speed = DAIKIN_FAN_AUTO << 8;
110  }
111 
112  // If swing is enabled switch first 4 bits to 1111
113  switch (this->swing_mode) {
115  fan_speed |= 0x0F00;
116  break;
118  fan_speed |= 0x000F;
119  break;
121  fan_speed |= 0x0F0F;
122  break;
123  default:
124  break;
125  }
126  return fan_speed;
127 }
128 
130  // Force special temperatures depending on the mode
131  switch (this->mode) {
133  return 0x32;
136  return 0xc0;
137  default:
138  uint8_t temperature = (uint8_t) roundf(clamp<float>(this->target_temperature, DAIKIN_TEMP_MIN, DAIKIN_TEMP_MAX));
139  return temperature << 1;
140  }
141 }
142 
143 bool DaikinClimate::parse_state_frame_(const uint8_t frame[]) {
144  uint8_t checksum = 0;
145  for (int i = 0; i < (DAIKIN_STATE_FRAME_SIZE - 1); i++) {
146  checksum += frame[i];
147  }
148  if (frame[DAIKIN_STATE_FRAME_SIZE - 1] != checksum)
149  return false;
150  uint8_t mode = frame[5];
151  if (mode & DAIKIN_MODE_ON) {
152  switch (mode & 0xF0) {
153  case DAIKIN_MODE_COOL:
154  this->mode = climate::CLIMATE_MODE_COOL;
155  break;
156  case DAIKIN_MODE_DRY:
157  this->mode = climate::CLIMATE_MODE_DRY;
158  break;
159  case DAIKIN_MODE_HEAT:
160  this->mode = climate::CLIMATE_MODE_HEAT;
161  break;
162  case DAIKIN_MODE_AUTO:
163  this->mode = climate::CLIMATE_MODE_HEAT_COOL;
164  break;
165  case DAIKIN_MODE_FAN:
166  this->mode = climate::CLIMATE_MODE_FAN_ONLY;
167  break;
168  }
169  } else {
170  this->mode = climate::CLIMATE_MODE_OFF;
171  }
172  uint8_t temperature = frame[6];
173  if (!(temperature & 0xC0)) {
174  this->target_temperature = temperature >> 1;
175  }
176  uint8_t fan_mode = frame[8];
177  uint8_t swing_mode = frame[9];
178  if (fan_mode & 0xF && swing_mode & 0xF) {
179  this->swing_mode = climate::CLIMATE_SWING_BOTH;
180  } else if (fan_mode & 0xF) {
181  this->swing_mode = climate::CLIMATE_SWING_VERTICAL;
182  } else if (swing_mode & 0xF) {
183  this->swing_mode = climate::CLIMATE_SWING_HORIZONTAL;
184  } else {
185  this->swing_mode = climate::CLIMATE_SWING_OFF;
186  }
187  switch (fan_mode & 0xF0) {
188  case DAIKIN_FAN_1:
189  case DAIKIN_FAN_2:
190  case DAIKIN_FAN_SILENT:
191  this->fan_mode = climate::CLIMATE_FAN_LOW;
192  break;
193  case DAIKIN_FAN_3:
194  this->fan_mode = climate::CLIMATE_FAN_MEDIUM;
195  break;
196  case DAIKIN_FAN_4:
197  case DAIKIN_FAN_5:
198  this->fan_mode = climate::CLIMATE_FAN_HIGH;
199  break;
200  case DAIKIN_FAN_AUTO:
201  this->fan_mode = climate::CLIMATE_FAN_AUTO;
202  break;
203  }
204  this->publish_state();
205  return true;
206 }
207 
209  uint8_t state_frame[DAIKIN_STATE_FRAME_SIZE] = {};
211  return false;
212  }
213  for (uint8_t pos = 0; pos < DAIKIN_STATE_FRAME_SIZE; pos++) {
214  uint8_t byte = 0;
215  for (int8_t bit = 0; bit < 8; bit++) {
217  byte |= 1 << bit;
218  } else if (!data.expect_item(DAIKIN_BIT_MARK, DAIKIN_ZERO_SPACE)) {
219  return false;
220  }
221  }
222  state_frame[pos] = byte;
223  if (pos == 0) {
224  // frame header
225  if (byte != 0x11)
226  return false;
227  } else if (pos == 1) {
228  // frame header
229  if (byte != 0xDA)
230  return false;
231  } else if (pos == 2) {
232  // frame header
233  if (byte != 0x27)
234  return false;
235  } else if (pos == 3) { // NOLINT(bugprone-branch-clone)
236  // frame header
237  if (byte != 0x00)
238  return false;
239  } else if (pos == 4) {
240  // frame type
241  if (byte != 0x00)
242  return false;
243  }
244  }
245  return this->parse_state_frame_(state_frame);
246 }
247 
248 } // namespace daikin
249 } // namespace esphome
The fan mode is set to Low.
Definition: climate_mode.h:54
value_type const & value() const
Definition: optional.h:89
ClimateSwingMode swing_mode
The active swing mode of the climate device.
Definition: climate.h:202
const uint8_t DAIKIN_MODE_AUTO
Definition: daikin.h:14
const uint8_t DAIKIN_FAN_AUTO
Definition: daikin.h:23
const uint8_t DAIKIN_MODE_ON
Definition: daikin.h:20
const uint32_t DAIKIN_ZERO_SPACE
Definition: daikin.h:37
The fan mode is set to Both.
Definition: climate_mode.h:74
const uint8_t DAIKIN_TEMP_MIN
Definition: daikin.h:10
const uint32_t DAIKIN_HEADER_SPACE
Definition: daikin.h:34
const uint32_t DAIKIN_BIT_MARK
Definition: daikin.h:35
float target_temperature
The target temperature of the climate device.
Definition: climate.h:186
const uint8_t DAIKIN_MODE_HEAT
Definition: daikin.h:16
bool on_receive(remote_base::RemoteReceiveData data) override
Definition: daikin.cpp:208
void set_carrier_frequency(uint32_t carrier_frequency)
Definition: remote_base.h:29
const uint32_t DAIKIN_HEADER_MARK
Definition: daikin.h:33
const uint32_t DAIKIN_MESSAGE_SPACE
Definition: daikin.h:38
const uint8_t DAIKIN_FAN_2
Definition: daikin.h:26
The climate device is set to heat to reach the target temperature.
Definition: climate_mode.h:18
const uint8_t DAIKIN_FAN_SILENT
Definition: daikin.h:24
void transmit_state() override
Definition: daikin.cpp:9
ClimateMode mode
The active mode of the climate device.
Definition: climate.h:173
The climate device is set to dry/humidity mode.
Definition: climate_mode.h:22
const uint32_t DAIKIN_ONE_SPACE
Definition: daikin.h:36
const uint8_t DAIKIN_FAN_5
Definition: daikin.h:29
const uint8_t DAIKIN_FAN_4
Definition: daikin.h:28
The fan mode is set to Horizontal.
Definition: climate_mode.h:78
The climate device is set to cool to reach the target temperature.
Definition: climate_mode.h:16
The fan mode is set to Auto.
Definition: climate_mode.h:52
const uint8_t DAIKIN_STATE_FRAME_SIZE
Definition: daikin.h:41
const uint8_t DAIKIN_MODE_OFF
Definition: daikin.h:19
RemoteTransmitterBase * transmitter_
Definition: remote_base.h:245
uint16_t temperature
Definition: sun_gtil2.cpp:26
The climate device is set to heat/cool to reach the target temperature.
Definition: climate_mode.h:14
The fan mode is set to Vertical.
Definition: climate_mode.h:76
uint8_t checksum
Definition: bl0939.h:35
const uint8_t DAIKIN_MODE_COOL
Definition: daikin.h:15
void publish_state()
Publish the state of the climate device, to be called from integrations.
Definition: climate.cpp:395
const uint8_t DAIKIN_FAN_3
Definition: daikin.h:27
The fan mode is set to High.
Definition: climate_mode.h:58
The swing mode is set to Off.
Definition: climate_mode.h:72
The climate device is off.
Definition: climate_mode.h:12
bool parse_state_frame_(const uint8_t frame[])
Definition: daikin.cpp:143
optional< ClimateFanMode > fan_mode
The active fan mode of the climate device.
Definition: climate.h:199
const uint8_t DAIKIN_TEMP_MAX
Definition: daikin.h:11
const uint8_t DAIKIN_FAN_1
Definition: daikin.h:25
This is a workaround until we can figure out a way to get the tflite-micro idf component code availab...
Definition: a01nyub.cpp:7
const uint8_t DAIKIN_MODE_DRY
Definition: daikin.h:17
const uint32_t DAIKIN_IR_FREQUENCY
Definition: daikin.h:32
The fan mode is set to Medium.
Definition: climate_mode.h:56
const uint8_t DAIKIN_MODE_FAN
Definition: daikin.h:18
bool expect_item(uint32_t mark, uint32_t space)
Definition: remote_base.cpp:74
The climate device only has the fan enabled, no heating or cooling is taking place.
Definition: climate_mode.h:20