mirror of
				https://github.com/esphome/esphome.git
				synced 2025-10-30 22:53:59 +00:00 
			
		
		
		
	[ld2450] Use Deduplicator for sensors
				
					
				
			This commit is contained in:
		| @@ -3,6 +3,7 @@ from esphome.components import uart | ||||
| import esphome.config_validation as cv | ||||
| from esphome.const import CONF_ID, CONF_THROTTLE | ||||
|  | ||||
| AUTO_LOAD = ["ld24xx"] | ||||
| DEPENDENCIES = ["uart"] | ||||
| CODEOWNERS = ["@hareeshmu"] | ||||
| MULTI_CONF = True | ||||
|   | ||||
| @@ -1,6 +1,5 @@ | ||||
| #include "ld2450.h" | ||||
| #include <utility> | ||||
| #include <cmath> | ||||
|  | ||||
| #ifdef USE_NUMBER | ||||
| #include "esphome/components/number/number.h" | ||||
| #endif | ||||
| @@ -11,8 +10,8 @@ | ||||
| #include "esphome/core/component.h" | ||||
| #include "esphome/core/helpers.h" | ||||
|  | ||||
| #define highbyte(val) (uint8_t)((val) >> 8) | ||||
| #define lowbyte(val) (uint8_t)((val) &0xff) | ||||
| #include <cmath> | ||||
| #include <numbers> | ||||
|  | ||||
| namespace esphome { | ||||
| namespace ld2450 { | ||||
| @@ -170,21 +169,16 @@ static inline int16_t hex_to_signed_int(const uint8_t *buffer, uint8_t offset) { | ||||
| } | ||||
|  | ||||
| static inline float calculate_angle(float base, float hypotenuse) { | ||||
|   if (base < 0.0 || hypotenuse <= 0.0) { | ||||
|     return 0.0; | ||||
|   if (base < 0.0f || hypotenuse <= 0.0f) { | ||||
|     return 0.0f; | ||||
|   } | ||||
|   float angle_radians = std::acos(base / hypotenuse); | ||||
|   float angle_degrees = angle_radians * (180.0 / M_PI); | ||||
|   float angle_radians = std::acosf(base / hypotenuse); | ||||
|   float angle_degrees = angle_radians * (180.0f / std::numbers::pi_v<float>); | ||||
|   return angle_degrees; | ||||
| } | ||||
|  | ||||
| static bool validate_header_footer(const uint8_t *header_footer, const uint8_t *buffer) { | ||||
|   for (uint8_t i = 0; i < HEADER_FOOTER_SIZE; i++) { | ||||
|     if (header_footer[i] != buffer[i]) { | ||||
|       return false;  // Mismatch in header/footer | ||||
|     } | ||||
|   } | ||||
|   return true;  // Valid header/footer | ||||
| static inline bool validate_header_footer(const uint8_t *header_footer, const uint8_t *buffer) { | ||||
|   return std::memcmp(header_footer, buffer, HEADER_FOOTER_SIZE) == 0; | ||||
| } | ||||
|  | ||||
| void LD2450Component::setup() { | ||||
| @@ -217,41 +211,41 @@ void LD2450Component::dump_config() { | ||||
| #endif | ||||
| #ifdef USE_SENSOR | ||||
|   ESP_LOGCONFIG(TAG, "Sensors:"); | ||||
|   LOG_SENSOR("  ", "MovingTargetCount", this->moving_target_count_sensor_); | ||||
|   LOG_SENSOR("  ", "StillTargetCount", this->still_target_count_sensor_); | ||||
|   LOG_SENSOR("  ", "TargetCount", this->target_count_sensor_); | ||||
|   for (sensor::Sensor *s : this->move_x_sensors_) { | ||||
|     LOG_SENSOR("  ", "TargetX", s); | ||||
|   LOG_SENSOR_WITH_DEDUP_SAFE("  ", "MovingTargetCount", this->moving_target_count_sensor_); | ||||
|   LOG_SENSOR_WITH_DEDUP_SAFE("  ", "StillTargetCount", this->still_target_count_sensor_); | ||||
|   LOG_SENSOR_WITH_DEDUP_SAFE("  ", "TargetCount", this->target_count_sensor_); | ||||
|   for (auto &s : this->move_x_sensors_) { | ||||
|     LOG_SENSOR_WITH_DEDUP_SAFE("  ", "TargetX", s); | ||||
|   } | ||||
|   for (sensor::Sensor *s : this->move_y_sensors_) { | ||||
|     LOG_SENSOR("  ", "TargetY", s); | ||||
|   for (auto &s : this->move_y_sensors_) { | ||||
|     LOG_SENSOR_WITH_DEDUP_SAFE("  ", "TargetY", s); | ||||
|   } | ||||
|   for (sensor::Sensor *s : this->move_angle_sensors_) { | ||||
|     LOG_SENSOR("  ", "TargetAngle", s); | ||||
|   for (auto &s : this->move_angle_sensors_) { | ||||
|     LOG_SENSOR_WITH_DEDUP_SAFE("  ", "TargetAngle", s); | ||||
|   } | ||||
|   for (sensor::Sensor *s : this->move_distance_sensors_) { | ||||
|     LOG_SENSOR("  ", "TargetDistance", s); | ||||
|   for (auto &s : this->move_distance_sensors_) { | ||||
|     LOG_SENSOR_WITH_DEDUP_SAFE("  ", "TargetDistance", s); | ||||
|   } | ||||
|   for (sensor::Sensor *s : this->move_resolution_sensors_) { | ||||
|     LOG_SENSOR("  ", "TargetResolution", s); | ||||
|   for (auto &s : this->move_resolution_sensors_) { | ||||
|     LOG_SENSOR_WITH_DEDUP_SAFE("  ", "TargetResolution", s); | ||||
|   } | ||||
|   for (sensor::Sensor *s : this->move_speed_sensors_) { | ||||
|     LOG_SENSOR("  ", "TargetSpeed", s); | ||||
|   for (auto &s : this->move_speed_sensors_) { | ||||
|     LOG_SENSOR_WITH_DEDUP_SAFE("  ", "TargetSpeed", s); | ||||
|   } | ||||
|   for (sensor::Sensor *s : this->zone_target_count_sensors_) { | ||||
|     LOG_SENSOR("  ", "ZoneTargetCount", s); | ||||
|   for (auto &s : this->zone_target_count_sensors_) { | ||||
|     LOG_SENSOR_WITH_DEDUP_SAFE("  ", "ZoneTargetCount", s); | ||||
|   } | ||||
|   for (sensor::Sensor *s : this->zone_moving_target_count_sensors_) { | ||||
|     LOG_SENSOR("  ", "ZoneMovingTargetCount", s); | ||||
|   for (auto &s : this->zone_moving_target_count_sensors_) { | ||||
|     LOG_SENSOR_WITH_DEDUP_SAFE("  ", "ZoneMovingTargetCount", s); | ||||
|   } | ||||
|   for (sensor::Sensor *s : this->zone_still_target_count_sensors_) { | ||||
|     LOG_SENSOR("  ", "ZoneStillTargetCount", s); | ||||
|   for (auto &s : this->zone_still_target_count_sensors_) { | ||||
|     LOG_SENSOR_WITH_DEDUP_SAFE("  ", "ZoneStillTargetCount", s); | ||||
|   } | ||||
| #endif | ||||
| #ifdef USE_TEXT_SENSOR | ||||
|   ESP_LOGCONFIG(TAG, "Text Sensors:"); | ||||
|   LOG_TEXT_SENSOR("  ", "Version", this->version_text_sensor_); | ||||
|   LOG_TEXT_SENSOR("  ", "Mac", this->mac_text_sensor_); | ||||
|   LOG_TEXT_SENSOR("  ", "MAC address", this->mac_text_sensor_); | ||||
|   for (text_sensor::TextSensor *s : this->direction_text_sensors_) { | ||||
|     LOG_TEXT_SENSOR("  ", "Direction", s); | ||||
|   } | ||||
| @@ -419,19 +413,19 @@ void LD2450Component::send_command_(uint8_t command, const uint8_t *command_valu | ||||
|   if (command_value != nullptr) { | ||||
|     len += command_value_len; | ||||
|   } | ||||
|   uint8_t len_cmd[] = {lowbyte(len), highbyte(len), command, 0x00}; | ||||
|   // 2 length bytes (low, high) + 2 command bytes (low, high) | ||||
|   uint8_t len_cmd[] = {len, 0x00, command, 0x00}; | ||||
|   this->write_array(len_cmd, sizeof(len_cmd)); | ||||
|  | ||||
|   // command value bytes | ||||
|   if (command_value != nullptr) { | ||||
|     for (uint8_t i = 0; i < command_value_len; i++) { | ||||
|       this->write_byte(command_value[i]); | ||||
|     } | ||||
|     this->write_array(command_value, command_value_len); | ||||
|   } | ||||
|   // frame footer bytes | ||||
|   this->write_array(CMD_FRAME_FOOTER, sizeof(CMD_FRAME_FOOTER)); | ||||
|   // FIXME to remove | ||||
|   delay(50);  // NOLINT | ||||
|  | ||||
|   if (command != CMD_ENABLE_CONF && command != CMD_DISABLE_CONF) { | ||||
|     delay(50);  // NOLINT | ||||
|   } | ||||
| } | ||||
|  | ||||
| // LD2450 Radar data message: | ||||
| @@ -459,8 +453,8 @@ void LD2450Component::handle_periodic_data_() { | ||||
|   int16_t target_count = 0; | ||||
|   int16_t still_target_count = 0; | ||||
|   int16_t moving_target_count = 0; | ||||
|   int16_t res = 0; | ||||
|   int16_t start = 0; | ||||
|   int16_t val = 0; | ||||
|   int16_t tx = 0; | ||||
|   int16_t ty = 0; | ||||
|   int16_t td = 0; | ||||
| @@ -478,85 +472,43 @@ void LD2450Component::handle_periodic_data_() { | ||||
|     start = TARGET_X + index * 8; | ||||
|     is_moving = false; | ||||
|     // tx is used for further calculations, so always needs to be populated | ||||
|     val = ld2450::decode_coordinate(this->buffer_data_[start], this->buffer_data_[start + 1]); | ||||
|     tx = val; | ||||
|     sensor::Sensor *sx = this->move_x_sensors_[index]; | ||||
|     if (sx != nullptr) { | ||||
|       if (this->cached_target_data_[index].x != val) { | ||||
|         sx->publish_state(val); | ||||
|         this->cached_target_data_[index].x = val; | ||||
|       } | ||||
|     } | ||||
|     tx = ld2450::decode_coordinate(this->buffer_data_[start], this->buffer_data_[start + 1]); | ||||
|     SAFE_PUBLISH_SENSOR(this->move_x_sensors_[index], tx); | ||||
|     // Y | ||||
|     start = TARGET_Y + index * 8; | ||||
|     // ty is used for further calculations, so always needs to be populated | ||||
|     val = ld2450::decode_coordinate(this->buffer_data_[start], this->buffer_data_[start + 1]); | ||||
|     ty = val; | ||||
|     sensor::Sensor *sy = this->move_y_sensors_[index]; | ||||
|     if (sy != nullptr) { | ||||
|       if (this->cached_target_data_[index].y != val) { | ||||
|         sy->publish_state(val); | ||||
|         this->cached_target_data_[index].y = val; | ||||
|       } | ||||
|     } | ||||
|     ty = ld2450::decode_coordinate(this->buffer_data_[start], this->buffer_data_[start + 1]); | ||||
|     SAFE_PUBLISH_SENSOR(this->move_y_sensors_[index], ty); | ||||
|     // RESOLUTION | ||||
|     start = TARGET_RESOLUTION + index * 8; | ||||
|     sensor::Sensor *sr = this->move_resolution_sensors_[index]; | ||||
|     if (sr != nullptr) { | ||||
|       val = (this->buffer_data_[start + 1] << 8) | this->buffer_data_[start]; | ||||
|       if (this->cached_target_data_[index].resolution != val) { | ||||
|         sr->publish_state(val); | ||||
|         this->cached_target_data_[index].resolution = val; | ||||
|       } | ||||
|     } | ||||
|     res = (this->buffer_data_[start + 1] << 8) | this->buffer_data_[start]; | ||||
|     SAFE_PUBLISH_SENSOR(this->move_resolution_sensors_[index], res); | ||||
| #endif | ||||
|     // SPEED | ||||
|     start = TARGET_SPEED + index * 8; | ||||
|     val = ld2450::decode_speed(this->buffer_data_[start], this->buffer_data_[start + 1]); | ||||
|     ts = val; | ||||
|     if (val) { | ||||
|     ts = ld2450::decode_speed(this->buffer_data_[start], this->buffer_data_[start + 1]); | ||||
|     if (ts) { | ||||
|       is_moving = true; | ||||
|       moving_target_count++; | ||||
|     } | ||||
| #ifdef USE_SENSOR | ||||
|     sensor::Sensor *ss = this->move_speed_sensors_[index]; | ||||
|     if (ss != nullptr) { | ||||
|       if (this->cached_target_data_[index].speed != val) { | ||||
|         ss->publish_state(val); | ||||
|         this->cached_target_data_[index].speed = val; | ||||
|       } | ||||
|     } | ||||
|     SAFE_PUBLISH_SENSOR(this->move_speed_sensors_[index], ts); | ||||
| #endif | ||||
|     // DISTANCE | ||||
|     // Optimized: use already decoded tx and ty values, replace pow() with multiplication | ||||
|     int32_t x_squared = (int32_t) tx * tx; | ||||
|     int32_t y_squared = (int32_t) ty * ty; | ||||
|     val = (uint16_t) sqrt(x_squared + y_squared); | ||||
|     td = val; | ||||
|     if (val > 0) { | ||||
|     td = (uint16_t) sqrtf(x_squared + y_squared); | ||||
|     if (td > 0) { | ||||
|       target_count++; | ||||
|     } | ||||
| #ifdef USE_SENSOR | ||||
|     sensor::Sensor *sd = this->move_distance_sensors_[index]; | ||||
|     if (sd != nullptr) { | ||||
|       if (this->cached_target_data_[index].distance != val) { | ||||
|         sd->publish_state(val); | ||||
|         this->cached_target_data_[index].distance = val; | ||||
|       } | ||||
|     } | ||||
|     SAFE_PUBLISH_SENSOR(this->move_distance_sensors_[index], td); | ||||
|     // ANGLE | ||||
|     angle = ld2450::calculate_angle(static_cast<float>(ty), static_cast<float>(td)); | ||||
|     if (tx > 0) { | ||||
|       angle = angle * -1; | ||||
|     } | ||||
|     sensor::Sensor *sa = this->move_angle_sensors_[index]; | ||||
|     if (sa != nullptr) { | ||||
|       if (std::isnan(this->cached_target_data_[index].angle) || | ||||
|           std::abs(this->cached_target_data_[index].angle - angle) > 0.1f) { | ||||
|         sa->publish_state(angle); | ||||
|         this->cached_target_data_[index].angle = angle; | ||||
|       } | ||||
|     } | ||||
|     SAFE_PUBLISH_SENSOR(this->move_angle_sensors_[index], angle); | ||||
| #endif | ||||
| #ifdef USE_TEXT_SENSOR | ||||
|     // DIRECTION | ||||
| @@ -570,11 +522,9 @@ void LD2450Component::handle_periodic_data_() { | ||||
|       direction = DIRECTION_STATIONARY; | ||||
|     } | ||||
|     text_sensor::TextSensor *tsd = this->direction_text_sensors_[index]; | ||||
|     if (tsd != nullptr) { | ||||
|       if (this->cached_target_data_[index].direction != direction) { | ||||
|         tsd->publish_state(find_str(ld2450::DIRECTION_BY_UINT, direction)); | ||||
|         this->cached_target_data_[index].direction = direction; | ||||
|       } | ||||
|     auto dir_str = find_str(ld2450::DIRECTION_BY_UINT, direction); | ||||
|     if (tsd != nullptr && (!tsd->has_state() || tsd->get_state() != dir_str)) { | ||||
|       tsd->publish_state(dir_str); | ||||
|     } | ||||
| #endif | ||||
|  | ||||
| @@ -599,53 +549,19 @@ void LD2450Component::handle_periodic_data_() { | ||||
|     zone_all_targets = zone_still_targets + zone_moving_targets; | ||||
|  | ||||
|     // Publish Still Target Count in Zones | ||||
|     sensor::Sensor *szstc = this->zone_still_target_count_sensors_[index]; | ||||
|     if (szstc != nullptr) { | ||||
|       if (this->cached_zone_data_[index].still_count != zone_still_targets) { | ||||
|         szstc->publish_state(zone_still_targets); | ||||
|         this->cached_zone_data_[index].still_count = zone_still_targets; | ||||
|       } | ||||
|     } | ||||
|     SAFE_PUBLISH_SENSOR(this->zone_still_target_count_sensors_[index], zone_still_targets); | ||||
|     // Publish Moving Target Count in Zones | ||||
|     sensor::Sensor *szmtc = this->zone_moving_target_count_sensors_[index]; | ||||
|     if (szmtc != nullptr) { | ||||
|       if (this->cached_zone_data_[index].moving_count != zone_moving_targets) { | ||||
|         szmtc->publish_state(zone_moving_targets); | ||||
|         this->cached_zone_data_[index].moving_count = zone_moving_targets; | ||||
|       } | ||||
|     } | ||||
|     SAFE_PUBLISH_SENSOR(this->zone_moving_target_count_sensors_[index], zone_moving_targets); | ||||
|     // Publish All Target Count in Zones | ||||
|     sensor::Sensor *sztc = this->zone_target_count_sensors_[index]; | ||||
|     if (sztc != nullptr) { | ||||
|       if (this->cached_zone_data_[index].total_count != zone_all_targets) { | ||||
|         sztc->publish_state(zone_all_targets); | ||||
|         this->cached_zone_data_[index].total_count = zone_all_targets; | ||||
|       } | ||||
|     } | ||||
|  | ||||
|     SAFE_PUBLISH_SENSOR(this->zone_target_count_sensors_[index], zone_all_targets); | ||||
|   }  // End loop thru zones | ||||
|  | ||||
|   // Target Count | ||||
|   if (this->target_count_sensor_ != nullptr) { | ||||
|     if (this->cached_global_data_.target_count != target_count) { | ||||
|       this->target_count_sensor_->publish_state(target_count); | ||||
|       this->cached_global_data_.target_count = target_count; | ||||
|     } | ||||
|   } | ||||
|   SAFE_PUBLISH_SENSOR(this->target_count_sensor_, target_count); | ||||
|   // Still Target Count | ||||
|   if (this->still_target_count_sensor_ != nullptr) { | ||||
|     if (this->cached_global_data_.still_count != still_target_count) { | ||||
|       this->still_target_count_sensor_->publish_state(still_target_count); | ||||
|       this->cached_global_data_.still_count = still_target_count; | ||||
|     } | ||||
|   } | ||||
|   SAFE_PUBLISH_SENSOR(this->still_target_count_sensor_, still_target_count); | ||||
|   // Moving Target Count | ||||
|   if (this->moving_target_count_sensor_ != nullptr) { | ||||
|     if (this->cached_global_data_.moving_count != moving_target_count) { | ||||
|       this->moving_target_count_sensor_->publish_state(moving_target_count); | ||||
|       this->cached_global_data_.moving_count = moving_target_count; | ||||
|     } | ||||
|   } | ||||
|   SAFE_PUBLISH_SENSOR(this->moving_target_count_sensor_, moving_target_count); | ||||
| #endif | ||||
|  | ||||
| #ifdef USE_BINARY_SENSOR | ||||
| @@ -942,28 +858,33 @@ void LD2450Component::query_target_tracking_mode_() { this->send_command_(CMD_QU | ||||
| void LD2450Component::query_zone_() { this->send_command_(CMD_QUERY_ZONE, nullptr, 0); } | ||||
|  | ||||
| #ifdef USE_SENSOR | ||||
| void LD2450Component::set_move_x_sensor(uint8_t target, sensor::Sensor *s) { this->move_x_sensors_[target] = s; } | ||||
| void LD2450Component::set_move_y_sensor(uint8_t target, sensor::Sensor *s) { this->move_y_sensors_[target] = s; } | ||||
| // These could leak memory, but they are only set once prior to 'setup()' and should never be used again. | ||||
| void LD2450Component::set_move_x_sensor(uint8_t target, sensor::Sensor *s) { | ||||
|   this->move_x_sensors_[target] = new SensorWithDedup<int16_t>(s); | ||||
| } | ||||
| void LD2450Component::set_move_y_sensor(uint8_t target, sensor::Sensor *s) { | ||||
|   this->move_y_sensors_[target] = new SensorWithDedup<int16_t>(s); | ||||
| } | ||||
| void LD2450Component::set_move_speed_sensor(uint8_t target, sensor::Sensor *s) { | ||||
|   this->move_speed_sensors_[target] = s; | ||||
|   this->move_speed_sensors_[target] = new SensorWithDedup<int16_t>(s); | ||||
| } | ||||
| void LD2450Component::set_move_angle_sensor(uint8_t target, sensor::Sensor *s) { | ||||
|   this->move_angle_sensors_[target] = s; | ||||
|   this->move_angle_sensors_[target] = new SensorWithDedup<float>(s); | ||||
| } | ||||
| void LD2450Component::set_move_distance_sensor(uint8_t target, sensor::Sensor *s) { | ||||
|   this->move_distance_sensors_[target] = s; | ||||
|   this->move_distance_sensors_[target] = new SensorWithDedup<uint16_t>(s); | ||||
| } | ||||
| void LD2450Component::set_move_resolution_sensor(uint8_t target, sensor::Sensor *s) { | ||||
|   this->move_resolution_sensors_[target] = s; | ||||
|   this->move_resolution_sensors_[target] = new SensorWithDedup<uint16_t>(s); | ||||
| } | ||||
| void LD2450Component::set_zone_target_count_sensor(uint8_t zone, sensor::Sensor *s) { | ||||
|   this->zone_target_count_sensors_[zone] = s; | ||||
|   this->zone_target_count_sensors_[zone] = new SensorWithDedup<uint8_t>(s); | ||||
| } | ||||
| void LD2450Component::set_zone_still_target_count_sensor(uint8_t zone, sensor::Sensor *s) { | ||||
|   this->zone_still_target_count_sensors_[zone] = s; | ||||
|   this->zone_still_target_count_sensors_[zone] = new SensorWithDedup<uint8_t>(s); | ||||
| } | ||||
| void LD2450Component::set_zone_moving_target_count_sensor(uint8_t zone, sensor::Sensor *s) { | ||||
|   this->zone_moving_target_count_sensors_[zone] = s; | ||||
|   this->zone_moving_target_count_sensors_[zone] = new SensorWithDedup<uint8_t>(s); | ||||
| } | ||||
| #endif | ||||
| #ifdef USE_TEXT_SENSOR | ||||
|   | ||||
| @@ -1,12 +1,7 @@ | ||||
| #pragma once | ||||
|  | ||||
| #include "esphome/components/uart/uart.h" | ||||
| #include "esphome/core/component.h" | ||||
| #include "esphome/core/defines.h" | ||||
| #include "esphome/core/helpers.h" | ||||
| #include "esphome/core/preferences.h" | ||||
| #include <limits> | ||||
| #include <cmath> | ||||
| #include "esphome/core/component.h" | ||||
| #ifdef USE_SENSOR | ||||
| #include "esphome/components/sensor/sensor.h" | ||||
| #endif | ||||
| @@ -29,18 +24,23 @@ | ||||
| #include "esphome/components/binary_sensor/binary_sensor.h" | ||||
| #endif | ||||
|  | ||||
| #ifndef M_PI | ||||
| #define M_PI 3.14 | ||||
| #endif | ||||
| #include "esphome/components/ld24xx/ld24xx.h" | ||||
| #include "esphome/components/uart/uart.h" | ||||
| #include "esphome/core/helpers.h" | ||||
| #include "esphome/core/preferences.h" | ||||
|  | ||||
| #include <array> | ||||
|  | ||||
| namespace esphome { | ||||
| namespace ld2450 { | ||||
|  | ||||
| using namespace ld24xx; | ||||
|  | ||||
| // Constants | ||||
| static const uint8_t DEFAULT_PRESENCE_TIMEOUT = 5;  // Timeout to reset presense status 5 sec. | ||||
| static const uint8_t MAX_LINE_LENGTH = 41;          // Max characters for serial buffer | ||||
| static const uint8_t MAX_TARGETS = 3;               // Max 3 Targets in LD2450 | ||||
| static const uint8_t MAX_ZONES = 3;                 // Max 3 Zones in LD2450 | ||||
| static constexpr uint8_t DEFAULT_PRESENCE_TIMEOUT = 5;  // Timeout to reset presense status 5 sec. | ||||
| static constexpr uint8_t MAX_LINE_LENGTH = 41;          // Max characters for serial buffer | ||||
| static constexpr uint8_t MAX_TARGETS = 3;               // Max 3 Targets in LD2450 | ||||
| static constexpr uint8_t MAX_ZONES = 3;                 // Max 3 Zones in LD2450 | ||||
|  | ||||
| enum Direction : uint8_t { | ||||
|   DIRECTION_APPROACHING = 0, | ||||
| @@ -81,9 +81,9 @@ class LD2450Component : public Component, public uart::UARTDevice { | ||||
|   SUB_BINARY_SENSOR(target) | ||||
| #endif | ||||
| #ifdef USE_SENSOR | ||||
|   SUB_SENSOR(moving_target_count) | ||||
|   SUB_SENSOR(still_target_count) | ||||
|   SUB_SENSOR(target_count) | ||||
|   SUB_SENSOR_WITH_DEDUP(moving_target_count, uint8_t) | ||||
|   SUB_SENSOR_WITH_DEDUP(still_target_count, uint8_t) | ||||
|   SUB_SENSOR_WITH_DEDUP(target_count, uint8_t) | ||||
| #endif | ||||
| #ifdef USE_TEXT_SENSOR | ||||
|   SUB_TEXT_SENSOR(mac) | ||||
| @@ -176,48 +176,23 @@ class LD2450Component : public Component, public uart::UARTDevice { | ||||
|   Target target_info_[MAX_TARGETS]; | ||||
|   Zone zone_config_[MAX_ZONES]; | ||||
|  | ||||
|   // Change detection - cache previous values to avoid redundant publishes | ||||
|   // All values are initialized to sentinel values that are outside the valid sensor ranges | ||||
|   // to ensure the first real measurement is always published | ||||
|   struct CachedTargetData { | ||||
|     int16_t x = std::numeric_limits<int16_t>::min();             // -32768, outside range of -4860 to 4860 | ||||
|     int16_t y = std::numeric_limits<int16_t>::min();             // -32768, outside range of 0 to 7560 | ||||
|     int16_t speed = std::numeric_limits<int16_t>::min();         // -32768, outside practical sensor range | ||||
|     uint16_t resolution = std::numeric_limits<uint16_t>::max();  // 65535, unlikely resolution value | ||||
|     uint16_t distance = std::numeric_limits<uint16_t>::max();    // 65535, outside range of 0 to ~8990 | ||||
|     Direction direction = DIRECTION_UNDEFINED;                   // Undefined, will differ from any real direction | ||||
|     float angle = NAN;                                           // NAN, safe sentinel for floats | ||||
|   } cached_target_data_[MAX_TARGETS]; | ||||
|  | ||||
|   struct CachedZoneData { | ||||
|     uint8_t still_count = std::numeric_limits<uint8_t>::max();   // 255, unlikely zone count | ||||
|     uint8_t moving_count = std::numeric_limits<uint8_t>::max();  // 255, unlikely zone count | ||||
|     uint8_t total_count = std::numeric_limits<uint8_t>::max();   // 255, unlikely zone count | ||||
|   } cached_zone_data_[MAX_ZONES]; | ||||
|  | ||||
|   struct CachedGlobalData { | ||||
|     uint8_t target_count = std::numeric_limits<uint8_t>::max();  // 255, max 3 targets possible | ||||
|     uint8_t still_count = std::numeric_limits<uint8_t>::max();   // 255, max 3 targets possible | ||||
|     uint8_t moving_count = std::numeric_limits<uint8_t>::max();  // 255, max 3 targets possible | ||||
|   } cached_global_data_; | ||||
|  | ||||
| #ifdef USE_NUMBER | ||||
|   ESPPreferenceObject pref_;  // only used when numbers are in use | ||||
|   ZoneOfNumbers zone_numbers_[MAX_ZONES]; | ||||
| #endif | ||||
| #ifdef USE_SENSOR | ||||
|   std::vector<sensor::Sensor *> move_x_sensors_ = std::vector<sensor::Sensor *>(MAX_TARGETS); | ||||
|   std::vector<sensor::Sensor *> move_y_sensors_ = std::vector<sensor::Sensor *>(MAX_TARGETS); | ||||
|   std::vector<sensor::Sensor *> move_speed_sensors_ = std::vector<sensor::Sensor *>(MAX_TARGETS); | ||||
|   std::vector<sensor::Sensor *> move_angle_sensors_ = std::vector<sensor::Sensor *>(MAX_TARGETS); | ||||
|   std::vector<sensor::Sensor *> move_distance_sensors_ = std::vector<sensor::Sensor *>(MAX_TARGETS); | ||||
|   std::vector<sensor::Sensor *> move_resolution_sensors_ = std::vector<sensor::Sensor *>(MAX_TARGETS); | ||||
|   std::vector<sensor::Sensor *> zone_target_count_sensors_ = std::vector<sensor::Sensor *>(MAX_ZONES); | ||||
|   std::vector<sensor::Sensor *> zone_still_target_count_sensors_ = std::vector<sensor::Sensor *>(MAX_ZONES); | ||||
|   std::vector<sensor::Sensor *> zone_moving_target_count_sensors_ = std::vector<sensor::Sensor *>(MAX_ZONES); | ||||
|   std::array<SensorWithDedup<int16_t> *, MAX_TARGETS> move_x_sensors_{}; | ||||
|   std::array<SensorWithDedup<int16_t> *, MAX_TARGETS> move_y_sensors_{}; | ||||
|   std::array<SensorWithDedup<int16_t> *, MAX_TARGETS> move_speed_sensors_{}; | ||||
|   std::array<SensorWithDedup<float> *, MAX_TARGETS> move_angle_sensors_{}; | ||||
|   std::array<SensorWithDedup<uint16_t> *, MAX_TARGETS> move_distance_sensors_{}; | ||||
|   std::array<SensorWithDedup<uint16_t> *, MAX_TARGETS> move_resolution_sensors_{}; | ||||
|   std::array<SensorWithDedup<uint8_t> *, MAX_ZONES> zone_target_count_sensors_{}; | ||||
|   std::array<SensorWithDedup<uint8_t> *, MAX_ZONES> zone_still_target_count_sensors_{}; | ||||
|   std::array<SensorWithDedup<uint8_t> *, MAX_ZONES> zone_moving_target_count_sensors_{}; | ||||
| #endif | ||||
| #ifdef USE_TEXT_SENSOR | ||||
|   std::vector<text_sensor::TextSensor *> direction_text_sensors_ = std::vector<text_sensor::TextSensor *>(3); | ||||
|   std::array<text_sensor::TextSensor *, 3> direction_text_sensors_{}; | ||||
| #endif | ||||
| }; | ||||
|  | ||||
|   | ||||
		Reference in New Issue
	
	Block a user