ESPHome  2022.1.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  switch (fan_mode & 0xF0) {
187  case DAIKIN_FAN_1:
188  case DAIKIN_FAN_2:
189  case DAIKIN_FAN_SILENT:
190  this->fan_mode = climate::CLIMATE_FAN_LOW;
191  break;
192  case DAIKIN_FAN_3:
193  this->fan_mode = climate::CLIMATE_FAN_MEDIUM;
194  break;
195  case DAIKIN_FAN_4:
196  case DAIKIN_FAN_5:
197  this->fan_mode = climate::CLIMATE_FAN_HIGH;
198  break;
199  case DAIKIN_FAN_AUTO:
200  this->fan_mode = climate::CLIMATE_FAN_AUTO;
201  break;
202  }
203  this->publish_state();
204  return true;
205 }
206 
208  uint8_t state_frame[DAIKIN_STATE_FRAME_SIZE] = {};
210  return false;
211  }
212  for (uint8_t pos = 0; pos < DAIKIN_STATE_FRAME_SIZE; pos++) {
213  uint8_t byte = 0;
214  for (int8_t bit = 0; bit < 8; bit++) {
216  byte |= 1 << bit;
217  else if (!data.expect_item(DAIKIN_BIT_MARK, DAIKIN_ZERO_SPACE)) {
218  return false;
219  }
220  }
221  state_frame[pos] = byte;
222  if (pos == 0) {
223  // frame header
224  if (byte != 0x11)
225  return false;
226  } else if (pos == 1) {
227  // frame header
228  if (byte != 0xDA)
229  return false;
230  } else if (pos == 2) {
231  // frame header
232  if (byte != 0x27)
233  return false;
234  } else if (pos == 3) { // NOLINT(bugprone-branch-clone)
235  // frame header
236  if (byte != 0x00)
237  return false;
238  } else if (pos == 4) {
239  // frame type
240  if (byte != 0x00)
241  return false;
242  }
243  }
244  return this->parse_state_frame_(state_frame);
245 }
246 
247 } // namespace daikin
248 } // 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:204
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:72
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:183
const uint8_t DAIKIN_MODE_HEAT
Definition: daikin.h:16
bool on_receive(remote_base::RemoteReceiveData data) override
Definition: daikin.cpp:207
void set_carrier_frequency(uint32_t carrier_frequency)
Definition: remote_base.h:30
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:175
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:76
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
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:74
uint8_t checksum
Definition: bl0940.h:33
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:380
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:70
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:198
const uint8_t DAIKIN_TEMP_MAX
Definition: daikin.h:11
const uint8_t DAIKIN_FAN_1
Definition: daikin.h:25
Library based on https://github.com/miguelbalboa/rfid and adapted to ESPHome by . ...
Definition: a4988.cpp:4
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.h:111
The climate device only has the fan enabled, no heating or cooling is taking place.
Definition: climate_mode.h:20
remote_transmitter::RemoteTransmitterComponent * transmitter_
Definition: climate_ir.h:67