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