mirror of
https://github.com/esphome/esphome.git
synced 2025-07-28 14:16:40 +00:00
[ld2450] Use `Deduplicator
` for sensors (#9863)
This commit is contained in:
parent
568e774116
commit
5bff9bc8d9
@ -3,6 +3,7 @@ from esphome.components import uart
|
|||||||
import esphome.config_validation as cv
|
import esphome.config_validation as cv
|
||||||
from esphome.const import CONF_ID, CONF_THROTTLE
|
from esphome.const import CONF_ID, CONF_THROTTLE
|
||||||
|
|
||||||
|
AUTO_LOAD = ["ld24xx"]
|
||||||
DEPENDENCIES = ["uart"]
|
DEPENDENCIES = ["uart"]
|
||||||
CODEOWNERS = ["@hareeshmu"]
|
CODEOWNERS = ["@hareeshmu"]
|
||||||
MULTI_CONF = True
|
MULTI_CONF = True
|
||||||
|
@ -1,6 +1,5 @@
|
|||||||
#include "ld2450.h"
|
#include "ld2450.h"
|
||||||
#include <utility>
|
|
||||||
#include <cmath>
|
|
||||||
#ifdef USE_NUMBER
|
#ifdef USE_NUMBER
|
||||||
#include "esphome/components/number/number.h"
|
#include "esphome/components/number/number.h"
|
||||||
#endif
|
#endif
|
||||||
@ -11,8 +10,8 @@
|
|||||||
#include "esphome/core/component.h"
|
#include "esphome/core/component.h"
|
||||||
#include "esphome/core/helpers.h"
|
#include "esphome/core/helpers.h"
|
||||||
|
|
||||||
#define highbyte(val) (uint8_t)((val) >> 8)
|
#include <cmath>
|
||||||
#define lowbyte(val) (uint8_t)((val) &0xff)
|
#include <numbers>
|
||||||
|
|
||||||
namespace esphome {
|
namespace esphome {
|
||||||
namespace ld2450 {
|
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) {
|
static inline float calculate_angle(float base, float hypotenuse) {
|
||||||
if (base < 0.0 || hypotenuse <= 0.0) {
|
if (base < 0.0f || hypotenuse <= 0.0f) {
|
||||||
return 0.0;
|
return 0.0f;
|
||||||
}
|
}
|
||||||
float angle_radians = std::acos(base / hypotenuse);
|
float angle_radians = acosf(base / hypotenuse);
|
||||||
float angle_degrees = angle_radians * (180.0 / M_PI);
|
float angle_degrees = angle_radians * (180.0f / std::numbers::pi_v<float>);
|
||||||
return angle_degrees;
|
return angle_degrees;
|
||||||
}
|
}
|
||||||
|
|
||||||
static bool validate_header_footer(const uint8_t *header_footer, const uint8_t *buffer) {
|
static inline bool validate_header_footer(const uint8_t *header_footer, const uint8_t *buffer) {
|
||||||
for (uint8_t i = 0; i < HEADER_FOOTER_SIZE; i++) {
|
return std::memcmp(header_footer, buffer, HEADER_FOOTER_SIZE) == 0;
|
||||||
if (header_footer[i] != buffer[i]) {
|
|
||||||
return false; // Mismatch in header/footer
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return true; // Valid header/footer
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void LD2450Component::setup() {
|
void LD2450Component::setup() {
|
||||||
@ -217,41 +211,41 @@ void LD2450Component::dump_config() {
|
|||||||
#endif
|
#endif
|
||||||
#ifdef USE_SENSOR
|
#ifdef USE_SENSOR
|
||||||
ESP_LOGCONFIG(TAG, "Sensors:");
|
ESP_LOGCONFIG(TAG, "Sensors:");
|
||||||
LOG_SENSOR(" ", "MovingTargetCount", this->moving_target_count_sensor_);
|
LOG_SENSOR_WITH_DEDUP_SAFE(" ", "MovingTargetCount", this->moving_target_count_sensor_);
|
||||||
LOG_SENSOR(" ", "StillTargetCount", this->still_target_count_sensor_);
|
LOG_SENSOR_WITH_DEDUP_SAFE(" ", "StillTargetCount", this->still_target_count_sensor_);
|
||||||
LOG_SENSOR(" ", "TargetCount", this->target_count_sensor_);
|
LOG_SENSOR_WITH_DEDUP_SAFE(" ", "TargetCount", this->target_count_sensor_);
|
||||||
for (sensor::Sensor *s : this->move_x_sensors_) {
|
for (auto &s : this->move_x_sensors_) {
|
||||||
LOG_SENSOR(" ", "TargetX", s);
|
LOG_SENSOR_WITH_DEDUP_SAFE(" ", "TargetX", s);
|
||||||
}
|
}
|
||||||
for (sensor::Sensor *s : this->move_y_sensors_) {
|
for (auto &s : this->move_y_sensors_) {
|
||||||
LOG_SENSOR(" ", "TargetY", s);
|
LOG_SENSOR_WITH_DEDUP_SAFE(" ", "TargetY", s);
|
||||||
}
|
}
|
||||||
for (sensor::Sensor *s : this->move_angle_sensors_) {
|
for (auto &s : this->move_angle_sensors_) {
|
||||||
LOG_SENSOR(" ", "TargetAngle", s);
|
LOG_SENSOR_WITH_DEDUP_SAFE(" ", "TargetAngle", s);
|
||||||
}
|
}
|
||||||
for (sensor::Sensor *s : this->move_distance_sensors_) {
|
for (auto &s : this->move_distance_sensors_) {
|
||||||
LOG_SENSOR(" ", "TargetDistance", s);
|
LOG_SENSOR_WITH_DEDUP_SAFE(" ", "TargetDistance", s);
|
||||||
}
|
}
|
||||||
for (sensor::Sensor *s : this->move_resolution_sensors_) {
|
for (auto &s : this->move_resolution_sensors_) {
|
||||||
LOG_SENSOR(" ", "TargetResolution", s);
|
LOG_SENSOR_WITH_DEDUP_SAFE(" ", "TargetResolution", s);
|
||||||
}
|
}
|
||||||
for (sensor::Sensor *s : this->move_speed_sensors_) {
|
for (auto &s : this->move_speed_sensors_) {
|
||||||
LOG_SENSOR(" ", "TargetSpeed", s);
|
LOG_SENSOR_WITH_DEDUP_SAFE(" ", "TargetSpeed", s);
|
||||||
}
|
}
|
||||||
for (sensor::Sensor *s : this->zone_target_count_sensors_) {
|
for (auto &s : this->zone_target_count_sensors_) {
|
||||||
LOG_SENSOR(" ", "ZoneTargetCount", s);
|
LOG_SENSOR_WITH_DEDUP_SAFE(" ", "ZoneTargetCount", s);
|
||||||
}
|
}
|
||||||
for (sensor::Sensor *s : this->zone_moving_target_count_sensors_) {
|
for (auto &s : this->zone_moving_target_count_sensors_) {
|
||||||
LOG_SENSOR(" ", "ZoneMovingTargetCount", s);
|
LOG_SENSOR_WITH_DEDUP_SAFE(" ", "ZoneMovingTargetCount", s);
|
||||||
}
|
}
|
||||||
for (sensor::Sensor *s : this->zone_still_target_count_sensors_) {
|
for (auto &s : this->zone_still_target_count_sensors_) {
|
||||||
LOG_SENSOR(" ", "ZoneStillTargetCount", s);
|
LOG_SENSOR_WITH_DEDUP_SAFE(" ", "ZoneStillTargetCount", s);
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
#ifdef USE_TEXT_SENSOR
|
#ifdef USE_TEXT_SENSOR
|
||||||
ESP_LOGCONFIG(TAG, "Text Sensors:");
|
ESP_LOGCONFIG(TAG, "Text Sensors:");
|
||||||
LOG_TEXT_SENSOR(" ", "Version", this->version_text_sensor_);
|
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_) {
|
for (text_sensor::TextSensor *s : this->direction_text_sensors_) {
|
||||||
LOG_TEXT_SENSOR(" ", "Direction", s);
|
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) {
|
if (command_value != nullptr) {
|
||||||
len += command_value_len;
|
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));
|
this->write_array(len_cmd, sizeof(len_cmd));
|
||||||
|
|
||||||
// command value bytes
|
// command value bytes
|
||||||
if (command_value != nullptr) {
|
if (command_value != nullptr) {
|
||||||
for (uint8_t i = 0; i < command_value_len; i++) {
|
this->write_array(command_value, command_value_len);
|
||||||
this->write_byte(command_value[i]);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
// frame footer bytes
|
// frame footer bytes
|
||||||
this->write_array(CMD_FRAME_FOOTER, sizeof(CMD_FRAME_FOOTER));
|
this->write_array(CMD_FRAME_FOOTER, sizeof(CMD_FRAME_FOOTER));
|
||||||
// FIXME to remove
|
|
||||||
|
if (command != CMD_ENABLE_CONF && command != CMD_DISABLE_CONF) {
|
||||||
delay(50); // NOLINT
|
delay(50); // NOLINT
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// LD2450 Radar data message:
|
// LD2450 Radar data message:
|
||||||
@ -459,8 +453,8 @@ void LD2450Component::handle_periodic_data_() {
|
|||||||
int16_t target_count = 0;
|
int16_t target_count = 0;
|
||||||
int16_t still_target_count = 0;
|
int16_t still_target_count = 0;
|
||||||
int16_t moving_target_count = 0;
|
int16_t moving_target_count = 0;
|
||||||
|
int16_t res = 0;
|
||||||
int16_t start = 0;
|
int16_t start = 0;
|
||||||
int16_t val = 0;
|
|
||||||
int16_t tx = 0;
|
int16_t tx = 0;
|
||||||
int16_t ty = 0;
|
int16_t ty = 0;
|
||||||
int16_t td = 0;
|
int16_t td = 0;
|
||||||
@ -478,85 +472,43 @@ void LD2450Component::handle_periodic_data_() {
|
|||||||
start = TARGET_X + index * 8;
|
start = TARGET_X + index * 8;
|
||||||
is_moving = false;
|
is_moving = false;
|
||||||
// tx is used for further calculations, so always needs to be populated
|
// 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 = ld2450::decode_coordinate(this->buffer_data_[start], this->buffer_data_[start + 1]);
|
||||||
tx = val;
|
SAFE_PUBLISH_SENSOR(this->move_x_sensors_[index], tx);
|
||||||
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;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
// Y
|
// Y
|
||||||
start = TARGET_Y + index * 8;
|
start = TARGET_Y + index * 8;
|
||||||
// ty is used for further calculations, so always needs to be populated
|
ty = ld2450::decode_coordinate(this->buffer_data_[start], this->buffer_data_[start + 1]);
|
||||||
val = ld2450::decode_coordinate(this->buffer_data_[start], this->buffer_data_[start + 1]);
|
SAFE_PUBLISH_SENSOR(this->move_y_sensors_[index], ty);
|
||||||
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;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
// RESOLUTION
|
// RESOLUTION
|
||||||
start = TARGET_RESOLUTION + index * 8;
|
start = TARGET_RESOLUTION + index * 8;
|
||||||
sensor::Sensor *sr = this->move_resolution_sensors_[index];
|
res = (this->buffer_data_[start + 1] << 8) | this->buffer_data_[start];
|
||||||
if (sr != nullptr) {
|
SAFE_PUBLISH_SENSOR(this->move_resolution_sensors_[index], res);
|
||||||
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;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
#endif
|
#endif
|
||||||
// SPEED
|
// SPEED
|
||||||
start = TARGET_SPEED + index * 8;
|
start = TARGET_SPEED + index * 8;
|
||||||
val = ld2450::decode_speed(this->buffer_data_[start], this->buffer_data_[start + 1]);
|
ts = ld2450::decode_speed(this->buffer_data_[start], this->buffer_data_[start + 1]);
|
||||||
ts = val;
|
if (ts) {
|
||||||
if (val) {
|
|
||||||
is_moving = true;
|
is_moving = true;
|
||||||
moving_target_count++;
|
moving_target_count++;
|
||||||
}
|
}
|
||||||
#ifdef USE_SENSOR
|
#ifdef USE_SENSOR
|
||||||
sensor::Sensor *ss = this->move_speed_sensors_[index];
|
SAFE_PUBLISH_SENSOR(this->move_speed_sensors_[index], ts);
|
||||||
if (ss != nullptr) {
|
|
||||||
if (this->cached_target_data_[index].speed != val) {
|
|
||||||
ss->publish_state(val);
|
|
||||||
this->cached_target_data_[index].speed = val;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
#endif
|
#endif
|
||||||
// DISTANCE
|
// DISTANCE
|
||||||
// Optimized: use already decoded tx and ty values, replace pow() with multiplication
|
// Optimized: use already decoded tx and ty values, replace pow() with multiplication
|
||||||
int32_t x_squared = (int32_t) tx * tx;
|
int32_t x_squared = (int32_t) tx * tx;
|
||||||
int32_t y_squared = (int32_t) ty * ty;
|
int32_t y_squared = (int32_t) ty * ty;
|
||||||
val = (uint16_t) sqrt(x_squared + y_squared);
|
td = (uint16_t) sqrtf(x_squared + y_squared);
|
||||||
td = val;
|
if (td > 0) {
|
||||||
if (val > 0) {
|
|
||||||
target_count++;
|
target_count++;
|
||||||
}
|
}
|
||||||
#ifdef USE_SENSOR
|
#ifdef USE_SENSOR
|
||||||
sensor::Sensor *sd = this->move_distance_sensors_[index];
|
SAFE_PUBLISH_SENSOR(this->move_distance_sensors_[index], td);
|
||||||
if (sd != nullptr) {
|
|
||||||
if (this->cached_target_data_[index].distance != val) {
|
|
||||||
sd->publish_state(val);
|
|
||||||
this->cached_target_data_[index].distance = val;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
// ANGLE
|
// ANGLE
|
||||||
angle = ld2450::calculate_angle(static_cast<float>(ty), static_cast<float>(td));
|
angle = ld2450::calculate_angle(static_cast<float>(ty), static_cast<float>(td));
|
||||||
if (tx > 0) {
|
if (tx > 0) {
|
||||||
angle = angle * -1;
|
angle = angle * -1;
|
||||||
}
|
}
|
||||||
sensor::Sensor *sa = this->move_angle_sensors_[index];
|
SAFE_PUBLISH_SENSOR(this->move_angle_sensors_[index], angle);
|
||||||
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;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
#endif
|
#endif
|
||||||
#ifdef USE_TEXT_SENSOR
|
#ifdef USE_TEXT_SENSOR
|
||||||
// DIRECTION
|
// DIRECTION
|
||||||
@ -570,11 +522,9 @@ void LD2450Component::handle_periodic_data_() {
|
|||||||
direction = DIRECTION_STATIONARY;
|
direction = DIRECTION_STATIONARY;
|
||||||
}
|
}
|
||||||
text_sensor::TextSensor *tsd = this->direction_text_sensors_[index];
|
text_sensor::TextSensor *tsd = this->direction_text_sensors_[index];
|
||||||
if (tsd != nullptr) {
|
const auto *dir_str = find_str(ld2450::DIRECTION_BY_UINT, direction);
|
||||||
if (this->cached_target_data_[index].direction != direction) {
|
if (tsd != nullptr && (!tsd->has_state() || tsd->get_state() != dir_str)) {
|
||||||
tsd->publish_state(find_str(ld2450::DIRECTION_BY_UINT, direction));
|
tsd->publish_state(dir_str);
|
||||||
this->cached_target_data_[index].direction = direction;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
@ -599,53 +549,19 @@ void LD2450Component::handle_periodic_data_() {
|
|||||||
zone_all_targets = zone_still_targets + zone_moving_targets;
|
zone_all_targets = zone_still_targets + zone_moving_targets;
|
||||||
|
|
||||||
// Publish Still Target Count in Zones
|
// Publish Still Target Count in Zones
|
||||||
sensor::Sensor *szstc = this->zone_still_target_count_sensors_[index];
|
SAFE_PUBLISH_SENSOR(this->zone_still_target_count_sensors_[index], zone_still_targets);
|
||||||
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;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
// Publish Moving Target Count in Zones
|
// Publish Moving Target Count in Zones
|
||||||
sensor::Sensor *szmtc = this->zone_moving_target_count_sensors_[index];
|
SAFE_PUBLISH_SENSOR(this->zone_moving_target_count_sensors_[index], zone_moving_targets);
|
||||||
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;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
// Publish All Target Count in Zones
|
// Publish All Target Count in Zones
|
||||||
sensor::Sensor *sztc = this->zone_target_count_sensors_[index];
|
SAFE_PUBLISH_SENSOR(this->zone_target_count_sensors_[index], zone_all_targets);
|
||||||
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;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
} // End loop thru zones
|
} // End loop thru zones
|
||||||
|
|
||||||
// Target Count
|
// Target Count
|
||||||
if (this->target_count_sensor_ != nullptr) {
|
SAFE_PUBLISH_SENSOR(this->target_count_sensor_, target_count);
|
||||||
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;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
// Still Target Count
|
// Still Target Count
|
||||||
if (this->still_target_count_sensor_ != nullptr) {
|
SAFE_PUBLISH_SENSOR(this->still_target_count_sensor_, still_target_count);
|
||||||
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;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
// Moving Target Count
|
// Moving Target Count
|
||||||
if (this->moving_target_count_sensor_ != nullptr) {
|
SAFE_PUBLISH_SENSOR(this->moving_target_count_sensor_, moving_target_count);
|
||||||
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;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
#ifdef USE_BINARY_SENSOR
|
#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); }
|
void LD2450Component::query_zone_() { this->send_command_(CMD_QUERY_ZONE, nullptr, 0); }
|
||||||
|
|
||||||
#ifdef USE_SENSOR
|
#ifdef USE_SENSOR
|
||||||
void LD2450Component::set_move_x_sensor(uint8_t target, sensor::Sensor *s) { this->move_x_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_y_sensor(uint8_t target, sensor::Sensor *s) { this->move_y_sensors_[target] = s; }
|
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) {
|
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) {
|
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) {
|
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) {
|
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) {
|
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) {
|
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) {
|
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
|
#endif
|
||||||
#ifdef USE_TEXT_SENSOR
|
#ifdef USE_TEXT_SENSOR
|
||||||
|
@ -1,12 +1,7 @@
|
|||||||
#pragma once
|
#pragma once
|
||||||
|
|
||||||
#include "esphome/components/uart/uart.h"
|
|
||||||
#include "esphome/core/component.h"
|
|
||||||
#include "esphome/core/defines.h"
|
#include "esphome/core/defines.h"
|
||||||
#include "esphome/core/helpers.h"
|
#include "esphome/core/component.h"
|
||||||
#include "esphome/core/preferences.h"
|
|
||||||
#include <limits>
|
|
||||||
#include <cmath>
|
|
||||||
#ifdef USE_SENSOR
|
#ifdef USE_SENSOR
|
||||||
#include "esphome/components/sensor/sensor.h"
|
#include "esphome/components/sensor/sensor.h"
|
||||||
#endif
|
#endif
|
||||||
@ -29,18 +24,23 @@
|
|||||||
#include "esphome/components/binary_sensor/binary_sensor.h"
|
#include "esphome/components/binary_sensor/binary_sensor.h"
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
#ifndef M_PI
|
#include "esphome/components/ld24xx/ld24xx.h"
|
||||||
#define M_PI 3.14
|
#include "esphome/components/uart/uart.h"
|
||||||
#endif
|
#include "esphome/core/helpers.h"
|
||||||
|
#include "esphome/core/preferences.h"
|
||||||
|
|
||||||
|
#include <array>
|
||||||
|
|
||||||
namespace esphome {
|
namespace esphome {
|
||||||
namespace ld2450 {
|
namespace ld2450 {
|
||||||
|
|
||||||
|
using namespace ld24xx;
|
||||||
|
|
||||||
// Constants
|
// Constants
|
||||||
static const uint8_t DEFAULT_PRESENCE_TIMEOUT = 5; // Timeout to reset presense status 5 sec.
|
static constexpr 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 constexpr uint8_t MAX_LINE_LENGTH = 41; // Max characters for serial buffer
|
||||||
static const uint8_t MAX_TARGETS = 3; // Max 3 Targets in LD2450
|
static constexpr 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 MAX_ZONES = 3; // Max 3 Zones in LD2450
|
||||||
|
|
||||||
enum Direction : uint8_t {
|
enum Direction : uint8_t {
|
||||||
DIRECTION_APPROACHING = 0,
|
DIRECTION_APPROACHING = 0,
|
||||||
@ -81,9 +81,9 @@ class LD2450Component : public Component, public uart::UARTDevice {
|
|||||||
SUB_BINARY_SENSOR(target)
|
SUB_BINARY_SENSOR(target)
|
||||||
#endif
|
#endif
|
||||||
#ifdef USE_SENSOR
|
#ifdef USE_SENSOR
|
||||||
SUB_SENSOR(moving_target_count)
|
SUB_SENSOR_WITH_DEDUP(moving_target_count, uint8_t)
|
||||||
SUB_SENSOR(still_target_count)
|
SUB_SENSOR_WITH_DEDUP(still_target_count, uint8_t)
|
||||||
SUB_SENSOR(target_count)
|
SUB_SENSOR_WITH_DEDUP(target_count, uint8_t)
|
||||||
#endif
|
#endif
|
||||||
#ifdef USE_TEXT_SENSOR
|
#ifdef USE_TEXT_SENSOR
|
||||||
SUB_TEXT_SENSOR(mac)
|
SUB_TEXT_SENSOR(mac)
|
||||||
@ -176,48 +176,23 @@ class LD2450Component : public Component, public uart::UARTDevice {
|
|||||||
Target target_info_[MAX_TARGETS];
|
Target target_info_[MAX_TARGETS];
|
||||||
Zone zone_config_[MAX_ZONES];
|
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
|
#ifdef USE_NUMBER
|
||||||
ESPPreferenceObject pref_; // only used when numbers are in use
|
ESPPreferenceObject pref_; // only used when numbers are in use
|
||||||
ZoneOfNumbers zone_numbers_[MAX_ZONES];
|
ZoneOfNumbers zone_numbers_[MAX_ZONES];
|
||||||
#endif
|
#endif
|
||||||
#ifdef USE_SENSOR
|
#ifdef USE_SENSOR
|
||||||
std::vector<sensor::Sensor *> move_x_sensors_ = std::vector<sensor::Sensor *>(MAX_TARGETS);
|
std::array<SensorWithDedup<int16_t> *, MAX_TARGETS> move_x_sensors_{};
|
||||||
std::vector<sensor::Sensor *> move_y_sensors_ = std::vector<sensor::Sensor *>(MAX_TARGETS);
|
std::array<SensorWithDedup<int16_t> *, MAX_TARGETS> move_y_sensors_{};
|
||||||
std::vector<sensor::Sensor *> move_speed_sensors_ = std::vector<sensor::Sensor *>(MAX_TARGETS);
|
std::array<SensorWithDedup<int16_t> *, MAX_TARGETS> move_speed_sensors_{};
|
||||||
std::vector<sensor::Sensor *> move_angle_sensors_ = std::vector<sensor::Sensor *>(MAX_TARGETS);
|
std::array<SensorWithDedup<float> *, MAX_TARGETS> move_angle_sensors_{};
|
||||||
std::vector<sensor::Sensor *> move_distance_sensors_ = std::vector<sensor::Sensor *>(MAX_TARGETS);
|
std::array<SensorWithDedup<uint16_t> *, MAX_TARGETS> move_distance_sensors_{};
|
||||||
std::vector<sensor::Sensor *> move_resolution_sensors_ = std::vector<sensor::Sensor *>(MAX_TARGETS);
|
std::array<SensorWithDedup<uint16_t> *, MAX_TARGETS> move_resolution_sensors_{};
|
||||||
std::vector<sensor::Sensor *> zone_target_count_sensors_ = std::vector<sensor::Sensor *>(MAX_ZONES);
|
std::array<SensorWithDedup<uint8_t> *, MAX_ZONES> zone_target_count_sensors_{};
|
||||||
std::vector<sensor::Sensor *> zone_still_target_count_sensors_ = std::vector<sensor::Sensor *>(MAX_ZONES);
|
std::array<SensorWithDedup<uint8_t> *, MAX_ZONES> zone_still_target_count_sensors_{};
|
||||||
std::vector<sensor::Sensor *> zone_moving_target_count_sensors_ = std::vector<sensor::Sensor *>(MAX_ZONES);
|
std::array<SensorWithDedup<uint8_t> *, MAX_ZONES> zone_moving_target_count_sensors_{};
|
||||||
#endif
|
#endif
|
||||||
#ifdef USE_TEXT_SENSOR
|
#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
|
#endif
|
||||||
};
|
};
|
||||||
|
|
||||||
|
Loading…
x
Reference in New Issue
Block a user