ESPHome  2024.5.0
ld2420.h
Go to the documentation of this file.
1 #pragma once
2 
6 #include "esphome/core/helpers.h"
7 #ifdef USE_TEXT_SENSOR
9 #endif
10 #ifdef USE_SELECT
12 #endif
13 #ifdef USE_NUMBER
15 #endif
16 #ifdef USE_BUTTON
18 #endif
19 #include <map>
20 #include <functional>
21 
22 namespace esphome {
23 namespace ld2420 {
24 
25 // Local const's
26 static const uint16_t REFRESH_RATE_MS = 1000;
27 
28 // Command sets
29 static const uint8_t CMD_ABD_DATA_REPLY_SIZE = 0x04;
30 static const uint8_t CMD_ABD_DATA_REPLY_START = 0x0A;
31 static const uint16_t CMD_DISABLE_CONF = 0x00FE;
32 static const uint16_t CMD_ENABLE_CONF = 0x00FF;
33 static const uint8_t CMD_MAX_BYTES = 0x64;
34 static const uint16_t CMD_PARM_HIGH_TRESH = 0x0012;
35 static const uint16_t CMD_PARM_LOW_TRESH = 0x0021;
36 static const uint16_t CMD_PROTOCOL_VER = 0x0002;
37 static const uint16_t CMD_READ_ABD_PARAM = 0x0008;
38 static const uint16_t CMD_READ_REG_ADDR = 0x0020;
39 static const uint16_t CMD_READ_REGISTER = 0x0002;
40 static const uint16_t CMD_READ_SERIAL_NUM = 0x0011;
41 static const uint16_t CMD_READ_SYS_PARAM = 0x0013;
42 static const uint16_t CMD_READ_VERSION = 0x0000;
43 static const uint8_t CMD_REG_DATA_REPLY_SIZE = 0x02;
44 static const uint16_t CMD_RESTART = 0x0068;
45 static const uint16_t CMD_SYSTEM_MODE = 0x0000;
46 static const uint16_t CMD_SYSTEM_MODE_GR = 0x0003;
47 static const uint16_t CMD_SYSTEM_MODE_MTT = 0x0001;
48 static const uint16_t CMD_SYSTEM_MODE_SIMPLE = 0x0064;
49 static const uint16_t CMD_SYSTEM_MODE_DEBUG = 0x0000;
50 static const uint16_t CMD_SYSTEM_MODE_ENERGY = 0x0004;
51 static const uint16_t CMD_SYSTEM_MODE_VS = 0x0002;
52 static const uint16_t CMD_WRITE_ABD_PARAM = 0x0007;
53 static const uint16_t CMD_WRITE_REGISTER = 0x0001;
54 static const uint16_t CMD_WRITE_SYS_PARAM = 0x0012;
55 
56 static const uint8_t LD2420_ERROR_NONE = 0x00;
57 static const uint8_t LD2420_ERROR_TIMEOUT = 0x02;
58 static const uint8_t LD2420_ERROR_UNKNOWN = 0x01;
59 static const uint8_t LD2420_TOTAL_GATES = 16;
60 static const uint8_t CALIBRATE_SAMPLES = 64;
61 
62 // Register address values
63 static const uint16_t CMD_MIN_GATE_REG = 0x0000;
64 static const uint16_t CMD_MAX_GATE_REG = 0x0001;
65 static const uint16_t CMD_TIMEOUT_REG = 0x0004;
66 static const uint16_t CMD_GATE_MOVE_THRESH[LD2420_TOTAL_GATES] = {0x0010, 0x0011, 0x0012, 0x0013, 0x0014, 0x0015,
67  0x0016, 0x0017, 0x0018, 0x0019, 0x001A, 0x001B,
68  0x001C, 0x001D, 0x001E, 0x001F};
69 static const uint16_t CMD_GATE_STILL_THRESH[LD2420_TOTAL_GATES] = {0x0020, 0x0021, 0x0022, 0x0023, 0x0024, 0x0025,
70  0x0026, 0x0027, 0x0028, 0x0029, 0x002A, 0x002B,
71  0x002C, 0x002D, 0x002E, 0x002F};
72 static const uint32_t FACTORY_MOVE_THRESH[LD2420_TOTAL_GATES] = {60000, 30000, 400, 250, 250, 250, 250, 250,
73  250, 250, 250, 250, 250, 250, 250, 250};
74 static const uint32_t FACTORY_STILL_THRESH[LD2420_TOTAL_GATES] = {40000, 20000, 200, 200, 200, 200, 200, 150,
75  150, 100, 100, 100, 100, 100, 100, 100};
76 static const uint16_t FACTORY_TIMEOUT = 120;
77 static const uint16_t FACTORY_MIN_GATE = 1;
78 static const uint16_t FACTORY_MAX_GATE = 12;
79 
80 // COMMAND_BYTE Header & Footer
81 static const uint8_t CMD_FRAME_COMMAND = 6;
82 static const uint8_t CMD_FRAME_DATA_LENGTH = 4;
83 static const uint32_t CMD_FRAME_FOOTER = 0x01020304;
84 static const uint32_t CMD_FRAME_HEADER = 0xFAFBFCFD;
85 static const uint32_t DEBUG_FRAME_FOOTER = 0xFAFBFCFD;
86 static const uint32_t DEBUG_FRAME_HEADER = 0x1410BFAA;
87 static const uint32_t ENERGY_FRAME_FOOTER = 0xF5F6F7F8;
88 static const uint32_t ENERGY_FRAME_HEADER = 0xF1F2F3F4;
89 static const uint8_t CMD_FRAME_STATUS = 7;
90 static const uint8_t CMD_ERROR_WORD = 8;
91 static const uint8_t ENERGY_SENSOR_START = 9;
92 static const uint8_t CALIBRATE_REPORT_INTERVAL = 4;
93 static const int CALIBRATE_VERSION_MIN = 154;
94 static const std::string OP_NORMAL_MODE_STRING = "Normal";
95 static const std::string OP_SIMPLE_MODE_STRING = "Simple";
96 
98 static const std::map<std::string, uint8_t> OP_MODE_TO_UINT{
99  {"Normal", OP_NORMAL_MODE}, {"Calibrate", OP_CALIBRATE_MODE}, {"Simple", OP_SIMPLE_MODE}};
100 static constexpr const char *ERR_MESSAGE[] = {"None", "Unknown", "Timeout"};
101 
103  public:
104  virtual void on_presence(bool presence){};
105  virtual void on_distance(uint16_t distance){};
106  virtual void on_energy(uint16_t *sensor_energy, size_t size){};
107  virtual void on_fw_version(std::string &fw){};
108 };
109 
111  public:
112  void setup() override;
113  void dump_config() override;
114  void loop() override;
115 #ifdef USE_SELECT
116  void set_operating_mode_select(select::Select *selector) { this->operating_selector_ = selector; };
117 #endif
118 #ifdef USE_NUMBER
119  void set_gate_timeout_number(number::Number *number) { this->gate_timeout_number_ = number; };
120  void set_gate_select_number(number::Number *number) { this->gate_select_number_ = number; };
121  void set_min_gate_distance_number(number::Number *number) { this->min_gate_distance_number_ = number; };
122  void set_max_gate_distance_number(number::Number *number) { this->max_gate_distance_number_ = number; };
124  this->gate_move_sensitivity_factor_number_ = number;
125  };
127  this->gate_still_sensitivity_factor_number_ = number;
128  };
129  void set_gate_still_threshold_numbers(int gate, number::Number *n) { this->gate_still_threshold_numbers_[gate] = n; };
130  void set_gate_move_threshold_numbers(int gate, number::Number *n) { this->gate_move_threshold_numbers_[gate] = n; };
131  bool is_gate_select() { return gate_select_number_ != nullptr; };
132  uint8_t get_gate_select_value() { return static_cast<uint8_t>(this->gate_select_number_->state); };
133  float get_min_gate_distance_value() { return min_gate_distance_number_->state; };
134  float get_max_gate_distance_value() { return max_gate_distance_number_->state; };
135  void publish_gate_move_threshold(uint8_t gate) {
136  // With gate_select we only use 1 number pointer, thus we hard code [0]
137  this->gate_move_threshold_numbers_[0]->publish_state(this->new_config.move_thresh[gate]);
138  };
139  void publish_gate_still_threshold(uint8_t gate) {
140  this->gate_still_threshold_numbers_[0]->publish_state(this->new_config.still_thresh[gate]);
141  };
142  void init_gate_config_numbers();
143  void refresh_gate_config_numbers();
144 #endif
145 #ifdef USE_BUTTON
146  void set_apply_config_button(button::Button *button) { this->apply_config_button_ = button; };
147  void set_revert_config_button(button::Button *button) { this->revert_config_button_ = button; };
148  void set_restart_module_button(button::Button *button) { this->restart_module_button_ = button; };
149  void set_factory_reset_button(button::Button *button) { this->factory_reset_button_ = button; };
150 #endif
151  void register_listener(LD2420Listener *listener) { this->listeners_.push_back(listener); }
152 
153  struct CmdFrameT {
154  uint32_t header{0};
155  uint16_t length{0};
156  uint16_t command{0};
157  uint8_t data[18];
158  uint16_t data_length{0};
159  uint32_t footer{0};
160  };
161 
162  struct RegConfigT {
163  uint16_t min_gate{0};
164  uint16_t max_gate{0};
165  uint16_t timeout{0};
166  uint32_t move_thresh[LD2420_TOTAL_GATES];
167  uint32_t still_thresh[LD2420_TOTAL_GATES];
168  };
169 
170  void send_module_restart();
171  void restart_module_action();
172  void apply_config_action();
173  void factory_reset_action();
174  void revert_config_action();
175  float get_setup_priority() const override;
176  int send_cmd_from_array(CmdFrameT cmd_frame);
177  void report_gate_data();
178  void handle_cmd_error(uint8_t error);
179  void set_operating_mode(const std::string &state);
180  void auto_calibrate_sensitivity();
181  void update_radar_data(uint16_t const *gate_energy, uint8_t sample_number);
182  uint8_t calc_checksum(void *data, size_t size);
183 
186  int32_t last_periodic_millis = millis();
187  int32_t report_periodic_millis = millis();
188  int32_t monitor_periodic_millis = millis();
189  int32_t last_normal_periodic_millis = millis();
190  bool output_energy_state{false};
191  uint8_t current_operating_mode{OP_NORMAL_MODE};
192  uint16_t radar_data[LD2420_TOTAL_GATES][CALIBRATE_SAMPLES];
193  uint16_t gate_avg[LD2420_TOTAL_GATES];
194  uint16_t gate_peak[LD2420_TOTAL_GATES];
195  uint8_t sample_number_counter{0};
196  uint16_t total_sample_number_counter{0};
197  float gate_move_sensitivity_factor{0.5};
198  float gate_still_sensitivity_factor{0.5};
199 #ifdef USE_SELECT
200  select::Select *operating_selector_{nullptr};
201 #endif
202 #ifdef USE_BUTTON
203  button::Button *apply_config_button_{nullptr};
204  button::Button *revert_config_button_{nullptr};
205  button::Button *restart_module_button_{nullptr};
206  button::Button *factory_reset_button_{nullptr};
207 #endif
208  void set_min_max_distances_timeout(uint32_t max_gate_distance, uint32_t min_gate_distance, uint32_t timeout);
209  void set_gate_threshold(uint8_t gate);
210  void set_reg_value(uint16_t reg, uint16_t value);
211  uint8_t set_config_mode(bool enable);
212  void set_system_mode(uint16_t mode);
213  void ld2420_restart();
214 
215  protected:
216  struct CmdReplyT {
217  uint8_t command;
218  uint8_t status;
219  uint32_t data[4];
220  uint8_t length;
221  uint16_t error;
222  volatile bool ack;
223  };
224 
225  int get_firmware_int_(const char *version_string);
226  void get_firmware_version_();
227  int get_gate_threshold_(uint8_t gate);
228  void get_reg_value_(uint16_t reg);
229  int get_min_max_distances_timeout_();
230  uint16_t get_mode_() { return this->system_mode_; };
231  void set_mode_(uint16_t mode) { this->system_mode_ = mode; };
232  bool get_presence_() { return this->presence_; };
233  void set_presence_(bool presence) { this->presence_ = presence; };
234  uint16_t get_distance_() { return this->distance_; };
235  void set_distance_(uint16_t distance) { this->distance_ = distance; };
236  bool get_cmd_active_() { return this->cmd_active_; };
237  void set_cmd_active_(bool active) { this->cmd_active_ = active; };
238  void handle_simple_mode_(const uint8_t *inbuf, int len);
239  void handle_energy_mode_(uint8_t *buffer, int len);
240  void handle_ack_data_(uint8_t *buffer, int len);
241  void readline_(int rx_data, uint8_t *buffer, int len);
242  void set_calibration_(bool state) { this->calibration_ = state; };
243  bool get_calibration_() { return this->calibration_; };
244 
245 #ifdef USE_NUMBER
246  number::Number *gate_timeout_number_{nullptr};
247  number::Number *gate_select_number_{nullptr};
248  number::Number *min_gate_distance_number_{nullptr};
249  number::Number *max_gate_distance_number_{nullptr};
250  number::Number *gate_move_sensitivity_factor_number_{nullptr};
251  number::Number *gate_still_sensitivity_factor_number_{nullptr};
252  std::vector<number::Number *> gate_still_threshold_numbers_ = std::vector<number::Number *>(16);
253  std::vector<number::Number *> gate_move_threshold_numbers_ = std::vector<number::Number *>(16);
254 #endif
255 
256  uint16_t gate_energy_[LD2420_TOTAL_GATES];
260  uint16_t system_mode_{CMD_SYSTEM_MODE_ENERGY};
261  bool cmd_active_{false};
262  char ld2420_firmware_ver_[8]{"v0.0.0"};
263  bool presence_{false};
264  bool calibration_{false};
265  uint16_t distance_{0};
266  uint8_t config_checksum_{0};
267  std::vector<LD2420Listener *> listeners_{};
268 };
269 
270 } // namespace ld2420
271 } // namespace esphome
void setup()
void loop()
void set_restart_module_button(button::Button *button)
Definition: ld2420.h:148
virtual void on_presence(bool presence)
Definition: ld2420.h:104
void set_min_gate_distance_number(number::Number *number)
Definition: ld2420.h:121
void publish_gate_move_threshold(uint8_t gate)
Definition: ld2420.h:135
void set_calibration_(bool state)
Definition: ld2420.h:242
Base class for all buttons.
Definition: button.h:29
void set_mode_(uint16_t mode)
Definition: ld2420.h:231
void set_distance_(uint16_t distance)
Definition: ld2420.h:235
void set_gate_still_threshold_numbers(int gate, number::Number *n)
Definition: ld2420.h:129
void set_gate_select_number(number::Number *number)
Definition: ld2420.h:120
uint32_t IRAM_ATTR HOT millis()
Definition: core.cpp:25
void set_factory_reset_button(button::Button *button)
Definition: ld2420.h:149
void set_gate_move_sensitivity_factor_number(number::Number *number)
Definition: ld2420.h:123
void set_presence_(bool presence)
Definition: ld2420.h:233
void set_gate_move_threshold_numbers(int gate, number::Number *n)
Definition: ld2420.h:130
void publish_gate_still_threshold(uint8_t gate)
Definition: ld2420.h:139
void set_revert_config_button(button::Button *button)
Definition: ld2420.h:147
Base-class for all numbers.
Definition: number.h:39
void set_max_gate_distance_number(number::Number *number)
Definition: ld2420.h:122
BedjetMode mode
BedJet operating mode.
Definition: bedjet_codec.h:151
void set_cmd_active_(bool active)
Definition: ld2420.h:237
void set_gate_timeout_number(number::Number *number)
Definition: ld2420.h:119
virtual void on_distance(uint16_t distance)
Definition: ld2420.h:105
virtual void on_fw_version(std::string &fw)
Definition: ld2420.h:107
void register_listener(LD2420Listener *listener)
Definition: ld2420.h:151
std::string size_t len
Definition: helpers.h:292
void set_gate_still_sensitivity_factor_number(number::Number *number)
Definition: ld2420.h:126
uint16_t length
Definition: tt21100.cpp:12
Base-class for all selects.
Definition: select.h:31
This is a workaround until we can figure out a way to get the tflite-micro idf component code availab...
Definition: a01nyub.cpp:7
void set_operating_mode_select(select::Select *selector)
Definition: ld2420.h:116
void set_apply_config_button(button::Button *button)
Definition: ld2420.h:146
virtual void on_energy(uint16_t *sensor_energy, size_t size)
Definition: ld2420.h:106
bool state
Definition: fan.h:34