ESPHome 2026.5.0
Loading...
Searching...
No Matches
whynter.cpp
Go to the documentation of this file.
1#include "whynter.h"
2#include "esphome/core/log.h"
3
4namespace esphome::whynter {
5
6static const char *const TAG = "climate.whynter";
7
8const uint16_t BITS = 32;
9
10// Static First Byte
11const uint32_t COMMAND_MASK = 0xFF << 24;
12const uint32_t COMMAND_CODE = 0x12 << 24;
13
14// Power
18
19// Mode
21const uint32_t MODE_MASK = 0b1111 << MODE_SHIFT;
22const uint32_t MODE_FAN = 0b0001 << MODE_SHIFT;
23const uint32_t MODE_DRY = 0b0010 << MODE_SHIFT;
24const uint32_t MODE_HEAT = 0b0100 << MODE_SHIFT;
25const uint32_t MODE_COOL = 0b1000 << MODE_SHIFT;
26
27// Fan Speed
29const uint32_t FAN_MASK = 0b111 << FAN_SHIFT;
30const uint32_t FAN_HIGH = 0b001 << FAN_SHIFT;
31const uint32_t FAN_MED = 0b010 << FAN_SHIFT;
32const uint32_t FAN_LOW = 0b100 << FAN_SHIFT;
33
34// Temperature Unit
37
38// Temperature Value
39const uint32_t TEMP_MASK = 0xFF;
41
43 uint32_t remote_state = COMMAND_CODE;
46 switch (this->mode) {
48 remote_state |= POWER_MASK;
49 remote_state |= MODE_FAN;
50 break;
52 remote_state |= POWER_MASK;
53 remote_state |= MODE_DRY;
54 break;
56 remote_state |= POWER_MASK;
57 remote_state |= MODE_HEAT;
58 break;
60 remote_state |= POWER_MASK;
61 remote_state |= MODE_COOL;
62 break;
64 remote_state |= POWER_OFF;
65 break;
66 default:
67 remote_state |= POWER_OFF;
68 }
69 mode_before_ = this->mode;
70
71 switch (this->fan_mode.value_or(climate::CLIMATE_FAN_ON)) {
73 remote_state |= FAN_LOW;
74 break;
76 remote_state |= FAN_MED;
77 break;
79 remote_state |= FAN_HIGH;
80 break;
81 default:
82 remote_state |= FAN_HIGH;
83 }
84
85 if (fahrenheit_) {
86 remote_state |= UNIT_MASK;
87 uint8_t temp =
89 temp = esphome::reverse_bits(temp);
90 remote_state |= temp;
91 } else {
92 uint8_t temp = (uint8_t) roundf(clamp<float>(this->target_temperature, TEMP_MIN_C, TEMP_MAX_C) - TEMP_OFFSET_C);
93 temp = esphome::reverse_bits(temp);
94 remote_state |= temp;
95 }
96
97 transmit_(remote_state);
98 this->publish_state();
99}
100
102 uint8_t nbits = 0;
103 uint32_t remote_state = 0;
104
105 if (!data.expect_item(this->header_high_, this->header_low_))
106 return false;
107
108 for (nbits = 0; nbits < 32; nbits++) {
109 if (data.expect_item(this->bit_high_, this->bit_one_low_)) {
110 remote_state = (remote_state << 1) | 1;
111 } else if (data.expect_item(this->bit_high_, this->bit_zero_low_)) {
112 remote_state = (remote_state << 1) | 0;
113 } else if (nbits == BITS) {
114 break;
115 } else {
116 return false;
117 }
118 }
119
120 ESP_LOGD(TAG, "Decoded 0x%02" PRIX32, remote_state);
121 if ((remote_state & COMMAND_MASK) != COMMAND_CODE)
122 return false;
123 if ((remote_state & POWER_MASK) != POWER_MASK) {
125 } else {
126 if ((remote_state & MODE_MASK) == MODE_FAN) {
128 } else if ((remote_state & MODE_MASK) == MODE_DRY) {
130 } else if ((remote_state & MODE_MASK) == MODE_HEAT) {
132 } else if ((remote_state & MODE_MASK) == MODE_COOL) {
134 }
135
136 // Temperature
137 if ((remote_state & UNIT_MASK) == UNIT_MASK) { // Fahrenheit
139 } else { // Celsius
140 this->target_temperature = (esphome::reverse_bits(remote_state & TEMP_MASK) >> 24) + TEMP_OFFSET_C;
141 }
142
143 // Fan Speed
144 if ((remote_state & FAN_MASK) == FAN_LOW) {
146 } else if ((remote_state & FAN_MASK) == FAN_MED) {
148 } else if ((remote_state & FAN_MASK) == FAN_HIGH) {
150 }
151 }
152 this->publish_state();
153
154 return true;
155}
156
158 ESP_LOGD(TAG, "Sending Whynter code: 0x%02" PRIX32, value);
159
160 auto transmit = this->transmitter_->transmit();
161 auto *data = transmit.get_data();
162
163 data->set_carrier_frequency(38000);
164 data->reserve(2 + BITS * 2u);
165
166 data->item(this->header_high_, this->header_low_);
167
168 for (uint32_t mask = 1UL << (BITS - 1); mask != 0; mask >>= 1) {
169 if (value & mask) {
170 data->item(this->bit_high_, this->bit_one_low_);
171 } else {
172 data->item(this->bit_high_, this->bit_zero_low_);
173 }
174 }
175 data->mark(this->bit_high_);
176 transmit.perform();
177}
178
179} // namespace esphome::whynter
ClimateMode mode
The active mode of the climate device.
Definition climate.h:293
optional< ClimateFanMode > fan_mode
The active fan mode of the climate device.
Definition climate.h:287
float target_temperature
The target temperature of the climate device.
Definition climate.h:274
void publish_state()
Publish the state of the climate device, to be called from integrations.
Definition climate.cpp:437
void transmit_(uint32_t value)
Definition whynter.cpp:157
bool on_receive(remote_base::RemoteReceiveData data) override
Handle received IR Buffer.
Definition whynter.cpp:101
climate::ClimateMode mode_before_
Definition whynter.h:48
void transmit_state() override
Transmit via IR the state of this climate controller.
Definition whynter.cpp:42
@ 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_LOW
The fan mode is set to Low.
@ CLIMATE_FAN_HIGH
The fan mode is set to High.
const uint32_t UNIT_MASK
Definition whynter.cpp:36
const uint32_t COMMAND_CODE
Definition whynter.cpp:12
const uint32_t UNIT_SHIFT
Definition whynter.cpp:35
const uint8_t TEMP_MAX_C
Definition whynter.h:11
const uint8_t TEMP_MAX_F
Definition whynter.h:13
const uint32_t MODE_COOL
Definition whynter.cpp:25
const uint32_t POWER_MASK
Definition whynter.cpp:16
const uint32_t MODE_FAN
Definition whynter.cpp:22
const uint32_t FAN_MASK
Definition whynter.cpp:29
const uint32_t TEMP_MASK
Definition whynter.cpp:39
const uint8_t TEMP_MIN_F
Definition whynter.h:12
const uint32_t COMMAND_MASK
Definition whynter.cpp:11
const uint8_t TEMP_MIN_C
Definition whynter.h:10
const uint16_t BITS
Definition whynter.cpp:8
const uint32_t FAN_HIGH
Definition whynter.cpp:30
const uint32_t POWER_OFF
Definition whynter.cpp:17
const uint32_t FAN_SHIFT
Definition whynter.cpp:28
const uint32_t FAN_MED
Definition whynter.cpp:31
const uint32_t TEMP_OFFSET_C
Definition whynter.cpp:40
const uint32_t MODE_SHIFT
Definition whynter.cpp:20
const uint32_t FAN_LOW
Definition whynter.cpp:32
const uint32_t POWER_SHIFT
Definition whynter.cpp:15
const uint32_t MODE_DRY
Definition whynter.cpp:23
const uint32_t MODE_HEAT
Definition whynter.cpp:24
const uint32_t MODE_MASK
Definition whynter.cpp:21
constexpr float celsius_to_fahrenheit(float value)
Convert degrees Celsius to degrees Fahrenheit.
Definition helpers.h:1610
constexpr float fahrenheit_to_celsius(float value)
Convert degrees Fahrenheit to degrees Celsius.
Definition helpers.h:1612
uint8_t reverse_bits(uint8_t x)
Reverse the order of 8 bits.
Definition helpers.h:898
static void uint32_t