Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Fix possible lock-up while reading UART #6

Merged
merged 2 commits into from
Feb 14, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
48 changes: 34 additions & 14 deletions components/LD2450/LD2450.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -115,8 +115,8 @@ namespace esphome::ld2450
else
{
command_queue_.erase(command_queue_.begin());
command_send_retries_ = 0;
}
command_send_retries_ = 0;
ESP_LOGW(TAG, "Sending command timed out! Is the sensor connected?");
}
else
Expand All @@ -132,36 +132,41 @@ namespace esphome::ld2450
{
// Inject leave config command after clearing the queue
command_queue_.push_back({COMMAND_LEAVE_CONFIG, 0x00});
command_send_retries_ = 0;
}

// Skip stream until start of message and parse header
while (!peek_status_ && available() >= 4)
if (!peek_status_ && available() >= 4)
{
// Try to read the header and abort on mismatch
const uint8_t *header;
bool skip = false;
uint8_t target;
if (peek() == update_header[0])
uint8_t message_type;
uint8_t first_byte = read();
if (first_byte == update_header[0])
{
header = update_header;
target = 1;
message_type = 1;
}
else
else if (first_byte == config_header[0])
{
header = config_header;
target = 2;
message_type = 2;
}
else
{
skip = true;
}

for (int i = 0; i < 4 && !skip; i++)
for (int i = 1; i < 4 && !skip; i++)
{
if (read() != header[i])
skip = true;
}
if (skip)
continue;

// Flag successful header reading
peek_status_ = target;
if (!skip)
// Flag successful header reading
peek_status_ = message_type;
}

if (peek_status_ == 1 && available() >= 28)
Expand Down Expand Up @@ -201,10 +206,25 @@ namespace esphome::ld2450
peek_status_ = 0;
}
}

if (sensor_available_ && millis() - last_message_received_ > SENSOR_UNAVAILABLE_TIMEOUT)
{
sensor_available_ = false;

ESP_LOGE(TAG, "LD2450-Sensor stopped sending updates!");

// Update zones and related components
for (Zone *zone : zones_)
{
zone->update(targets_, sensor_available_);
}
}
}

void LD2450::process_message(uint8_t *msg, int len)
{
sensor_available_ = true;
last_message_received_ = millis();
for (int i = 0; i < 3; i++)
{
int offset = 8 * i;
Expand Down Expand Up @@ -251,7 +271,7 @@ namespace esphome::ld2450
// Update zones and related components
for (Zone *zone : zones_)
{
zone->update(targets_);
zone->update(targets_, sensor_available_);
}
}

Expand Down Expand Up @@ -396,7 +416,7 @@ namespace esphome::ld2450

// Write message length
write(static_cast<uint8_t>(len));
write(static_cast<uint8_t>(len << 8));
write(static_cast<uint8_t>(len >> 8));

// Write message content
write_array(msg, len);
Expand Down
21 changes: 19 additions & 2 deletions components/LD2450/LD2450.h
Original file line number Diff line number Diff line change
Expand Up @@ -21,7 +21,9 @@
#include "esphome/components/button/button.h"
#endif

#define COMMAND_MAX_RETRIES 5
#define SENSOR_UNAVAILABLE_TIMEOUT 1000

#define COMMAND_MAX_RETRIES 10
#define COMMAND_RETRY_DELAY 100

#define COMMAND_ENTER_CONFIG 0xFF
Expand Down Expand Up @@ -215,6 +217,15 @@ namespace esphome::ld2450
return targets_[i];
}

/**
* @brief Gets the state of the connected sensor
* @return True if the sensor is connected and communicating, False otherwise
*/
bool is_sensor_available()
{
return sensor_available_;
}

/**
* @brief Reads and logs the sensors version number.
*/
Expand Down Expand Up @@ -315,11 +326,17 @@ namespace esphome::ld2450
/// @brief Indicated that the sensor is currently factory resetting
bool is_applying_changes_ = false;

/// @brief indicates if the sensor is communicating
bool sensor_available_ = false;

/// @brief Expected length of the configuration message
int configuration_message_length_ = 0;

/// @brief timestamp of the last message which was sent to the sensor
long command_last_sent_ = 0;
uint32_t command_last_sent_ = 0;

/// @brief timestamp of the last received message
uint32_t last_message_received_ = 0;

/// @brief Queue of commands to execute
std::vector<std::vector<uint8_t>> command_queue_;
Expand Down
6 changes: 3 additions & 3 deletions components/LD2450/target.h
Original file line number Diff line number Diff line change
Expand Up @@ -125,7 +125,7 @@ namespace esphome::ld2450
* @brief Time since last last change in values.
* @return timestamp in milliseconds since start
*/
long get_last_change()
uint32_t get_last_change()
{
return last_change_;
}
Expand Down Expand Up @@ -206,10 +206,10 @@ namespace esphome::ld2450
bool fast_off_detection_ = false;

/// @brief time stamp of the last debug message which was sent.
long last_debug_message_ = 0;
uint32_t last_debug_message_ = 0;

/// @brief time of the last value change
long last_change_ = 0;
uint32_t last_change_ = 0;

/// @brief sensor reference of the x position sensor
PollingSensor *x_position_sensor_ = nullptr;
Expand Down
15 changes: 14 additions & 1 deletion components/LD2450/zone.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -39,8 +39,21 @@ namespace esphome::ld2450
#endif
}

void Zone::update(std::vector<Target *> &targets)
void Zone::update(std::vector<Target *> &targets, bool sensor_available)
{
if (!sensor_available)
{
#ifdef USE_BINARY_SENSOR
if (occupancy_binary_sensor_ != nullptr)
occupancy_binary_sensor_->publish_state(false);
#endif
#ifdef USE_SENSOR
if (target_count_sensor_ != nullptr)
target_count_sensor_->publish_state(NAN);
#endif
return;
}

if (polygon_.size() < 3)
return;

Expand Down
5 changes: 3 additions & 2 deletions components/LD2450/zone.h
Original file line number Diff line number Diff line change
Expand Up @@ -74,8 +74,9 @@ namespace esphome::ld2450
/**
* @brief Updates sensors related to this zone.
* @param targets Reference to a vector of targets which will be used for calculation
* @param available True if the sensor is currently available, false otherwise
* */
void update(std::vector<Target *> &targets);
void update(std::vector<Target *> &targets, bool sensor_available);

/**
* Logs the Zone configuration.
Expand Down Expand Up @@ -142,6 +143,6 @@ namespace esphome::ld2450
int target_timeout_ = 5000;

/// @brief Map of targets which are currently tracked inside of this polygon with their last seen timestamp
std::map<Target *, long> tracked_targets_{};
std::map<Target *, uint32_t> tracked_targets_{};
};
} // namespace esphome::ld2450
Loading