ESPHome  2024.12.2
hitachi_ac424.cpp
Go to the documentation of this file.
1 #include "hitachi_ac424.h"
2 
3 namespace esphome {
4 namespace hitachi_ac424 {
5 
6 static const char *const TAG = "climate.hitachi_ac424";
7 
8 void set_bits(uint8_t *const dst, const uint8_t offset, const uint8_t nbits, const uint8_t data) {
9  if (offset >= 8 || !nbits)
10  return; // Short circuit as it won't change.
11  // Calculate the mask for the supplied value.
12  uint8_t mask = UINT8_MAX >> (8 - ((nbits > 8) ? 8 : nbits));
13  // Calculate the mask & clear the space for the data.
14  // Clear the destination bits.
15  *dst &= ~(uint8_t) (mask << offset);
16  // Merge in the data.
17  *dst |= ((data & mask) << offset);
18 }
19 
20 void set_bit(uint8_t *const data, const uint8_t position, const bool on) {
21  uint8_t mask = 1 << position;
22  if (on) {
23  *data |= mask;
24  } else {
25  *data &= ~mask;
26  }
27 }
28 
29 uint8_t *invert_byte_pairs(uint8_t *ptr, const uint16_t length) {
30  for (uint16_t i = 1; i < length; i += 2) {
31  // Code done this way to avoid a compiler warning bug.
32  uint8_t inv = ~*(ptr + i - 1);
33  *(ptr + i) = inv;
34  }
35  return ptr;
36 }
37 
39 
43 }
44 
46 
48  uint8_t new_mode = mode;
49  switch (mode) {
50  // Fan mode sets a special temp.
53  break;
57  break;
58  default:
59  new_mode = HITACHI_AC424_MODE_COOL;
60  }
62  if (new_mode != HITACHI_AC424_MODE_FAN)
64  set_fan_(get_fan_()); // Reset the fan speed after the mode change.
65  set_power_(true);
66 }
67 
68 void HitachiClimate::set_temp_(uint8_t celsius, bool set_previous) {
69  uint8_t temp;
70  temp = std::min(celsius, HITACHI_AC424_TEMP_MAX);
71  temp = std::max(temp, HITACHI_AC424_TEMP_MIN);
73  if (previous_temp_ > temp) {
75  } else if (previous_temp_ < temp) {
77  }
78  if (set_previous)
79  previous_temp_ = temp;
80 }
81 
83 
85  uint8_t new_speed = std::max(speed, HITACHI_AC424_FAN_MIN);
86  uint8_t fan_max = HITACHI_AC424_FAN_MAX;
87 
88  // Only 2 x low speeds in Dry mode or Auto
90  fan_max = HITACHI_AC424_FAN_AUTO;
91  } else if (get_mode_() == HITACHI_AC424_MODE_DRY) {
92  fan_max = HITACHI_AC424_FAN_MAX_DRY;
93  } else if (get_mode_() == HITACHI_AC424_MODE_FAN && speed == HITACHI_AC424_FAN_AUTO) {
94  // Fan Mode does not have auto. Set to safe low
95  new_speed = HITACHI_AC424_FAN_MIN;
96  }
97 
98  new_speed = std::min(new_speed, fan_max);
99  // Handle the setting the button value if we are going to change the value.
100  if (new_speed != get_fan_())
102  // Set the values
103 
104  set_bits(&remote_state_[HITACHI_AC424_FAN_BYTE], 4, 4, new_speed);
105  remote_state_[9] = 0x92;
106 
107  // When fan is at min/max, additional bytes seem to be set
108  if (new_speed == HITACHI_AC424_FAN_MIN)
109  remote_state_[9] = 0x98;
110  remote_state_[29] = 0x01;
111 }
112 
114  uint8_t button = get_button_(); // Get the current button value.
115  if (on) {
116  button = HITACHI_AC424_BUTTON_SWINGV; // Set the button to SwingV.
117  } else if (button == HITACHI_AC424_BUTTON_SWINGV) { // Asked to unset it
118  // It was set previous, so use Power as a default
120  }
121  set_button_(button);
122 }
123 
125 
127  set_swing_v_toggle_(on); // Set the button value.
129 }
130 
133 }
134 
136  if (position > HITACHI_AC424_SWINGH_LEFT_MAX) {
138  return;
139  }
142 }
143 
147 }
148 
150 
152 
154  switch (this->mode) {
157  break;
160  break;
163  break;
166  break;
169  break;
171  set_power_(false);
172  break;
173  default:
174  ESP_LOGW(TAG, "Unsupported mode: %s", LOG_STR_ARG(climate_mode_to_string(this->mode)));
175  }
176 
177  set_temp_(static_cast<uint8_t>(this->target_temperature));
178 
179  switch (this->fan_mode.value()) {
182  break;
185  break;
188  break;
191  default:
193  }
194 
195  switch (this->swing_mode) {
197  set_swing_v_(true);
199  break;
201  set_swing_v_(true);
203  break;
205  set_swing_v_(false);
207  break;
209  set_swing_v_(false);
211  break;
212  }
213 
214  // TODO: find change value to set button, now always set to power button
216 
218 
219  auto transmit = this->transmitter_->transmit();
220  auto *data = transmit.get_data();
222 
223  uint8_t repeat = 0;
224  for (uint8_t r = 0; r <= repeat; r++) {
225  // Header
227  // Data
228  for (uint8_t i : remote_state_) {
229  for (uint8_t j = 0; j < 8; j++) {
230  data->mark(HITACHI_AC424_BIT_MARK);
231  bool bit = i & (1 << j);
233  }
234  }
235  // Footer
237  }
238  transmit.perform();
239 
240  dump_state_("Sent", remote_state_);
241 }
242 
243 bool HitachiClimate::parse_mode_(const uint8_t remote_state[]) {
244  uint8_t power = remote_state[HITACHI_AC424_POWER_BYTE];
245  ESP_LOGV(TAG, "Power: %02X %02X", remote_state[HITACHI_AC424_POWER_BYTE], power);
246  uint8_t mode = remote_state[HITACHI_AC424_MODE_BYTE] & 0xF;
247  ESP_LOGV(TAG, "Mode: %02X %02X", remote_state[HITACHI_AC424_MODE_BYTE], mode);
248  if (power == HITACHI_AC424_POWER_ON) {
249  switch (mode) {
251  this->mode = climate::CLIMATE_MODE_COOL;
252  break;
254  this->mode = climate::CLIMATE_MODE_DRY;
255  break;
257  this->mode = climate::CLIMATE_MODE_HEAT;
258  break;
260  this->mode = climate::CLIMATE_MODE_HEAT_COOL;
261  break;
263  this->mode = climate::CLIMATE_MODE_FAN_ONLY;
264  break;
265  }
266  } else {
267  this->mode = climate::CLIMATE_MODE_OFF;
268  }
269  return true;
270 }
271 
272 bool HitachiClimate::parse_temperature_(const uint8_t remote_state[]) {
273  uint8_t temperature =
274  HITACHI_AC424_GETBITS8(remote_state[HITACHI_AC424_TEMP_BYTE], HITACHI_AC424_TEMP_OFFSET, HITACHI_AC424_TEMP_SIZE);
276  ESP_LOGV(TAG, "Temperature: %02X %02u %04f", remote_state[HITACHI_AC424_TEMP_BYTE], temperature,
277  this->target_temperature);
278  return true;
279 }
280 
281 bool HitachiClimate::parse_fan_(const uint8_t remote_state[]) {
282  uint8_t fan_mode = remote_state[HITACHI_AC424_FAN_BYTE] >> 4 & 0xF;
283  ESP_LOGV(TAG, "Fan: %02X %02X", remote_state[HITACHI_AC424_FAN_BYTE], fan_mode);
284  switch (fan_mode) {
287  this->fan_mode = climate::CLIMATE_FAN_LOW;
288  break;
290  this->fan_mode = climate::CLIMATE_FAN_MEDIUM;
291  break;
294  this->fan_mode = climate::CLIMATE_FAN_HIGH;
295  break;
297  this->fan_mode = climate::CLIMATE_FAN_AUTO;
298  break;
299  }
300  return true;
301 }
302 
303 bool HitachiClimate::parse_swing_(const uint8_t remote_state[]) {
304  uint8_t swing_modeh = HITACHI_AC424_GETBITS8(remote_state[HITACHI_AC424_SWINGH_BYTE], HITACHI_AC424_SWINGH_OFFSET,
306  ESP_LOGV(TAG, "SwingH: %02X %02X", remote_state[HITACHI_AC424_SWINGH_BYTE], swing_modeh);
307 
308  if ((swing_modeh & 0x3) == 0x3) {
310  } else {
312  }
313 
314  return true;
315 }
316 
318  // Validate header
320  ESP_LOGVV(TAG, "Header fail");
321  return false;
322  }
323 
324  uint8_t recv_state[HITACHI_AC424_STATE_LENGTH] = {0};
325  // Read all bytes.
326  for (uint8_t pos = 0; pos < HITACHI_AC424_STATE_LENGTH; pos++) {
327  // Read bit
328  for (int8_t bit = 0; bit < 8; bit++) {
330  recv_state[pos] |= 1 << bit;
332  ESP_LOGVV(TAG, "Byte %d bit %d fail", pos, bit);
333  return false;
334  }
335  }
336  }
337 
338  // Validate footer
339  if (!data.expect_mark(HITACHI_AC424_BIT_MARK)) {
340  ESP_LOGVV(TAG, "Footer fail");
341  return false;
342  }
343 
344  dump_state_("Recv", recv_state);
345 
346  // parse mode
347  this->parse_mode_(recv_state);
348  // parse temperature
349  this->parse_temperature_(recv_state);
350  // parse fan
351  this->parse_fan_(recv_state);
352  // parse swingv
353  this->parse_swing_(recv_state);
354  this->publish_state();
355  for (uint8_t i = 0; i < HITACHI_AC424_STATE_LENGTH; i++)
356  remote_state_[i] = recv_state[i];
357 
358  return true;
359 }
360 
361 void HitachiClimate::dump_state_(const char action[], uint8_t state[]) {
362  for (uint16_t i = 0; i < HITACHI_AC424_STATE_LENGTH - 10; i += 10) {
363  ESP_LOGV(TAG, "%s: %02X %02X %02X %02X %02X %02X %02X %02X %02X %02X", action, state[i + 0], state[i + 1],
364  state[i + 2], state[i + 3], state[i + 4], state[i + 5], state[i + 6], state[i + 7], state[i + 8],
365  state[i + 9]);
366  }
367  ESP_LOGV(TAG, "%s: %02X %02X %02X", action, state[40], state[41], state[42]);
368 }
369 
370 } // namespace hitachi_ac424
371 } // namespace esphome
The fan mode is set to Low.
Definition: climate_mode.h:54
const uint8_t HITACHI_AC424_BUTTON_FAN
Definition: hitachi_ac424.h:21
value_type const & value() const
Definition: optional.h:89
const uint8_t HITACHI_AC424_BUTTON_BYTE
Definition: hitachi_ac424.h:17
ClimateSwingMode swing_mode
The active swing mode of the climate device.
Definition: climate.h:202
uint8_t * invert_byte_pairs(uint8_t *ptr, const uint16_t length)
The fan mode is set to Both.
Definition: climate_mode.h:74
const uint8_t HITACHI_AC424_POWER_BYTE
Definition: hitachi_ac424.h:54
void set_bit(uint8_t *const data, const uint8_t position, const bool on)
const uint8_t HITACHI_AC424_BUTTON_TEMP_DOWN
Definition: hitachi_ac424.h:22
const uint8_t HITACHI_AC424_FAN_HIGH
Definition: hitachi_ac424.h:49
const uint16_t HITACHI_AC424_HDR_MARK
Definition: hitachi_ac424.h:9
float target_temperature
The target temperature of the climate device.
Definition: climate.h:186
const uint8_t HITACHI_AC424_FAN_MEDIUM
Definition: hitachi_ac424.h:48
void set_carrier_frequency(uint32_t carrier_frequency)
Definition: remote_base.h:34
const uint16_t HITACHI_AC424_ZERO_SPACE
Definition: hitachi_ac424.h:13
const LogString * climate_mode_to_string(ClimateMode mode)
Convert the given ClimateMode to a human-readable string.
Definition: climate_mode.cpp:6
const uint16_t HITACHI_AC424_HDR_SPACE
Definition: hitachi_ac424.h:10
The climate device is set to heat to reach the target temperature.
Definition: climate_mode.h:18
const uint8_t HITACHI_AC424_TEMP_FAN
Definition: hitachi_ac424.h:33
const uint8_t HITACHI_AC424_SWINGH_BYTE
Definition: hitachi_ac424.h:58
ClimateMode mode
The active mode of the climate device.
Definition: climate.h:173
const uint8_t HITACHI_AC424_BUTTON_SWINGH
Definition: hitachi_ac424.h:25
int speed
Definition: fan.h:35
const uint8_t HITACHI_AC424_TEMP_SIZE
Definition: hitachi_ac424.h:30
bool parse_swing_(const uint8_t remote_state[])
const uint8_t HITACHI_AC424_MODE_AUTO
Definition: hitachi_ac424.h:42
const uint8_t HITACHI_AC424_MODE_FAN
Definition: hitachi_ac424.h:38
The climate device is set to dry/humidity mode.
Definition: climate_mode.h:22
const uint8_t HITACHI_AC424_POWER_OFF
Definition: hitachi_ac424.h:56
const uint8_t HITACHI_AC424_SWINGV_OFFSET
Definition: hitachi_ac424.h:69
const uint8_t HITACHI_AC424_POWER_ON
Definition: hitachi_ac424.h:55
bool parse_mode_(const uint8_t remote_state[])
const uint16_t HITACHI_AC424_ONE_SPACE
Definition: hitachi_ac424.h:12
const uint8_t HITACHI_AC424_FAN_MAX
Definition: hitachi_ac424.h:51
const uint16_t HITACHI_AC424_STATE_LENGTH
Definition: hitachi_ac424.h:74
const uint16_t HITACHI_AC424_BIT_MARK
Definition: hitachi_ac424.h:11
const uint8_t HITACHI_AC424_FAN_AUTO
Definition: hitachi_ac424.h:50
const uint8_t HITACHI_AC424_FAN_MIN
Definition: hitachi_ac424.h:46
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 HITACHI_AC424_TEMP_OFFSET
Definition: hitachi_ac424.h:29
const uint8_t HITACHI_AC424_TEMP_MIN
Definition: hitachi_ac424.h:31
const uint8_t HITACHI_AC424_MODE_DRY
Definition: hitachi_ac424.h:40
const uint8_t HITACHI_AC424_MODE_BYTE
Definition: hitachi_ac424.h:37
RemoteTransmitterBase * transmitter_
Definition: remote_base.h:276
const uint8_t HITACHI_AC424_BUTTON_SWINGV
Definition: hitachi_ac424.h:24
const uint8_t HITACHI_AC424_SWINGH_AUTO
Definition: hitachi_ac424.h:61
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
const uint8_t HITACHI_AC424_FAN_LOW
Definition: hitachi_ac424.h:47
The fan mode is set to Vertical.
Definition: climate_mode.h:76
void set_bits(uint8_t *const dst, const uint8_t offset, const uint8_t nbits, const uint8_t data)
const uint8_t HITACHI_AC424_MODE_HEAT
Definition: hitachi_ac424.h:41
bool parse_fan_(const uint8_t remote_state[])
const uint8_t HITACHI_AC424_SWINGV_BYTE
Definition: hitachi_ac424.h:68
const uint8_t HITACHI_AC424_MODE_COOL
Definition: hitachi_ac424.h:39
const uint8_t HITACHI_AC424_SWINGH_SIZE
Definition: hitachi_ac424.h:60
void publish_state()
Publish the state of the climate device, to be called from integrations.
Definition: climate.cpp:395
void set_temp_(uint8_t celsius, bool set_previous=false)
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_temperature_(const uint8_t remote_state[])
const uint8_t HITACHI_AC424_TEMP_MAX
Definition: hitachi_ac424.h:32
optional< ClimateFanMode > fan_mode
The active fan mode of the climate device.
Definition: climate.h:199
const uint8_t HITACHI_AC424_SWINGH_MIDDLE
Definition: hitachi_ac424.h:64
The fan mode is set to On.
Definition: climate_mode.h:48
bool on_receive(remote_base::RemoteReceiveData data) override
uint16_t length
Definition: tt21100.cpp:12
const uint8_t HITACHI_AC424_BUTTON_TEMP_UP
Definition: hitachi_ac424.h:23
Implementation of SPI Controller mode.
Definition: a01nyub.cpp:7
const uint8_t HITACHI_AC424_FAN_BYTE
Definition: hitachi_ac424.h:45
const uint8_t HITACHI_AC424_FAN_MAX_DRY
Definition: hitachi_ac424.h:52
const uint32_t HITACHI_AC424_MIN_GAP
Definition: hitachi_ac424.h:14
const uint8_t HITACHI_AC424_SWINGH_OFFSET
Definition: hitachi_ac424.h:59
const uint8_t HITACHI_AC424_TEMP_BYTE
Definition: hitachi_ac424.h:28
The fan mode is set to Medium.
Definition: climate_mode.h:56
float position
Definition: cover.h:14
uint8_t remote_state_[HITACHI_AC424_STATE_LENGTH]
Definition: hitachi_ac424.h:90
const uint8_t HITACHI_AC424_BUTTON_POWER
Definition: hitachi_ac424.h:18
const uint8_t HITACHI_AC424_SWINGH_LEFT_MAX
Definition: hitachi_ac424.h:66
const uint16_t HITACHI_AC424_FREQ
Definition: hitachi_ac424.h:15
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
ClimateAction action
The active state of the climate device.
Definition: climate.h:176
bool state
Definition: fan.h:34
void dump_state_(const char action[], uint8_t remote_state[])