ESPHome 2025.9.0-dev
Loading...
Searching...
No Matches
seeed_mr24hpc1.cpp
Go to the documentation of this file.
1#include "seeed_mr24hpc1.h"
2
4#include "esphome/core/log.h"
5
6#include <utility>
7
8namespace esphome {
9namespace seeed_mr24hpc1 {
10
11static const char *const TAG = "seeed_mr24hpc1";
12
13// Prints the component's configuration data. dump_config() prints all of the component's configuration
14// items in an easy-to-read format, including the configuration key-value pairs.
16 ESP_LOGCONFIG(TAG, "MR24HPC1:");
17#ifdef USE_TEXT_SENSOR
18 LOG_TEXT_SENSOR(" ", "Heartbeat Text Sensor", this->heartbeat_state_text_sensor_);
19 LOG_TEXT_SENSOR(" ", "Product Model Text Sensor", this->product_model_text_sensor_);
20 LOG_TEXT_SENSOR(" ", "Product ID Text Sensor", this->product_id_text_sensor_);
21 LOG_TEXT_SENSOR(" ", "Hardware Model Text Sensor", this->hardware_model_text_sensor_);
22 LOG_TEXT_SENSOR(" ", "Firware Verison Text Sensor", this->firware_version_text_sensor_);
23 LOG_TEXT_SENSOR(" ", "Keep Away Text Sensor", this->keep_away_text_sensor_);
24 LOG_TEXT_SENSOR(" ", "Motion Status Text Sensor", this->motion_status_text_sensor_);
25 LOG_TEXT_SENSOR(" ", "Custom Mode End Text Sensor", this->custom_mode_end_text_sensor_);
26#endif
27#ifdef USE_BINARY_SENSOR
28 LOG_BINARY_SENSOR(" ", "Has Target Binary Sensor", this->has_target_binary_sensor_);
29#endif
30#ifdef USE_SENSOR
31 LOG_SENSOR(" ", "Custom Presence Of Detection Sensor", this->custom_presence_of_detection_sensor_);
32 LOG_SENSOR(" ", "Movement Signs Sensor", this->movement_signs_sensor_);
33 LOG_SENSOR(" ", "Custom Motion Distance Sensor", this->custom_motion_distance_sensor_);
34 LOG_SENSOR(" ", "Custom Spatial Static Sensor", this->custom_spatial_static_value_sensor_);
35 LOG_SENSOR(" ", "Custom Spatial Motion Sensor", this->custom_spatial_motion_value_sensor_);
36 LOG_SENSOR(" ", "Custom Motion Speed Sensor", this->custom_motion_speed_sensor_);
37 LOG_SENSOR(" ", "Custom Mode Num Sensor", this->custom_mode_num_sensor_);
38#endif
39#ifdef USE_SWITCH
40 LOG_SWITCH(" ", "Underly Open Function Switch", this->underlying_open_function_switch_);
41#endif
42#ifdef USE_BUTTON
43 LOG_BUTTON(" ", "Restart Button", this->restart_button_);
44 LOG_BUTTON(" ", "Custom Set End Button", this->custom_set_end_button_);
45#endif
46#ifdef USE_SELECT
47 LOG_SELECT(" ", "Scene Mode Select", this->scene_mode_select_);
48 LOG_SELECT(" ", "Unman Time Select", this->unman_time_select_);
49 LOG_SELECT(" ", "Existence Boundary Select", this->existence_boundary_select_);
50 LOG_SELECT(" ", "Motion Boundary Select", this->motion_boundary_select_);
51#endif
52#ifdef USE_NUMBER
53 LOG_NUMBER(" ", "Sensitivity Number", this->sensitivity_number_);
54 LOG_NUMBER(" ", "Custom Mode Number", this->custom_mode_number_);
55 LOG_NUMBER(" ", "Existence Threshold Number", this->existence_threshold_number_);
56 LOG_NUMBER(" ", "Motion Threshold Number", this->motion_threshold_number_);
57 LOG_NUMBER(" ", "Motion Trigger Time Number", this->motion_trigger_number_);
58 LOG_NUMBER(" ", "Motion To Rest Time Number", this->motion_to_rest_number_);
59 LOG_NUMBER(" ", "Custom Unman Time Number", this->custom_unman_time_number_);
60#endif
61}
62
63// Initialisation functions
65 this->check_uart_settings(115200);
66
67 if (this->custom_mode_number_ != nullptr) {
68 this->custom_mode_number_->publish_state(0); // Zero out the custom mode
69 }
70 if (this->custom_mode_num_sensor_ != nullptr) {
71 this->custom_mode_num_sensor_->publish_state(0);
72 }
73 if (this->custom_mode_end_text_sensor_ != nullptr) {
74 this->custom_mode_end_text_sensor_->publish_state("Not in custom mode");
75 }
76 this->set_custom_end_mode();
77 this->poll_time_base_func_check_ = true;
78 this->check_dev_inf_sign_ = true;
79 this->sg_start_query_data_ = STANDARD_FUNCTION_QUERY_PRODUCT_MODE;
80 this->sg_data_len_ = 0;
81 this->sg_frame_len_ = 0;
82 this->sg_recv_data_state_ = FRAME_IDLE;
83 this->s_output_info_switch_flag_ = OUTPUT_SWITCH_INIT;
84
85 memset(this->c_product_mode_, 0, PRODUCT_BUF_MAX_SIZE);
86 memset(this->c_product_id_, 0, PRODUCT_BUF_MAX_SIZE);
87 memset(this->c_firmware_version_, 0, PRODUCT_BUF_MAX_SIZE);
88 memset(this->c_hardware_model_, 0, PRODUCT_BUF_MAX_SIZE);
89 memset(this->sg_frame_prase_buf_, 0, FRAME_BUF_MAX_SIZE);
90 memset(this->sg_frame_buf_, 0, FRAME_BUF_MAX_SIZE);
91
92 this->set_interval(8000, [this]() { this->update_(); });
93}
94
95// Timed polling of radar data
96void MR24HPC1Component::update_() {
97 this->get_radar_output_information_switch(); // Query the key status every so often
98 this->poll_time_base_func_check_ = true; // Query the base functionality information at regular intervals
99}
100
101// main loop
103 uint8_t byte;
104
105 // Is there data on the serial port
106 while (this->available()) {
107 this->read_byte(&byte);
108 this->r24_split_data_frame_(byte); // split data frame
109 }
110
111 if ((this->s_output_info_switch_flag_ == OUTPUT_SWTICH_OFF) &&
112 (this->sg_start_query_data_ > CUSTOM_FUNCTION_QUERY_TIME_OF_ENTER_UNMANNED) && (!this->check_dev_inf_sign_)) {
113 this->sg_start_query_data_ = STANDARD_FUNCTION_QUERY_SCENE_MODE;
114 } else if ((this->s_output_info_switch_flag_ == OUTPUT_SWITCH_ON) &&
115 (this->sg_start_query_data_ < CUSTOM_FUNCTION_QUERY_EXISTENCE_BOUNDARY) && (!this->check_dev_inf_sign_)) {
116 this->sg_start_query_data_ = CUSTOM_FUNCTION_QUERY_EXISTENCE_BOUNDARY;
117 } else if (this->check_dev_inf_sign_ && (this->sg_start_query_data_ > STANDARD_FUNCTION_QUERY_HARDWARE_MODE)) {
118 // First time power up information polling
119 this->sg_start_query_data_ = STANDARD_FUNCTION_QUERY_PRODUCT_MODE;
120 }
121
122 // Polling Functions
123 if (this->poll_time_base_func_check_) {
124 switch (this->sg_start_query_data_) {
126 this->get_product_mode();
127 this->sg_start_query_data_++;
128 break;
130 this->get_product_id();
131 this->sg_start_query_data_++;
132 break;
134 this->get_product_mode();
135 this->get_product_id();
136 this->get_firmware_version();
137 this->sg_start_query_data_++;
138 break;
139 case STANDARD_FUNCTION_QUERY_HARDWARE_MODE: // Above is the equipment information
140 this->get_product_mode();
141 this->get_product_id();
142 this->get_hardware_model();
143 this->sg_start_query_data_++;
144 this->check_dev_inf_sign_ = false;
145 break;
147 this->get_scene_mode();
148 this->sg_start_query_data_++;
149 break;
151 this->get_sensitivity();
152 this->sg_start_query_data_++;
153 break;
155 this->get_unmanned_time();
156 this->sg_start_query_data_++;
157 break;
159 this->get_human_status();
160 this->sg_start_query_data_++;
161 break;
163 this->get_human_motion_info();
164 this->sg_start_query_data_++;
165 break;
168 this->sg_start_query_data_++;
169 break;
170 case STANDARD_FUNCTION_QUERY_KEEPAWAY_STATUS: // The above is the basic functional information
171 this->get_keep_away();
172 this->sg_start_query_data_++;
173 break;
175 this->get_custom_mode();
176 this->sg_start_query_data_++;
177 break;
179 this->get_heartbeat_packet();
180 this->sg_start_query_data_++;
181 break;
184 this->sg_start_query_data_++;
185 break;
187 this->get_motion_boundary();
188 this->sg_start_query_data_++;
189 break;
192 this->sg_start_query_data_++;
193 break;
195 this->get_motion_threshold();
196 this->sg_start_query_data_++;
197 break;
200 this->sg_start_query_data_++;
201 break;
204 this->sg_start_query_data_++;
205 break;
207 this->get_custom_unman_time();
208 this->sg_start_query_data_++;
209 if (this->s_output_info_switch_flag_ == OUTPUT_SWTICH_OFF) {
210 this->poll_time_base_func_check_ = false; // Avoiding high-speed polling that can cause the device to jam
211 }
212 break;
214 this->get_human_status();
215 this->sg_start_query_data_++;
216 break;
219 this->sg_start_query_data_++;
220 break;
223 this->sg_start_query_data_++;
224 break;
227 this->sg_start_query_data_++;
228 break;
231 this->sg_start_query_data_++;
232 break;
235 this->sg_start_query_data_++;
236 this->poll_time_base_func_check_ = false; // Avoiding high-speed polling that can cause the device to jam
237 break;
238 default:
239 break;
240 }
241 }
242}
243
244// Calculate CRC check digit
245static uint8_t get_frame_crc_sum(const uint8_t *data, int len) {
246 unsigned int crc_sum = 0;
247 for (int i = 0; i < len - 3; i++) {
248 crc_sum += data[i];
249 }
250 return crc_sum & 0xff;
251}
252
253// Check that the check digit is correct
254static int get_frame_check_status(uint8_t *data, int len) {
255 uint8_t crc_sum = get_frame_crc_sum(data, len);
256 uint8_t verified = data[len - 3];
257 return (verified == crc_sum) ? 1 : 0;
258}
259
260// split data frame
261void MR24HPC1Component::r24_split_data_frame_(uint8_t value) {
262 switch (this->sg_recv_data_state_) {
263 case FRAME_IDLE: // starting value
264 if (FRAME_HEADER1_VALUE == value) {
265 this->sg_recv_data_state_ = FRAME_HEADER2;
266 }
267 break;
268 case FRAME_HEADER2:
269 if (FRAME_HEADER2_VALUE == value) {
270 this->sg_frame_buf_[0] = FRAME_HEADER1_VALUE;
271 this->sg_frame_buf_[1] = FRAME_HEADER2_VALUE;
272 this->sg_recv_data_state_ = FRAME_CTL_WORD;
273 } else {
274 this->sg_recv_data_state_ = FRAME_IDLE;
275 ESP_LOGD(TAG, "FRAME_IDLE ERROR value:%x", value);
276 }
277 break;
278 case FRAME_CTL_WORD:
279 this->sg_frame_buf_[2] = value;
280 this->sg_recv_data_state_ = FRAME_CMD_WORD;
281 break;
282 case FRAME_CMD_WORD:
283 this->sg_frame_buf_[3] = value;
284 this->sg_recv_data_state_ = FRAME_DATA_LEN_H;
285 break;
286 case FRAME_DATA_LEN_H:
287 if (value <= 4) {
288 this->sg_data_len_ = value * 256;
289 this->sg_frame_buf_[4] = value;
290 this->sg_recv_data_state_ = FRAME_DATA_LEN_L;
291 } else {
292 this->sg_data_len_ = 0;
293 this->sg_recv_data_state_ = FRAME_IDLE;
294 ESP_LOGD(TAG, "FRAME_DATA_LEN_H ERROR value:%x", value);
295 }
296 break;
297 case FRAME_DATA_LEN_L:
298 this->sg_data_len_ += value;
299 if (this->sg_data_len_ > 32) {
300 ESP_LOGD(TAG, "len=%d, FRAME_DATA_LEN_L ERROR value:%x", this->sg_data_len_, value);
301 this->sg_data_len_ = 0;
302 this->sg_recv_data_state_ = FRAME_IDLE;
303 } else {
304 this->sg_frame_buf_[5] = value;
305 this->sg_frame_len_ = 6;
306 this->sg_recv_data_state_ = FRAME_DATA_BYTES;
307 }
308 break;
309 case FRAME_DATA_BYTES:
310 this->sg_data_len_ -= 1;
311 this->sg_frame_buf_[this->sg_frame_len_++] = value;
312 if (this->sg_data_len_ <= 0) {
313 this->sg_recv_data_state_ = FRAME_DATA_CRC;
314 }
315 break;
316 case FRAME_DATA_CRC:
317 this->sg_frame_buf_[this->sg_frame_len_++] = value;
318 this->sg_recv_data_state_ = FRAME_TAIL1;
319 break;
320 case FRAME_TAIL1:
321 if (FRAME_TAIL1_VALUE == value) {
322 this->sg_recv_data_state_ = FRAME_TAIL2;
323 } else {
324 this->sg_recv_data_state_ = FRAME_IDLE;
325 this->sg_frame_len_ = 0;
326 this->sg_data_len_ = 0;
327 ESP_LOGD(TAG, "FRAME_TAIL1 ERROR value:%x", value);
328 }
329 break;
330 case FRAME_TAIL2:
331 if (FRAME_TAIL2_VALUE == value) {
332 this->sg_frame_buf_[this->sg_frame_len_++] = FRAME_TAIL1_VALUE;
333 this->sg_frame_buf_[this->sg_frame_len_++] = FRAME_TAIL2_VALUE;
334 memcpy(this->sg_frame_prase_buf_, this->sg_frame_buf_, this->sg_frame_len_);
335 if (get_frame_check_status(this->sg_frame_prase_buf_, this->sg_frame_len_)) {
336 this->r24_parse_data_frame_(this->sg_frame_prase_buf_, this->sg_frame_len_);
337 } else {
338 ESP_LOGD(TAG, "frame check failer!");
339 }
340 } else {
341 ESP_LOGD(TAG, "FRAME_TAIL2 ERROR value:%x", value);
342 }
343 memset(this->sg_frame_prase_buf_, 0, FRAME_BUF_MAX_SIZE);
344 memset(this->sg_frame_buf_, 0, FRAME_BUF_MAX_SIZE);
345 this->sg_frame_len_ = 0;
346 this->sg_data_len_ = 0;
347 this->sg_recv_data_state_ = FRAME_IDLE;
348 break;
349 default:
350 this->sg_recv_data_state_ = FRAME_IDLE;
351 }
352}
353
354// Parses data frames related to product information
355void MR24HPC1Component::r24_frame_parse_product_information_(uint8_t *data) {
356 uint16_t product_len = encode_uint16(data[FRAME_COMMAND_WORD_INDEX + 1], data[FRAME_COMMAND_WORD_INDEX + 2]);
357 if (data[FRAME_COMMAND_WORD_INDEX] == COMMAND_PRODUCT_MODE) {
358 if ((this->product_model_text_sensor_ != nullptr) && (product_len < PRODUCT_BUF_MAX_SIZE)) {
359 memset(this->c_product_mode_, 0, PRODUCT_BUF_MAX_SIZE);
360 memcpy(this->c_product_mode_, &data[FRAME_DATA_INDEX], product_len);
361 this->product_model_text_sensor_->publish_state(this->c_product_mode_);
362 } else {
363 ESP_LOGD(TAG, "Reply: get product_mode error!");
364 }
365 } else if (data[FRAME_COMMAND_WORD_INDEX] == COMMAND_PRODUCT_ID) {
366 if ((this->product_id_text_sensor_ != nullptr) && (product_len < PRODUCT_BUF_MAX_SIZE)) {
367 memset(this->c_product_id_, 0, PRODUCT_BUF_MAX_SIZE);
368 memcpy(this->c_product_id_, &data[FRAME_DATA_INDEX], product_len);
369 this->product_id_text_sensor_->publish_state(this->c_product_id_);
370 } else {
371 ESP_LOGD(TAG, "Reply: get productId error!");
372 }
373 } else if (data[FRAME_COMMAND_WORD_INDEX] == COMMAND_HARDWARE_MODEL) {
374 if ((this->hardware_model_text_sensor_ != nullptr) && (product_len < PRODUCT_BUF_MAX_SIZE)) {
375 memset(this->c_hardware_model_, 0, PRODUCT_BUF_MAX_SIZE);
376 memcpy(this->c_hardware_model_, &data[FRAME_DATA_INDEX], product_len);
377 this->hardware_model_text_sensor_->publish_state(this->c_hardware_model_);
378 ESP_LOGD(TAG, "Reply: get hardware_model :%s", this->c_hardware_model_);
379 } else {
380 ESP_LOGD(TAG, "Reply: get hardwareModel error!");
381 }
382 } else if (data[FRAME_COMMAND_WORD_INDEX] == COMMAND_FIRMWARE_VERSION) {
383 if ((this->firware_version_text_sensor_ != nullptr) && (product_len < PRODUCT_BUF_MAX_SIZE)) {
384 memset(this->c_firmware_version_, 0, PRODUCT_BUF_MAX_SIZE);
385 memcpy(this->c_firmware_version_, &data[FRAME_DATA_INDEX], product_len);
386 this->firware_version_text_sensor_->publish_state(this->c_firmware_version_);
387 } else {
388 ESP_LOGD(TAG, "Reply: get firmwareVersion error!");
389 }
390 }
391}
392
393// Parsing the underlying open parameters
394void MR24HPC1Component::r24_frame_parse_open_underlying_information_(uint8_t *data) {
395 if (data[FRAME_COMMAND_WORD_INDEX] == 0x00) {
396 if (this->underlying_open_function_switch_ != nullptr) {
397 this->underlying_open_function_switch_->publish_state(
398 data[FRAME_DATA_INDEX]); // Underlying Open Parameter Switch Status Updates
399 }
400 if (data[FRAME_DATA_INDEX]) {
401 this->s_output_info_switch_flag_ = OUTPUT_SWITCH_ON;
402 } else {
403 this->s_output_info_switch_flag_ = OUTPUT_SWTICH_OFF;
404 }
405 } else if (data[FRAME_COMMAND_WORD_INDEX] == 0x01) {
406 if (this->custom_spatial_static_value_sensor_ != nullptr) {
407 this->custom_spatial_static_value_sensor_->publish_state(data[FRAME_DATA_INDEX]);
408 }
409 if (this->custom_presence_of_detection_sensor_ != nullptr) {
410 this->custom_presence_of_detection_sensor_->publish_state(data[FRAME_DATA_INDEX + 1] * 0.5f);
411 }
412 if (this->custom_spatial_motion_value_sensor_ != nullptr) {
413 this->custom_spatial_motion_value_sensor_->publish_state(data[FRAME_DATA_INDEX + 2]);
414 }
415 if (this->custom_motion_distance_sensor_ != nullptr) {
416 this->custom_motion_distance_sensor_->publish_state(data[FRAME_DATA_INDEX + 3] * 0.5f);
417 }
418 if (this->custom_motion_speed_sensor_ != nullptr) {
419 this->custom_motion_speed_sensor_->publish_state((data[FRAME_DATA_INDEX + 4] - 10) * 0.5f);
420 }
421 } else if ((data[FRAME_COMMAND_WORD_INDEX] == 0x06) || (data[FRAME_COMMAND_WORD_INDEX] == 0x86)) {
422 // none:0x00 close_to:0x01 far_away:0x02
423 if ((this->keep_away_text_sensor_ != nullptr) && (data[FRAME_DATA_INDEX] < 3)) {
424 this->keep_away_text_sensor_->publish_state(S_KEEP_AWAY_STR[data[FRAME_DATA_INDEX]]);
425 }
426 } else if ((this->movement_signs_sensor_ != nullptr) &&
427 ((data[FRAME_COMMAND_WORD_INDEX] == 0x07) || (data[FRAME_COMMAND_WORD_INDEX] == 0x87))) {
428 this->movement_signs_sensor_->publish_state(data[FRAME_DATA_INDEX]);
429 } else if ((this->existence_threshold_number_ != nullptr) &&
430 ((data[FRAME_COMMAND_WORD_INDEX] == 0x08) || (data[FRAME_COMMAND_WORD_INDEX] == 0x88))) {
431 this->existence_threshold_number_->publish_state(data[FRAME_DATA_INDEX]);
432 } else if ((this->motion_threshold_number_ != nullptr) &&
433 ((data[FRAME_COMMAND_WORD_INDEX] == 0x09) || (data[FRAME_COMMAND_WORD_INDEX] == 0x89))) {
434 this->motion_threshold_number_->publish_state(data[FRAME_DATA_INDEX]);
435 } else if ((this->existence_boundary_select_ != nullptr) &&
436 ((data[FRAME_COMMAND_WORD_INDEX] == 0x0a) || (data[FRAME_COMMAND_WORD_INDEX] == 0x8a))) {
437 if (this->existence_boundary_select_->has_index(data[FRAME_DATA_INDEX] - 1)) {
438 this->existence_boundary_select_->publish_state(S_BOUNDARY_STR[data[FRAME_DATA_INDEX] - 1]);
439 }
440 } else if ((this->motion_boundary_select_ != nullptr) &&
441 ((data[FRAME_COMMAND_WORD_INDEX] == 0x0b) || (data[FRAME_COMMAND_WORD_INDEX] == 0x8b))) {
442 if (this->motion_boundary_select_->has_index(data[FRAME_DATA_INDEX] - 1)) {
443 this->motion_boundary_select_->publish_state(S_BOUNDARY_STR[data[FRAME_DATA_INDEX] - 1]);
444 }
445 } else if ((this->motion_trigger_number_ != nullptr) &&
446 ((data[FRAME_COMMAND_WORD_INDEX] == 0x0c) || (data[FRAME_COMMAND_WORD_INDEX] == 0x8c))) {
447 uint32_t motion_trigger_time = encode_uint32(data[FRAME_DATA_INDEX], data[FRAME_DATA_INDEX + 1],
448 data[FRAME_DATA_INDEX + 2], data[FRAME_DATA_INDEX + 3]);
449 this->motion_trigger_number_->publish_state(motion_trigger_time);
450 } else if ((this->motion_to_rest_number_ != nullptr) &&
451 ((data[FRAME_COMMAND_WORD_INDEX] == 0x0d) || (data[FRAME_COMMAND_WORD_INDEX] == 0x8d))) {
452 uint32_t move_to_rest_time = encode_uint32(data[FRAME_DATA_INDEX], data[FRAME_DATA_INDEX + 1],
453 data[FRAME_DATA_INDEX + 2], data[FRAME_DATA_INDEX + 3]);
454 this->motion_to_rest_number_->publish_state(move_to_rest_time);
455 } else if ((this->custom_unman_time_number_ != nullptr) &&
456 ((data[FRAME_COMMAND_WORD_INDEX] == 0x0e) || (data[FRAME_COMMAND_WORD_INDEX] == 0x8e))) {
457 uint32_t enter_unmanned_time = encode_uint32(data[FRAME_DATA_INDEX], data[FRAME_DATA_INDEX + 1],
458 data[FRAME_DATA_INDEX + 2], data[FRAME_DATA_INDEX + 3]);
459 float custom_unmanned_time = enter_unmanned_time / 1000.0;
460 this->custom_unman_time_number_->publish_state(custom_unmanned_time);
461 } else if (data[FRAME_COMMAND_WORD_INDEX] == 0x80) {
462 if (data[FRAME_DATA_INDEX]) {
463 this->s_output_info_switch_flag_ = OUTPUT_SWITCH_ON;
464 } else {
465 this->s_output_info_switch_flag_ = OUTPUT_SWTICH_OFF;
466 }
467 if (this->underlying_open_function_switch_ != nullptr) {
468 this->underlying_open_function_switch_->publish_state(data[FRAME_DATA_INDEX]);
469 }
470 } else if ((this->custom_spatial_static_value_sensor_ != nullptr) && (data[FRAME_COMMAND_WORD_INDEX] == 0x81)) {
471 this->custom_spatial_static_value_sensor_->publish_state(data[FRAME_DATA_INDEX]);
472 } else if ((this->custom_spatial_motion_value_sensor_ != nullptr) && (data[FRAME_COMMAND_WORD_INDEX] == 0x82)) {
473 this->custom_spatial_motion_value_sensor_->publish_state(data[FRAME_DATA_INDEX]);
474 } else if ((this->custom_presence_of_detection_sensor_ != nullptr) && (data[FRAME_COMMAND_WORD_INDEX] == 0x83)) {
475 this->custom_presence_of_detection_sensor_->publish_state(
476 S_PRESENCE_OF_DETECTION_RANGE_STR[data[FRAME_DATA_INDEX]]);
477 } else if ((this->custom_motion_distance_sensor_ != nullptr) && (data[FRAME_COMMAND_WORD_INDEX] == 0x84)) {
478 this->custom_motion_distance_sensor_->publish_state(data[FRAME_DATA_INDEX] * 0.5f);
479 } else if ((this->custom_motion_speed_sensor_ != nullptr) && (data[FRAME_COMMAND_WORD_INDEX] == 0x85)) {
480 this->custom_motion_speed_sensor_->publish_state((data[FRAME_DATA_INDEX] - 10) * 0.5f);
481 }
482}
483
484void MR24HPC1Component::r24_parse_data_frame_(uint8_t *data, uint8_t len) {
485 switch (data[FRAME_CONTROL_WORD_INDEX]) {
486 case 0x01: {
487 if ((this->heartbeat_state_text_sensor_ != nullptr) && (data[FRAME_COMMAND_WORD_INDEX] == 0x01)) {
488 this->heartbeat_state_text_sensor_->publish_state("Equipment Normal");
489 } else if (data[FRAME_COMMAND_WORD_INDEX] == 0x02) {
490 ESP_LOGD(TAG, "Reply: query restart packet");
491 } else if (this->heartbeat_state_text_sensor_ != nullptr) {
492 this->heartbeat_state_text_sensor_->publish_state("Equipment Abnormal");
493 }
494 } break;
495 case 0x02: {
496 this->r24_frame_parse_product_information_(data);
497 } break;
498 case 0x05: {
499 this->r24_frame_parse_work_status_(data);
500 } break;
501 case 0x08: {
502 this->r24_frame_parse_open_underlying_information_(data);
503 } break;
504 case 0x80: {
505 this->r24_frame_parse_human_information_(data);
506 } break;
507 default:
508 ESP_LOGD(TAG, "control word:0x%02X not found", data[FRAME_CONTROL_WORD_INDEX]);
509 break;
510 }
511}
512
513void MR24HPC1Component::r24_frame_parse_work_status_(uint8_t *data) {
514 if (data[FRAME_COMMAND_WORD_INDEX] == 0x01) {
515 ESP_LOGD(TAG, "Reply: get radar init status 0x%02X", data[FRAME_DATA_INDEX]);
516 } else if (data[FRAME_COMMAND_WORD_INDEX] == 0x07) {
517 if ((this->scene_mode_select_ != nullptr) && (this->scene_mode_select_->has_index(data[FRAME_DATA_INDEX]))) {
518 this->scene_mode_select_->publish_state(S_SCENE_STR[data[FRAME_DATA_INDEX]]);
519 } else {
520 ESP_LOGD(TAG, "Select has index offset %d Error", data[FRAME_DATA_INDEX]);
521 }
522 } else if ((this->sensitivity_number_ != nullptr) &&
523 ((data[FRAME_COMMAND_WORD_INDEX] == 0x08) || (data[FRAME_COMMAND_WORD_INDEX] == 0x88))) {
524 // 1-3
525 this->sensitivity_number_->publish_state(data[FRAME_DATA_INDEX]);
526 } else if (data[FRAME_COMMAND_WORD_INDEX] == 0x09) {
527 // 1-4
528 if (this->custom_mode_num_sensor_ != nullptr) {
529 this->custom_mode_num_sensor_->publish_state(data[FRAME_DATA_INDEX]);
530 }
531 if (this->custom_mode_number_ != nullptr) {
532 this->custom_mode_number_->publish_state(0);
533 }
534 if (this->custom_mode_end_text_sensor_ != nullptr) {
535 this->custom_mode_end_text_sensor_->publish_state("Setup in progress");
536 }
537 } else if (data[FRAME_COMMAND_WORD_INDEX] == 0x81) {
538 ESP_LOGD(TAG, "Reply: get radar init status 0x%02X", data[FRAME_DATA_INDEX]);
539 } else if (data[FRAME_COMMAND_WORD_INDEX] == 0x87) {
540 if ((this->scene_mode_select_ != nullptr) && (this->scene_mode_select_->has_index(data[FRAME_DATA_INDEX]))) {
541 this->scene_mode_select_->publish_state(S_SCENE_STR[data[FRAME_DATA_INDEX]]);
542 } else {
543 ESP_LOGD(TAG, "Select has index offset %d Error", data[FRAME_DATA_INDEX]);
544 }
545 } else if ((this->custom_mode_end_text_sensor_ != nullptr) && (data[FRAME_COMMAND_WORD_INDEX] == 0x0A)) {
546 this->custom_mode_end_text_sensor_->publish_state("Set Success!");
547 } else if (data[FRAME_COMMAND_WORD_INDEX] == 0x89) {
548 if (data[FRAME_DATA_INDEX] == 0) {
549 if (this->custom_mode_end_text_sensor_ != nullptr) {
550 this->custom_mode_end_text_sensor_->publish_state("Not in custom mode");
551 }
552 if (this->custom_mode_number_ != nullptr) {
553 this->custom_mode_number_->publish_state(0);
554 }
555 if (this->custom_mode_num_sensor_ != nullptr) {
556 this->custom_mode_num_sensor_->publish_state(data[FRAME_DATA_INDEX]);
557 }
558 } else {
559 if (this->custom_mode_num_sensor_ != nullptr) {
560 this->custom_mode_num_sensor_->publish_state(data[FRAME_DATA_INDEX]);
561 }
562 }
563 } else {
564 ESP_LOGD(TAG, "[%s] No found COMMAND_WORD(%02X) in Frame", __FUNCTION__, data[FRAME_COMMAND_WORD_INDEX]);
565 }
566}
567
568void MR24HPC1Component::r24_frame_parse_human_information_(uint8_t *data) {
569 if ((this->has_target_binary_sensor_ != nullptr) &&
570 ((data[FRAME_COMMAND_WORD_INDEX] == 0x01) || (data[FRAME_COMMAND_WORD_INDEX] == 0x81))) {
571 this->has_target_binary_sensor_->publish_state(S_SOMEONE_EXISTS_STR[data[FRAME_DATA_INDEX]]);
572 } else if ((this->motion_status_text_sensor_ != nullptr) &&
573 ((data[FRAME_COMMAND_WORD_INDEX] == 0x02) || (data[FRAME_COMMAND_WORD_INDEX] == 0x82))) {
574 if (data[FRAME_DATA_INDEX] < 3) {
575 this->motion_status_text_sensor_->publish_state(S_MOTION_STATUS_STR[data[FRAME_DATA_INDEX]]);
576 }
577 } else if ((this->movement_signs_sensor_ != nullptr) &&
578 ((data[FRAME_COMMAND_WORD_INDEX] == 0x03) || (data[FRAME_COMMAND_WORD_INDEX] == 0x83))) {
579 this->movement_signs_sensor_->publish_state(data[FRAME_DATA_INDEX]);
580 } else if ((this->unman_time_select_ != nullptr) &&
581 ((data[FRAME_COMMAND_WORD_INDEX] == 0x0A) || (data[FRAME_COMMAND_WORD_INDEX] == 0x8A))) {
582 // none:0x00 1s:0x01 30s:0x02 1min:0x03 2min:0x04 5min:0x05 10min:0x06 30min:0x07 1hour:0x08
583 if (data[FRAME_DATA_INDEX] < 9) {
584 this->unman_time_select_->publish_state(S_UNMANNED_TIME_STR[data[FRAME_DATA_INDEX]]);
585 }
586 } else if ((this->keep_away_text_sensor_ != nullptr) &&
587 ((data[FRAME_COMMAND_WORD_INDEX] == 0x0B) || (data[FRAME_COMMAND_WORD_INDEX] == 0x8B))) {
588 // none:0x00 close_to:0x01 far_away:0x02
589 if (data[FRAME_DATA_INDEX] < 3) {
590 this->keep_away_text_sensor_->publish_state(S_KEEP_AWAY_STR[data[FRAME_DATA_INDEX]]);
591 }
592 } else {
593 ESP_LOGD(TAG, "[%s] No found COMMAND_WORD(%02X) in Frame", __FUNCTION__, data[FRAME_COMMAND_WORD_INDEX]);
594 }
595}
596
597// Sending data frames
598void MR24HPC1Component::send_query_(const uint8_t *query, size_t string_length) {
599 this->write_array(query, string_length);
600}
601
602// Send Heartbeat Packet Command
603void MR24HPC1Component::get_heartbeat_packet() { this->send_query_(GET_HEARTBEAT, sizeof(GET_HEARTBEAT)); }
604
605// Issuance of the underlying open parameter query command
607 this->send_query_(GET_RADAR_OUTPUT_INFORMATION_SWITCH, sizeof(GET_RADAR_OUTPUT_INFORMATION_SWITCH));
608}
609
610// Issuance of product model orders
611void MR24HPC1Component::get_product_mode() { this->send_query_(GET_PRODUCT_MODE, sizeof(GET_PRODUCT_MODE)); }
612
613// Issuing the Get Product ID command
614void MR24HPC1Component::get_product_id() { this->send_query_(GET_PRODUCT_ID, sizeof(GET_PRODUCT_ID)); }
615
616// Issuing hardware model commands
617void MR24HPC1Component::get_hardware_model() { this->send_query_(GET_HARDWARE_MODEL, sizeof(GET_HARDWARE_MODEL)); }
618
619// Issuing software version commands
621 this->send_query_(GET_FIRMWARE_VERSION, sizeof(GET_FIRMWARE_VERSION));
622}
623
624void MR24HPC1Component::get_human_status() { this->send_query_(GET_HUMAN_STATUS, sizeof(GET_HUMAN_STATUS)); }
625
627 this->send_query_(GET_HUMAN_MOTION_INFORMATION, sizeof(GET_HUMAN_MOTION_INFORMATION));
628}
629
631 this->send_query_(GET_BODY_MOTION_PARAMETERS, sizeof(GET_BODY_MOTION_PARAMETERS));
632}
633
634void MR24HPC1Component::get_keep_away() { this->send_query_(GET_KEEP_AWAY, sizeof(GET_KEEP_AWAY)); }
635
636void MR24HPC1Component::get_scene_mode() { this->send_query_(GET_SCENE_MODE, sizeof(GET_SCENE_MODE)); }
637
638void MR24HPC1Component::get_sensitivity() { this->send_query_(GET_SENSITIVITY, sizeof(GET_SENSITIVITY)); }
639
640void MR24HPC1Component::get_unmanned_time() { this->send_query_(GET_UNMANNED_TIME, sizeof(GET_UNMANNED_TIME)); }
641
642void MR24HPC1Component::get_custom_mode() { this->send_query_(GET_CUSTOM_MODE, sizeof(GET_CUSTOM_MODE)); }
643
645 this->send_query_(GET_EXISTENCE_BOUNDARY, sizeof(GET_EXISTENCE_BOUNDARY));
646}
647
648void MR24HPC1Component::get_motion_boundary() { this->send_query_(GET_MOTION_BOUNDARY, sizeof(GET_MOTION_BOUNDARY)); }
649
651 this->send_query_(GET_SPATIAL_STATIC_VALUE, sizeof(GET_SPATIAL_STATIC_VALUE));
652}
653
655 this->send_query_(GET_SPATIAL_MOTION_VALUE, sizeof(GET_SPATIAL_MOTION_VALUE));
656}
657
659 this->send_query_(GET_DISTANCE_OF_STATIC_OBJECT, sizeof(GET_DISTANCE_OF_STATIC_OBJECT));
660}
661
663 this->send_query_(GET_DISTANCE_OF_MOVING_OBJECT, sizeof(GET_DISTANCE_OF_MOVING_OBJECT));
664}
665
667 this->send_query_(GET_TARGET_MOVEMENT_SPEED, sizeof(GET_TARGET_MOVEMENT_SPEED));
668}
669
671 this->send_query_(GET_EXISTENCE_THRESHOLD, sizeof(GET_EXISTENCE_THRESHOLD));
672}
673
675 this->send_query_(GET_MOTION_THRESHOLD, sizeof(GET_MOTION_THRESHOLD));
676}
677
679 this->send_query_(GET_MOTION_TRIGGER_TIME, sizeof(GET_MOTION_TRIGGER_TIME));
680}
681
683 this->send_query_(GET_MOTION_TO_REST_TIME, sizeof(GET_MOTION_TO_REST_TIME));
684}
685
687 this->send_query_(GET_CUSTOM_UNMAN_TIME, sizeof(GET_CUSTOM_UNMAN_TIME));
688}
689
690// Logic of setting: After setting, query whether the setting is successful or not!
691
693 if (enable) {
694 this->send_query_(UNDERLYING_SWITCH_ON, sizeof(UNDERLYING_SWITCH_ON));
695 } else {
696 this->send_query_(UNDERLYING_SWITCH_OFF, sizeof(UNDERLYING_SWITCH_OFF));
697 }
698 if (this->keep_away_text_sensor_ != nullptr) {
699 this->keep_away_text_sensor_->publish_state("");
700 }
701 if (this->motion_status_text_sensor_ != nullptr) {
702 this->motion_status_text_sensor_->publish_state("");
703 }
704 if (this->custom_spatial_static_value_sensor_ != nullptr) {
705 this->custom_spatial_static_value_sensor_->publish_state(NAN);
706 }
707 if (this->custom_spatial_motion_value_sensor_ != nullptr) {
708 this->custom_spatial_motion_value_sensor_->publish_state(NAN);
709 }
710 if (this->custom_motion_distance_sensor_ != nullptr) {
711 this->custom_motion_distance_sensor_->publish_state(NAN);
712 }
713 if (this->custom_presence_of_detection_sensor_ != nullptr) {
714 this->custom_presence_of_detection_sensor_->publish_state(NAN);
715 }
716 if (this->custom_motion_speed_sensor_ != nullptr) {
717 this->custom_motion_speed_sensor_->publish_state(NAN);
718 }
719}
720
722 uint8_t send_data_len = 10;
723 uint8_t send_data[10] = {0x53, 0x59, 0x05, 0x07, 0x00, 0x01, value, 0x00, 0x54, 0x43};
724 send_data[7] = get_frame_crc_sum(send_data, send_data_len);
725 this->send_query_(send_data, send_data_len);
726 if (this->custom_mode_number_ != nullptr) {
727 this->custom_mode_number_->publish_state(0);
728 }
729 if (this->custom_mode_num_sensor_ != nullptr) {
730 this->custom_mode_num_sensor_->publish_state(0);
731 }
732 this->get_scene_mode();
733 this->get_sensitivity();
734 this->get_custom_mode();
736 this->get_motion_boundary();
738 this->get_motion_threshold();
741 this->get_custom_unman_time();
742}
743
745 if (value == 0x00)
746 return;
747 uint8_t send_data_len = 10;
748 uint8_t send_data[10] = {0x53, 0x59, 0x05, 0x08, 0x00, 0x01, value, 0x00, 0x54, 0x43};
749 send_data[7] = get_frame_crc_sum(send_data, send_data_len);
750 this->send_query_(send_data, send_data_len);
751 this->get_scene_mode();
752 this->get_sensitivity();
753}
754
756 this->send_query_(SET_RESTART, sizeof(SET_RESTART));
757 this->check_dev_inf_sign_ = true;
758}
759
761 uint8_t send_data_len = 10;
762 uint8_t send_data[10] = {0x53, 0x59, 0x80, 0x0a, 0x00, 0x01, value, 0x00, 0x54, 0x43};
763 send_data[7] = get_frame_crc_sum(send_data, send_data_len);
764 this->send_query_(send_data, send_data_len);
765 this->get_unmanned_time();
766}
767
769 if (mode == 0) {
770 this->set_custom_end_mode(); // Equivalent to end setting
771 if (this->custom_mode_number_ != nullptr) {
772 this->custom_mode_number_->publish_state(0);
773 }
774 return;
775 }
776 uint8_t send_data_len = 10;
777 uint8_t send_data[10] = {0x53, 0x59, 0x05, 0x09, 0x00, 0x01, mode, 0x00, 0x54, 0x43};
778 send_data[7] = get_frame_crc_sum(send_data, send_data_len);
779 this->send_query_(send_data, send_data_len);
781 this->get_motion_boundary();
783 this->get_motion_threshold();
786 this->get_custom_unman_time();
787 this->get_custom_mode();
788 this->get_scene_mode();
789 this->get_sensitivity();
790}
791
793 uint8_t send_data_len = 10;
794 uint8_t send_data[10] = {0x53, 0x59, 0x05, 0x0a, 0x00, 0x01, 0x0F, 0xCB, 0x54, 0x43};
795 this->send_query_(send_data, send_data_len);
796 if (this->custom_mode_number_ != nullptr) {
797 this->custom_mode_number_->publish_state(0); // Clear setpoints
798 }
800 this->get_motion_boundary();
802 this->get_motion_threshold();
805 this->get_custom_unman_time();
806 this->get_custom_mode();
807 this->get_scene_mode();
808 this->get_sensitivity();
809}
810
812 if ((this->custom_mode_num_sensor_ != nullptr) && (this->custom_mode_num_sensor_->state == 0))
813 return; // You'll have to check that you're in custom mode to set it up
814 uint8_t send_data_len = 10;
815 uint8_t send_data[10] = {0x53, 0x59, 0x08, 0x0A, 0x00, 0x01, (uint8_t) (value + 1), 0x00, 0x54, 0x43};
816 send_data[7] = get_frame_crc_sum(send_data, send_data_len);
817 this->send_query_(send_data, send_data_len);
819}
820
822 if ((this->custom_mode_num_sensor_ != nullptr) && (this->custom_mode_num_sensor_->state == 0))
823 return; // You'll have to check that you're in custom mode to set it up
824 uint8_t send_data_len = 10;
825 uint8_t send_data[10] = {0x53, 0x59, 0x08, 0x0B, 0x00, 0x01, (uint8_t) (value + 1), 0x00, 0x54, 0x43};
826 send_data[7] = get_frame_crc_sum(send_data, send_data_len);
827 this->send_query_(send_data, send_data_len);
828 this->get_motion_boundary();
829}
830
832 if ((this->custom_mode_num_sensor_ != nullptr) && (this->custom_mode_num_sensor_->state == 0))
833 return; // You'll have to check that you're in custom mode to set it up
834 uint8_t send_data_len = 10;
835 uint8_t send_data[10] = {0x53, 0x59, 0x08, 0x08, 0x00, 0x01, value, 0x00, 0x54, 0x43};
836 send_data[7] = get_frame_crc_sum(send_data, send_data_len);
837 this->send_query_(send_data, send_data_len);
839}
840
842 if ((this->custom_mode_num_sensor_ != nullptr) && (this->custom_mode_num_sensor_->state == 0))
843 return; // You'll have to check that you're in custom mode to set it up
844 uint8_t send_data_len = 10;
845 uint8_t send_data[10] = {0x53, 0x59, 0x08, 0x09, 0x00, 0x01, value, 0x00, 0x54, 0x43};
846 send_data[7] = get_frame_crc_sum(send_data, send_data_len);
847 this->send_query_(send_data, send_data_len);
848 this->get_motion_threshold();
849}
850
852 if ((this->custom_mode_num_sensor_ != nullptr) && (this->custom_mode_num_sensor_->state == 0))
853 return; // You'll have to check that you're in custom mode to set it up
854 uint8_t send_data_len = 13;
855 uint8_t send_data[13] = {0x53, 0x59, 0x08, 0x0C, 0x00, 0x04, 0x00, 0x00, 0x00, value, 0x00, 0x54, 0x43};
856 send_data[10] = get_frame_crc_sum(send_data, send_data_len);
857 this->send_query_(send_data, send_data_len);
859}
860
862 if ((this->custom_mode_num_sensor_ != nullptr) && (this->custom_mode_num_sensor_->state == 0))
863 return; // You'll have to check that you're in custom mode to set it up
864 uint8_t h8_num = (value >> 8) & 0xff;
865 uint8_t l8_num = value & 0xff;
866 uint8_t send_data_len = 13;
867 uint8_t send_data[13] = {0x53, 0x59, 0x08, 0x0D, 0x00, 0x04, 0x00, 0x00, h8_num, l8_num, 0x00, 0x54, 0x43};
868 send_data[10] = get_frame_crc_sum(send_data, send_data_len);
869 this->send_query_(send_data, send_data_len);
871}
872
874 if ((this->custom_mode_num_sensor_ != nullptr) && (this->custom_mode_num_sensor_->state == 0))
875 return; // You'll have to check that you're in custom mode to set it up
876 uint32_t value_ms = value * 1000;
877 uint8_t h24_num = (value_ms >> 24) & 0xff;
878 uint8_t h16_num = (value_ms >> 16) & 0xff;
879 uint8_t h8_num = (value_ms >> 8) & 0xff;
880 uint8_t l8_num = value_ms & 0xff;
881 uint8_t send_data_len = 13;
882 uint8_t send_data[13] = {0x53, 0x59, 0x08, 0x0E, 0x00, 0x04, h24_num, h16_num, h8_num, l8_num, 0x00, 0x54, 0x43};
883 send_data[10] = get_frame_crc_sum(send_data, send_data_len);
884 this->send_query_(send_data, send_data_len);
885 this->get_custom_unman_time();
886}
887
888} // namespace seeed_mr24hpc1
889} // namespace esphome
BedjetMode mode
BedJet operating mode.
void set_interval(const std::string &name, uint32_t interval, std::function< void()> &&f)
Set an interval function with a unique name.
Definition component.cpp:89
void check_uart_settings(uint32_t baud_rate, uint8_t stop_bits=1, UARTParityOptions parity=UART_CONFIG_PARITY_NONE, uint8_t data_bits=8)
Check that the configuration of the UART bus matches the provided values and otherwise print a warnin...
Definition uart.cpp:13
bool read_byte(uint8_t *data)
Definition uart.h:29
void write_array(const uint8_t *data, size_t len)
Definition uart.h:21
Providing packet encoding functions for exchanging data with a remote host.
Definition a01nyub.cpp:7
std::string size_t len
Definition helpers.h:279
constexpr uint32_t encode_uint32(uint8_t byte1, uint8_t byte2, uint8_t byte3, uint8_t byte4)
Encode a 32-bit value given four bytes in most to least significant byte order.
Definition helpers.h:181
constexpr uint16_t encode_uint16(uint8_t msb, uint8_t lsb)
Encode a 16-bit value given the most and least significant byte.
Definition helpers.h:173