mirror of
https://github.com/esphome/esphome.git
synced 2025-07-28 14:16:40 +00:00
[nextion] Add optional max_queue_size
limit to prevent queue overflows (#8976)
This commit is contained in:
parent
1dd3c6de90
commit
80fd827f8b
@ -14,6 +14,7 @@ CONF_COMPONENT_NAME = "component_name"
|
|||||||
CONF_EXIT_REPARSE_ON_START = "exit_reparse_on_start"
|
CONF_EXIT_REPARSE_ON_START = "exit_reparse_on_start"
|
||||||
CONF_FONT_ID = "font_id"
|
CONF_FONT_ID = "font_id"
|
||||||
CONF_FOREGROUND_PRESSED_COLOR = "foreground_pressed_color"
|
CONF_FOREGROUND_PRESSED_COLOR = "foreground_pressed_color"
|
||||||
|
CONF_MAX_QUEUE_SIZE = "max_queue_size"
|
||||||
CONF_ON_BUFFER_OVERFLOW = "on_buffer_overflow"
|
CONF_ON_BUFFER_OVERFLOW = "on_buffer_overflow"
|
||||||
CONF_ON_PAGE = "on_page"
|
CONF_ON_PAGE = "on_page"
|
||||||
CONF_ON_SETUP = "on_setup"
|
CONF_ON_SETUP = "on_setup"
|
||||||
|
@ -16,6 +16,7 @@ from .base_component import (
|
|||||||
CONF_AUTO_WAKE_ON_TOUCH,
|
CONF_AUTO_WAKE_ON_TOUCH,
|
||||||
CONF_COMMAND_SPACING,
|
CONF_COMMAND_SPACING,
|
||||||
CONF_EXIT_REPARSE_ON_START,
|
CONF_EXIT_REPARSE_ON_START,
|
||||||
|
CONF_MAX_QUEUE_SIZE,
|
||||||
CONF_ON_BUFFER_OVERFLOW,
|
CONF_ON_BUFFER_OVERFLOW,
|
||||||
CONF_ON_SETUP,
|
CONF_ON_SETUP,
|
||||||
CONF_ON_SLEEP,
|
CONF_ON_SLEEP,
|
||||||
@ -93,6 +94,7 @@ CONFIG_SCHEMA = (
|
|||||||
cv.positive_time_period_milliseconds,
|
cv.positive_time_period_milliseconds,
|
||||||
cv.Range(max=TimePeriod(milliseconds=255)),
|
cv.Range(max=TimePeriod(milliseconds=255)),
|
||||||
),
|
),
|
||||||
|
cv.Optional(CONF_MAX_QUEUE_SIZE): cv.positive_int,
|
||||||
}
|
}
|
||||||
)
|
)
|
||||||
.extend(cv.polling_component_schema("5s"))
|
.extend(cv.polling_component_schema("5s"))
|
||||||
@ -125,6 +127,10 @@ async def to_code(config):
|
|||||||
var = cg.new_Pvariable(config[CONF_ID])
|
var = cg.new_Pvariable(config[CONF_ID])
|
||||||
await uart.register_uart_device(var, config)
|
await uart.register_uart_device(var, config)
|
||||||
|
|
||||||
|
if max_queue_size := config.get(CONF_MAX_QUEUE_SIZE):
|
||||||
|
cg.add_define("USE_NEXTION_MAX_QUEUE_SIZE")
|
||||||
|
cg.add(var.set_max_queue_size(max_queue_size))
|
||||||
|
|
||||||
if command_spacing := config.get(CONF_COMMAND_SPACING):
|
if command_spacing := config.get(CONF_COMMAND_SPACING):
|
||||||
cg.add_define("USE_NEXTION_COMMAND_SPACING")
|
cg.add_define("USE_NEXTION_COMMAND_SPACING")
|
||||||
cg.add(var.set_command_spacing(command_spacing.total_milliseconds))
|
cg.add(var.set_command_spacing(command_spacing.total_milliseconds))
|
||||||
|
@ -173,6 +173,10 @@ void Nextion::dump_config() {
|
|||||||
#ifdef USE_NEXTION_COMMAND_SPACING
|
#ifdef USE_NEXTION_COMMAND_SPACING
|
||||||
ESP_LOGCONFIG(TAG, " Command spacing: %" PRIu8 "ms", this->command_pacer_.get_spacing());
|
ESP_LOGCONFIG(TAG, " Command spacing: %" PRIu8 "ms", this->command_pacer_.get_spacing());
|
||||||
#endif // USE_NEXTION_COMMAND_SPACING
|
#endif // USE_NEXTION_COMMAND_SPACING
|
||||||
|
|
||||||
|
#ifdef USE_NEXTION_MAX_QUEUE_SIZE
|
||||||
|
ESP_LOGCONFIG(TAG, " Max queue size: %zu", this->max_queue_size_);
|
||||||
|
#endif
|
||||||
}
|
}
|
||||||
|
|
||||||
float Nextion::get_setup_priority() const { return setup_priority::DATA; }
|
float Nextion::get_setup_priority() const { return setup_priority::DATA; }
|
||||||
@ -998,11 +1002,24 @@ uint16_t Nextion::recv_ret_string_(std::string &response, uint32_t timeout, bool
|
|||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @brief
|
* @brief Add a command to the Nextion queue that expects no response.
|
||||||
*
|
*
|
||||||
* @param variable_name Name for the queue
|
* This is typically used for write-only operations such as variable assignments or component updates
|
||||||
|
* where no return value or acknowledgment is expected from the display.
|
||||||
|
*
|
||||||
|
* If the `max_queue_size` limit is configured and reached, the command will be skipped.
|
||||||
|
*
|
||||||
|
* @param variable_name Name of the variable or component associated with the command.
|
||||||
*/
|
*/
|
||||||
void Nextion::add_no_result_to_queue_(const std::string &variable_name) {
|
void Nextion::add_no_result_to_queue_(const std::string &variable_name) {
|
||||||
|
#ifdef USE_NEXTION_MAX_QUEUE_SIZE
|
||||||
|
if (this->max_queue_size_ > 0 && this->nextion_queue_.size() >= this->max_queue_size_) {
|
||||||
|
ESP_LOGW(TAG, "Nextion queue full (%zu entries), dropping NORESULT command: %s", this->nextion_queue_.size(),
|
||||||
|
variable_name.c_str());
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
ExternalRAMAllocator<nextion::NextionQueue> allocator(ExternalRAMAllocator<nextion::NextionQueue>::ALLOW_FAILURE);
|
ExternalRAMAllocator<nextion::NextionQueue> allocator(ExternalRAMAllocator<nextion::NextionQueue>::ALLOW_FAILURE);
|
||||||
nextion::NextionQueue *nextion_queue = allocator.allocate(1);
|
nextion::NextionQueue *nextion_queue = allocator.allocate(1);
|
||||||
if (nextion_queue == nullptr) {
|
if (nextion_queue == nullptr) {
|
||||||
@ -1138,10 +1155,27 @@ void Nextion::add_no_result_to_queue_with_set_internal_(const std::string &varia
|
|||||||
state_value.c_str());
|
state_value.c_str());
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief Queue a GET command for a component that expects a response from the Nextion display.
|
||||||
|
*
|
||||||
|
* This method is used for querying values such as sensor states, text content, or switch status.
|
||||||
|
* The component will be added to the Nextion queue only if the display is already set up,
|
||||||
|
* the queue has not reached the configured maximum size (if set), and the command is sent successfully.
|
||||||
|
*
|
||||||
|
* @param component Pointer to the Nextion component that will handle the response.
|
||||||
|
*/
|
||||||
void Nextion::add_to_get_queue(NextionComponentBase *component) {
|
void Nextion::add_to_get_queue(NextionComponentBase *component) {
|
||||||
if ((!this->is_setup() && !this->ignore_is_setup_))
|
if ((!this->is_setup() && !this->ignore_is_setup_))
|
||||||
return;
|
return;
|
||||||
|
|
||||||
|
#ifdef USE_NEXTION_MAX_QUEUE_SIZE
|
||||||
|
if (this->max_queue_size_ > 0 && this->nextion_queue_.size() >= this->max_queue_size_) {
|
||||||
|
ESP_LOGW(TAG, "Nextion queue full (%zu entries), dropping GET for \"%s\"", this->nextion_queue_.size(),
|
||||||
|
component->get_variable_name().c_str());
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
ExternalRAMAllocator<nextion::NextionQueue> allocator(ExternalRAMAllocator<nextion::NextionQueue>::ALLOW_FAILURE);
|
ExternalRAMAllocator<nextion::NextionQueue> allocator(ExternalRAMAllocator<nextion::NextionQueue>::ALLOW_FAILURE);
|
||||||
nextion::NextionQueue *nextion_queue = allocator.allocate(1);
|
nextion::NextionQueue *nextion_queue = allocator.allocate(1);
|
||||||
if (nextion_queue == nullptr) {
|
if (nextion_queue == nullptr) {
|
||||||
|
@ -75,6 +75,20 @@ class NextionCommandPacer {
|
|||||||
|
|
||||||
class Nextion : public NextionBase, public PollingComponent, public uart::UARTDevice {
|
class Nextion : public NextionBase, public PollingComponent, public uart::UARTDevice {
|
||||||
public:
|
public:
|
||||||
|
#ifdef USE_NEXTION_MAX_QUEUE_SIZE
|
||||||
|
/**
|
||||||
|
* @brief Set the maximum allowed queue size
|
||||||
|
* @param size Max number of entries allowed in nextion_queue_
|
||||||
|
*/
|
||||||
|
inline void set_max_queue_size(size_t size) { this->max_queue_size_ = size; }
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief Get the maximum allowed queue size
|
||||||
|
* @return Current limit (0 = unlimited)
|
||||||
|
*/
|
||||||
|
inline size_t get_max_queue_size() const { return this->max_queue_size_; }
|
||||||
|
#endif // USE_NEXTION_MAX_QUEUE_SIZE
|
||||||
|
|
||||||
#ifdef USE_NEXTION_COMMAND_SPACING
|
#ifdef USE_NEXTION_COMMAND_SPACING
|
||||||
/**
|
/**
|
||||||
* @brief Set the command spacing for the display
|
* @brief Set the command spacing for the display
|
||||||
@ -1273,6 +1287,9 @@ class Nextion : public NextionBase, public PollingComponent, public uart::UARTDe
|
|||||||
bool is_connected() { return this->is_connected_; }
|
bool is_connected() { return this->is_connected_; }
|
||||||
|
|
||||||
protected:
|
protected:
|
||||||
|
#ifdef USE_NEXTION_MAX_QUEUE_SIZE
|
||||||
|
size_t max_queue_size_{0};
|
||||||
|
#endif // USE_NEXTION_MAX_QUEUE_SIZE
|
||||||
#ifdef USE_NEXTION_COMMAND_SPACING
|
#ifdef USE_NEXTION_COMMAND_SPACING
|
||||||
NextionCommandPacer command_pacer_{0};
|
NextionCommandPacer command_pacer_{0};
|
||||||
#endif // USE_NEXTION_COMMAND_SPACING
|
#endif // USE_NEXTION_COMMAND_SPACING
|
||||||
|
@ -281,6 +281,7 @@ display:
|
|||||||
id: main_lcd
|
id: main_lcd
|
||||||
update_interval: 5s
|
update_interval: 5s
|
||||||
command_spacing: 5ms
|
command_spacing: 5ms
|
||||||
|
max_queue_size: 50
|
||||||
on_sleep:
|
on_sleep:
|
||||||
then:
|
then:
|
||||||
lambda: 'ESP_LOGD("display","Display went to sleep");'
|
lambda: 'ESP_LOGD("display","Display went to sleep");'
|
||||||
|
Loading…
x
Reference in New Issue
Block a user