ESPHome 2025.5.0
Loading...
Searching...
No Matches
hitachi_ac344.cpp
Go to the documentation of this file.
1#include "hitachi_ac344.h"
2
3namespace esphome {
4namespace hitachi_ac344 {
5
6static const char *const TAG = "climate.hitachi_ac344";
7
8void 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
20void 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
29uint8_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
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_AC344_MODE_COOL;
60 }
62 if (new_mode != HITACHI_AC344_MODE_FAN)
64 set_fan_(get_fan_()); // Reset the fan speed after the mode change.
65 set_power_(true);
66}
67
68void HitachiClimate::set_temp_(uint8_t celsius, bool set_previous) {
69 uint8_t temp;
70 temp = std::min(celsius, HITACHI_AC344_TEMP_MAX);
71 temp = std::max(temp, HITACHI_AC344_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
84void HitachiClimate::set_fan_(uint8_t speed) {
85 uint8_t new_speed = std::max(speed, HITACHI_AC344_FAN_MIN);
86 uint8_t fan_max = HITACHI_AC344_FAN_MAX;
87
88 // Only 2 x low speeds in Dry mode or Auto
90 fan_max = HITACHI_AC344_FAN_AUTO;
91 } else if (get_mode_() == HITACHI_AC344_MODE_DRY) {
94 // Fan Mode does not have auto. Set to safe low
95 new_speed = HITACHI_AC344_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
105 remote_state_[9] = 0x92;
106
107 // When fan is at min/max, additional bytes seem to be set
108 if (new_speed == HITACHI_AC344_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_AC344_BUTTON_SWINGV; // Set the button to SwingV.
117 } else if (button == HITACHI_AC344_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
130
134
143
147
149
151
153 switch (this->mode) {
156 break;
159 break;
162 break;
165 break;
168 break;
170 set_power_(false);
171 break;
172 default:
173 ESP_LOGW(TAG, "Unsupported mode: %s", LOG_STR_ARG(climate_mode_to_string(this->mode)));
174 }
175
176 set_temp_(static_cast<uint8_t>(this->target_temperature));
177
178 switch (this->fan_mode.value()) {
181 break;
184 break;
187 break;
190 default:
192 }
193
194 switch (this->swing_mode) {
196 set_swing_v_(true);
198 break;
200 set_swing_v_(true);
202 break;
204 set_swing_v_(false);
206 break;
208 set_swing_v_(false);
210 break;
211 }
212
213 // TODO: find change value to set button, now always set to power button
215
217
218 auto transmit = this->transmitter_->transmit();
219 auto *data = transmit.get_data();
221
222 uint8_t repeat = 0;
223 for (uint8_t r = 0; r <= repeat; r++) {
224 // Header
226 // Data
227 for (uint8_t i : remote_state_) {
228 for (uint8_t j = 0; j < 8; j++) {
229 data->mark(HITACHI_AC344_BIT_MARK);
230 bool bit = i & (1 << j);
232 }
233 }
234 // Footer
236 }
237 transmit.perform();
238
239 dump_state_("Sent", remote_state_);
240}
241
242bool HitachiClimate::parse_mode_(const uint8_t remote_state[]) {
243 uint8_t power = remote_state[HITACHI_AC344_POWER_BYTE];
244 ESP_LOGV(TAG, "Power: %02X %02X", remote_state[HITACHI_AC344_POWER_BYTE], power);
245 uint8_t mode = remote_state[HITACHI_AC344_MODE_BYTE] & 0xF;
246 ESP_LOGV(TAG, "Mode: %02X %02X", remote_state[HITACHI_AC344_MODE_BYTE], mode);
247 if (power == HITACHI_AC344_POWER_ON) {
248 switch (mode) {
250 this->mode = climate::CLIMATE_MODE_COOL;
251 break;
253 this->mode = climate::CLIMATE_MODE_DRY;
254 break;
256 this->mode = climate::CLIMATE_MODE_HEAT;
257 break;
260 break;
263 break;
264 }
265 } else {
266 this->mode = climate::CLIMATE_MODE_OFF;
267 }
268 return true;
269}
270
271bool HitachiClimate::parse_temperature_(const uint8_t remote_state[]) {
272 uint8_t temperature =
275 ESP_LOGV(TAG, "Temperature: %02X %02u %04f", remote_state[HITACHI_AC344_TEMP_BYTE], temperature,
276 this->target_temperature);
277 return true;
278}
279
280bool HitachiClimate::parse_fan_(const uint8_t remote_state[]) {
281 uint8_t fan_mode = remote_state[HITACHI_AC344_FAN_BYTE] >> 4 & 0xF;
282 ESP_LOGV(TAG, "Fan: %02X %02X", remote_state[HITACHI_AC344_FAN_BYTE], fan_mode);
283 switch (fan_mode) {
286 this->fan_mode = climate::CLIMATE_FAN_LOW;
287 break;
289 this->fan_mode = climate::CLIMATE_FAN_MEDIUM;
290 break;
293 this->fan_mode = climate::CLIMATE_FAN_HIGH;
294 break;
296 this->fan_mode = climate::CLIMATE_FAN_AUTO;
297 break;
298 }
299 return true;
300}
301
302bool HitachiClimate::parse_swing_(const uint8_t remote_state[]) {
303 uint8_t swing_modeh =
305 ESP_LOGV(TAG, "SwingH: %02X %02X", remote_state[HITACHI_AC344_SWINGH_BYTE], swing_modeh);
306
307 if ((swing_modeh & 0x3) == 0x3) {
309 } else {
311 }
312
313 return true;
314}
315
317 // Validate header
319 ESP_LOGVV(TAG, "Header fail");
320 return false;
321 }
322
323 uint8_t recv_state[HITACHI_AC344_STATE_LENGTH] = {0};
324 // Read all bytes.
325 for (uint8_t pos = 0; pos < HITACHI_AC344_STATE_LENGTH; pos++) {
326 // Read bit
327 for (int8_t bit = 0; bit < 8; bit++) {
329 recv_state[pos] |= 1 << bit;
331 ESP_LOGVV(TAG, "Byte %d bit %d fail", pos, bit);
332 return false;
333 }
334 }
335 }
336
337 // Validate footer
339 ESP_LOGVV(TAG, "Footer fail");
340 return false;
341 }
342
343 dump_state_("Recv", recv_state);
344
345 // parse mode
346 this->parse_mode_(recv_state);
347 // parse temperature
348 this->parse_temperature_(recv_state);
349 // parse fan
350 this->parse_fan_(recv_state);
351 // parse swingv
352 this->parse_swing_(recv_state);
353 this->publish_state();
354 for (uint8_t i = 0; i < HITACHI_AC344_STATE_LENGTH; i++)
355 remote_state_[i] = recv_state[i];
356
357 return true;
358}
359
360void HitachiClimate::dump_state_(const char action[], uint8_t state[]) {
361 for (uint16_t i = 0; i < HITACHI_AC344_STATE_LENGTH - 10; i += 10) {
362 ESP_LOGV(TAG, "%s: %02X %02X %02X %02X %02X %02X %02X %02X %02X %02X", action, state[i + 0], state[i + 1],
363 state[i + 2], state[i + 3], state[i + 4], state[i + 5], state[i + 6], state[i + 7], state[i + 8],
364 state[i + 9]);
365 }
366 ESP_LOGV(TAG, "%s: %02X %02X %02X", action, state[40], state[41], state[42]);
367}
368
369} // namespace hitachi_ac344
370} // namespace esphome
BedjetMode mode
BedJet operating mode.
ClimateMode mode
The active mode of the climate device.
Definition climate.h:173
optional< ClimateFanMode > fan_mode
The active fan mode of the climate device.
Definition climate.h:199
float target_temperature
The target temperature of the climate device.
Definition climate.h:186
ClimateSwingMode swing_mode
The active swing mode of the climate device.
Definition climate.h:202
ClimateAction action
The active state of the climate device.
Definition climate.h:176
void publish_state()
Publish the state of the climate device, to be called from integrations.
Definition climate.cpp:395
bool on_receive(remote_base::RemoteReceiveData data) override
void dump_state_(const char action[], uint8_t remote_state[])
bool parse_temperature_(const uint8_t remote_state[])
bool parse_mode_(const uint8_t remote_state[])
bool parse_fan_(const uint8_t remote_state[])
void set_temp_(uint8_t celsius, bool set_previous=false)
uint8_t remote_state_[HITACHI_AC344_STATE_LENGTH]
bool parse_swing_(const uint8_t remote_state[])
value_type const & value() const
Definition optional.h:89
bool expect_item(uint32_t mark, uint32_t space)
void set_carrier_frequency(uint32_t carrier_frequency)
Definition remote_base.h:34
float position
Definition cover.h:0
int speed
Definition fan.h:1
bool state
Definition fan.h:0
@ 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_HIGH
The fan mode is set to High.
const uint8_t HITACHI_AC344_SWINGV_OFFSET
const uint8_t HITACHI_AC344_TEMP_MIN
const uint8_t HITACHI_AC344_BUTTON_FAN
const uint16_t HITACHI_AC344_BIT_MARK
void set_bit(uint8_t *const data, const uint8_t position, const bool on)
const uint8_t HITACHI_AC344_BUTTON_BYTE
const uint8_t HITACHI_AC344_TEMP_BYTE
const uint8_t HITACHI_AC344_MODE_BYTE
const uint8_t HITACHI_AC344_SWINGV_BYTE
const uint16_t HITACHI_AC344_ZERO_SPACE
const uint8_t HITACHI_AC344_SWINGH_SIZE
const uint8_t HITACHI_AC344_FAN_MIN
const uint8_t HITACHI_AC344_BUTTON_POWER
uint8_t * invert_byte_pairs(uint8_t *ptr, const uint16_t length)
const uint8_t HITACHI_AC344_BUTTON_SWINGH
const uint8_t HITACHI_AC344_FAN_MAX
const uint8_t HITACHI_AC344_MODE_DRY
const uint16_t HITACHI_AC344_HDR_SPACE
const uint8_t HITACHI_AC344_FAN_MAX_DRY
const uint8_t HITACHI_AC344_MODE_FAN
void set_bits(uint8_t *const dst, const uint8_t offset, const uint8_t nbits, const uint8_t data)
const uint16_t HITACHI_AC344_FREQ
const uint8_t HITACHI_AC344_SWINGH_AUTO
const uint8_t HITACHI_AC344_BUTTON_TEMP_DOWN
const uint8_t HITACHI_AC344_MODE_AUTO
const uint8_t HITACHI_AC344_BUTTON_TEMP_UP
const uint8_t HITACHI_AC344_MODE_COOL
const uint16_t HITACHI_AC344_STATE_LENGTH
const uint8_t HITACHI_AC344_SWINGH_OFFSET
const uint8_t HITACHI_AC344_POWER_ON
const uint8_t HITACHI_AC344_TEMP_SIZE
const uint8_t HITACHI_AC344_FAN_HIGH
const uint8_t HITACHI_AC344_MODE_HEAT
const uint8_t HITACHI_AC344_FAN_BYTE
const uint16_t HITACHI_AC344_HDR_MARK
const uint8_t HITACHI_AC344_SWINGH_LEFT_MAX
const uint8_t HITACHI_AC344_TEMP_MAX
const uint8_t HITACHI_AC344_TEMP_OFFSET
const uint8_t HITACHI_AC344_FAN_LOW
const uint32_t HITACHI_AC344_MIN_GAP
const uint8_t HITACHI_AC344_FAN_MEDIUM
const uint8_t HITACHI_AC344_POWER_OFF
const uint8_t HITACHI_AC344_SWINGH_MIDDLE
const uint8_t HITACHI_AC344_POWER_BYTE
const uint8_t HITACHI_AC344_FAN_AUTO
const uint16_t HITACHI_AC344_ONE_SPACE
const uint8_t HITACHI_AC344_SWINGH_BYTE
const uint8_t HITACHI_AC344_BUTTON_SWINGV
const uint8_t HITACHI_AC344_TEMP_FAN
Providing packet encoding functions for exchanging data with a remote host.
Definition a01nyub.cpp:7
uint16_t temperature
Definition sun_gtil2.cpp:12
uint16_t length
Definition tt21100.cpp:0