ESPHome  2024.11.0
ballu.cpp
Go to the documentation of this file.
1 #include "ballu.h"
2 #include "esphome/core/log.h"
3 
4 namespace esphome {
5 namespace ballu {
6 
7 static const char *const TAG = "ballu.climate";
8 
9 const uint16_t BALLU_HEADER_MARK = 9000;
10 const uint16_t BALLU_HEADER_SPACE = 4500;
11 const uint16_t BALLU_BIT_MARK = 575;
12 const uint16_t BALLU_ONE_SPACE = 1675;
13 const uint16_t BALLU_ZERO_SPACE = 550;
14 
15 const uint32_t BALLU_CARRIER_FREQUENCY = 38000;
16 
17 const uint8_t BALLU_STATE_LENGTH = 13;
18 
19 const uint8_t BALLU_AUTO = 0;
20 const uint8_t BALLU_COOL = 0x20;
21 const uint8_t BALLU_DRY = 0x40;
22 const uint8_t BALLU_HEAT = 0x80;
23 const uint8_t BALLU_FAN = 0xc0;
24 
25 const uint8_t BALLU_FAN_AUTO = 0xa0;
26 const uint8_t BALLU_FAN_HIGH = 0x20;
27 const uint8_t BALLU_FAN_MED = 0x40;
28 const uint8_t BALLU_FAN_LOW = 0x60;
29 
30 const uint8_t BALLU_SWING_VER = 0x07;
31 const uint8_t BALLU_SWING_HOR = 0xe0;
32 const uint8_t BALLU_POWER = 0x20;
33 
35  uint8_t remote_state[BALLU_STATE_LENGTH] = {0};
36 
37  auto temp = (uint8_t) roundf(clamp(this->target_temperature, YKR_K_002E_TEMP_MIN, YKR_K_002E_TEMP_MAX));
38  auto swing_ver =
40  auto swing_hor =
42 
43  remote_state[0] = 0xc3;
44  remote_state[1] = ((temp - 8) << 3) | (swing_ver ? 0 : BALLU_SWING_VER);
45  remote_state[2] = swing_hor ? 0 : BALLU_SWING_HOR;
46  remote_state[9] = (this->mode == climate::CLIMATE_MODE_OFF) ? 0 : BALLU_POWER;
47  remote_state[11] = 0x1e;
48 
49  // Fan speed
50  switch (this->fan_mode.value()) {
52  remote_state[4] |= BALLU_FAN_HIGH;
53  break;
55  remote_state[4] |= BALLU_FAN_MED;
56  break;
58  remote_state[4] |= BALLU_FAN_LOW;
59  break;
61  remote_state[4] |= BALLU_FAN_AUTO;
62  break;
63  default:
64  break;
65  }
66 
67  // Mode
68  switch (this->mode) {
70  remote_state[6] |= BALLU_AUTO;
71  break;
73  remote_state[6] |= BALLU_HEAT;
74  break;
76  remote_state[6] |= BALLU_COOL;
77  break;
79  remote_state[6] |= BALLU_DRY;
80  break;
82  remote_state[6] |= BALLU_FAN;
83  break;
85  remote_state[6] |= BALLU_AUTO;
86  default:
87  break;
88  }
89 
90  // Checksum
91  for (uint8_t i = 0; i < BALLU_STATE_LENGTH - 1; i++)
92  remote_state[12] += remote_state[i];
93 
94  ESP_LOGV(TAG, "Sending: %02X %02X %02X %02X %02X %02X %02X %02X %02X %02X %02X %02X %02X", remote_state[0],
95  remote_state[1], remote_state[2], remote_state[3], remote_state[4], remote_state[5], remote_state[6],
96  remote_state[7], remote_state[8], remote_state[9], remote_state[10], remote_state[11], remote_state[12]);
97 
98  // Send code
99  auto transmit = this->transmitter_->transmit();
100  auto *data = transmit.get_data();
101 
102  data->set_carrier_frequency(38000);
103 
104  // Header
105  data->mark(BALLU_HEADER_MARK);
106  data->space(BALLU_HEADER_SPACE);
107  // Data
108  for (uint8_t i : remote_state) {
109  for (uint8_t j = 0; j < 8; j++) {
110  data->mark(BALLU_BIT_MARK);
111  bool bit = i & (1 << j);
112  data->space(bit ? BALLU_ONE_SPACE : BALLU_ZERO_SPACE);
113  }
114  }
115  // Footer
116  data->mark(BALLU_BIT_MARK);
117 
118  transmit.perform();
119 }
120 
122  // Validate header
123  if (!data.expect_item(BALLU_HEADER_MARK, BALLU_HEADER_SPACE)) {
124  ESP_LOGV(TAG, "Header fail");
125  return false;
126  }
127 
128  uint8_t remote_state[BALLU_STATE_LENGTH] = {0};
129  // Read all bytes.
130  for (int i = 0; i < BALLU_STATE_LENGTH; i++) {
131  // Read bit
132  for (int j = 0; j < 8; j++) {
133  if (data.expect_item(BALLU_BIT_MARK, BALLU_ONE_SPACE)) {
134  remote_state[i] |= 1 << j;
135 
136  } else if (!data.expect_item(BALLU_BIT_MARK, BALLU_ZERO_SPACE)) {
137  ESP_LOGV(TAG, "Byte %d bit %d fail", i, j);
138  return false;
139  }
140  }
141 
142  ESP_LOGVV(TAG, "Byte %d %02X", i, remote_state[i]);
143  }
144  // Validate footer
145  if (!data.expect_mark(BALLU_BIT_MARK)) {
146  ESP_LOGV(TAG, "Footer fail");
147  return false;
148  }
149 
150  uint8_t checksum = 0;
151  // Calculate checksum and compare with signal value.
152  for (uint8_t i = 0; i < BALLU_STATE_LENGTH - 1; i++)
153  checksum += remote_state[i];
154 
155  if (checksum != remote_state[BALLU_STATE_LENGTH - 1]) {
156  ESP_LOGVV(TAG, "Checksum fail");
157  return false;
158  }
159 
160  ESP_LOGV(TAG, "Received: %02X %02X %02X %02X %02X %02X %02X %02X %02X %02X %02X %02X %02X", remote_state[0],
161  remote_state[1], remote_state[2], remote_state[3], remote_state[4], remote_state[5], remote_state[6],
162  remote_state[7], remote_state[8], remote_state[9], remote_state[10], remote_state[11], remote_state[12]);
163 
164  // verify header remote code
165  if (remote_state[0] != 0xc3)
166  return false;
167 
168  // powr on/off button
169  ESP_LOGV(TAG, "Power: %02X", (remote_state[9] & BALLU_POWER));
170 
171  if ((remote_state[9] & BALLU_POWER) != BALLU_POWER) {
173  } else {
174  auto mode = remote_state[6] & 0xe0;
175  ESP_LOGV(TAG, "Mode: %02X", mode);
176  switch (mode) {
177  case BALLU_HEAT:
179  break;
180  case BALLU_COOL:
182  break;
183  case BALLU_DRY:
185  break;
186  case BALLU_FAN:
188  break;
189  case BALLU_AUTO:
191  break;
192  }
193  }
194 
195  // Set received temp
196  int temp = remote_state[1] & 0xf8;
197  ESP_LOGVV(TAG, "Temperature Raw: %02X", temp);
198  temp = ((uint8_t) temp >> 3) + 8;
199  ESP_LOGVV(TAG, "Temperature Climate: %u", temp);
200  this->target_temperature = temp;
201 
202  // Set received fan speed
203  auto fan = remote_state[4] & 0xe0;
204  ESP_LOGVV(TAG, "Fan: %02X", fan);
205  switch (fan) {
206  case BALLU_FAN_HIGH:
208  break;
209  case BALLU_FAN_MED:
211  break;
212  case BALLU_FAN_LOW:
214  break;
215  case BALLU_FAN_AUTO:
216  default:
218  break;
219  }
220 
221  // Set received swing status
222  ESP_LOGVV(TAG, "Swing status: %02X %02X", remote_state[1] & BALLU_SWING_VER, remote_state[2] & BALLU_SWING_HOR);
223  if (((remote_state[1] & BALLU_SWING_VER) != BALLU_SWING_VER) &&
224  ((remote_state[2] & BALLU_SWING_HOR) != BALLU_SWING_HOR)) {
226  } else if ((remote_state[1] & BALLU_SWING_VER) != BALLU_SWING_VER) {
228  } else if ((remote_state[2] & BALLU_SWING_HOR) != BALLU_SWING_HOR) {
230  } else {
232  }
233 
234  this->publish_state();
235  return true;
236 }
237 
238 } // namespace ballu
239 } // 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 BALLU_FAN_HIGH
Definition: ballu.cpp:26
The fan mode is set to Both.
Definition: climate_mode.h:74
const uint8_t BALLU_STATE_LENGTH
Definition: ballu.cpp:17
float target_temperature
The target temperature of the climate device.
Definition: climate.h:186
void set_carrier_frequency(uint32_t carrier_frequency)
Definition: remote_base.h:34
const uint8_t BALLU_FAN_AUTO
Definition: ballu.cpp:25
uint8_t checksum
Definition: bl0906.h:210
const uint8_t BALLU_POWER
Definition: ballu.cpp:32
The climate device is set to heat to reach the target temperature.
Definition: climate_mode.h:18
const uint8_t BALLU_FAN
Definition: ballu.cpp:23
ClimateMode mode
The active mode of the climate device.
Definition: climate.h:173
const float YKR_K_002E_TEMP_MAX
Definition: ballu.h:12
bool on_receive(remote_base::RemoteReceiveData data) override
Handle received IR Buffer.
Definition: ballu.cpp:121
void transmit_state() override
Transmit via IR the state of this climate controller.
Definition: ballu.cpp:34
const uint32_t BALLU_CARRIER_FREQUENCY
Definition: ballu.cpp:15
The climate device is set to dry/humidity mode.
Definition: climate_mode.h:22
constexpr const T & clamp(const T &v, const T &lo, const T &hi, Compare comp)
Definition: helpers.h:93
const uint16_t BALLU_HEADER_MARK
Definition: ballu.cpp:9
const uint16_t BALLU_ZERO_SPACE
Definition: ballu.cpp:13
const uint8_t BALLU_SWING_VER
Definition: ballu.cpp:30
const uint8_t BALLU_HEAT
Definition: ballu.cpp:22
const float YKR_K_002E_TEMP_MIN
Definition: ballu.h:11
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 BALLU_AUTO
Definition: ballu.cpp:19
RemoteTransmitterBase * transmitter_
Definition: remote_base.h:276
const uint8_t BALLU_FAN_LOW
Definition: ballu.cpp:28
const uint8_t BALLU_SWING_HOR
Definition: ballu.cpp:31
The climate device is adjusting the temperatre dynamically.
Definition: climate_mode.h:27
The fan mode is set to Vertical.
Definition: climate_mode.h:76
void publish_state()
Publish the state of the climate device, to be called from integrations.
Definition: climate.cpp:395
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
optional< ClimateFanMode > fan_mode
The active fan mode of the climate device.
Definition: climate.h:199
Implementation of SPI Controller mode.
Definition: a01nyub.cpp:7
const uint16_t BALLU_ONE_SPACE
Definition: ballu.cpp:12
const uint8_t BALLU_COOL
Definition: ballu.cpp:20
The fan mode is set to Medium.
Definition: climate_mode.h:56
const uint8_t BALLU_DRY
Definition: ballu.cpp:21
const uint16_t BALLU_HEADER_SPACE
Definition: ballu.cpp:10
const uint8_t BALLU_FAN_MED
Definition: ballu.cpp:27
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
const uint16_t BALLU_BIT_MARK
Definition: ballu.cpp:11