97template<
size_t N> uint8_t
find_uint8(
const StringToUint8 (&arr)[N],
const std::string &str) {
98 for (
const auto &entry : arr) {
105template<
size_t N>
const char *
find_str(
const Uint8ToString (&arr)[N], uint8_t value) {
106 for (
const auto &entry : arr) {
107 if (value == entry.value)
114static constexpr uint8_t CMD_ENABLE_CONF = 0xFF;
115static constexpr uint8_t CMD_DISABLE_CONF = 0xFE;
116static constexpr uint8_t CMD_QUERY_VERSION = 0xA0;
117static constexpr uint8_t CMD_QUERY_MAC_ADDRESS = 0xA5;
118static constexpr uint8_t CMD_RESET = 0xA2;
119static constexpr uint8_t CMD_RESTART = 0xA3;
120static constexpr uint8_t CMD_BLUETOOTH = 0xA4;
121static constexpr uint8_t CMD_SINGLE_TARGET_MODE = 0x80;
122static constexpr uint8_t CMD_MULTI_TARGET_MODE = 0x90;
123static constexpr uint8_t CMD_QUERY_TARGET_MODE = 0x91;
124static constexpr uint8_t CMD_SET_BAUD_RATE = 0xA1;
125static constexpr uint8_t CMD_QUERY_ZONE = 0xC1;
126static constexpr uint8_t CMD_SET_ZONE = 0xC2;
128static constexpr uint8_t HEADER_FOOTER_SIZE = 4;
130static constexpr uint8_t CMD_FRAME_HEADER[HEADER_FOOTER_SIZE] = {0xFD, 0xFC, 0xFB, 0xFA};
131static constexpr uint8_t CMD_FRAME_FOOTER[HEADER_FOOTER_SIZE] = {0x04, 0x03, 0x02, 0x01};
133static constexpr uint8_t DATA_FRAME_HEADER[HEADER_FOOTER_SIZE] = {0xAA, 0xFF, 0x03, 0x00};
134static constexpr uint8_t DATA_FRAME_FOOTER[2] = {0x55, 0xCC};
137static constexpr uint8_t ZONE_ACK_FRAME_SIZE = 40;
139static constexpr uint8_t NO_MAC[] = {0x08, 0x05, 0x04, 0x03, 0x02, 0x01};
143static inline void convert_int_values_to_hex(
const int *values, uint8_t *bytes) {
144 for (uint8_t i = 0; i < 4; i++) {
145 uint16_t
val = values[i] & 0xFFFF;
147 bytes[i * 2 + 1] = (
val >> 8) & 0xFF;
151static inline int16_t decode_coordinate(uint8_t low_byte, uint8_t high_byte) {
152 int16_t coordinate = (high_byte & 0x7F) << 8 | low_byte;
153 if ((high_byte & 0x80) == 0) {
154 coordinate = -coordinate;
159static inline int16_t decode_speed(uint8_t low_byte, uint8_t high_byte) {
160 int16_t
speed = (high_byte & 0x7F) << 8 | low_byte;
161 if ((high_byte & 0x80) == 0) {
167static inline bool validate_header_footer(
const uint8_t *header_footer,
const uint8_t *
buffer) {
168 return std::memcmp(header_footer,
buffer, HEADER_FOOTER_SIZE) == 0;
173static inline uint8_t drop_to_next_header(uint8_t *
buffer, uint8_t
len) {
174 for (uint8_t start = 1; start <
len; start++) {
175 const size_t n = std::min<size_t>(HEADER_FOOTER_SIZE,
len - start);
176 if (std::memcmp(&
buffer[start], CMD_FRAME_HEADER, n) == 0 ||
177 std::memcmp(&
buffer[start], DATA_FRAME_HEADER, n) == 0) {
187 if (this->presence_timeout_number_ !=
nullptr) {
188 this->
pref_ = this->presence_timeout_number_->make_entity_preference<
float>();
189 this->set_presence_timeout();
192#ifdef LD2450_POLYGON_ZONE_COUNT
197 this->restart_and_read_all_info();
200void LD2450Component::dump_config() {
201 char mac_s[MAC_ADDRESS_PRETTY_BUFFER_SIZE];
207 " Firmware version: %s\n"
210#ifdef USE_BINARY_SENSOR
211 ESP_LOGCONFIG(TAG,
"Binary Sensors:");
212 LOG_BINARY_SENSOR(
" ",
"MovingTarget", this->moving_target_binary_sensor_);
213 LOG_BINARY_SENSOR(
" ",
"StillTarget", this->still_target_binary_sensor_);
214 LOG_BINARY_SENSOR(
" ",
"Target", this->target_binary_sensor_);
217 ESP_LOGCONFIG(TAG,
"Sensors:");
218 LOG_SENSOR_WITH_DEDUP_SAFE(
" ",
"MovingTargetCount", this->moving_target_count_sensor_);
219 LOG_SENSOR_WITH_DEDUP_SAFE(
" ",
"StillTargetCount", this->still_target_count_sensor_);
220 LOG_SENSOR_WITH_DEDUP_SAFE(
" ",
"TargetCount", this->target_count_sensor_);
222 LOG_SENSOR_WITH_DEDUP_SAFE(
" ",
"TargetX", s);
225 LOG_SENSOR_WITH_DEDUP_SAFE(
" ",
"TargetY", s);
228 LOG_SENSOR_WITH_DEDUP_SAFE(
" ",
"TargetAngle", s);
231 LOG_SENSOR_WITH_DEDUP_SAFE(
" ",
"TargetDistance", s);
234 LOG_SENSOR_WITH_DEDUP_SAFE(
" ",
"TargetResolution", s);
237 LOG_SENSOR_WITH_DEDUP_SAFE(
" ",
"TargetSpeed", s);
240 LOG_SENSOR_WITH_DEDUP_SAFE(
" ",
"ZoneTargetCount", s);
243 LOG_SENSOR_WITH_DEDUP_SAFE(
" ",
"ZoneMovingTargetCount", s);
246 LOG_SENSOR_WITH_DEDUP_SAFE(
" ",
"ZoneStillTargetCount", s);
249#ifdef USE_TEXT_SENSOR
250 ESP_LOGCONFIG(TAG,
"Text Sensors:");
251 LOG_TEXT_SENSOR(
" ",
"Version", this->version_text_sensor_);
252 LOG_TEXT_SENSOR(
" ",
"MAC address", this->mac_text_sensor_);
254 LOG_TEXT_SENSOR(
" ",
"Direction", s);
258 ESP_LOGCONFIG(TAG,
"Numbers:");
259 LOG_NUMBER(
" ",
"PresenceTimeout", this->presence_timeout_number_);
261 LOG_NUMBER(
" ",
"ZoneX1", n.x1);
262 LOG_NUMBER(
" ",
"ZoneY1", n.y1);
263 LOG_NUMBER(
" ",
"ZoneX2", n.x2);
264 LOG_NUMBER(
" ",
"ZoneY2", n.y2);
268 ESP_LOGCONFIG(TAG,
"Selects:");
269 LOG_SELECT(
" ",
"BaudRate", this->baud_rate_select_);
270 LOG_SELECT(
" ",
"ZoneType", this->zone_type_select_);
273 ESP_LOGCONFIG(TAG,
"Switches:");
274 LOG_SWITCH(
" ",
"Bluetooth", this->bluetooth_switch_);
275 LOG_SWITCH(
" ",
"MultiTarget", this->multi_target_switch_);
278 ESP_LOGCONFIG(TAG,
"Buttons:");
279 LOG_BUTTON(
" ",
"FactoryReset", this->factory_reset_button_);
280 LOG_BUTTON(
" ",
"Restart", this->restart_button_);
282#ifdef LD2450_POLYGON_ZONE_COUNT
283 ESP_LOGCONFIG(TAG,
"Polygon Zones:");
284 for (PolygonZone *zone : this->polygon_zones_) {
290void LD2450Component::loop() {
293 uint8_t buf[MAX_LINE_LENGTH];
295 size_t to_read = std::min(avail,
sizeof(buf));
301 for (
size_t i = 0; i < to_read; i++) {
312 if (target.x > zone.
x1 && target.x < zone.
x2 && target.y > zone.
y1 && target.y < zone.
y2) {
313 if (target.is_moving) {
323void LD2450Component::reset_radar_zone() {
334void LD2450Component::set_radar_zone(int32_t zone_type, int32_t zone1_x1, int32_t zone1_y1, int32_t zone1_x2,
335 int32_t zone1_y2, int32_t zone2_x1, int32_t zone2_y1, int32_t zone2_x2,
336 int32_t zone2_y2, int32_t zone3_x1, int32_t zone3_y1, int32_t zone3_x2,
339 int zone_parameters[12] = {zone1_x1, zone1_y1, zone1_x2, zone1_y2, zone2_x1, zone2_y1,
340 zone2_x2, zone2_y2, zone3_x1, zone3_y1, zone3_x2, zone3_y2};
341 for (uint8_t i = 0; i < MAX_ZONES; i++) {
352 uint8_t cmd_value[26] = {};
353 uint8_t zone_type_bytes[2] = {
static_cast<uint8_t
>(this->
zone_type_), 0x00};
354 uint8_t area_config[24] = {};
355 for (uint8_t i = 0; i < MAX_ZONES; i++) {
358 ld2450::convert_int_values_to_hex(values, area_config + (i * 8));
360 std::memcpy(cmd_value, zone_type_bytes,
sizeof(zone_type_bytes));
361 std::memcpy(cmd_value + 2, area_config,
sizeof(area_config));
363 this->
send_command_(CMD_SET_ZONE, cmd_value,
sizeof(cmd_value));
369 if (check_millis == 0) {
373 this->
timeout_ = ld2450::convert_seconds_to_ms(DEFAULT_PRESENCE_TIMEOUT);
380 uint8_t index, start;
381 for (index = 0; index < MAX_ZONES; index++) {
382 start = 12 + index * 8;
389 if (this->zone_numbers_[index].x1 !=
nullptr) {
390 this->zone_numbers_[index].x1->publish_state(this->
zone_config_[index].x1);
391 this->zone_numbers_[index].y1->publish_state(this->
zone_config_[index].y1);
392 this->zone_numbers_[index].x2->publish_state(this->
zone_config_[index].x2);
393 this->zone_numbers_[index].y2->publish_state(this->
zone_config_[index].y2);
400void LD2450Component::read_all_info() {
408 if (this->baud_rate_select_ !=
nullptr) {
410 this->baud_rate_select_->publish_state(*index);
413 this->publish_zone_type();
418void LD2450Component::query_zone_info() {
425void LD2450Component::restart_and_read_all_info() {
428 this->
set_timeout(1500, [
this]() { this->read_all_info(); });
433 ESP_LOGV(TAG,
"Sending COMMAND %02X", command);
435 this->
write_array(CMD_FRAME_HEADER,
sizeof(CMD_FRAME_HEADER));
438 if (command_value !=
nullptr) {
439 len += command_value_len;
442 uint8_t len_cmd[] = {
len, 0x00, command, 0x00};
445 if (command_value !=
nullptr) {
446 this->
write_array(command_value, command_value_len);
449 this->
write_array(CMD_FRAME_FOOTER,
sizeof(CMD_FRAME_FOOTER));
451 if (command != CMD_ENABLE_CONF && command != CMD_DISABLE_CONF) {
461 ESP_LOGE(TAG,
"Invalid length");
464 if (!ld2450::validate_header_footer(DATA_FRAME_HEADER, this->
buffer_data_) ||
467 ESP_LOGE(TAG,
"Invalid header/footer");
471 int16_t target_count = 0;
472 int16_t still_target_count = 0;
473 int16_t moving_target_count = 0;
483 bool is_moving =
false;
485#if defined(USE_BINARY_SENSOR) || defined(USE_SENSOR) || defined(USE_TEXT_SENSOR)
487 for (index = 0; index < MAX_TARGETS; index++) {
506 moving_target_count++;
510 int32_t x_squared = (int32_t) tx * tx;
511 int32_t y_squared = (int32_t) ty * ty;
512 td = (uint16_t) sqrtf(x_squared + y_squared);
518 SAFE_PUBLISH_SENSOR_UNKNOWN(this->move_x_sensors_[index]);
519 SAFE_PUBLISH_SENSOR_UNKNOWN(this->move_y_sensors_[index]);
520 SAFE_PUBLISH_SENSOR_UNKNOWN(this->move_resolution_sensors_[index]);
521 SAFE_PUBLISH_SENSOR_UNKNOWN(this->move_speed_sensors_[index]);
522 SAFE_PUBLISH_SENSOR_UNKNOWN(this->move_distance_sensors_[index]);
523 SAFE_PUBLISH_SENSOR_UNKNOWN(this->move_angle_sensors_[index]);
525 SAFE_PUBLISH_SENSOR(this->move_x_sensors_[index], tx);
526 SAFE_PUBLISH_SENSOR(this->move_y_sensors_[index], ty);
527 SAFE_PUBLISH_SENSOR(this->move_resolution_sensors_[index], res);
528 SAFE_PUBLISH_SENSOR(this->move_speed_sensors_[index], ts);
529 SAFE_PUBLISH_SENSOR(this->move_distance_sensors_[index], td);
531 angle = atan2f(
static_cast<float>(-tx),
static_cast<float>(ty)) * (180.0f / std::numbers::pi_v<float>);
532 SAFE_PUBLISH_SENSOR(this->move_angle_sensors_[index], angle);
535#ifdef USE_TEXT_SENSOR
548 if (tsd !=
nullptr) {
562 still_target_count = target_count - moving_target_count;
565#ifdef LD2450_POLYGON_ZONE_COUNT
568 if (!zone->has_polygon())
570 bool target_inside =
false;
573 if ((target.x != 0 || target.y != 0) && zone->contains(target.x, target.y)) {
574 target_inside =
true;
584 uint8_t zone_still_targets = 0;
585 uint8_t zone_moving_targets = 0;
586 uint8_t zone_all_targets = 0;
587 for (index = 0; index < MAX_ZONES; index++) {
589 zone_all_targets = zone_still_targets + zone_moving_targets;
592 SAFE_PUBLISH_SENSOR(this->zone_still_target_count_sensors_[index], zone_still_targets);
594 SAFE_PUBLISH_SENSOR(this->zone_moving_target_count_sensors_[index], zone_moving_targets);
596 SAFE_PUBLISH_SENSOR(this->zone_target_count_sensors_[index], zone_all_targets);
600 SAFE_PUBLISH_SENSOR(this->target_count_sensor_, target_count);
602 SAFE_PUBLISH_SENSOR(this->still_target_count_sensor_, still_target_count);
604 SAFE_PUBLISH_SENSOR(this->moving_target_count_sensor_, moving_target_count);
608#ifdef USE_BINARY_SENSOR
610 if (this->target_binary_sensor_ !=
nullptr) {
611 if (target_count > 0) {
612 this->target_binary_sensor_->publish_state(
true);
615 this->target_binary_sensor_->publish_state(
false);
617 ESP_LOGV(TAG,
"Clear presence waiting timeout: %" PRIu32, this->
timeout_);
622 if (this->moving_target_binary_sensor_ !=
nullptr) {
623 if (moving_target_count > 0) {
624 this->moving_target_binary_sensor_->publish_state(
true);
627 this->moving_target_binary_sensor_->publish_state(
false);
632 if (this->still_target_binary_sensor_ !=
nullptr) {
633 if (still_target_count > 0) {
634 this->still_target_binary_sensor_->publish_state(
true);
637 this->still_target_binary_sensor_->publish_state(
false);
642#ifdef USE_BINARY_SENSOR
644 if (target_count > 0) {
647 if (moving_target_count > 0) {
650 if (still_target_count > 0) {
661 ESP_LOGE(TAG,
"Invalid length");
664 if (!ld2450::validate_header_footer(CMD_FRAME_HEADER, this->
buffer_data_)) {
670 ESP_LOGE(TAG,
"Invalid status");
679 case CMD_ENABLE_CONF:
680 ESP_LOGV(TAG,
"Enable conf");
683 case CMD_DISABLE_CONF:
684 ESP_LOGV(TAG,
"Disabled conf");
687 case CMD_SET_BAUD_RATE:
688 ESP_LOGV(TAG,
"Baud rate change");
690 if (this->baud_rate_select_ !=
nullptr) {
691 auto baud = this->baud_rate_select_->current_option();
692 ESP_LOGE(TAG,
"Change baud rate to %.*s and reinstall", (
int) baud.size(), baud.c_str());
697 case CMD_QUERY_VERSION: {
701 ESP_LOGV(TAG,
"Firmware version: %s", version_s);
702#ifdef USE_TEXT_SENSOR
703 if (this->version_text_sensor_ !=
nullptr) {
704 this->version_text_sensor_->publish_state(version_s);
710 case CMD_QUERY_MAC_ADDRESS: {
720 char mac_s[MAC_ADDRESS_PRETTY_BUFFER_SIZE];
722 ESP_LOGV(TAG,
"MAC address: %s", mac_str);
723#ifdef USE_TEXT_SENSOR
724 if (this->mac_text_sensor_ !=
nullptr) {
725 this->mac_text_sensor_->publish_state(mac_str);
729 if (this->bluetooth_switch_ !=
nullptr) {
737 ESP_LOGV(TAG,
"Bluetooth");
740 case CMD_SINGLE_TARGET_MODE:
741 ESP_LOGV(TAG,
"Single target conf");
743 if (this->multi_target_switch_ !=
nullptr) {
744 this->multi_target_switch_->publish_state(
false);
749 case CMD_MULTI_TARGET_MODE:
750 ESP_LOGV(TAG,
"Multi target conf");
752 if (this->multi_target_switch_ !=
nullptr) {
753 this->multi_target_switch_->publish_state(
true);
758 case CMD_QUERY_TARGET_MODE:
759 ESP_LOGV(TAG,
"Query target tracking mode");
761 if (this->multi_target_switch_ !=
nullptr) {
762 this->multi_target_switch_->publish_state(this->
buffer_data_[10] == 0x02);
771 ESP_LOGV(TAG,
"Query zone conf");
773 this->publish_zone_type();
775 if (this->zone_type_select_ !=
nullptr) {
776 auto zone = this->zone_type_select_->current_option();
777 ESP_LOGV(TAG,
"Change zone type to: %.*s", (
int) zone.size(), zone.c_str());
781 ESP_LOGV(TAG,
"Zone: Disabled");
784 ESP_LOGV(TAG,
"Zone: Area detection");
787 ESP_LOGV(TAG,
"Zone: Area filter");
793 ESP_LOGV(TAG,
"Set zone conf");
794 this->query_zone_info();
814 ESP_LOGW(TAG,
"Max command length exceeded; ignoring");
831 ESP_LOGV(TAG,
"Ack Data incomplete");
834 ld2450::validate_header_footer(CMD_FRAME_HEADER, this->
buffer_data_)) {
835 ESP_LOGW(TAG,
"Truncated zone ACK");
839 uint8_t pending[ZONE_ACK_FRAME_SIZE];
844 for (uint8_t i = 0; i < pending_len; i++) {
852 const uint8_t cmd = enable ? CMD_ENABLE_CONF : CMD_DISABLE_CONF;
853 const uint8_t cmd_value[2] = {0x01, 0x00};
854 this->
send_command_(cmd, enable ? cmd_value :
nullptr,
sizeof(cmd_value));
858void LD2450Component::set_bluetooth(
bool enable) {
860 const uint8_t cmd_value[2] = {enable ? (uint8_t) 0x01 : (uint8_t) 0x00, 0x00};
861 this->
send_command_(CMD_BLUETOOTH, cmd_value,
sizeof(cmd_value));
862 this->
set_timeout(200, [
this]() { this->restart_and_read_all_info(); });
866void LD2450Component::set_baud_rate(
const char *
state) {
869 this->
send_command_(CMD_SET_BAUD_RATE, cmd_value,
sizeof(cmd_value));
874void LD2450Component::set_zone_type(
const char *
state) {
875 ESP_LOGV(TAG,
"Set zone type: %s",
state);
882void LD2450Component::publish_zone_type() {
884 if (this->zone_type_select_ !=
nullptr) {
891void LD2450Component::set_multi_target(
bool enable) {
893 uint8_t cmd = enable ? CMD_MULTI_TARGET_MODE : CMD_SINGLE_TARGET_MODE;
899void LD2450Component::factory_reset() {
902 this->
set_timeout(200, [
this]() { this->restart_and_read_all_info(); });
913 uint8_t cmd_value[2] = {0x01, 0x00};
924void LD2450Component::set_move_x_sensor(uint8_t target,
sensor::Sensor *s) {
925 this->move_x_sensors_[target].set_sensor(s);
927void LD2450Component::set_move_y_sensor(uint8_t target,
sensor::Sensor *s) {
928 this->move_y_sensors_[target].set_sensor(s);
930void LD2450Component::set_move_speed_sensor(uint8_t target, sensor::Sensor *s) {
931 this->move_speed_sensors_[target].set_sensor(s);
933void LD2450Component::set_move_angle_sensor(uint8_t target, sensor::Sensor *s) {
934 this->move_angle_sensors_[target].set_sensor(s);
936void LD2450Component::set_move_distance_sensor(uint8_t target, sensor::Sensor *s) {
937 this->move_distance_sensors_[target].set_sensor(s);
939void LD2450Component::set_move_resolution_sensor(uint8_t target, sensor::Sensor *s) {
940 this->move_resolution_sensors_[target].set_sensor(s);
942void LD2450Component::set_zone_target_count_sensor(uint8_t zone, sensor::Sensor *s) {
943 this->zone_target_count_sensors_[zone].set_sensor(s);
945void LD2450Component::set_zone_still_target_count_sensor(uint8_t zone, sensor::Sensor *s) {
946 this->zone_still_target_count_sensors_[zone].set_sensor(s);
948void LD2450Component::set_zone_moving_target_count_sensor(uint8_t zone, sensor::Sensor *s) {
949 this->zone_moving_target_count_sensors_[zone].set_sensor(s);
952#ifdef USE_TEXT_SENSOR
953void LD2450Component::set_direction_text_sensor(uint8_t target, text_sensor::TextSensor *s) {
954 this->direction_text_sensors_[target] = s;
960void LD2450Component::set_zone_coordinate(number::Number *n) {
962 while (zone < MAX_ZONES && this->
zone_numbers_[zone].x1 != n && this->zone_numbers_[zone].y1 != n &&
963 this->zone_numbers_[zone].x2 != n && this->zone_numbers_[zone].y2 != n)
965 if (zone == MAX_ZONES)
967 number::Number *x1sens = this->zone_numbers_[zone].x1;
968 number::Number *y1sens = this->zone_numbers_[zone].y1;
969 number::Number *x2sens = this->zone_numbers_[zone].x2;
970 number::Number *y2sens = this->zone_numbers_[zone].y2;
971 if (!x1sens->has_state() || !y1sens->has_state() || !x2sens->has_state() || !y2sens->has_state()) {
981void LD2450Component::set_zone_numbers(uint8_t zone, number::Number *x1, number::Number *y1, number::Number *x2,
982 number::Number *y2) {
983 if (zone < MAX_ZONES) {
984 this->zone_numbers_[zone].x1 = x1;
985 this->zone_numbers_[zone].y1 = y1;
986 this->zone_numbers_[zone].x2 = x2;
987 this->zone_numbers_[zone].y2 = y2;
994void LD2450Component::set_presence_timeout() {
995 if (this->presence_timeout_number_ !=
nullptr) {
996 if (this->presence_timeout_number_->state == 0) {
998 this->presence_timeout_number_->publish_state(timeout);
999 this->
timeout_ = ld2450::convert_seconds_to_ms(timeout);
1001 if (this->presence_timeout_number_->has_state()) {
1003 this->
timeout_ = ld2450::convert_seconds_to_ms(this->presence_timeout_number_->state);
1015 value = DEFAULT_PRESENCE_TIMEOUT;
uint32_t IRAM_ATTR HOT get_loop_component_start_time() const
Get the cached time in milliseconds from when the current component started its loop execution.
virtual void setup()
Where the component's initialization should happen.
void set_timeout(const char *name, uint32_t timeout, std::function< void()> &&f)
Set a timeout function with a const char* name.
void save_to_flash_(float value)
std::array< SensorWithDedup< int16_t >, MAX_TARGETS > move_y_sensors_
std::array< SensorWithDedup< uint8_t >, MAX_ZONES > zone_moving_target_count_sensors_
std::array< Deduplicator< uint8_t >, MAX_TARGETS > direction_dedup_
uint32_t still_presence_millis_
void send_command_(uint8_t command_str, const uint8_t *command_value, uint8_t command_value_len)
std::array< SensorWithDedup< uint8_t >, MAX_ZONES > zone_target_count_sensors_
void query_target_tracking_mode_()
void send_set_zone_command_()
void set_config_mode_(bool enable)
std::array< text_sensor::TextSensor *, MAX_TARGETS > direction_text_sensors_
void count_targets_in_zone_(const Zone &zone, uint8_t &still, uint8_t &moving)
StaticVector< PolygonZone *, LD2450_POLYGON_ZONE_COUNT > polygon_zones_
uint32_t moving_presence_millis_
void readline_(int readch)
std::array< SensorWithDedup< uint16_t >, MAX_TARGETS > move_resolution_sensors_
uint8_t buffer_data_[MAX_LINE_LENGTH]
uint8_t mac_address_[MAC_ADDRESS_SIZE]
Target target_info_[MAX_TARGETS]
uint32_t presence_millis_
Zone zone_config_[MAX_ZONES]
ESPPreferenceObject pref_
std::array< SensorWithDedup< uint16_t >, MAX_TARGETS > move_distance_sensors_
std::array< SensorWithDedup< uint8_t >, MAX_ZONES > zone_still_target_count_sensors_
LazyCallbackManager< void()> data_callback_
std::array< SensorWithDedup< int16_t >, MAX_TARGETS > move_speed_sensors_
std::array< SensorWithDedup< float >, MAX_TARGETS > move_angle_sensors_
float restore_from_flash_()
ZoneOfNumbers zone_numbers_[MAX_ZONES]
void handle_periodic_data_()
std::array< SensorWithDedup< int16_t >, MAX_TARGETS > move_x_sensors_
bool get_timeout_status_(uint32_t check_millis)
A zone with any polygon shape.
Base-class for all sensors.
void publish_state(const std::string &state)
uint32_t get_baud_rate() const
optional< std::array< uint8_t, N > > read_array()
void write_array(const uint8_t *data, size_t len)
constexpr uint32_t BAUD_RATES[]
constexpr Uint8ToString DIRECTION_BY_UINT[]
ESPHOME_LOG_TAG(TAG, "ld2450")
constexpr StringToUint8 ZONE_TYPE_BY_STR[]
constexpr StringToUint8 BAUD_RATES_BY_STR[]
constexpr Uint8ToString ZONE_TYPE_BY_UINT[]
uint8_t find_uint8(const StringToUint8(&arr)[N], const std::string &str)
const char * find_str(const Uint8ToString(&arr)[N], uint8_t value)
void format_version_str(const uint8_t *version, std::span< char, 20 > buffer)
const char * format_mac_str(const uint8_t *mac_address, std::span< char, MAC_ADDRESS_PRETTY_BUFFER_SIZE > buffer)
optional< size_t > find_index(const uint32_t(&arr)[N], uint32_t value)
std::vector< uint8_t > bytes
value[LAYOUT.day_index()]
char * format_hex_pretty_to(char *buffer, size_t buffer_size, const uint8_t *data, size_t length, char separator)
Format byte array as uppercase hex to buffer (base implementation).
constexpr T encode_value_le(const uint8_t *bytes)
Encode a value from its constituent bytes (from least to most significant) in an array with length si...
constexpr size_t format_hex_pretty_size(size_t byte_count)
Calculate buffer size needed for format_hex_pretty_to with separator: "XX:XX:...:XX\0".
void HOT delay(uint32_t ms)
Application App
Global storage of Application pointer - only one Application can exist.