From 323209523ba975b2b4de1606b366f4c1f60e3068 Mon Sep 17 00:00:00 2001 From: Damien Sorel Date: Mon, 3 Mar 2025 17:44:15 +0100 Subject: [PATCH] [ld2450] fix null exception & zone target_count not published (#8348) Co-authored-by: Keith Burzinski --- esphome/components/ld2450/ld2450.cpp | 63 ++++++++++---------- esphome/components/ld2450/ld2450.h | 19 +++--- esphome/components/ld2450/number/__init__.py | 61 +++++++++---------- 3 files changed, 75 insertions(+), 68 deletions(-) diff --git a/esphome/components/ld2450/ld2450.cpp b/esphome/components/ld2450/ld2450.cpp index dd564e6ed5..5bd7635dec 100644 --- a/esphome/components/ld2450/ld2450.cpp +++ b/esphome/components/ld2450/ld2450.cpp @@ -110,8 +110,10 @@ LD2450Component::LD2450Component() {} void LD2450Component::setup() { ESP_LOGCONFIG(TAG, "Setting up HLK-LD2450..."); #ifdef USE_NUMBER - this->pref_ = global_preferences->make_preference(this->presence_timeout_number_->get_object_id_hash()); - this->set_presence_timeout(); + if (this->presence_timeout_number_ != nullptr) { + this->pref_ = global_preferences->make_preference(this->presence_timeout_number_->get_object_id_hash()); + this->set_presence_timeout(); + } #endif this->restart_and_read_all_info(); } @@ -171,17 +173,11 @@ void LD2450Component::dump_config() { } #endif #ifdef USE_NUMBER - for (number::Number *n : this->zone_x1_numbers_) { - LOG_NUMBER(" ", "ZoneX1Number", n); - } - for (number::Number *n : this->zone_y1_numbers_) { - LOG_NUMBER(" ", "ZoneY1Number", n); - } - for (number::Number *n : this->zone_x2_numbers_) { - LOG_NUMBER(" ", "ZoneX2Number", n); - } - for (number::Number *n : this->zone_y2_numbers_) { - LOG_NUMBER(" ", "ZoneY2Number", n); + for (auto n : this->zone_numbers_) { + LOG_NUMBER(" ", "ZoneX1Number", n.x1); + LOG_NUMBER(" ", "ZoneY1Number", n.y1); + LOG_NUMBER(" ", "ZoneX2Number", n.x2); + LOG_NUMBER(" ", "ZoneY2Number", n.y2); } #endif #ifdef USE_SELECT @@ -281,10 +277,13 @@ void LD2450Component::process_zone_(uint8_t *buffer) { this->zone_config_[index].x2 = ld2450::hex_to_signed_int(buffer, start + 4); this->zone_config_[index].y2 = ld2450::hex_to_signed_int(buffer, start + 6); #ifdef USE_NUMBER - this->zone_x1_numbers_[index]->publish_state(this->zone_config_[index].x1); - this->zone_y1_numbers_[index]->publish_state(this->zone_config_[index].y1); - this->zone_x2_numbers_[index]->publish_state(this->zone_config_[index].x2); - this->zone_y2_numbers_[index]->publish_state(this->zone_config_[index].y2); + // only one null check as all coordinates are required for a single zone + if (this->zone_numbers_[index].x1 != nullptr) { + this->zone_numbers_[index].x1->publish_state(this->zone_config_[index].x1); + this->zone_numbers_[index].y1->publish_state(this->zone_config_[index].y1); + this->zone_numbers_[index].x2->publish_state(this->zone_config_[index].x2); + this->zone_numbers_[index].y2->publish_state(this->zone_config_[index].y2); + } #endif } } @@ -480,21 +479,20 @@ void LD2450Component::handle_periodic_data_(uint8_t *buffer, uint8_t len) { uint8_t zone_moving_targets = 0; uint8_t zone_all_targets = 0; for (index = 0; index < MAX_ZONES; index++) { + zone_still_targets = this->count_targets_in_zone_(this->zone_config_[index], false); + zone_moving_targets = this->count_targets_in_zone_(this->zone_config_[index], true); + 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) { - zone_still_targets = this->count_targets_in_zone_(this->zone_config_[index], false); szstc->publish_state(zone_still_targets); } // Publish Moving Target Count in Zones sensor::Sensor *szmtc = this->zone_moving_target_count_sensors_[index]; if (szmtc != nullptr) { - zone_moving_targets = this->count_targets_in_zone_(this->zone_config_[index], true); szmtc->publish_state(zone_moving_targets); } - - zone_all_targets = zone_still_targets + zone_moving_targets; - // Publish All Target Count in Zones sensor::Sensor *sztc = this->zone_target_count_sensors_[index]; if (sztc != nullptr) { @@ -820,10 +818,10 @@ void LD2450Component::set_direction_text_sensor(uint8_t target, text_sensor::Tex // Send Zone coordinates data to LD2450 #ifdef USE_NUMBER void LD2450Component::set_zone_coordinate(uint8_t zone) { - number::Number *x1sens = this->zone_x1_numbers_[zone]; - number::Number *y1sens = this->zone_y1_numbers_[zone]; - number::Number *x2sens = this->zone_x2_numbers_[zone]; - number::Number *y2sens = this->zone_y2_numbers_[zone]; + number::Number *x1sens = this->zone_numbers_[zone].x1; + number::Number *y1sens = this->zone_numbers_[zone].y1; + number::Number *x2sens = this->zone_numbers_[zone].x2; + number::Number *y2sens = this->zone_numbers_[zone].y2; if (!x1sens->has_state() || !y1sens->has_state() || !x2sens->has_state() || !y2sens->has_state()) { return; } @@ -834,10 +832,15 @@ void LD2450Component::set_zone_coordinate(uint8_t zone) { this->send_set_zone_command_(); } -void LD2450Component::set_zone_x1_number(uint8_t zone, number::Number *n) { this->zone_x1_numbers_[zone] = n; } -void LD2450Component::set_zone_y1_number(uint8_t zone, number::Number *n) { this->zone_y1_numbers_[zone] = n; } -void LD2450Component::set_zone_x2_number(uint8_t zone, number::Number *n) { this->zone_x2_numbers_[zone] = n; } -void LD2450Component::set_zone_y2_number(uint8_t zone, number::Number *n) { this->zone_y2_numbers_[zone] = n; } +void LD2450Component::set_zone_numbers(uint8_t zone, number::Number *x1, number::Number *y1, number::Number *x2, + number::Number *y2) { + if (zone < MAX_ZONES) { + this->zone_numbers_[zone].x1 = x1; + this->zone_numbers_[zone].y1 = y1; + this->zone_numbers_[zone].x2 = x2; + this->zone_numbers_[zone].y2 = y2; + } +} #endif // Set Presence Timeout load and save from flash diff --git a/esphome/components/ld2450/ld2450.h b/esphome/components/ld2450/ld2450.h index 2fed7dc0c9..32e4bc02e4 100644 --- a/esphome/components/ld2450/ld2450.h +++ b/esphome/components/ld2450/ld2450.h @@ -57,6 +57,15 @@ struct Zone { int16_t y2 = 0; }; +#ifdef USE_NUMBER +struct ZoneOfNumbers { + number::Number *x1 = nullptr; + number::Number *y1 = nullptr; + number::Number *x2 = nullptr; + number::Number *y2 = nullptr; +}; +#endif + enum BaudRateStructure : uint8_t { BAUD_RATE_9600 = 1, BAUD_RATE_19200 = 2, @@ -152,10 +161,7 @@ class LD2450Component : public Component, public uart::UARTDevice { #endif #ifdef USE_NUMBER void set_zone_coordinate(uint8_t zone); - void set_zone_x1_number(uint8_t zone, number::Number *n); - void set_zone_y1_number(uint8_t zone, number::Number *n); - void set_zone_x2_number(uint8_t zone, number::Number *n); - void set_zone_y2_number(uint8_t zone, number::Number *n); + void set_zone_numbers(uint8_t zone, number::Number *x1, number::Number *y1, number::Number *x2, number::Number *y2); #endif #ifdef USE_SENSOR void set_move_x_sensor(uint8_t target, sensor::Sensor *s); @@ -206,10 +212,7 @@ class LD2450Component : public Component, public uart::UARTDevice { std::string mac_{}; #ifdef USE_NUMBER ESPPreferenceObject pref_; // only used when numbers are in use - std::vector zone_x1_numbers_ = std::vector(MAX_ZONES); - std::vector zone_y1_numbers_ = std::vector(MAX_ZONES); - std::vector zone_x2_numbers_ = std::vector(MAX_ZONES); - std::vector zone_y2_numbers_ = std::vector(MAX_ZONES); + ZoneOfNumbers zone_numbers_[MAX_ZONES]; #endif #ifdef USE_SENSOR std::vector move_x_sensors_ = std::vector(MAX_TARGETS); diff --git a/esphome/components/ld2450/number/__init__.py b/esphome/components/ld2450/number/__init__.py index 8e83de56a0..d2098f6131 100644 --- a/esphome/components/ld2450/number/__init__.py +++ b/esphome/components/ld2450/number/__init__.py @@ -88,33 +88,34 @@ async def to_code(config): ) await cg.register_parented(n, config[CONF_LD2450_ID]) cg.add(ld2450_component.set_presence_timeout_number(n)) - for x in range(MAX_ZONES): - if zone_conf := config.get(f"zone_{x + 1}"): - if zone_x1_config := zone_conf.get(CONF_X1): - n = cg.new_Pvariable(zone_x1_config[CONF_ID], x) - await number.register_number( - n, zone_x1_config, min_value=-4860, max_value=4860, step=1 - ) - await cg.register_parented(n, config[CONF_LD2450_ID]) - cg.add(ld2450_component.set_zone_x1_number(x, n)) - if zone_y1_config := zone_conf.get(CONF_Y1): - n = cg.new_Pvariable(zone_y1_config[CONF_ID], x) - await number.register_number( - n, zone_y1_config, min_value=0, max_value=7560, step=1 - ) - await cg.register_parented(n, config[CONF_LD2450_ID]) - cg.add(ld2450_component.set_zone_y1_number(x, n)) - if zone_x2_config := zone_conf.get(CONF_X2): - n = cg.new_Pvariable(zone_x2_config[CONF_ID], x) - await number.register_number( - n, zone_x2_config, min_value=-4860, max_value=4860, step=1 - ) - await cg.register_parented(n, config[CONF_LD2450_ID]) - cg.add(ld2450_component.set_zone_x2_number(x, n)) - if zone_y2_config := zone_conf.get(CONF_Y2): - n = cg.new_Pvariable(zone_y2_config[CONF_ID], x) - await number.register_number( - n, zone_y2_config, min_value=0, max_value=7560, step=1 - ) - await cg.register_parented(n, config[CONF_LD2450_ID]) - cg.add(ld2450_component.set_zone_y2_number(x, n)) + for zone_num in range(MAX_ZONES): + if zone_conf := config.get(f"zone_{zone_num + 1}"): + zone_x1_config = zone_conf.get(CONF_X1) + x1 = cg.new_Pvariable(zone_x1_config[CONF_ID], zone_num) + await number.register_number( + x1, zone_x1_config, min_value=-4860, max_value=4860, step=1 + ) + await cg.register_parented(x1, config[CONF_LD2450_ID]) + + zone_y1_config = zone_conf.get(CONF_Y1) + y1 = cg.new_Pvariable(zone_y1_config[CONF_ID], zone_num) + await number.register_number( + y1, zone_y1_config, min_value=0, max_value=7560, step=1 + ) + await cg.register_parented(y1, config[CONF_LD2450_ID]) + + zone_x2_config = zone_conf.get(CONF_X2) + x2 = cg.new_Pvariable(zone_x2_config[CONF_ID], zone_num) + await number.register_number( + x2, zone_x2_config, min_value=-4860, max_value=4860, step=1 + ) + await cg.register_parented(x2, config[CONF_LD2450_ID]) + + zone_y2_config = zone_conf.get(CONF_Y2) + y2 = cg.new_Pvariable(zone_y2_config[CONF_ID], zone_num) + await number.register_number( + y2, zone_y2_config, min_value=0, max_value=7560, step=1 + ) + await cg.register_parented(y2, config[CONF_LD2450_ID]) + + cg.add(ld2450_component.set_zone_numbers(zone_num, x1, y1, x2, y2))