ESPHome  2023.8.3
tuya.h
Go to the documentation of this file.
1 #pragma once
2 
4 #include "esphome/core/defines.h"
5 #include "esphome/core/helpers.h"
7 
8 #ifdef USE_TIME
10 #include "esphome/core/time.h"
11 #endif
12 
13 #include <vector>
14 
15 namespace esphome {
16 namespace tuya {
17 
18 enum class TuyaDatapointType : uint8_t {
19  RAW = 0x00, // variable length
20  BOOLEAN = 0x01, // 1 byte (0/1)
21  INTEGER = 0x02, // 4 byte
22  STRING = 0x03, // variable length
23  ENUM = 0x04, // 1 byte
24  BITMASK = 0x05, // 1/2/4 bytes
25 };
26 
27 struct TuyaDatapoint {
28  uint8_t id;
30  size_t len;
31  union {
32  bool value_bool;
33  int value_int;
34  uint32_t value_uint;
35  uint8_t value_enum;
36  uint32_t value_bitmask;
37  };
38  std::string value_string;
39  std::vector<uint8_t> value_raw;
40 };
41 
43  uint8_t datapoint_id;
44  std::function<void(TuyaDatapoint)> on_datapoint;
45 };
46 
47 enum class TuyaCommandType : uint8_t {
48  HEARTBEAT = 0x00,
49  PRODUCT_QUERY = 0x01,
50  CONF_QUERY = 0x02,
51  WIFI_STATE = 0x03,
52  WIFI_RESET = 0x04,
53  WIFI_SELECT = 0x05,
54  DATAPOINT_DELIVER = 0x06,
55  DATAPOINT_REPORT = 0x07,
56  DATAPOINT_QUERY = 0x08,
57  WIFI_TEST = 0x0E,
58  LOCAL_TIME_QUERY = 0x1C,
59  WIFI_RSSI = 0x24,
60  VACUUM_MAP_UPLOAD = 0x28,
61  GET_NETWORK_STATUS = 0x2B,
62 };
63 
64 enum class TuyaInitState : uint8_t {
65  INIT_HEARTBEAT = 0x00,
67  INIT_CONF,
68  INIT_WIFI,
70  INIT_DONE,
71 };
72 
73 struct TuyaCommand {
75  std::vector<uint8_t> payload;
76 };
77 
78 class Tuya : public Component, public uart::UARTDevice {
79  public:
80  float get_setup_priority() const override { return setup_priority::LATE; }
81  void setup() override;
82  void loop() override;
83  void dump_config() override;
84  void register_listener(uint8_t datapoint_id, const std::function<void(TuyaDatapoint)> &func);
85  void set_raw_datapoint_value(uint8_t datapoint_id, const std::vector<uint8_t> &value);
86  void set_boolean_datapoint_value(uint8_t datapoint_id, bool value);
87  void set_integer_datapoint_value(uint8_t datapoint_id, uint32_t value);
88  void set_status_pin(InternalGPIOPin *status_pin) { this->status_pin_ = status_pin; }
89  void set_string_datapoint_value(uint8_t datapoint_id, const std::string &value);
90  void set_enum_datapoint_value(uint8_t datapoint_id, uint8_t value);
91  void set_bitmask_datapoint_value(uint8_t datapoint_id, uint32_t value, uint8_t length);
92  void force_set_raw_datapoint_value(uint8_t datapoint_id, const std::vector<uint8_t> &value);
93  void force_set_boolean_datapoint_value(uint8_t datapoint_id, bool value);
94  void force_set_integer_datapoint_value(uint8_t datapoint_id, uint32_t value);
95  void force_set_string_datapoint_value(uint8_t datapoint_id, const std::string &value);
96  void force_set_enum_datapoint_value(uint8_t datapoint_id, uint8_t value);
97  void force_set_bitmask_datapoint_value(uint8_t datapoint_id, uint32_t value, uint8_t length);
98  TuyaInitState get_init_state();
99 #ifdef USE_TIME
100  void set_time_id(time::RealTimeClock *time_id) { this->time_id_ = time_id; }
101 #endif
102  void add_ignore_mcu_update_on_datapoints(uint8_t ignore_mcu_update_on_datapoints) {
103  this->ignore_mcu_update_on_datapoints_.push_back(ignore_mcu_update_on_datapoints);
104  }
105  void add_on_initialized_callback(std::function<void()> callback) {
106  this->initialized_callback_.add(std::move(callback));
107  }
108 
109  protected:
110  void handle_char_(uint8_t c);
111  void handle_datapoints_(const uint8_t *buffer, size_t len);
112  optional<TuyaDatapoint> get_datapoint_(uint8_t datapoint_id);
113  bool validate_message_();
114 
115  void handle_command_(uint8_t command, uint8_t version, const uint8_t *buffer, size_t len);
116  void send_raw_command_(TuyaCommand command);
117  void process_command_queue_();
118  void send_command_(const TuyaCommand &command);
119  void send_empty_command_(TuyaCommandType command);
120  void set_numeric_datapoint_value_(uint8_t datapoint_id, TuyaDatapointType datapoint_type, uint32_t value,
121  uint8_t length, bool forced);
122  void set_string_datapoint_value_(uint8_t datapoint_id, const std::string &value, bool forced);
123  void set_raw_datapoint_value_(uint8_t datapoint_id, const std::vector<uint8_t> &value, bool forced);
124  void send_datapoint_command_(uint8_t datapoint_id, TuyaDatapointType datapoint_type, std::vector<uint8_t> data);
125  void set_status_pin_();
126  void send_wifi_status_();
127  uint8_t get_wifi_status_code_();
128  uint8_t get_wifi_rssi_();
129 
130 #ifdef USE_TIME
131  void send_local_time_();
133  bool time_sync_callback_registered_{false};
134 #endif
136  bool init_failed_{false};
137  int init_retries_{0};
138  uint8_t protocol_version_ = -1;
140  int status_pin_reported_ = -1;
141  int reset_pin_reported_ = -1;
142  uint32_t last_command_timestamp_ = 0;
143  uint32_t last_rx_char_timestamp_ = 0;
144  std::string product_ = "";
145  std::vector<TuyaDatapointListener> listeners_;
146  std::vector<TuyaDatapoint> datapoints_;
147  std::vector<uint8_t> rx_message_;
148  std::vector<uint8_t> ignore_mcu_update_on_datapoints_{};
149  std::vector<TuyaCommand> command_queue_;
150  optional<TuyaCommandType> expected_response_{};
151  uint8_t wifi_status_ = -1;
152  CallbackManager<void()> initialized_callback_{};
153 };
154 
155 } // namespace tuya
156 } // namespace esphome
void setup()
void loop()
TuyaDatapointType type
Definition: tuya.h:29
TuyaCommandType
Definition: tuya.h:47
float get_setup_priority() const override
Definition: tuya.h:80
The RealTimeClock class exposes common timekeeping functions via the device&#39;s local real-time clock...
const float LATE
For components that should be initialized at the very end of the setup process.
Definition: component.cpp:27
void set_time_id(time::RealTimeClock *time_id)
Definition: tuya.h:100
TuyaDatapointType
Definition: tuya.h:18
std::vector< TuyaDatapointListener > listeners_
Definition: tuya.h:145
void add_on_initialized_callback(std::function< void()> callback)
Definition: tuya.h:105
std::vector< TuyaDatapoint > datapoints_
Definition: tuya.h:146
std::vector< uint8_t > rx_message_
Definition: tuya.h:147
TuyaCommandType cmd
Definition: tuya.h:74
std::string value_string
Definition: tuya.h:38
std::function< void(TuyaDatapoint)> on_datapoint
Definition: tuya.h:44
std::vector< uint8_t > payload
Definition: tuya.h:75
void set_status_pin(InternalGPIOPin *status_pin)
Definition: tuya.h:88
std::string size_t len
Definition: helpers.h:289
uint16_t length
Definition: tt21100.cpp:12
std::vector< TuyaCommand > command_queue_
Definition: tuya.h:149
TuyaInitState
Definition: tuya.h:64
std::vector< uint8_t > value_raw
Definition: tuya.h:39
void add_ignore_mcu_update_on_datapoints(uint8_t ignore_mcu_update_on_datapoints)
Definition: tuya.h:102