ESPHome 2026.1.4
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#ifdef USE_NUMBER
68 if (this->custom_mode_number_ != nullptr) {
69 this->custom_mode_number_->publish_state(0); // Zero out the custom mode
70 }
71#endif
72#ifdef USE_SENSOR
73 if (this->custom_mode_num_sensor_ != nullptr) {
74 this->custom_mode_num_sensor_->publish_state(0);
75 }
76#endif
77#ifdef USE_TEXT_SENSOR
78 if (this->custom_mode_end_text_sensor_ != nullptr) {
79 this->custom_mode_end_text_sensor_->publish_state("Not in custom mode");
80 }
81#endif
82 this->set_custom_end_mode();
83 this->poll_time_base_func_check_ = true;
84 this->check_dev_inf_sign_ = true;
85 this->sg_start_query_data_ = STANDARD_FUNCTION_QUERY_PRODUCT_MODE;
86 this->sg_data_len_ = 0;
87 this->sg_frame_len_ = 0;
88 this->sg_recv_data_state_ = FRAME_IDLE;
89 this->s_output_info_switch_flag_ = OUTPUT_SWITCH_INIT;
90
91 memset(this->c_product_mode_, 0, PRODUCT_BUF_MAX_SIZE);
92 memset(this->c_product_id_, 0, PRODUCT_BUF_MAX_SIZE);
93 memset(this->c_firmware_version_, 0, PRODUCT_BUF_MAX_SIZE);
94 memset(this->c_hardware_model_, 0, PRODUCT_BUF_MAX_SIZE);
95 memset(this->sg_frame_prase_buf_, 0, FRAME_BUF_MAX_SIZE);
96 memset(this->sg_frame_buf_, 0, FRAME_BUF_MAX_SIZE);
97
98 this->set_interval(8000, [this]() { this->update_(); });
99}
100
101// Timed polling of radar data
102void MR24HPC1Component::update_() {
103 this->get_radar_output_information_switch(); // Query the key status every so often
104 this->poll_time_base_func_check_ = true; // Query the base functionality information at regular intervals
105}
106
107// main loop
109 uint8_t byte;
110
111 // Is there data on the serial port
112 while (this->available()) {
113 this->read_byte(&byte);
114 this->r24_split_data_frame_(byte); // split data frame
115 }
116
117 if ((this->s_output_info_switch_flag_ == OUTPUT_SWTICH_OFF) &&
118 (this->sg_start_query_data_ > CUSTOM_FUNCTION_QUERY_TIME_OF_ENTER_UNMANNED) && (!this->check_dev_inf_sign_)) {
119 this->sg_start_query_data_ = STANDARD_FUNCTION_QUERY_SCENE_MODE;
120 } else if ((this->s_output_info_switch_flag_ == OUTPUT_SWITCH_ON) &&
121 (this->sg_start_query_data_ < CUSTOM_FUNCTION_QUERY_EXISTENCE_BOUNDARY) && (!this->check_dev_inf_sign_)) {
122 this->sg_start_query_data_ = CUSTOM_FUNCTION_QUERY_EXISTENCE_BOUNDARY;
123 } else if (this->check_dev_inf_sign_ && (this->sg_start_query_data_ > STANDARD_FUNCTION_QUERY_HARDWARE_MODE)) {
124 // First time power up information polling
125 this->sg_start_query_data_ = STANDARD_FUNCTION_QUERY_PRODUCT_MODE;
126 }
127
128 // Polling Functions
129 if (this->poll_time_base_func_check_) {
130 switch (this->sg_start_query_data_) {
132 this->get_product_mode();
133 this->sg_start_query_data_++;
134 break;
136 this->get_product_id();
137 this->sg_start_query_data_++;
138 break;
140 this->get_product_mode();
141 this->get_product_id();
142 this->get_firmware_version();
143 this->sg_start_query_data_++;
144 break;
145 case STANDARD_FUNCTION_QUERY_HARDWARE_MODE: // Above is the equipment information
146 this->get_product_mode();
147 this->get_product_id();
148 this->get_hardware_model();
149 this->sg_start_query_data_++;
150 this->check_dev_inf_sign_ = false;
151 break;
153 this->get_scene_mode();
154 this->sg_start_query_data_++;
155 break;
157 this->get_sensitivity();
158 this->sg_start_query_data_++;
159 break;
161 this->get_unmanned_time();
162 this->sg_start_query_data_++;
163 break;
165 this->get_human_status();
166 this->sg_start_query_data_++;
167 break;
169 this->get_human_motion_info();
170 this->sg_start_query_data_++;
171 break;
174 this->sg_start_query_data_++;
175 break;
176 case STANDARD_FUNCTION_QUERY_KEEPAWAY_STATUS: // The above is the basic functional information
177 this->get_keep_away();
178 this->sg_start_query_data_++;
179 break;
181 this->get_custom_mode();
182 this->sg_start_query_data_++;
183 break;
185 this->get_heartbeat_packet();
186 this->sg_start_query_data_++;
187 break;
190 this->sg_start_query_data_++;
191 break;
193 this->get_motion_boundary();
194 this->sg_start_query_data_++;
195 break;
198 this->sg_start_query_data_++;
199 break;
201 this->get_motion_threshold();
202 this->sg_start_query_data_++;
203 break;
206 this->sg_start_query_data_++;
207 break;
210 this->sg_start_query_data_++;
211 break;
213 this->get_custom_unman_time();
214 this->sg_start_query_data_++;
215 if (this->s_output_info_switch_flag_ == OUTPUT_SWTICH_OFF) {
216 this->poll_time_base_func_check_ = false; // Avoiding high-speed polling that can cause the device to jam
217 }
218 break;
220 this->get_human_status();
221 this->sg_start_query_data_++;
222 break;
225 this->sg_start_query_data_++;
226 break;
229 this->sg_start_query_data_++;
230 break;
233 this->sg_start_query_data_++;
234 break;
237 this->sg_start_query_data_++;
238 break;
241 this->sg_start_query_data_++;
242 this->poll_time_base_func_check_ = false; // Avoiding high-speed polling that can cause the device to jam
243 break;
244 default:
245 break;
246 }
247 }
248}
249
250// Calculate CRC check digit
251static uint8_t get_frame_crc_sum(const uint8_t *data, int len) {
252 unsigned int crc_sum = 0;
253 for (int i = 0; i < len - 3; i++) {
254 crc_sum += data[i];
255 }
256 return crc_sum & 0xff;
257}
258
259// Check that the check digit is correct
260static int get_frame_check_status(uint8_t *data, int len) {
261 uint8_t crc_sum = get_frame_crc_sum(data, len);
262 uint8_t verified = data[len - 3];
263 return (verified == crc_sum) ? 1 : 0;
264}
265
266// split data frame
267void MR24HPC1Component::r24_split_data_frame_(uint8_t value) {
268 switch (this->sg_recv_data_state_) {
269 case FRAME_IDLE: // starting value
270 if (FRAME_HEADER1_VALUE == value) {
271 this->sg_recv_data_state_ = FRAME_HEADER2;
272 }
273 break;
274 case FRAME_HEADER2:
275 if (FRAME_HEADER2_VALUE == value) {
276 this->sg_frame_buf_[0] = FRAME_HEADER1_VALUE;
277 this->sg_frame_buf_[1] = FRAME_HEADER2_VALUE;
278 this->sg_recv_data_state_ = FRAME_CTL_WORD;
279 } else {
280 this->sg_recv_data_state_ = FRAME_IDLE;
281 ESP_LOGD(TAG, "FRAME_IDLE ERROR value:%x", value);
282 }
283 break;
284 case FRAME_CTL_WORD:
285 this->sg_frame_buf_[2] = value;
286 this->sg_recv_data_state_ = FRAME_CMD_WORD;
287 break;
288 case FRAME_CMD_WORD:
289 this->sg_frame_buf_[3] = value;
290 this->sg_recv_data_state_ = FRAME_DATA_LEN_H;
291 break;
292 case FRAME_DATA_LEN_H:
293 if (value <= 4) {
294 this->sg_data_len_ = value * 256;
295 this->sg_frame_buf_[4] = value;
296 this->sg_recv_data_state_ = FRAME_DATA_LEN_L;
297 } else {
298 this->sg_data_len_ = 0;
299 this->sg_recv_data_state_ = FRAME_IDLE;
300 ESP_LOGD(TAG, "FRAME_DATA_LEN_H ERROR value:%x", value);
301 }
302 break;
303 case FRAME_DATA_LEN_L:
304 this->sg_data_len_ += value;
305 if (this->sg_data_len_ > 32) {
306 ESP_LOGD(TAG, "len=%d, FRAME_DATA_LEN_L ERROR value:%x", this->sg_data_len_, value);
307 this->sg_data_len_ = 0;
308 this->sg_recv_data_state_ = FRAME_IDLE;
309 } else {
310 this->sg_frame_buf_[5] = value;
311 this->sg_frame_len_ = 6;
312 this->sg_recv_data_state_ = FRAME_DATA_BYTES;
313 }
314 break;
315 case FRAME_DATA_BYTES:
316 this->sg_data_len_ -= 1;
317 this->sg_frame_buf_[this->sg_frame_len_++] = value;
318 if (this->sg_data_len_ <= 0) {
319 this->sg_recv_data_state_ = FRAME_DATA_CRC;
320 }
321 break;
322 case FRAME_DATA_CRC:
323 this->sg_frame_buf_[this->sg_frame_len_++] = value;
324 this->sg_recv_data_state_ = FRAME_TAIL1;
325 break;
326 case FRAME_TAIL1:
327 if (FRAME_TAIL1_VALUE == value) {
328 this->sg_recv_data_state_ = FRAME_TAIL2;
329 } else {
330 this->sg_recv_data_state_ = FRAME_IDLE;
331 this->sg_frame_len_ = 0;
332 this->sg_data_len_ = 0;
333 ESP_LOGD(TAG, "FRAME_TAIL1 ERROR value:%x", value);
334 }
335 break;
336 case FRAME_TAIL2:
337 if (FRAME_TAIL2_VALUE == value) {
338 this->sg_frame_buf_[this->sg_frame_len_++] = FRAME_TAIL1_VALUE;
339 this->sg_frame_buf_[this->sg_frame_len_++] = FRAME_TAIL2_VALUE;
340 memcpy(this->sg_frame_prase_buf_, this->sg_frame_buf_, this->sg_frame_len_);
341 if (get_frame_check_status(this->sg_frame_prase_buf_, this->sg_frame_len_)) {
342 this->r24_parse_data_frame_(this->sg_frame_prase_buf_, this->sg_frame_len_);
343 } else {
344 ESP_LOGD(TAG, "frame check failer!");
345 }
346 } else {
347 ESP_LOGD(TAG, "FRAME_TAIL2 ERROR value:%x", value);
348 }
349 memset(this->sg_frame_prase_buf_, 0, FRAME_BUF_MAX_SIZE);
350 memset(this->sg_frame_buf_, 0, FRAME_BUF_MAX_SIZE);
351 this->sg_frame_len_ = 0;
352 this->sg_data_len_ = 0;
353 this->sg_recv_data_state_ = FRAME_IDLE;
354 break;
355 default:
356 this->sg_recv_data_state_ = FRAME_IDLE;
357 }
358}
359
360// Parses data frames related to product information
361void MR24HPC1Component::r24_frame_parse_product_information_(uint8_t *data) {
362#ifdef USE_TEXT_SENSOR
363 uint16_t product_len = encode_uint16(data[FRAME_COMMAND_WORD_INDEX + 1], data[FRAME_COMMAND_WORD_INDEX + 2]);
364 if (data[FRAME_COMMAND_WORD_INDEX] == COMMAND_PRODUCT_MODE) {
365 if ((this->product_model_text_sensor_ != nullptr) && (product_len < PRODUCT_BUF_MAX_SIZE)) {
366 memset(this->c_product_mode_, 0, PRODUCT_BUF_MAX_SIZE);
367 memcpy(this->c_product_mode_, &data[FRAME_DATA_INDEX], product_len);
368 this->product_model_text_sensor_->publish_state(this->c_product_mode_);
369 } else {
370 ESP_LOGD(TAG, "Reply: get product_mode error!");
371 }
372 } else if (data[FRAME_COMMAND_WORD_INDEX] == COMMAND_PRODUCT_ID) {
373 if ((this->product_id_text_sensor_ != nullptr) && (product_len < PRODUCT_BUF_MAX_SIZE)) {
374 memset(this->c_product_id_, 0, PRODUCT_BUF_MAX_SIZE);
375 memcpy(this->c_product_id_, &data[FRAME_DATA_INDEX], product_len);
376 this->product_id_text_sensor_->publish_state(this->c_product_id_);
377 } else {
378 ESP_LOGD(TAG, "Reply: get productId error!");
379 }
380 } else if (data[FRAME_COMMAND_WORD_INDEX] == COMMAND_HARDWARE_MODEL) {
381 if ((this->hardware_model_text_sensor_ != nullptr) && (product_len < PRODUCT_BUF_MAX_SIZE)) {
382 memset(this->c_hardware_model_, 0, PRODUCT_BUF_MAX_SIZE);
383 memcpy(this->c_hardware_model_, &data[FRAME_DATA_INDEX], product_len);
384 this->hardware_model_text_sensor_->publish_state(this->c_hardware_model_);
385 ESP_LOGD(TAG, "Reply: get hardware_model :%s", this->c_hardware_model_);
386 } else {
387 ESP_LOGD(TAG, "Reply: get hardwareModel error!");
388 }
389 } else if (data[FRAME_COMMAND_WORD_INDEX] == COMMAND_FIRMWARE_VERSION) {
390 if ((this->firware_version_text_sensor_ != nullptr) && (product_len < PRODUCT_BUF_MAX_SIZE)) {
391 memset(this->c_firmware_version_, 0, PRODUCT_BUF_MAX_SIZE);
392 memcpy(this->c_firmware_version_, &data[FRAME_DATA_INDEX], product_len);
393 this->firware_version_text_sensor_->publish_state(this->c_firmware_version_);
394 } else {
395 ESP_LOGD(TAG, "Reply: get firmwareVersion error!");
396 }
397 }
398#endif
399}
400
401// Parsing the underlying open parameters
402void MR24HPC1Component::r24_frame_parse_open_underlying_information_(uint8_t *data) {
403 switch (data[FRAME_COMMAND_WORD_INDEX]) {
404 case 0x00:
405 case 0x80:
406#ifdef USE_SWITCH
407 if (this->underlying_open_function_switch_ != nullptr) {
408 this->underlying_open_function_switch_->publish_state(data[FRAME_DATA_INDEX]);
409 }
410#endif
411 this->s_output_info_switch_flag_ = data[FRAME_DATA_INDEX] ? OUTPUT_SWITCH_ON : OUTPUT_SWTICH_OFF;
412 break;
413#ifdef USE_SENSOR
414 case 0x01:
415 if (this->custom_spatial_static_value_sensor_ != nullptr) {
416 this->custom_spatial_static_value_sensor_->publish_state(data[FRAME_DATA_INDEX]);
417 }
418 if (this->custom_presence_of_detection_sensor_ != nullptr) {
419 this->custom_presence_of_detection_sensor_->publish_state(data[FRAME_DATA_INDEX + 1] * 0.5f);
420 }
421 if (this->custom_spatial_motion_value_sensor_ != nullptr) {
422 this->custom_spatial_motion_value_sensor_->publish_state(data[FRAME_DATA_INDEX + 2]);
423 }
424 if (this->custom_motion_distance_sensor_ != nullptr) {
425 this->custom_motion_distance_sensor_->publish_state(data[FRAME_DATA_INDEX + 3] * 0.5f);
426 }
427 if (this->custom_motion_speed_sensor_ != nullptr) {
428 this->custom_motion_speed_sensor_->publish_state((data[FRAME_DATA_INDEX + 4] - 10) * 0.5f);
429 }
430 break;
431 case 0x07:
432 case 0x87:
433 if (this->movement_signs_sensor_ != nullptr) {
434 this->movement_signs_sensor_->publish_state(data[FRAME_DATA_INDEX]);
435 }
436 break;
437 case 0x81:
438 if (this->custom_spatial_static_value_sensor_ != nullptr) {
439 this->custom_spatial_static_value_sensor_->publish_state(data[FRAME_DATA_INDEX]);
440 }
441 break;
442 case 0x82:
443 if (this->custom_spatial_motion_value_sensor_ != nullptr) {
444 this->custom_spatial_motion_value_sensor_->publish_state(data[FRAME_DATA_INDEX]);
445 }
446 break;
447 case 0x83:
448 if (this->custom_presence_of_detection_sensor_ != nullptr) {
449 this->custom_presence_of_detection_sensor_->publish_state(
450 S_PRESENCE_OF_DETECTION_RANGE_STR[data[FRAME_DATA_INDEX]]);
451 }
452 break;
453 case 0x84:
454 if (this->custom_motion_distance_sensor_ != nullptr) {
455 this->custom_motion_distance_sensor_->publish_state(data[FRAME_DATA_INDEX] * 0.5f);
456 }
457 break;
458 case 0x85:
459 if (this->custom_motion_speed_sensor_ != nullptr) {
460 this->custom_motion_speed_sensor_->publish_state((data[FRAME_DATA_INDEX] - 10) * 0.5f);
461 }
462 break;
463#endif
464#ifdef USE_TEXT_SENSOR
465 case 0x06:
466 case 0x86:
467 // none:0x00 close_to:0x01 far_away:0x02
468 if ((this->keep_away_text_sensor_ != nullptr) && (data[FRAME_DATA_INDEX] < 3)) {
469 this->keep_away_text_sensor_->publish_state(S_KEEP_AWAY_STR[data[FRAME_DATA_INDEX]]);
470 }
471 break;
472#endif
473#ifdef USE_NUMBER
474 case 0x08:
475 case 0x88:
476 if (this->existence_threshold_number_ != nullptr) {
477 this->existence_threshold_number_->publish_state(data[FRAME_DATA_INDEX]);
478 }
479 break;
480 case 0x09:
481 case 0x89:
482 if (this->motion_threshold_number_ != nullptr) {
483 this->motion_threshold_number_->publish_state(data[FRAME_DATA_INDEX]);
484 }
485 break;
486 case 0x0c:
487 case 0x8c:
488 if (this->motion_trigger_number_ != nullptr) {
489 uint32_t motion_trigger_time = encode_uint32(data[FRAME_DATA_INDEX], data[FRAME_DATA_INDEX + 1],
490 data[FRAME_DATA_INDEX + 2], data[FRAME_DATA_INDEX + 3]);
491 this->motion_trigger_number_->publish_state(motion_trigger_time);
492 }
493 break;
494 case 0x0d:
495 case 0x8d:
496 if (this->motion_to_rest_number_ != nullptr) {
497 uint32_t move_to_rest_time = encode_uint32(data[FRAME_DATA_INDEX], data[FRAME_DATA_INDEX + 1],
498 data[FRAME_DATA_INDEX + 2], data[FRAME_DATA_INDEX + 3]);
499 this->motion_to_rest_number_->publish_state(move_to_rest_time);
500 }
501 break;
502 case 0x0e:
503 case 0x8e:
504 if (this->custom_unman_time_number_ != nullptr) {
505 uint32_t enter_unmanned_time = encode_uint32(data[FRAME_DATA_INDEX], data[FRAME_DATA_INDEX + 1],
506 data[FRAME_DATA_INDEX + 2], data[FRAME_DATA_INDEX + 3]);
507 this->custom_unman_time_number_->publish_state(enter_unmanned_time / 1000.0f);
508 }
509 break;
510#endif
511#ifdef USE_SELECT
512 case 0x0a:
513 case 0x8a:
514 if (this->existence_boundary_select_ != nullptr) {
515 if (this->existence_boundary_select_->has_index(data[FRAME_DATA_INDEX] - 1)) {
516 this->existence_boundary_select_->publish_state(data[FRAME_DATA_INDEX] - 1);
517 }
518 }
519 break;
520 case 0x0b:
521 case 0x8b:
522 if (this->motion_boundary_select_ != nullptr) {
523 if (this->motion_boundary_select_->has_index(data[FRAME_DATA_INDEX] - 1)) {
524 this->motion_boundary_select_->publish_state(data[FRAME_DATA_INDEX] - 1);
525 }
526 }
527 break;
528#endif
529 }
530}
531
532void MR24HPC1Component::r24_parse_data_frame_(uint8_t *data, uint8_t len) {
533 switch (data[FRAME_CONTROL_WORD_INDEX]) {
534 case 0x01: {
535 if (data[FRAME_COMMAND_WORD_INDEX] == 0x02) {
536 ESP_LOGD(TAG, "Reply: query restart packet");
537 break;
538 }
539#ifdef USE_TEXT_SENSOR
540 if (this->heartbeat_state_text_sensor_ != nullptr) {
541 this->heartbeat_state_text_sensor_->publish_state(
542 data[FRAME_COMMAND_WORD_INDEX] == 0x01 ? "Equipment Normal" : "Equipment Abnormal");
543 }
544#endif
545 } break;
546 case 0x02: {
547 this->r24_frame_parse_product_information_(data);
548 } break;
549 case 0x05: {
550 this->r24_frame_parse_work_status_(data);
551 } break;
552 case 0x08: {
553 this->r24_frame_parse_open_underlying_information_(data);
554 } break;
555 case 0x80: {
556 this->r24_frame_parse_human_information_(data);
557 } break;
558 default:
559 ESP_LOGD(TAG, "control word:0x%02X not found", data[FRAME_CONTROL_WORD_INDEX]);
560 break;
561 }
562}
563
564void MR24HPC1Component::r24_frame_parse_work_status_(uint8_t *data) {
565 switch (data[FRAME_COMMAND_WORD_INDEX]) {
566 case 0x01:
567 case 0x81:
568 ESP_LOGD(TAG, "Reply: get radar init status 0x%02X", data[FRAME_DATA_INDEX]);
569 break;
570 case 0x09:
571#ifdef USE_SENSOR
572 if (this->custom_mode_num_sensor_ != nullptr) {
573 this->custom_mode_num_sensor_->publish_state(data[FRAME_DATA_INDEX]);
574 }
575#endif
576#ifdef USE_NUMBER
577 if (this->custom_mode_number_ != nullptr) {
578 this->custom_mode_number_->publish_state(0);
579 }
580#endif
581#ifdef USE_TEXT_SENSOR
582 if (this->custom_mode_end_text_sensor_ != nullptr) {
583 this->custom_mode_end_text_sensor_->publish_state("Setup in progress");
584 }
585#endif
586 break;
587 case 0x89:
588#ifdef USE_SENSOR
589 if (this->custom_mode_num_sensor_ != nullptr) {
590 this->custom_mode_num_sensor_->publish_state(data[FRAME_DATA_INDEX]);
591 }
592#endif
593 if (data[FRAME_DATA_INDEX] == 0) {
594#ifdef USE_TEXT_SENSOR
595 if (this->custom_mode_end_text_sensor_ != nullptr) {
596 this->custom_mode_end_text_sensor_->publish_state("Not in custom mode");
597 }
598#endif
599#ifdef USE_NUMBER
600 if (this->custom_mode_number_ != nullptr) {
601 this->custom_mode_number_->publish_state(0);
602 }
603#endif
604 }
605 break;
606#ifdef USE_SELECT
607 case 0x07:
608 case 0x87:
609 if ((this->scene_mode_select_ != nullptr) && (this->scene_mode_select_->has_index(data[FRAME_DATA_INDEX]))) {
610 this->scene_mode_select_->publish_state(data[FRAME_DATA_INDEX]);
611 } else {
612 ESP_LOGD(TAG, "Select has index offset %d Error", data[FRAME_DATA_INDEX]);
613 }
614 break;
615#endif
616#ifdef USE_NUMBER
617 case 0x08:
618 case 0x88:
619 if (this->sensitivity_number_ != nullptr) {
620 this->sensitivity_number_->publish_state(data[FRAME_DATA_INDEX]);
621 }
622 break;
623#endif
624#ifdef USE_TEXT_SENSOR
625 case 0x0A:
626 if (this->custom_mode_end_text_sensor_ != nullptr) {
627 this->custom_mode_end_text_sensor_->publish_state("Set Success!");
628 }
629 break;
630#endif
631 default:
632 ESP_LOGD(TAG, "[%s] No found COMMAND_WORD(%02X) in Frame", __FUNCTION__, data[FRAME_COMMAND_WORD_INDEX]);
633 break;
634 }
635}
636
637void MR24HPC1Component::r24_frame_parse_human_information_(uint8_t *data) {
638 switch (data[FRAME_COMMAND_WORD_INDEX]) {
639#ifdef USE_BINARY_SENSOR
640 case 0x01:
641 case 0x81:
642 if (this->has_target_binary_sensor_ != nullptr) {
643 this->has_target_binary_sensor_->publish_state(S_SOMEONE_EXISTS_STR[data[FRAME_DATA_INDEX]]);
644 }
645 break;
646#endif
647#ifdef USE_SENSOR
648 case 0x03:
649 case 0x83:
650 if (this->movement_signs_sensor_ != nullptr) {
651 this->movement_signs_sensor_->publish_state(data[FRAME_DATA_INDEX]);
652 }
653 break;
654#endif
655#ifdef USE_TEXT_SENSOR
656 case 0x02:
657 case 0x82:
658 if ((this->motion_status_text_sensor_ != nullptr) && (data[FRAME_DATA_INDEX] < 3)) {
659 this->motion_status_text_sensor_->publish_state(S_MOTION_STATUS_STR[data[FRAME_DATA_INDEX]]);
660 }
661 break;
662 case 0x0B:
663 case 0x8B:
664 // none:0x00 close_to:0x01 far_away:0x02
665 if ((this->keep_away_text_sensor_ != nullptr) && (data[FRAME_DATA_INDEX] < 3)) {
666 this->keep_away_text_sensor_->publish_state(S_KEEP_AWAY_STR[data[FRAME_DATA_INDEX]]);
667 }
668 break;
669#endif
670#ifdef USE_SELECT
671 case 0x0A:
672 case 0x8A:
673 // none:0x00 1s:0x01 30s:0x02 1min:0x03 2min:0x04 5min:0x05 10min:0x06 30min:0x07 1hour:0x08
674 if ((this->unman_time_select_ != nullptr) && (data[FRAME_DATA_INDEX] < 9)) {
675 this->unman_time_select_->publish_state(data[FRAME_DATA_INDEX]);
676 }
677 break;
678#endif
679 default:
680 ESP_LOGD(TAG, "[%s] No found COMMAND_WORD(%02X) in Frame", __FUNCTION__, data[FRAME_COMMAND_WORD_INDEX]);
681 break;
682 }
683}
684
685// Sending data frames
686void MR24HPC1Component::send_query_(const uint8_t *query, size_t string_length) {
687 this->write_array(query, string_length);
688}
689
690// Send Heartbeat Packet Command
691void MR24HPC1Component::get_heartbeat_packet() { this->send_query_(GET_HEARTBEAT, sizeof(GET_HEARTBEAT)); }
692
693// Issuance of the underlying open parameter query command
695 this->send_query_(GET_RADAR_OUTPUT_INFORMATION_SWITCH, sizeof(GET_RADAR_OUTPUT_INFORMATION_SWITCH));
696}
697
698// Issuance of product model orders
699void MR24HPC1Component::get_product_mode() { this->send_query_(GET_PRODUCT_MODE, sizeof(GET_PRODUCT_MODE)); }
700
701// Issuing the Get Product ID command
702void MR24HPC1Component::get_product_id() { this->send_query_(GET_PRODUCT_ID, sizeof(GET_PRODUCT_ID)); }
703
704// Issuing hardware model commands
705void MR24HPC1Component::get_hardware_model() { this->send_query_(GET_HARDWARE_MODEL, sizeof(GET_HARDWARE_MODEL)); }
706
707// Issuing software version commands
709 this->send_query_(GET_FIRMWARE_VERSION, sizeof(GET_FIRMWARE_VERSION));
710}
711
712void MR24HPC1Component::get_human_status() { this->send_query_(GET_HUMAN_STATUS, sizeof(GET_HUMAN_STATUS)); }
713
715 this->send_query_(GET_HUMAN_MOTION_INFORMATION, sizeof(GET_HUMAN_MOTION_INFORMATION));
716}
717
719 this->send_query_(GET_BODY_MOTION_PARAMETERS, sizeof(GET_BODY_MOTION_PARAMETERS));
720}
721
722void MR24HPC1Component::get_keep_away() { this->send_query_(GET_KEEP_AWAY, sizeof(GET_KEEP_AWAY)); }
723
724void MR24HPC1Component::get_scene_mode() { this->send_query_(GET_SCENE_MODE, sizeof(GET_SCENE_MODE)); }
725
726void MR24HPC1Component::get_sensitivity() { this->send_query_(GET_SENSITIVITY, sizeof(GET_SENSITIVITY)); }
727
728void MR24HPC1Component::get_unmanned_time() { this->send_query_(GET_UNMANNED_TIME, sizeof(GET_UNMANNED_TIME)); }
729
730void MR24HPC1Component::get_custom_mode() { this->send_query_(GET_CUSTOM_MODE, sizeof(GET_CUSTOM_MODE)); }
731
733 this->send_query_(GET_EXISTENCE_BOUNDARY, sizeof(GET_EXISTENCE_BOUNDARY));
734}
735
736void MR24HPC1Component::get_motion_boundary() { this->send_query_(GET_MOTION_BOUNDARY, sizeof(GET_MOTION_BOUNDARY)); }
737
739 this->send_query_(GET_SPATIAL_STATIC_VALUE, sizeof(GET_SPATIAL_STATIC_VALUE));
740}
741
743 this->send_query_(GET_SPATIAL_MOTION_VALUE, sizeof(GET_SPATIAL_MOTION_VALUE));
744}
745
747 this->send_query_(GET_DISTANCE_OF_STATIC_OBJECT, sizeof(GET_DISTANCE_OF_STATIC_OBJECT));
748}
749
751 this->send_query_(GET_DISTANCE_OF_MOVING_OBJECT, sizeof(GET_DISTANCE_OF_MOVING_OBJECT));
752}
753
755 this->send_query_(GET_TARGET_MOVEMENT_SPEED, sizeof(GET_TARGET_MOVEMENT_SPEED));
756}
757
759 this->send_query_(GET_EXISTENCE_THRESHOLD, sizeof(GET_EXISTENCE_THRESHOLD));
760}
761
763 this->send_query_(GET_MOTION_THRESHOLD, sizeof(GET_MOTION_THRESHOLD));
764}
765
767 this->send_query_(GET_MOTION_TRIGGER_TIME, sizeof(GET_MOTION_TRIGGER_TIME));
768}
769
771 this->send_query_(GET_MOTION_TO_REST_TIME, sizeof(GET_MOTION_TO_REST_TIME));
772}
773
775 this->send_query_(GET_CUSTOM_UNMAN_TIME, sizeof(GET_CUSTOM_UNMAN_TIME));
776}
777
778// Logic of setting: After setting, query whether the setting is successful or not!
779
781 if (enable) {
782 this->send_query_(UNDERLYING_SWITCH_ON, sizeof(UNDERLYING_SWITCH_ON));
783 } else {
784 this->send_query_(UNDERLYING_SWITCH_OFF, sizeof(UNDERLYING_SWITCH_OFF));
785 }
786#ifdef USE_TEXT_SENSOR
787 if (this->keep_away_text_sensor_ != nullptr) {
788 this->keep_away_text_sensor_->publish_state("");
789 }
790 if (this->motion_status_text_sensor_ != nullptr) {
791 this->motion_status_text_sensor_->publish_state("");
792 }
793#endif
794#ifdef USE_SENSOR
795 if (this->custom_spatial_static_value_sensor_ != nullptr) {
796 this->custom_spatial_static_value_sensor_->publish_state(NAN);
797 }
798 if (this->custom_spatial_motion_value_sensor_ != nullptr) {
799 this->custom_spatial_motion_value_sensor_->publish_state(NAN);
800 }
801 if (this->custom_motion_distance_sensor_ != nullptr) {
802 this->custom_motion_distance_sensor_->publish_state(NAN);
803 }
804 if (this->custom_presence_of_detection_sensor_ != nullptr) {
805 this->custom_presence_of_detection_sensor_->publish_state(NAN);
806 }
807 if (this->custom_motion_speed_sensor_ != nullptr) {
808 this->custom_motion_speed_sensor_->publish_state(NAN);
809 }
810#endif
811}
812
814 uint8_t send_data_len = 10;
815 uint8_t send_data[10] = {0x53, 0x59, 0x05, 0x07, 0x00, 0x01, value, 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);
818#ifdef USE_NUMBER
819 if (this->custom_mode_number_ != nullptr) {
820 this->custom_mode_number_->publish_state(0);
821 }
822#endif
823#ifdef USE_SENSOR
824 if (this->custom_mode_num_sensor_ != nullptr) {
825 this->custom_mode_num_sensor_->publish_state(0);
826 }
827#endif
828 this->get_scene_mode();
829 this->get_sensitivity();
830 this->get_custom_mode();
832 this->get_motion_boundary();
834 this->get_motion_threshold();
837 this->get_custom_unman_time();
838}
839
841 if (value == 0x00)
842 return;
843 uint8_t send_data_len = 10;
844 uint8_t send_data[10] = {0x53, 0x59, 0x05, 0x08, 0x00, 0x01, value, 0x00, 0x54, 0x43};
845 send_data[7] = get_frame_crc_sum(send_data, send_data_len);
846 this->send_query_(send_data, send_data_len);
847 this->get_scene_mode();
848 this->get_sensitivity();
849}
850
852 this->send_query_(SET_RESTART, sizeof(SET_RESTART));
853 this->check_dev_inf_sign_ = true;
854}
855
857 uint8_t send_data_len = 10;
858 uint8_t send_data[10] = {0x53, 0x59, 0x80, 0x0a, 0x00, 0x01, value, 0x00, 0x54, 0x43};
859 send_data[7] = get_frame_crc_sum(send_data, send_data_len);
860 this->send_query_(send_data, send_data_len);
861 this->get_unmanned_time();
862}
863
865 if (mode == 0) {
866 this->set_custom_end_mode(); // Equivalent to end setting
867#ifdef USE_NUMBER
868 if (this->custom_mode_number_ != nullptr) {
869 this->custom_mode_number_->publish_state(0);
870 }
871#endif
872 return;
873 }
874 uint8_t send_data_len = 10;
875 uint8_t send_data[10] = {0x53, 0x59, 0x05, 0x09, 0x00, 0x01, mode, 0x00, 0x54, 0x43};
876 send_data[7] = get_frame_crc_sum(send_data, send_data_len);
877 this->send_query_(send_data, send_data_len);
879 this->get_motion_boundary();
881 this->get_motion_threshold();
884 this->get_custom_unman_time();
885 this->get_custom_mode();
886 this->get_scene_mode();
887 this->get_sensitivity();
888}
889
891 uint8_t send_data_len = 10;
892 uint8_t send_data[10] = {0x53, 0x59, 0x05, 0x0a, 0x00, 0x01, 0x0F, 0xCB, 0x54, 0x43};
893 this->send_query_(send_data, send_data_len);
894#ifdef USE_NUMBER
895 if (this->custom_mode_number_ != nullptr) {
896 this->custom_mode_number_->publish_state(0); // Clear setpoints
897 }
898#endif
900 this->get_motion_boundary();
902 this->get_motion_threshold();
905 this->get_custom_unman_time();
906 this->get_custom_mode();
907 this->get_scene_mode();
908 this->get_sensitivity();
909}
910
912#ifdef USE_SENSOR
913 if ((this->custom_mode_num_sensor_ != nullptr) && (this->custom_mode_num_sensor_->state == 0))
914 return; // You'll have to check that you're in custom mode to set it up
915#endif
916 uint8_t send_data_len = 10;
917 uint8_t send_data[10] = {0x53, 0x59, 0x08, 0x0A, 0x00, 0x01, (uint8_t) (value + 1), 0x00, 0x54, 0x43};
918 send_data[7] = get_frame_crc_sum(send_data, send_data_len);
919 this->send_query_(send_data, send_data_len);
921}
922
924#ifdef USE_SENSOR
925 if ((this->custom_mode_num_sensor_ != nullptr) && (this->custom_mode_num_sensor_->state == 0))
926 return; // You'll have to check that you're in custom mode to set it up
927#endif
928 uint8_t send_data_len = 10;
929 uint8_t send_data[10] = {0x53, 0x59, 0x08, 0x0B, 0x00, 0x01, (uint8_t) (value + 1), 0x00, 0x54, 0x43};
930 send_data[7] = get_frame_crc_sum(send_data, send_data_len);
931 this->send_query_(send_data, send_data_len);
932 this->get_motion_boundary();
933}
934
936#ifdef USE_SENSOR
937 if ((this->custom_mode_num_sensor_ != nullptr) && (this->custom_mode_num_sensor_->state == 0))
938 return; // You'll have to check that you're in custom mode to set it up
939#endif
940 uint8_t send_data_len = 10;
941 uint8_t send_data[10] = {0x53, 0x59, 0x08, 0x08, 0x00, 0x01, value, 0x00, 0x54, 0x43};
942 send_data[7] = get_frame_crc_sum(send_data, send_data_len);
943 this->send_query_(send_data, send_data_len);
945}
946
948#ifdef USE_SENSOR
949 if ((this->custom_mode_num_sensor_ != nullptr) && (this->custom_mode_num_sensor_->state == 0))
950 return; // You'll have to check that you're in custom mode to set it up
951#endif
952 uint8_t send_data_len = 10;
953 uint8_t send_data[10] = {0x53, 0x59, 0x08, 0x09, 0x00, 0x01, value, 0x00, 0x54, 0x43};
954 send_data[7] = get_frame_crc_sum(send_data, send_data_len);
955 this->send_query_(send_data, send_data_len);
956 this->get_motion_threshold();
957}
958
960#ifdef USE_SENSOR
961 if ((this->custom_mode_num_sensor_ != nullptr) && (this->custom_mode_num_sensor_->state == 0))
962 return; // You'll have to check that you're in custom mode to set it up
963#endif
964 uint8_t send_data_len = 13;
965 uint8_t send_data[13] = {0x53, 0x59, 0x08, 0x0C, 0x00, 0x04, 0x00, 0x00, 0x00, value, 0x00, 0x54, 0x43};
966 send_data[10] = get_frame_crc_sum(send_data, send_data_len);
967 this->send_query_(send_data, send_data_len);
969}
970
972#ifdef USE_SENSOR
973 if ((this->custom_mode_num_sensor_ != nullptr) && (this->custom_mode_num_sensor_->state == 0))
974 return; // You'll have to check that you're in custom mode to set it up
975#endif
976 uint8_t h8_num = (value >> 8) & 0xff;
977 uint8_t l8_num = value & 0xff;
978 uint8_t send_data_len = 13;
979 uint8_t send_data[13] = {0x53, 0x59, 0x08, 0x0D, 0x00, 0x04, 0x00, 0x00, h8_num, l8_num, 0x00, 0x54, 0x43};
980 send_data[10] = get_frame_crc_sum(send_data, send_data_len);
981 this->send_query_(send_data, send_data_len);
983}
984
986#ifdef USE_SENSOR
987 if ((this->custom_mode_num_sensor_ != nullptr) && (this->custom_mode_num_sensor_->state == 0))
988 return; // You'll have to check that you're in custom mode to set it up
989#endif
990 uint32_t value_ms = value * 1000;
991 uint8_t h24_num = (value_ms >> 24) & 0xff;
992 uint8_t h16_num = (value_ms >> 16) & 0xff;
993 uint8_t h8_num = (value_ms >> 8) & 0xff;
994 uint8_t l8_num = value_ms & 0xff;
995 uint8_t send_data_len = 13;
996 uint8_t send_data[13] = {0x53, 0x59, 0x08, 0x0E, 0x00, 0x04, h24_num, h16_num, h8_num, l8_num, 0x00, 0x54, 0x43};
997 send_data[10] = get_frame_crc_sum(send_data, send_data_len);
998 this->send_query_(send_data, send_data_len);
999 this->get_custom_unman_time();
1000}
1001
1002} // namespace seeed_mr24hpc1
1003} // namespace esphome
BedjetMode mode
BedJet operating mode.
ESPDEPRECATED("Use const char* or uint32_t overload instead. Removed in 2026.7.0", "2026.1.0") void set_interval(const std voi set_interval)(const char *name, uint32_t interval, std::function< void()> &&f)
Set an interval function with a unique name.
Definition component.h:327
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:12
bool read_byte(uint8_t *data)
Definition uart.h:34
void write_array(const uint8_t *data, size_t len)
Definition uart.h:26
Providing packet encoding functions for exchanging data with a remote host.
Definition a01nyub.cpp:7
std::string size_t len
Definition helpers.h:595
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:471
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:463