ESPHome 2025.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 {
5namespace whynter {
6
7static const char *const TAG = "climate.whynter";
8
9const uint16_t BITS = 32;
10
11// Static First Byte
12const uint32_t COMMAND_MASK = 0xFF << 24;
13const uint32_t COMMAND_CODE = 0x12 << 24;
14
15// Power
16const uint32_t POWER_SHIFT = 8;
17const uint32_t POWER_MASK = 1 << POWER_SHIFT;
18const uint32_t POWER_OFF = 0 << POWER_SHIFT;
19
20// Mode
21const uint32_t MODE_SHIFT = 16;
22const uint32_t MODE_MASK = 0b1111 << MODE_SHIFT;
23const uint32_t MODE_FAN = 0b0001 << MODE_SHIFT;
24const uint32_t MODE_DRY = 0b0010 << MODE_SHIFT;
25const uint32_t MODE_HEAT = 0b0100 << MODE_SHIFT;
26const uint32_t MODE_COOL = 0b1000 << MODE_SHIFT;
27
28// Fan Speed
29const uint32_t FAN_SHIFT = 20;
30const uint32_t FAN_MASK = 0b111 << FAN_SHIFT;
31const uint32_t FAN_HIGH = 0b001 << FAN_SHIFT;
32const uint32_t FAN_MED = 0b010 << FAN_SHIFT;
33const uint32_t FAN_LOW = 0b100 << FAN_SHIFT;
34
35// Temperature Unit
36const uint32_t UNIT_SHIFT = 10;
37const uint32_t UNIT_MASK = 1 << UNIT_SHIFT;
38
39// Temperature Value
40const uint32_t TEMP_MASK = 0xFF;
41const uint32_t TEMP_OFFSET_C = 16;
42
44 uint32_t remote_state = COMMAND_CODE;
47 switch (this->mode) {
49 remote_state |= POWER_MASK;
50 remote_state |= MODE_FAN;
51 break;
53 remote_state |= POWER_MASK;
54 remote_state |= MODE_DRY;
55 break;
57 remote_state |= POWER_MASK;
58 remote_state |= MODE_HEAT;
59 break;
61 remote_state |= POWER_MASK;
62 remote_state |= MODE_COOL;
63 break;
65 remote_state |= POWER_OFF;
66 break;
67 default:
68 remote_state |= POWER_OFF;
69 }
70 mode_before_ = this->mode;
71
72 switch (this->fan_mode.value()) {
74 remote_state |= FAN_LOW;
75 break;
77 remote_state |= FAN_MED;
78 break;
80 remote_state |= FAN_HIGH;
81 break;
82 default:
83 remote_state |= FAN_HIGH;
84 }
85
86 if (fahrenheit_) {
87 remote_state |= UNIT_MASK;
88 uint8_t temp =
90 temp = esphome::reverse_bits(temp);
91 remote_state |= temp;
92 } else {
93 uint8_t temp = (uint8_t) roundf(clamp<float>(this->target_temperature, TEMP_MIN_C, TEMP_MAX_C) - TEMP_OFFSET_C);
94 temp = esphome::reverse_bits(temp);
95 remote_state |= temp;
96 }
97
98 transmit_(remote_state);
99 this->publish_state();
100}
101
103 uint8_t nbits = 0;
104 uint32_t remote_state = 0;
105
106 if (!data.expect_item(this->header_high_, this->header_low_))
107 return false;
108
109 for (nbits = 0; nbits < 32; nbits++) {
110 if (data.expect_item(this->bit_high_, this->bit_one_low_)) {
111 remote_state = (remote_state << 1) | 1;
112 } else if (data.expect_item(this->bit_high_, this->bit_zero_low_)) {
113 remote_state = (remote_state << 1) | 0;
114 } else if (nbits == BITS) {
115 break;
116 } else {
117 return false;
118 }
119 }
120
121 ESP_LOGD(TAG, "Decoded 0x%02" PRIX32, remote_state);
122 if ((remote_state & COMMAND_MASK) != COMMAND_CODE)
123 return false;
124 if ((remote_state & POWER_MASK) != POWER_MASK) {
126 } else {
127 if ((remote_state & MODE_MASK) == MODE_FAN) {
129 } else if ((remote_state & MODE_MASK) == MODE_DRY) {
131 } else if ((remote_state & MODE_MASK) == MODE_HEAT) {
133 } else if ((remote_state & MODE_MASK) == MODE_COOL) {
135 }
136
137 // Temperature
138 if ((remote_state & UNIT_MASK) == UNIT_MASK) { // Fahrenheit
140 } else { // Celsius
141 this->target_temperature = (esphome::reverse_bits(remote_state & TEMP_MASK) >> 24) + TEMP_OFFSET_C;
142 }
143
144 // Fan Speed
145 if ((remote_state & FAN_MASK) == FAN_LOW) {
147 } else if ((remote_state & FAN_MASK) == FAN_MED) {
149 } else if ((remote_state & FAN_MASK) == FAN_HIGH) {
151 }
152 }
153 this->publish_state();
154
155 return true;
156}
157
158void Whynter::transmit_(uint32_t value) {
159 ESP_LOGD(TAG, "Sending Whynter code: 0x%02" PRIX32, value);
160
161 auto transmit = this->transmitter_->transmit();
162 auto *data = transmit.get_data();
163
164 data->set_carrier_frequency(38000);
165 data->reserve(2 + BITS * 2u);
166
167 data->item(this->header_high_, this->header_low_);
168
169 for (uint32_t mask = 1UL << (BITS - 1); mask != 0; mask >>= 1) {
170 if (value & mask) {
171 data->item(this->bit_high_, this->bit_one_low_);
172 } else {
173 data->item(this->bit_high_, this->bit_zero_low_);
174 }
175 }
176 data->mark(this->bit_high_);
177 transmit.perform();
178}
179
180} // namespace whynter
181} // namespace esphome
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
void publish_state()
Publish the state of the climate device, to be called from integrations.
Definition climate.cpp:395
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
void transmit_(uint32_t value)
Definition whynter.cpp:158
bool on_receive(remote_base::RemoteReceiveData data) override
Handle received IR Buffer.
Definition whynter.cpp:102
climate::ClimateMode mode_before_
Definition whynter.h:49
void transmit_state() override
Transmit via IR the state of this climate controller.
Definition whynter.cpp:43
@ 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_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:37
const uint32_t COMMAND_CODE
Definition whynter.cpp:13
const uint32_t UNIT_SHIFT
Definition whynter.cpp:36
const uint8_t TEMP_MAX_C
Definition whynter.h:12
const uint8_t TEMP_MAX_F
Definition whynter.h:14
const uint32_t MODE_COOL
Definition whynter.cpp:26
const uint32_t POWER_MASK
Definition whynter.cpp:17
const uint32_t MODE_FAN
Definition whynter.cpp:23
const uint32_t FAN_MASK
Definition whynter.cpp:30
const uint32_t TEMP_MASK
Definition whynter.cpp:40
const uint8_t TEMP_MIN_F
Definition whynter.h:13
const uint32_t COMMAND_MASK
Definition whynter.cpp:12
const uint8_t TEMP_MIN_C
Definition whynter.h:11
const uint16_t BITS
Definition whynter.cpp:9
const uint32_t FAN_HIGH
Definition whynter.cpp:31
const uint32_t POWER_OFF
Definition whynter.cpp:18
const uint32_t FAN_SHIFT
Definition whynter.cpp:29
const uint32_t FAN_MED
Definition whynter.cpp:32
const uint32_t TEMP_OFFSET_C
Definition whynter.cpp:41
const uint32_t MODE_SHIFT
Definition whynter.cpp:21
const uint32_t FAN_LOW
Definition whynter.cpp:33
const uint32_t POWER_SHIFT
Definition whynter.cpp:16
const uint32_t MODE_DRY
Definition whynter.cpp:24
const uint32_t MODE_HEAT
Definition whynter.cpp:25
const uint32_t MODE_MASK
Definition whynter.cpp:22
Providing packet encoding functions for exchanging data with a remote host.
Definition a01nyub.cpp:7
constexpr float celsius_to_fahrenheit(float value)
Convert degrees Celsius to degrees Fahrenheit.
Definition helpers.h:482
constexpr float fahrenheit_to_celsius(float value)
Convert degrees Fahrenheit to degrees Celsius.
Definition helpers.h:484
uint8_t reverse_bits(uint8_t x)
Reverse the order of 8 bits.
Definition helpers.h:231