ESPHome 2026.11.0-dev
Loading...
Searching...
No Matches
gree.cpp
Go to the documentation of this file.
1#include "gree.h"
4
5namespace esphome::gree {
6
7ESPHOME_LOG_TAG(TAG, "gree.climate");
8
10 if (model == GREE_YAN) {
11 // YAN only has a vertical vane; the horizontal swing IR bytes are not defined for this model.
14 }
15 if (model == GREE_YX1FF) {
16 this->fan_modes_.insert(climate::CLIMATE_FAN_QUIET); // YX1FF 4 speed
17 }
18 // Models with a sleep preset
19 if (model == GREE_YX1FF || model == GREE_YAC1FB9) {
22 }
23
24 this->model_ = model;
25}
26
27void GreeClimate::set_mode_bit(uint8_t bit_mask, bool enabled) {
28 assign_bits(this->mode_bits_, bit_mask, enabled);
29 this->transmit_state();
30}
31
33 uint8_t remote_state[8] = {0x00, 0x00, 0x00, 0x00, 0x00, 0x20, 0x00, 0x00};
34 const Model model = this->model_;
35
36 remote_state[0] = this->fan_speed_() | this->operation_mode_();
37 remote_state[1] = this->temperature_();
38
39 if (model == GREE_YAN) {
40 remote_state[3] = 0x50; // bits 4..7 always 0101
41 remote_state[4] = this->vertical_swing_();
42 }
43
44 if (model == GREE_YX1FF || model == GREE_YAG) {
45 remote_state[2] = 0x60;
46 remote_state[3] = 0x50;
47 remote_state[4] = this->vertical_swing_();
48 }
49
50 if (model == GREE_YAG) {
51 remote_state[5] = 0x40;
52
53 if (this->vertical_swing_() == GREE_VDIR_SWING || this->horizontal_swing_() == GREE_HDIR_SWING) {
54 remote_state[0] |= (1 << 6);
55 }
56 }
57
58 if (model == GREE_YAC || model == GREE_YAG) {
59 remote_state[4] |= (this->horizontal_swing_() << 4);
60 }
61
62 if (model == GREE_YAA || model == GREE_YAC || model == GREE_YAC1FB9) {
63 remote_state[3] = 0x50; // bits 4..7 always 0101
64 remote_state[6] = 0x20; // YAA1FB, FAA1FB1, YB1F2 bits 4..7 always 0010
65
66 if (this->vertical_swing_() == GREE_VDIR_SWING) {
67 remote_state[0] |= (1 << 6); // Enable swing by setting bit 6
68 } else if (this->vertical_swing_() != GREE_VDIR_AUTO) {
69 remote_state[5] = this->vertical_swing_();
70 }
71 }
72
73 if (model == GREE_YAN || model == GREE_YAA || model == GREE_YAC || model == GREE_YAC1FB9) {
74 // Merge the mode bits into remote_state[2]
75 // Clear the mode bits (bits 4-7) and OR in the current mode_bits_
76 remote_state[2] = (remote_state[2] & 0x0F) | this->mode_bits_;
77 }
78
79 if (model == GREE_YX1FF) {
80 if (this->fan_speed_() == GREE_FAN_TURBO) {
81 remote_state[2] |= GREE_FAN_TURBO_BIT;
82 }
83 }
84
85 if (this->preset_() == GREE_PRESET_SLEEP) {
86 remote_state[0] |= GREE_PRESET_SLEEP_BIT;
87 }
88
89 // Calculate the checksum
90 if (model == GREE_YAN || model == GREE_YX1FF) {
91 remote_state[7] = ((remote_state[0] << 4) + (remote_state[1] << 4) + 0xC0);
92 } else {
93 remote_state[7] =
94 ((((remote_state[0] & 0x0F) + (remote_state[1] & 0x0F) + (remote_state[2] & 0x0F) + (remote_state[3] & 0x0F) +
95 ((remote_state[4] & 0xF0) >> 4) + ((remote_state[5] & 0xF0) >> 4) + ((remote_state[6] & 0xF0) >> 4) + 0x0A) &
96 0x0F)
97 << 4);
98 }
99
100 auto transmit = this->transmitter_->transmit();
101 auto *data = transmit.get_data();
102 data->set_carrier_frequency(GREE_IR_FREQUENCY);
103
104 data->mark(GREE_HEADER_MARK);
105 if (model == GREE_YAC1FB9) {
106 data->space(GREE_YAC1FB9_HEADER_SPACE);
107 } else {
108 data->space(GREE_HEADER_SPACE);
109 }
110
111 for (int i = 0; i < 4; i++) {
112 for (uint8_t mask = 1; mask > 0; mask <<= 1) { // iterate through bit mask
113 data->mark(GREE_BIT_MARK);
114 bool bit = remote_state[i] & mask;
115 data->space(bit ? GREE_ONE_SPACE : GREE_ZERO_SPACE);
116 }
117 }
118
119 data->mark(GREE_BIT_MARK);
120 data->space(GREE_ZERO_SPACE);
121 data->mark(GREE_BIT_MARK);
122 data->space(GREE_ONE_SPACE);
123 data->mark(GREE_BIT_MARK);
124 data->space(GREE_ZERO_SPACE);
125
126 data->mark(GREE_BIT_MARK);
127 if (model == GREE_YAC1FB9) {
128 data->space(GREE_YAC1FB9_MESSAGE_SPACE);
129 } else {
130 data->space(GREE_MESSAGE_SPACE);
131 }
132
133 for (int i = 4; i < 8; i++) {
134 for (uint8_t mask = 1; mask > 0; mask <<= 1) { // iterate through bit mask
135 data->mark(GREE_BIT_MARK);
136 bool bit = remote_state[i] & mask;
137 data->space(bit ? GREE_ONE_SPACE : GREE_ZERO_SPACE);
138 }
139 }
140
141 data->mark(GREE_BIT_MARK);
142 data->space(0);
143
144 transmit.perform();
145}
146
148 uint8_t operating_mode = GREE_MODE_ON;
149
150 switch (this->mode) {
152 operating_mode |= GREE_MODE_COOL;
153 break;
155 operating_mode |= GREE_MODE_DRY;
156 break;
158 operating_mode |= GREE_MODE_HEAT;
159 break;
161 operating_mode |= GREE_MODE_AUTO;
162 break;
164 operating_mode |= GREE_MODE_FAN;
165 break;
167 default:
168 operating_mode = GREE_MODE_OFF;
169 break;
170 }
171
172 return operating_mode;
173}
174
176 // YX1FF has 4 fan speeds -- we treat low as quiet and turbo as high
177 if (this->model_ == GREE_YX1FF) {
178 switch (this->fan_mode.value_or(climate::CLIMATE_FAN_ON)) {
180 return GREE_FAN_1;
182 return GREE_FAN_2;
184 return GREE_FAN_3;
186 return GREE_FAN_TURBO;
188 default:
189 return GREE_FAN_AUTO;
190 }
191 }
192
193 switch (this->fan_mode.value_or(climate::CLIMATE_FAN_ON)) {
195 return GREE_FAN_1;
197 return GREE_FAN_2;
199 return GREE_FAN_3;
201 default:
202 return GREE_FAN_AUTO;
203 }
204}
205
207 switch (this->swing_mode) {
210 return GREE_HDIR_SWING;
211 default:
212 return GREE_HDIR_MANUAL;
213 }
214}
215
217 switch (this->swing_mode) {
220 return GREE_VDIR_SWING;
221 default:
222 return GREE_VDIR_MANUAL;
223 }
224}
225
227 return (uint8_t) roundf(clamp<float>(this->target_temperature, GREE_TEMP_MIN, GREE_TEMP_MAX)) - GREE_TEMP_MIN;
228}
229
231 // YX1FF and YAC1FB9 have sleep preset
232 if (this->model_ == GREE_YX1FF || this->model_ == GREE_YAC1FB9) {
233 switch (this->preset.value_or(climate::CLIMATE_PRESET_NONE)) {
235 return GREE_PRESET_NONE;
237 return GREE_PRESET_SLEEP;
238 default:
239 return GREE_PRESET_NONE;
240 }
241 }
242
243 return GREE_PRESET_NONE;
244}
245
246} // namespace esphome::gree
constexpr void insert(ValueType value)
Add a single value to the set (std::set compatibility)
constexpr void erase(ValueType value)
Remove a value from the set (std::set compatibility)
ClimateMode mode
The active mode of the climate device.
Definition climate.h:317
optional< ClimateFanMode > fan_mode
The active fan mode of the climate device.
Definition climate.h:311
float target_temperature
The target temperature of the climate device.
Definition climate.h:298
ClimateSwingMode swing_mode
The active swing mode of the climate device.
Definition climate.h:323
optional< ClimatePreset > preset
The active preset of the climate device.
Definition climate.h:314
climate::ClimatePresetMask presets_
Definition climate_ir.h:84
climate::ClimateFanModeMask fan_modes_
Definition climate_ir.h:82
climate::ClimateSwingModeMask swing_modes_
Definition climate_ir.h:83
void set_mode_bit(uint8_t bit_mask, bool enabled)
Definition gree.cpp:27
void set_model(Model model)
Definition gree.cpp:9
uint8_t horizontal_swing_()
Definition gree.cpp:206
void transmit_state() override
Definition gree.cpp:32
@ CLIMATE_PRESET_NONE
No preset is active.
@ CLIMATE_PRESET_SLEEP
Device is prepared for sleep.
@ 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_QUIET
The fan mode is set to Quiet.
@ CLIMATE_FAN_HIGH
The fan mode is set to High.
@ GREE_YAC1FB9
Definition gree.h:89
@ GREE_YX1FF
Definition gree.h:89
ESPHOME_LOG_TAG(TAG, "gree.climate")
ESPHOME_ALWAYS_INLINE constexpr void assign_bits(T &value, std::type_identity_t< T > mask, bool on)
Set the bits of mask in value when on is true, clear them otherwise.
Definition helpers.h:1072