ESPHome 2026.5.1
Loading...
Searching...
No Matches
emmeti.cpp
Go to the documentation of this file.
1#include "emmeti.h"
3
4namespace esphome::emmeti {
5
6static const char *const TAG = "emmeti.climate";
7
8// setters
10 return (uint8_t) roundf(clamp<float>(this->target_temperature, EMMETI_TEMP_MIN, EMMETI_TEMP_MAX) - EMMETI_TEMP_MIN);
11}
12
28
30 switch (this->fan_mode.value_or(climate::CLIMATE_FAN_ON)) {
32 return EMMETI_FAN_1;
34 return EMMETI_FAN_2;
36 return EMMETI_FAN_3;
38 default:
39 return EMMETI_FAN_AUTO;
40 }
41}
42
45 switch (this->blades_) {
46 case EMMETI_BLADES_1:
47 case EMMETI_BLADES_2:
50 break;
51 case EMMETI_BLADES_3:
54 break;
55 case EMMETI_BLADES_4:
56 case EMMETI_BLADES_5:
59 break;
60 default:
62 break;
63 }
64 } else {
65 switch (this->blades_) {
66 case EMMETI_BLADES_1:
67 case EMMETI_BLADES_2:
70 break;
71 case EMMETI_BLADES_3:
74 break;
75 case EMMETI_BLADES_4:
76 case EMMETI_BLADES_5:
79 break;
80 default:
82 break;
83 }
84 }
85 return this->blades_;
86}
87
88uint8_t EmmetiClimate::gen_checksum_() { return (this->set_temp_() + this->set_mode_() + 2) % 16; }
89
90// getters
91float EmmetiClimate::get_temp_(uint8_t temp) { return (float) (temp + EMMETI_TEMP_MIN); }
92
109
111 switch (fan_speed) {
112 case EMMETI_FAN_1:
114 case EMMETI_FAN_2:
116 case EMMETI_FAN_3:
118 case EMMETI_FAN_AUTO:
119 default:
121 }
122}
123
127
128template<typename T> T EmmetiClimate::reverse_(T val, size_t len) {
129 T result = 0;
130 for (size_t i = 0; i < len; i++) {
131 result |= ((val & 1 << i) != 0) << (len - 1 - i);
132 }
133 return result;
134}
135
136template<typename T> void EmmetiClimate::add_(T val, size_t len, esphome::remote_base::RemoteTransmitData *data) {
137 for (size_t i = len; i > 0; i--) {
138 data->mark(EMMETI_BIT_MARK);
139 data->space((val & (1 << (i - 1))) ? EMMETI_ONE_SPACE : EMMETI_ZERO_SPACE);
140 }
141}
142
144 data->mark(EMMETI_BIT_MARK);
145 data->space((val & 1) ? EMMETI_ONE_SPACE : EMMETI_ZERO_SPACE);
146}
147
148template<typename T>
150 this->add_(this->reverse_(val, len), len, data);
151}
152
154 uint8_t expected = this->gen_checksum_();
155 ESP_LOGV(TAG, "Expected checksum: %X, Checksum received: %X", expected, checksum);
156
157 return checksum == expected;
158}
159
161 auto transmit = this->transmitter_->transmit();
162 auto *data = transmit.get_data();
163 data->set_carrier_frequency(EMMETI_IR_FREQUENCY);
164
165 data->mark(EMMETI_HEADER_MARK);
166 data->space(EMMETI_HEADER_SPACE);
167
168 if (this->mode != climate::CLIMATE_MODE_OFF) {
169 this->reverse_add_(this->set_mode_(), 3, data);
170 this->add_(1, data);
171 this->reverse_add_(this->set_fan_speed_(), 2, data);
172 this->add_(this->swing_mode != climate::CLIMATE_SWING_OFF, data);
173 this->add_(0, data); // sleep mode
174 this->reverse_add_(this->set_temp_(), 4, data);
175 this->add_(0, 8, data); // zeros
176 this->add_(0, data); // turbo mode
177 this->add_(1, data); // light
178 this->add_(1, data); // tree icon thingy
179 this->add_(0, data); // blow mode
180 this->add_(0x52, 11, data); // idk
181
182 data->mark(EMMETI_BIT_MARK);
183 data->space(EMMETI_MESSAGE_SPACE);
184
185 this->reverse_add_(this->set_blades_(), 4, data);
186 this->add_(0, 4, data); // zeros
187 this->reverse_add_(2, 2, data); // thermometer
188 this->add_(0, 18, data); // zeros
189 this->reverse_add_(this->gen_checksum_(), 4, data);
190 } else {
191 this->add_(9, 12, data);
192 this->add_(0, 8, data);
193 this->add_(0x2052, 15, data);
194 data->mark(EMMETI_BIT_MARK);
195 data->space(EMMETI_MESSAGE_SPACE);
196 this->add_(0, 8, data);
197 this->add_(1, 2, data);
198 this->add_(0, 18, data);
199 this->add_(0x0C, 4, data);
200 }
201 data->mark(EMMETI_BIT_MARK);
202 data->space(0);
203
204 transmit.perform();
205}
206
208 this->mode = this->get_mode_(curr_state.mode);
209 this->fan_mode = this->get_fan_speed_(curr_state.fan_speed);
210 this->target_temperature = this->get_temp_(curr_state.temp);
211 this->swing_mode = this->get_swing_(curr_state.bitmap);
212 // this->blades_ = curr_state.fan_pos;
213 if (!(curr_state.bitmap & 0x01)) {
215 }
216
217 this->publish_state();
218 return true;
219}
220
222 if (!data.expect_item(EMMETI_HEADER_MARK, EMMETI_HEADER_SPACE)) {
223 return false;
224 }
225 ESP_LOGD(TAG, "Received emmeti frame");
226
227 EmmetiState curr_state;
228
229 for (size_t pos = 0; pos < 3; pos++) {
230 if (data.expect_item(EMMETI_BIT_MARK, EMMETI_ONE_SPACE)) {
231 curr_state.mode |= 1 << pos;
232 } else if (!data.expect_item(EMMETI_BIT_MARK, EMMETI_ZERO_SPACE)) {
233 return false;
234 }
235 }
236
237 ESP_LOGD(TAG, "Mode: %d", curr_state.mode);
238
239 if (data.expect_item(EMMETI_BIT_MARK, EMMETI_ONE_SPACE)) {
240 curr_state.bitmap |= 1 << 0;
241 } else if (!data.expect_item(EMMETI_BIT_MARK, EMMETI_ZERO_SPACE)) {
242 return false;
243 }
244
245 ESP_LOGD(TAG, "On: %d", curr_state.bitmap & 0x01);
246
247 for (size_t pos = 0; pos < 2; pos++) {
248 if (data.expect_item(EMMETI_BIT_MARK, EMMETI_ONE_SPACE)) {
249 curr_state.fan_speed |= 1 << pos;
250 } else if (!data.expect_item(EMMETI_BIT_MARK, EMMETI_ZERO_SPACE)) {
251 return false;
252 }
253 }
254
255 ESP_LOGD(TAG, "Fan speed: %d", curr_state.fan_speed);
256
257 for (size_t pos = 0; pos < 2; pos++) {
258 if (data.expect_item(EMMETI_BIT_MARK, EMMETI_ONE_SPACE)) {
259 curr_state.bitmap |= 1 << (pos + 1);
260 } else if (!data.expect_item(EMMETI_BIT_MARK, EMMETI_ZERO_SPACE)) {
261 return false;
262 }
263 }
264
265 ESP_LOGD(TAG, "Swing: %d, Sleep: %d", (curr_state.bitmap >> 1) & 0x01, (curr_state.bitmap >> 2) & 0x01);
266
267 for (size_t pos = 0; pos < 4; pos++) {
268 if (data.expect_item(EMMETI_BIT_MARK, EMMETI_ONE_SPACE)) {
269 curr_state.temp |= 1 << pos;
270 } else if (!data.expect_item(EMMETI_BIT_MARK, EMMETI_ZERO_SPACE)) {
271 return false;
272 }
273 }
274
275 ESP_LOGD(TAG, "Temp: %d", curr_state.temp);
276
277 for (size_t pos = 0; pos < 8; pos++) {
278 if (!data.expect_item(EMMETI_BIT_MARK, EMMETI_ZERO_SPACE)) {
279 return false;
280 }
281 }
282
283 for (size_t pos = 0; pos < 4; pos++) {
284 if (data.expect_item(EMMETI_BIT_MARK, EMMETI_ONE_SPACE)) {
285 curr_state.bitmap |= 1 << (pos + 3);
286 } else if (!data.expect_item(EMMETI_BIT_MARK, EMMETI_ZERO_SPACE)) {
287 return false;
288 }
289 }
290
291 ESP_LOGD(TAG, "Turbo: %d, Light: %d, Tree: %d, Blow: %d", (curr_state.bitmap >> 3) & 0x01,
292 (curr_state.bitmap >> 4) & 0x01, (curr_state.bitmap >> 5) & 0x01, (curr_state.bitmap >> 6) & 0x01);
293
294 uint16_t control_data = 0;
295 for (size_t pos = 0; pos < 11; pos++) {
296 if (data.expect_item(EMMETI_BIT_MARK, EMMETI_ONE_SPACE)) {
297 control_data |= 1 << pos;
298 } else if (!data.expect_item(EMMETI_BIT_MARK, EMMETI_ZERO_SPACE)) {
299 return false;
300 }
301 }
302
303 if (control_data != 0x250) {
304 return false;
305 }
306
307 return this->parse_state_frame_(curr_state);
308}
309
310} // namespace esphome::emmeti
BedjetMode mode
BedJet operating mode.
uint8_t checksum
Definition bl0906.h:3
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
ClimateSwingMode swing_mode
The active swing mode of the climate device.
Definition climate.h:299
void publish_state()
Publish the state of the climate device, to be called from integrations.
Definition climate.cpp:437
bool on_receive(remote_base::RemoteReceiveData data) override
Definition emmeti.cpp:221
climate::ClimateSwingMode get_swing_(uint8_t bitmap)
Definition emmeti.cpp:124
void transmit_state() override
Definition emmeti.cpp:160
void add_(T val, size_t len, esphome::remote_base::RemoteTransmitData *ata)
Definition emmeti.cpp:136
bool parse_state_frame_(EmmetiState curr_state)
Definition emmeti.cpp:207
climate::ClimateFanMode get_fan_speed_(uint8_t fan)
Definition emmeti.cpp:110
T reverse_(T val, size_t len)
Definition emmeti.cpp:128
void reverse_add_(T val, size_t len, esphome::remote_base::RemoteTransmitData *data)
Definition emmeti.cpp:149
bool check_checksum_(uint8_t checksum)
Definition emmeti.cpp:153
float get_temp_(uint8_t temp)
Definition emmeti.cpp:91
climate::ClimateMode get_mode_(uint8_t mode)
Definition emmeti.cpp:93
mopeka_std_values val[3]
ClimateSwingMode
Enum for all modes a climate swing can be in NOTE: If adding values, update ClimateSwingModeMask in c...
@ CLIMATE_SWING_OFF
The swing mode is set to Off.
@ CLIMATE_SWING_VERTICAL
The fan mode is set to Vertical.
ClimateMode
Enum for all modes a climate device can be in.
@ 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.
ClimateFanMode
NOTE: If adding values, update ClimateFanModeMask in climate_traits.h to use the new last value.
@ 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 uint32_t EMMETI_MESSAGE_SPACE
Definition emmeti.h:51
const uint32_t EMMETI_ZERO_SPACE
Definition emmeti.h:50
const uint32_t EMMETI_HEADER_MARK
Definition emmeti.h:46
@ EMMETI_MODE_HEAT_COOL
Definition emmeti.h:13
const uint32_t EMMETI_IR_FREQUENCY
Definition emmeti.h:45
const uint32_t EMMETI_HEADER_SPACE
Definition emmeti.h:47
const uint32_t EMMETI_BIT_MARK
Definition emmeti.h:48
const uint8_t EMMETI_TEMP_MAX
Definition emmeti.h:8
@ EMMETI_BLADES_FULL
Definition emmeti.h:33
@ EMMETI_BLADES_MID
Definition emmeti.h:40
@ EMMETI_BLADES_STOP
Definition emmeti.h:32
@ EMMETI_BLADES_HIGH
Definition emmeti.h:41
@ EMMETI_BLADES_LOW
Definition emmeti.h:39
const uint8_t EMMETI_TEMP_MIN
Definition emmeti.h:7
const uint32_t EMMETI_ONE_SPACE
Definition emmeti.h:49
std::string size_t len
size_t size_t pos
Definition helpers.h:1038