diff --git a/esphome/components/uart/uart.cpp b/esphome/components/uart/uart.cpp index 56b8e6401e8..1c545af8956 100644 --- a/esphome/components/uart/uart.cpp +++ b/esphome/components/uart/uart.cpp @@ -33,6 +33,13 @@ void UARTDevice::check_uart_settings(uint32_t baud_rate, uint8_t stop_bits, UART } } +void UARTDevice::discard_available() { + UARTComponent *parent = this->parent_; + uint8_t byte; + while (parent->available() && parent->read_byte(&byte)) { + } +} + const LogString *parity_to_str(UARTParityOptions parity) { return UARTParityStrings::get_log_str(static_cast(parity), UARTParityStrings::LAST_INDEX); } diff --git a/esphome/components/uart/uart.h b/esphome/components/uart/uart.h index a0840aa26a7..e8f98304bc9 100644 --- a/esphome/components/uart/uart.h +++ b/esphome/components/uart/uart.h @@ -90,6 +90,9 @@ class UARTDevice { count); } + /// Read and drop every byte waiting in the receive buffer. + void discard_available(); + UARTFlushResult flush() { return this->parent_->flush(); } // Compat APIs diff --git a/tests/components/uart/uart_read_available.cpp b/tests/components/uart/uart_read_available.cpp index 10c3e7fa0ef..6adc0b475df 100644 --- a/tests/components/uart/uart_read_available.cpp +++ b/tests/components/uart/uart_read_available.cpp @@ -141,4 +141,42 @@ TEST(UARTReadAvailableTest, ChunksWithCountStopEarly) { EXPECT_EQ(uart.remaining(), 14u); } +TEST(UARTReadAvailableTest, DiscardDropsEveryWaitingByte) { + ::testing::NiceMock uart(make_bytes(5)); + UARTDevice dev(&uart); + dev.discard_available(); + EXPECT_EQ(uart.remaining(), 0u); +} + +TEST(UARTReadAvailableTest, DiscardWithNothingAvailableDoesNotRead) { + ::testing::NiceMock uart(std::vector{}); + UARTDevice dev(&uart); + dev.discard_available(); + EXPECT_TRUE(uart.read_sizes.empty()); +} + +TEST(UARTReadAvailableTest, DiscardDropsBytesThatArriveWhileDraining) { + ::testing::NiceMock uart(std::vector{1, 2}); + bool appended = false; + ON_CALL(uart, available()).WillByDefault(Invoke([&]() -> size_t { + if (!appended && uart.read_sizes.size() == 1) { + uart.append({9, 9}); + appended = true; + } + return uart.remaining(); + })); + UARTDevice dev(&uart); + dev.discard_available(); + EXPECT_TRUE(appended); + EXPECT_EQ(uart.remaining(), 0u); +} + +TEST(UARTReadAvailableTest, DiscardStopsOnReadFailure) { + ::testing::NiceMock uart(make_bytes(5)); + uart.fail_after_reads = 2; + UARTDevice dev(&uart); + dev.discard_available(); + EXPECT_EQ(uart.read_sizes.size(), 3u); +} + } // namespace esphome::uart::testing