ESPHome  2024.5.0
emmeti.cpp
Go to the documentation of this file.
1 #include "emmeti.h"
3 
4 namespace esphome {
5 namespace emmeti {
6 
7 static const char *const TAG = "emmeti.climate";
8 
9 // setters
11  return (uint8_t) roundf(clamp<float>(this->target_temperature, EMMETI_TEMP_MIN, EMMETI_TEMP_MAX) - EMMETI_TEMP_MIN);
12 }
13 
15  switch (this->mode) {
17  return EMMETI_MODE_COOL;
19  return EMMETI_MODE_DRY;
21  return EMMETI_MODE_HEAT;
23  return EMMETI_MODE_FAN;
25  default:
26  return EMMETI_MODE_HEAT_COOL;
27  }
28 }
29 
31  switch (this->fan_mode.value()) {
33  return EMMETI_FAN_1;
35  return EMMETI_FAN_2;
37  return EMMETI_FAN_3;
39  default:
40  return EMMETI_FAN_AUTO;
41  }
42 }
43 
46  switch (this->blades_) {
47  case EMMETI_BLADES_1:
48  case EMMETI_BLADES_2:
49  case EMMETI_BLADES_HIGH:
51  break;
52  case EMMETI_BLADES_3:
53  case EMMETI_BLADES_MID:
54  this->blades_ = EMMETI_BLADES_MID;
55  break;
56  case EMMETI_BLADES_4:
57  case EMMETI_BLADES_5:
58  case EMMETI_BLADES_LOW:
59  this->blades_ = EMMETI_BLADES_LOW;
60  break;
61  default:
63  break;
64  }
65  } else {
66  switch (this->blades_) {
67  case EMMETI_BLADES_1:
68  case EMMETI_BLADES_2:
69  case EMMETI_BLADES_HIGH:
70  this->blades_ = EMMETI_BLADES_1;
71  break;
72  case EMMETI_BLADES_3:
73  case EMMETI_BLADES_MID:
74  this->blades_ = EMMETI_BLADES_3;
75  break;
76  case EMMETI_BLADES_4:
77  case EMMETI_BLADES_5:
78  case EMMETI_BLADES_LOW:
79  this->blades_ = EMMETI_BLADES_5;
80  break;
81  default:
83  break;
84  }
85  }
86  return this->blades_;
87 }
88 
89 uint8_t EmmetiClimate::gen_checksum_() { return (this->set_temp_() + this->set_mode_() + 2) % 16; }
90 
91 // getters
92 float EmmetiClimate::get_temp_(uint8_t temp) { return (float) (temp + EMMETI_TEMP_MIN); }
93 
95  switch (mode) {
96  case EMMETI_MODE_COOL:
98  case EMMETI_MODE_DRY:
100  case EMMETI_MODE_HEAT:
104  case EMMETI_MODE_FAN:
106  default:
108  }
109 }
110 
112  switch (fan_speed) {
113  case EMMETI_FAN_1:
115  case EMMETI_FAN_2:
117  case EMMETI_FAN_3:
119  case EMMETI_FAN_AUTO:
120  default:
122  }
123 }
124 
126  return (bitmap >> 1) & 0x01 ? climate::CLIMATE_SWING_VERTICAL : climate::CLIMATE_SWING_OFF;
127 }
128 
129 template<typename T> T EmmetiClimate::reverse_(T val, size_t len) {
130  T result = 0;
131  for (size_t i = 0; i < len; i++) {
132  result |= ((val & 1 << i) != 0) << (len - 1 - i);
133  }
134  return result;
135 }
136 
137 template<typename T> void EmmetiClimate::add_(T val, size_t len, esphome::remote_base::RemoteTransmitData *data) {
138  for (size_t i = len; i > 0; i--) {
139  data->mark(EMMETI_BIT_MARK);
140  data->space((val & (1 << (i - 1))) ? EMMETI_ONE_SPACE : EMMETI_ZERO_SPACE);
141  }
142 }
143 
145  data->mark(EMMETI_BIT_MARK);
146  data->space((val & 1) ? EMMETI_ONE_SPACE : EMMETI_ZERO_SPACE);
147 }
148 
149 template<typename T>
151  this->add_(this->reverse_(val, len), len, data);
152 }
153 
155  uint8_t expected = this->gen_checksum_();
156  ESP_LOGV(TAG, "Expected checksum: %X", expected);
157  ESP_LOGV(TAG, "Checksum received: %X", checksum);
158 
159  return checksum == expected;
160 }
161 
163  auto transmit = this->transmitter_->transmit();
164  auto *data = transmit.get_data();
166 
167  data->mark(EMMETI_HEADER_MARK);
168  data->space(EMMETI_HEADER_SPACE);
169 
170  if (this->mode != climate::CLIMATE_MODE_OFF) {
171  this->reverse_add_(this->set_mode_(), 3, data);
172  this->add_(1, data);
173  this->reverse_add_(this->set_fan_speed_(), 2, data);
174  this->add_(this->swing_mode != climate::CLIMATE_SWING_OFF, data);
175  this->add_(0, data); // sleep mode
176  this->reverse_add_(this->set_temp_(), 4, data);
177  this->add_(0, 8, data); // zeros
178  this->add_(0, data); // turbo mode
179  this->add_(1, data); // light
180  this->add_(1, data); // tree icon thingy
181  this->add_(0, data); // blow mode
182  this->add_(0x52, 11, data); // idk
183 
184  data->mark(EMMETI_BIT_MARK);
185  data->space(EMMETI_MESSAGE_SPACE);
186 
187  this->reverse_add_(this->set_blades_(), 4, data);
188  this->add_(0, 4, data); // zeros
189  this->reverse_add_(2, 2, data); // thermometer
190  this->add_(0, 18, data); // zeros
191  this->reverse_add_(this->gen_checksum_(), 4, data);
192  } else {
193  this->add_(9, 12, data);
194  this->add_(0, 8, data);
195  this->add_(0x2052, 15, data);
196  data->mark(EMMETI_BIT_MARK);
197  data->space(EMMETI_MESSAGE_SPACE);
198  this->add_(0, 8, data);
199  this->add_(1, 2, data);
200  this->add_(0, 18, data);
201  this->add_(0x0C, 4, data);
202  }
203  data->mark(EMMETI_BIT_MARK);
204  data->space(0);
205 
206  transmit.perform();
207 }
208 
210  this->mode = this->get_mode_(curr_state.mode);
211  this->fan_mode = this->get_fan_speed_(curr_state.fan_speed);
212  this->target_temperature = this->get_temp_(curr_state.temp);
213  this->swing_mode = this->get_swing_(curr_state.bitmap);
214  // this->blades_ = curr_state.fan_pos;
215  if (!(curr_state.bitmap & 0x01)) {
217  }
218 
219  this->publish_state();
220  return true;
221 }
222 
225  return false;
226  }
227  ESP_LOGD(TAG, "Received emmeti frame");
228 
229  EmmetiState curr_state;
230 
231  for (size_t pos = 0; pos < 3; pos++) {
233  curr_state.mode |= 1 << pos;
234  } else if (!data.expect_item(EMMETI_BIT_MARK, EMMETI_ZERO_SPACE)) {
235  return false;
236  }
237  }
238 
239  ESP_LOGD(TAG, "Mode: %d", curr_state.mode);
240 
242  curr_state.bitmap |= 1 << 0;
243  } else if (!data.expect_item(EMMETI_BIT_MARK, EMMETI_ZERO_SPACE)) {
244  return false;
245  }
246 
247  ESP_LOGD(TAG, "On: %d", curr_state.bitmap & 0x01);
248 
249  for (size_t pos = 0; pos < 2; pos++) {
251  curr_state.fan_speed |= 1 << pos;
252  } else if (!data.expect_item(EMMETI_BIT_MARK, EMMETI_ZERO_SPACE)) {
253  return false;
254  }
255  }
256 
257  ESP_LOGD(TAG, "Fan speed: %d", curr_state.fan_speed);
258 
259  for (size_t pos = 0; pos < 2; pos++) {
261  curr_state.bitmap |= 1 << (pos + 1);
262  } else if (!data.expect_item(EMMETI_BIT_MARK, EMMETI_ZERO_SPACE)) {
263  return false;
264  }
265  }
266 
267  ESP_LOGD(TAG, "Swing: %d", (curr_state.bitmap >> 1) & 0x01);
268  ESP_LOGD(TAG, "Sleep: %d", (curr_state.bitmap >> 2) & 0x01);
269 
270  for (size_t pos = 0; pos < 4; pos++) {
272  curr_state.temp |= 1 << pos;
273  } else if (!data.expect_item(EMMETI_BIT_MARK, EMMETI_ZERO_SPACE)) {
274  return false;
275  }
276  }
277 
278  ESP_LOGD(TAG, "Temp: %d", curr_state.temp);
279 
280  for (size_t pos = 0; pos < 8; pos++) {
282  return false;
283  }
284  }
285 
286  for (size_t pos = 0; pos < 4; pos++) {
288  curr_state.bitmap |= 1 << (pos + 3);
289  } else if (!data.expect_item(EMMETI_BIT_MARK, EMMETI_ZERO_SPACE)) {
290  return false;
291  }
292  }
293 
294  ESP_LOGD(TAG, "Turbo: %d", (curr_state.bitmap >> 3) & 0x01);
295  ESP_LOGD(TAG, "Light: %d", (curr_state.bitmap >> 4) & 0x01);
296  ESP_LOGD(TAG, "Tree: %d", (curr_state.bitmap >> 5) & 0x01);
297  ESP_LOGD(TAG, "Blow: %d", (curr_state.bitmap >> 6) & 0x01);
298 
299  uint16_t control_data = 0;
300  for (size_t pos = 0; pos < 11; pos++) {
302  control_data |= 1 << pos;
303  } else if (!data.expect_item(EMMETI_BIT_MARK, EMMETI_ZERO_SPACE)) {
304  return false;
305  }
306  }
307 
308  if (control_data != 0x250) {
309  return false;
310  }
311 
312  return this->parse_state_frame_(curr_state);
313 }
314 
315 } // namespace emmeti
316 } // namespace esphome
The fan mode is set to Low.
Definition: climate_mode.h:54
value_type const & value() const
Definition: optional.h:89
ClimateSwingMode swing_mode
The active swing mode of the climate device.
Definition: climate.h:202
float target_temperature
The target temperature of the climate device.
Definition: climate.h:186
void set_carrier_frequency(uint32_t carrier_frequency)
Definition: remote_base.h:34
bool parse_state_frame_(EmmetiState curr_state)
Definition: emmeti.cpp:209
The climate device is set to heat to reach the target temperature.
Definition: climate_mode.h:18
const uint32_t EMMETI_HEADER_MARK
Definition: emmeti.h:47
ClimateMode mode
The active mode of the climate device.
Definition: climate.h:173
float get_temp_(uint8_t temp)
Definition: emmeti.cpp:92
const uint32_t EMMETI_MESSAGE_SPACE
Definition: emmeti.h:52
mopeka_std_values val[4]
The climate device is set to dry/humidity mode.
Definition: climate_mode.h:22
climate::ClimateSwingMode get_swing_(uint8_t bitmap)
Definition: emmeti.cpp:125
ClimateSwingMode
Enum for all modes a climate swing can be in.
Definition: climate_mode.h:70
bool check_checksum_(uint8_t checksum)
Definition: emmeti.cpp:154
climate::ClimateFanMode get_fan_speed_(uint8_t fan)
Definition: emmeti.cpp:111
void reverse_add_(T val, size_t len, esphome::remote_base::RemoteTransmitData *data)
Definition: emmeti.cpp:150
The climate device is set to cool to reach the target temperature.
Definition: climate_mode.h:16
The fan mode is set to Auto.
Definition: climate_mode.h:52
const uint32_t EMMETI_IR_FREQUENCY
Definition: emmeti.h:46
RemoteTransmitterBase * transmitter_
Definition: remote_base.h:276
The climate device is set to heat/cool to reach the target temperature.
Definition: climate_mode.h:14
The fan mode is set to Vertical.
Definition: climate_mode.h:76
uint8_t checksum
Definition: bl0939.h:35
void publish_state()
Publish the state of the climate device, to be called from integrations.
Definition: climate.cpp:395
The fan mode is set to High.
Definition: climate_mode.h:58
ClimateMode
Enum for all modes a climate device can be in.
Definition: climate_mode.h:10
const uint32_t EMMETI_HEADER_SPACE
Definition: emmeti.h:48
The swing mode is set to Off.
Definition: climate_mode.h:72
The climate device is off.
Definition: climate_mode.h:12
climate::ClimateMode get_mode_(uint8_t mode)
Definition: emmeti.cpp:94
optional< ClimateFanMode > fan_mode
The active fan mode of the climate device.
Definition: climate.h:199
const uint32_t EMMETI_ONE_SPACE
Definition: emmeti.h:50
const uint32_t EMMETI_BIT_MARK
Definition: emmeti.h:49
std::string size_t len
Definition: helpers.h:292
void transmit_state() override
Definition: emmeti.cpp:162
void add_(T val, size_t len, esphome::remote_base::RemoteTransmitData *ata)
Definition: emmeti.cpp:137
This is a workaround until we can figure out a way to get the tflite-micro idf component code availab...
Definition: a01nyub.cpp:7
T reverse_(T val, size_t len)
Definition: emmeti.cpp:129
const uint8_t EMMETI_TEMP_MAX
Definition: emmeti.h:9
bool on_receive(remote_base::RemoteReceiveData data) override
Definition: emmeti.cpp:223
The fan mode is set to Medium.
Definition: climate_mode.h:56
const uint32_t EMMETI_ZERO_SPACE
Definition: emmeti.h:51
bool expect_item(uint32_t mark, uint32_t space)
Definition: remote_base.cpp:74
The climate device only has the fan enabled, no heating or cooling is taking place.
Definition: climate_mode.h:20
const uint8_t EMMETI_TEMP_MIN
Definition: emmeti.h:8