mirror of
https://github.com/esphome/esphome.git
synced 2026-09-20 19:48:39 +00:00
Merge remote-tracking branch 'upstream/dev' into integration
This commit is contained in:
@@ -601,28 +601,11 @@ void LD2410Component::readline_(int readch) {
|
||||
return; // No data available
|
||||
}
|
||||
|
||||
// Frame header synchronization: verify first 4 bytes match a known frame header.
|
||||
// This prevents the parser from getting stuck in an overflow loop after losing sync
|
||||
// (e.g. after module restart or UART noise).
|
||||
if (this->buffer_pos_ < HEADER_FOOTER_SIZE) {
|
||||
const uint8_t byte = static_cast<uint8_t>(readch);
|
||||
// Verify header bytes match the frame type established by byte 0
|
||||
if (this->buffer_pos_ > 0) {
|
||||
const uint8_t *expected = (this->buffer_data_[0] == DATA_FRAME_HEADER[0]) ? DATA_FRAME_HEADER : CMD_FRAME_HEADER;
|
||||
if (byte != expected[this->buffer_pos_]) {
|
||||
this->buffer_pos_ = 0; // Reset and fall through to check if this byte starts a new frame
|
||||
}
|
||||
}
|
||||
// First byte must match start of a data or command frame header
|
||||
if (this->buffer_pos_ == 0 && byte != DATA_FRAME_HEADER[0] && byte != CMD_FRAME_HEADER[0]) {
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
if (this->buffer_pos_ < MAX_LINE_LENGTH - 1) {
|
||||
this->buffer_data_[this->buffer_pos_++] = readch;
|
||||
this->buffer_data_[this->buffer_pos_] = 0;
|
||||
} else {
|
||||
// We should never get here, but just in case...
|
||||
ESP_LOGW(TAG, "Max command length exceeded; ignoring");
|
||||
this->buffer_pos_ = 0;
|
||||
return;
|
||||
|
||||
@@ -21,7 +21,9 @@
|
||||
namespace esphome::ld2420 {
|
||||
|
||||
static constexpr uint8_t CALIBRATE_SAMPLES = 64;
|
||||
static constexpr uint8_t MAX_LINE_LENGTH = 46; // Max characters for serial buffer
|
||||
// Energy frame is 45 bytes; +1 for null terminator, +4 so that a frame footer always lands
|
||||
// inside the buffer during footer-based resynchronization after losing sync.
|
||||
static constexpr uint8_t MAX_LINE_LENGTH = 50;
|
||||
static constexpr uint8_t TOTAL_GATES = 16;
|
||||
|
||||
enum OpMode : uint8_t {
|
||||
|
||||
@@ -769,28 +769,11 @@ void LD2450Component::readline_(int readch) {
|
||||
return; // No data available
|
||||
}
|
||||
|
||||
// Frame header synchronization: verify first 4 bytes match a known frame header.
|
||||
// This prevents the parser from accumulating mid-frame data after losing sync
|
||||
// (e.g. after module restart or UART noise).
|
||||
if (this->buffer_pos_ < HEADER_FOOTER_SIZE) {
|
||||
const uint8_t byte = static_cast<uint8_t>(readch);
|
||||
// Verify header bytes match the frame type established by byte 0
|
||||
if (this->buffer_pos_ > 0) {
|
||||
const uint8_t *expected = (this->buffer_data_[0] == DATA_FRAME_HEADER[0]) ? DATA_FRAME_HEADER : CMD_FRAME_HEADER;
|
||||
if (byte != expected[this->buffer_pos_]) {
|
||||
this->buffer_pos_ = 0; // Reset and fall through to check if this byte starts a new frame
|
||||
}
|
||||
}
|
||||
// First byte must match start of a data or command frame header
|
||||
if (this->buffer_pos_ == 0 && byte != DATA_FRAME_HEADER[0] && byte != CMD_FRAME_HEADER[0]) {
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
if (this->buffer_pos_ < MAX_LINE_LENGTH - 1) {
|
||||
this->buffer_data_[this->buffer_pos_++] = readch;
|
||||
this->buffer_data_[this->buffer_pos_] = 0;
|
||||
} else {
|
||||
// We should never get here, but just in case...
|
||||
ESP_LOGW(TAG, "Max command length exceeded; ignoring");
|
||||
this->buffer_pos_ = 0;
|
||||
return;
|
||||
|
||||
@@ -93,10 +93,7 @@ TEST_F(LD2450ReadlineTest, CmdFooterInGarbageResyncs) {
|
||||
TEST_F(LD2450ReadlineTest, OverflowResetsBuffer) {
|
||||
// Fill the buffer to capacity with filler that won't match any footer.
|
||||
// MAX_LINE_LENGTH is 45, usable is 44. The 45th byte triggers overflow.
|
||||
std::vector<uint8_t> overflow_data;
|
||||
for (int i = 0; i < MAX_LINE_LENGTH; i++) {
|
||||
overflow_data.push_back(0x11); // Filler that won't match any footer
|
||||
}
|
||||
std::vector<uint8_t> overflow_data(MAX_LINE_LENGTH, 0x11);
|
||||
this->ld2450_.feed(overflow_data);
|
||||
// After overflow, buffer_pos_ resets to 0 (via the < 4 early return path)
|
||||
EXPECT_LT(this->ld2450_.buffer_pos_, 4);
|
||||
@@ -104,10 +101,7 @@ TEST_F(LD2450ReadlineTest, OverflowResetsBuffer) {
|
||||
|
||||
TEST_F(LD2450ReadlineTest, OverflowThenValidFrame) {
|
||||
// Overflow, then a valid frame should be processed.
|
||||
std::vector<uint8_t> overflow_data;
|
||||
for (int i = 0; i < MAX_LINE_LENGTH; i++) {
|
||||
overflow_data.push_back(0x11);
|
||||
}
|
||||
std::vector<uint8_t> overflow_data(MAX_LINE_LENGTH, 0x11);
|
||||
this->ld2450_.feed(overflow_data);
|
||||
|
||||
auto frame = make_periodic_frame();
|
||||
@@ -119,11 +113,7 @@ TEST_F(LD2450ReadlineTest, BufferLargeEnoughForDesyncedFooter) {
|
||||
// The key fix: the buffer (45) is large enough that a desynced periodic frame's
|
||||
// footer (at most 30 bytes into the stream) will land inside the buffer before overflow.
|
||||
// Simulate starting 10 bytes into a periodic frame, then a full frame follows.
|
||||
std::vector<uint8_t> mid_frame;
|
||||
// 10 bytes of "mid-frame" data (no footer match)
|
||||
for (int i = 0; i < 10; i++) {
|
||||
mid_frame.push_back(0x30 + i);
|
||||
}
|
||||
std::vector<uint8_t> mid_frame = {0x30, 0x31, 0x32, 0x33, 0x34, 0x35, 0x36, 0x37, 0x38, 0x39};
|
||||
// Then a complete periodic frame whose footer will land at position 40 (10 + 30),
|
||||
// well within the buffer size of 45.
|
||||
auto frame = make_periodic_frame();
|
||||
|
||||
Reference in New Issue
Block a user