From 3f6eafc88094956223229a2c62451238e96ea700 Mon Sep 17 00:00:00 2001 From: "J. Nick Koston" Date: Fri, 16 Oct 2026 13:39:46 -1000 Subject: [PATCH] Queue a stop/start sequence only when it fits whole --- esphome/components/dfrobot_sen0395/automation.h | 3 +++ .../components/dfrobot_sen0395/dfrobot_sen0395.cpp | 9 +++++++++ esphome/components/dfrobot_sen0395/dfrobot_sen0395.h | 2 ++ tests/components/dfrobot_sen0395/settings_action.cpp | 12 ++++++++++++ 4 files changed, 26 insertions(+) diff --git a/esphome/components/dfrobot_sen0395/automation.h b/esphome/components/dfrobot_sen0395/automation.h index c4f742750e1..1f4d406e670 100644 --- a/esphome/components/dfrobot_sen0395/automation.h +++ b/esphome/components/dfrobot_sen0395/automation.h @@ -29,6 +29,9 @@ class DfrobotSen0395SettingsAction final : public Action, public Parented TEMPLATABLE_VALUE(float, det_max4) void play(const Ts &...x) override { + // Worst case: stop, factory reset, six settings, save, start + if (!this->parent_->has_queue_room(10)) + return; this->parent_->enqueue(CommandType::COMMAND_TYPE_POWER, false); if (this->factory_reset_.has_value() && this->factory_reset_.value(x...) == true) { this->parent_->enqueue(CommandType::COMMAND_TYPE_FACTORY_RESET); diff --git a/esphome/components/dfrobot_sen0395/dfrobot_sen0395.cpp b/esphome/components/dfrobot_sen0395/dfrobot_sen0395.cpp index cda381b84e5..6c6e50c073d 100644 --- a/esphome/components/dfrobot_sen0395/dfrobot_sen0395.cpp +++ b/esphome/components/dfrobot_sen0395/dfrobot_sen0395.cpp @@ -57,6 +57,13 @@ bool DfrobotSen0395Component::enqueue(CommandType type, uint8_t arg) { return true; } +bool DfrobotSen0395Component::has_queue_room(size_t count) const { + if (COMMAND_QUEUE_SIZE - this->cmd_queue_.size() >= count) + return true; + ESP_LOGE(TAG, "Command queue is full"); + return false; +} + void DfrobotSen0395Component::enqueue_det_range_cfg(float min1, float max1, float min2, float max2, float min3, float max3, float min4, float max4) { // TODO: Print warning when values are rounded @@ -89,6 +96,8 @@ void DfrobotSen0395Component::enqueue_set_latency(float delay_after_detection, f void DfrobotSen0395Component::enqueue_saved_setting(CommandType type, bool value) { const bool was_active = this->active_; + if (!this->has_queue_room(was_active ? 4 : 2)) + return; if (was_active) this->enqueue(CommandType::COMMAND_TYPE_POWER, false); this->enqueue(type, value); diff --git a/esphome/components/dfrobot_sen0395/dfrobot_sen0395.h b/esphome/components/dfrobot_sen0395/dfrobot_sen0395.h index e711a5b84db..fa20e250523 100644 --- a/esphome/components/dfrobot_sen0395/dfrobot_sen0395.h +++ b/esphome/components/dfrobot_sen0395/dfrobot_sen0395.h @@ -97,6 +97,8 @@ class DfrobotSen0395Component final : public uart::UARTDevice, public Component // Commands run one at a time from a queue, at least 1 s apart, so loop() never blocks bool enqueue(CommandType type, uint8_t arg = 0); + /// True when count more commands fit; logs when they do not, so a stop/start sequence is never queued in part + bool has_queue_room(size_t count) const; /// Queue a detection range config; segments are used up to the first one with a negative bound void enqueue_det_range_cfg(float min1, float max1, float min2, float max2, float min3, float max3, float min4, float max4); diff --git a/tests/components/dfrobot_sen0395/settings_action.cpp b/tests/components/dfrobot_sen0395/settings_action.cpp index c5099220319..cee64e09e5d 100644 --- a/tests/components/dfrobot_sen0395/settings_action.cpp +++ b/tests/components/dfrobot_sen0395/settings_action.cpp @@ -142,4 +142,16 @@ TEST_F(SettingsActionTest, FloatTriggerUnpairedSegmentIsNotEvaluated) { EXPECT_EQ(call_record().segment_calls[0], 0); } +TEST_F(SettingsActionTest, QueuesNothingWithoutRoomForWholeSequence) { + for (int i = 0; i < 11; i++) + ASSERT_TRUE(this->radar_.enqueue(CommandType::COMMAND_TYPE_SAVE_CFG)); + DfrobotSen0395SettingsAction<> action; + action.set_parent(&this->radar_); + action.play(); + EXPECT_TRUE(this->radar_.has_queue_room(9)); + this->radar_.enqueue_saved_setting(CommandType::COMMAND_TYPE_LED_MODE, true); + EXPECT_TRUE(this->radar_.has_queue_room(7)); + EXPECT_FALSE(this->radar_.has_queue_room(8)); +} + } // namespace esphome::dfrobot_sen0395::testing