diff --git a/esphome/components/daikin/daikin.cpp b/esphome/components/daikin/daikin.cpp index 0701344a8b25..ea14d565f4f1 100644 --- a/esphome/components/daikin/daikin.cpp +++ b/esphome/components/daikin/daikin.cpp @@ -5,17 +5,71 @@ namespace esphome { namespace daikin { static const char *TAG = "daikin.climate"; +// TODO: Make these inputs +static bool ARC432A14 = true; +static bool comfort_mode = false; +static bool powerful_mode = false; +static bool economy_mode = false; +static const uint8_t FRAME_THREE_OFFSET = 16; +static const uint8_t HEADER_ID = 3; +static const uint8_t MESSAGE_ID = 4; +static const uint8_t COMFORT_ID = 6; +static const uint8_t SWING_VERTICAL_ID = (FRAME_THREE_OFFSET + 8); +static const uint8_t SWING_HORIZONTAL_ID = (FRAME_THREE_OFFSET + 9); +static const uint8_t TIMER_A_ID = (FRAME_THREE_OFFSET + 10); +static const uint8_t TIMER_B_ID = (FRAME_THREE_OFFSET + 11); +static const uint8_t TIMER_C_ID = (FRAME_THREE_OFFSET + 12); +static const uint8_t POWERFUL_ID = (FRAME_THREE_OFFSET + 13); +static const uint8_t ECONOMY_ID = (FRAME_THREE_OFFSET + 16); void DaikinClimate::transmit_state() { - uint8_t remote_state[35] = {0x11, 0xDA, 0x27, 0x00, 0xC5, 0x00, 0x00, 0xD7, 0x11, 0xDA, 0x27, 0x00, + uint8_t remote_state[35] = {0x11, 0xDA, 0x27, 0x00, 0xC5, 0x00, 0x00, 0x00, 0x11, 0xDA, 0x27, 0x00, 0x42, 0x49, 0x05, 0xA2, 0x11, 0xDA, 0x27, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x06, 0x60, 0x00, 0x00, 0xC0, 0x00, 0x00, 0x00}; + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xC0, 0x00, 0x00, 0x00}; + // Original author's setting. Untested. + if (!ARC432A14) { + remote_state[27] = 0x06; + remote_state[28] = 0x60; + } + + // Frame #1 + if (ARC432A14) { + remote_state[HEADER_ID] = 0xF0; + remote_state[MESSAGE_ID] = 0x00; + } + if (comfort_mode) { + remote_state[COMFORT_ID] = 0x10; + } + // Calculate checksum + for (int i = 0; i < 7; i++) { + remote_state[7] += remote_state[i]; + } + + // Calculations frame #3 + if (this->swing_mode == climate::CLIMATE_SWING_HORIZONTAL) { + remote_state[SWING_HORIZONTAL_ID] |= 0xF0; + } + // FUTURE: +#if 0 + if (this->swing_mode == climate::CLIMATE_SWING_WIDE) + { + remote_state[SWING_HORIZONTAL_ID] &= 0x0F; + remote_state[SWING_HORIZONTAL_ID] |= 0xE0; + } +#endif remote_state[21] = this->operation_mode_(); remote_state[22] = this->temperature_(); + // Vertical swing covered in fan speed. uint16_t fan_speed = this->fan_speed_(); remote_state[24] = fan_speed >> 8; remote_state[25] = fan_speed & 0xff; + if (powerful_mode) { + remote_state[POWERFUL_ID] = 0x01; + } + if (economy_mode) { + remote_state[ECONOMY_ID] |= 0x04; + } // Calculate checksum for (int i = 16; i < 34; i++) { @@ -40,17 +94,20 @@ void DaikinClimate::transmit_state() { data->mark(DAIKIN_HEADER_MARK); data->space(DAIKIN_HEADER_SPACE); - for (int i = 8; i < 16; i++) { - for (uint8_t mask = 1; mask > 0; mask <<= 1) { // iterate through bit mask - data->mark(DAIKIN_BIT_MARK); - bool bit = remote_state[i] & mask; - data->space(bit ? DAIKIN_ONE_SPACE : DAIKIN_ZERO_SPACE); + // Second frame not necessary for ARC432A14 + if (!ARC432A14) { + for (int i = 8; i < 16; i++) { + for (uint8_t mask = 1; mask > 0; mask <<= 1) { // iterate through bit mask + data->mark(DAIKIN_BIT_MARK); + bool bit = remote_state[i] & mask; + data->space(bit ? DAIKIN_ONE_SPACE : DAIKIN_ZERO_SPACE); + } } + data->mark(DAIKIN_BIT_MARK); + data->space(DAIKIN_MESSAGE_SPACE); + data->mark(DAIKIN_HEADER_MARK); + data->space(DAIKIN_HEADER_SPACE); } - data->mark(DAIKIN_BIT_MARK); - data->space(DAIKIN_MESSAGE_SPACE); - data->mark(DAIKIN_HEADER_MARK); - data->space(DAIKIN_HEADER_SPACE); for (int i = 16; i < 35; i++) { for (uint8_t mask = 1; mask > 0; mask <<= 1) { // iterate through bit mask @@ -104,6 +161,9 @@ uint16_t DaikinClimate::fan_speed_() { case climate::CLIMATE_FAN_HIGH: fan_speed = DAIKIN_FAN_5 << 8; break; + case climate::CLIMATE_FAN_FOCUS: + fan_speed = DAIKIN_FAN_SILENT; + break; case climate::CLIMATE_FAN_AUTO: default: fan_speed = DAIKIN_FAN_AUTO << 8; diff --git a/esphome/components/daikin/daikin.h b/esphome/components/daikin/daikin.h index c0a472bce766..4478d7f78806 100644 --- a/esphome/components/daikin/daikin.h +++ b/esphome/components/daikin/daikin.h @@ -36,6 +36,7 @@ const uint32_t DAIKIN_BIT_MARK = 520; const uint32_t DAIKIN_ONE_SPACE = 1370; const uint32_t DAIKIN_ZERO_SPACE = 360; const uint32_t DAIKIN_MESSAGE_SPACE = 32300; +const uint32_t DAIKIN_MESSAGE_SHORT_SPACE = 25000; // State Frame size const uint8_t DAIKIN_STATE_FRAME_SIZE = 19; @@ -46,9 +47,10 @@ class DaikinClimate : public climate_ir::ClimateIR { : climate_ir::ClimateIR( DAIKIN_TEMP_MIN, DAIKIN_TEMP_MAX, 1.0f, true, true, std::vector{climate::CLIMATE_FAN_AUTO, climate::CLIMATE_FAN_LOW, - climate::CLIMATE_FAN_MEDIUM, climate::CLIMATE_FAN_HIGH}, - std::vector{climate::CLIMATE_SWING_OFF, climate::CLIMATE_SWING_VERTICAL, - climate::CLIMATE_SWING_HORIZONTAL, climate::CLIMATE_SWING_BOTH}) {} + climate::CLIMATE_FAN_MEDIUM, climate::CLIMATE_FAN_HIGH, + climate::CLIMATE_FAN_FOCUS}, + std::vector{climate::CLIMATE_SWING_OFF, climate::CLIMATE_SWING_HORIZONTAL, + climate::CLIMATE_SWING_VERTICAL}) {} protected: // Transmit via IR the state of this climate controller.