Files
esphome-dev/esphome/components/midea_dongle/midea_frame.h
T
Sergey V. DUDANOV f34c9b33fc Midea climate support (#1328)
* Added support for Midea IoT climate devices via UART interface (USB-dongle)

* Fixed lint checks

* Fixed lint checks

* CODEOWNERS update

* Clang-format

* Clang-format

* Add network device notification message support (show WiFi sign on devices)

* Make wifi_signal_sensor optional component

* Some optimization

* Optimizations and code formatting

* Fixed lint checks

* Fixed lint checks

* Fixed sign error

* Code changes

* Network notify repeat every 10 min

* Added log messages

* Fixed lint checks

* Refactoring: MideaClimate => MideaAC

* Using enums instead literals in Midea states

* Enum changed to be more correct

* Shrink notify frame to 32 bytes

* Fixed lint checks

* Change notify frame appliance type to common broadcast

* Control optimization

* Fixed control error

* Control command now don't reset others uncontrollable properties of device

* Fixed lint checks

* Some optimization

* on_receive callback give const Frame

* Fix control

* Fixes

* Some minor changes

* Fixed lint error

* No dependency from wifi_signal sensor for stretched WiFi icon. New option: stretched_icon instead wifi_signal_id.

* Fix option name

* Added export of outdoor temperature as sensor value

* Fixed lint errors

* Fixed pylint error

* Minor fix

* Fix temperature overflow in some cases

* Added answer on QueryNetwork command from appliance. Now don't wait for ack on 0x0D command.

* Fix lint error

* Added humidity setpoint optional sensor

* Added boolean options 'swing_horizontal' and 'swing_both'

* Added debug frame output

* Added debug frame output

* Fix lints error

* Some debug output optimization

* Fix lint check

* Some code optimization: adding templates

* Fix lint error

* Added sensors device classes

* Python code reformatted with black formatter

* RX frame debug message

RX frame debug message now prints before checking

* Remove CRC check for receiving frames

* Added experimental power usage option

* Added power usage option

* Fixed lint errors

* Major changes. See esp-docs.

* Added tests in test4.yaml

* Added tests in test1.yaml

* Added wifi dependency

* Fix test1.yaml

* Some fix :)

* One more refactoring

* One more refactoring

* One more refactoring
2021-03-17 17:27:50 -03:00

105 lines
3.1 KiB
C++

#pragma once
#include "esphome/core/component.h"
namespace esphome {
namespace midea_dongle {
static const uint8_t OFFSET_START = 0;
static const uint8_t OFFSET_LENGTH = 1;
static const uint8_t OFFSET_APPTYPE = 2;
static const uint8_t OFFSET_BODY = 10;
static const uint8_t SYNC_BYTE = 0xAA;
class Frame {
public:
Frame() = delete;
Frame(uint8_t *data) : pbuf_(data) {}
Frame(const Frame &frame) : pbuf_(frame.data()) {}
// Frame buffer
uint8_t *data() const { return this->pbuf_; }
// Frame size
uint8_t size() const { return this->length_() + OFFSET_LENGTH; }
uint8_t app_type() const { return this->pbuf_[OFFSET_APPTYPE]; }
template<typename T> typename std::enable_if<std::is_base_of<Frame, T>::value, T>::type as() const {
return T(*this);
}
String to_string() const;
protected:
uint8_t *pbuf_;
uint8_t length_() const { return this->pbuf_[OFFSET_LENGTH]; }
};
class BaseFrame : public Frame {
public:
BaseFrame() = delete;
BaseFrame(uint8_t *data) : Frame(data) {}
BaseFrame(const Frame &frame) : Frame(frame) {}
// Check for valid
bool is_valid() const;
// Prepare for sending to device
void finalize();
uint8_t get_type() const { return this->pbuf_[9]; }
void set_type(uint8_t value) { this->pbuf_[9] = value; }
bool has_response_type(uint8_t type) const { return this->resp_type_() == type; }
bool has_type(uint8_t type) const { return this->get_type() == type; }
protected:
static const uint8_t PROGMEM CRC_TABLE[256];
void set_bytemask_(uint8_t idx, uint8_t mask, bool state);
uint8_t resp_type_() const { return this->pbuf_[OFFSET_BODY]; }
bool has_valid_crc_() const;
bool has_valid_cs_() const;
void update_crc_();
void update_cs_();
};
template<typename T = Frame, size_t buf_size = 36> class StaticFrame : public T {
public:
// Default constructor
StaticFrame() : T(this->buf_) {}
// Copy constructor
StaticFrame(const Frame &src) : T(this->buf_) {
if (src.length_() < sizeof(this->buf_)) {
memcpy(this->buf_, src.data(), src.length_() + OFFSET_LENGTH);
}
}
// Constructor for RAM data
StaticFrame(const uint8_t *src) : T(this->buf_) {
const uint8_t len = src[OFFSET_LENGTH];
if (len < sizeof(this->buf_)) {
memcpy(this->buf_, src, len + OFFSET_LENGTH);
}
}
// Constructor for PROGMEM data
StaticFrame(const __FlashStringHelper *pgm) : T(this->buf_) {
const uint8_t *src = reinterpret_cast<decltype(src)>(pgm);
const uint8_t len = pgm_read_byte(src + OFFSET_LENGTH);
if (len < sizeof(this->buf_)) {
memcpy_P(this->buf_, src, len + OFFSET_LENGTH);
}
}
protected:
uint8_t buf_[buf_size];
};
// Device network notification frame
class NotifyFrame : public midea_dongle::StaticFrame<BaseFrame, 32> {
public:
NotifyFrame() : StaticFrame(FPSTR(NotifyFrame::INIT)) {}
void set_signal_strength(uint8_t value) { this->pbuf_[12] = value; }
uint8_t get_signal_strength() const { return this->pbuf_[12]; }
void set_connected(bool state) { this->pbuf_[18] = state ? 0 : 1; }
bool is_connected() const { return !this->pbuf_[18]; }
private:
static const uint8_t PROGMEM INIT[];
};
} // namespace midea_dongle
} // namespace esphome