diff --git a/esphome/components/nextion/base_component.py b/esphome/components/nextion/base_component.py index 392481e39a..86551cbe23 100644 --- a/esphome/components/nextion/base_component.py +++ b/esphome/components/nextion/base_component.py @@ -16,6 +16,7 @@ CONF_EXIT_REPARSE_ON_START = "exit_reparse_on_start" CONF_FONT_ID = "font_id" CONF_FOREGROUND_PRESSED_COLOR = "foreground_pressed_color" CONF_MAX_COMMANDS_PER_LOOP = "max_commands_per_loop" +CONF_MAX_QUEUE_AGE = "max_queue_age" CONF_MAX_QUEUE_SIZE = "max_queue_size" CONF_ON_BUFFER_OVERFLOW = "on_buffer_overflow" CONF_ON_PAGE = "on_page" @@ -25,6 +26,7 @@ CONF_ON_WAKE = "on_wake" CONF_PRECISION = "precision" CONF_SKIP_CONNECTION_HANDSHAKE = "skip_connection_handshake" CONF_START_UP_PAGE = "start_up_page" +CONF_STARTUP_OVERRIDE_MS = "startup_override_ms" CONF_TFT_URL = "tft_url" CONF_TOUCH_SLEEP_TIMEOUT = "touch_sleep_timeout" CONF_VARIABLE_NAME = "variable_name" diff --git a/esphome/components/nextion/display.py b/esphome/components/nextion/display.py index 0b4ba3a171..ffc509fc64 100644 --- a/esphome/components/nextion/display.py +++ b/esphome/components/nextion/display.py @@ -23,6 +23,7 @@ from .base_component import ( CONF_DUMP_DEVICE_INFO, CONF_EXIT_REPARSE_ON_START, CONF_MAX_COMMANDS_PER_LOOP, + CONF_MAX_QUEUE_AGE, CONF_MAX_QUEUE_SIZE, CONF_ON_BUFFER_OVERFLOW, CONF_ON_PAGE, @@ -31,6 +32,7 @@ from .base_component import ( CONF_ON_WAKE, CONF_SKIP_CONNECTION_HANDSHAKE, CONF_START_UP_PAGE, + CONF_STARTUP_OVERRIDE_MS, CONF_TFT_URL, CONF_TOUCH_SLEEP_TIMEOUT, CONF_WAKE_UP_PAGE, @@ -65,6 +67,12 @@ CONFIG_SCHEMA = ( ), cv.Optional(CONF_DUMP_DEVICE_INFO, default=False): cv.boolean, cv.Optional(CONF_EXIT_REPARSE_ON_START, default=False): cv.boolean, + cv.Optional(CONF_MAX_QUEUE_AGE, default="8000ms"): cv.All( + cv.positive_time_period_milliseconds, + cv.Range( + min=TimePeriod(milliseconds=0), max=TimePeriod(milliseconds=65535) + ), + ), cv.Optional(CONF_MAX_COMMANDS_PER_LOOP): cv.uint16_t, cv.Optional(CONF_MAX_QUEUE_SIZE): cv.positive_int, cv.Optional(CONF_ON_BUFFER_OVERFLOW): automation.validate_automation( @@ -100,6 +108,12 @@ CONFIG_SCHEMA = ( } ), cv.Optional(CONF_SKIP_CONNECTION_HANDSHAKE, default=False): cv.boolean, + cv.Optional(CONF_STARTUP_OVERRIDE_MS, default="8000ms"): cv.All( + cv.positive_time_period_milliseconds, + cv.Range( + min=TimePeriod(milliseconds=0), max=TimePeriod(milliseconds=65535) + ), + ), cv.Optional(CONF_START_UP_PAGE): cv.uint8_t, cv.Optional(CONF_TFT_URL): cv.url, cv.Optional(CONF_TOUCH_SLEEP_TIMEOUT): cv.Any( @@ -138,6 +152,8 @@ async def to_code(config): var = cg.new_Pvariable(config[CONF_ID]) await uart.register_uart_device(var, config) + cg.add(var.set_max_queue_age(config[CONF_MAX_QUEUE_AGE])) + 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)) @@ -146,6 +162,8 @@ async def to_code(config): cg.add_define("USE_NEXTION_COMMAND_SPACING") cg.add(var.set_command_spacing(command_spacing.total_milliseconds)) + cg.add(var.set_startup_override_ms(config[CONF_STARTUP_OVERRIDE_MS])) + if CONF_BRIGHTNESS in config: cg.add(var.set_brightness(config[CONF_BRIGHTNESS])) diff --git a/esphome/components/nextion/nextion.cpp b/esphome/components/nextion/nextion.cpp index 354288e1a3..4bba33f961 100644 --- a/esphome/components/nextion/nextion.cpp +++ b/esphome/components/nextion/nextion.cpp @@ -152,21 +152,25 @@ void Nextion::dump_config() { #else // USE_NEXTION_CONFIG_SKIP_CONNECTION_HANDSHAKE ESP_LOGCONFIG(TAG, #ifdef USE_NEXTION_CONFIG_DUMP_DEVICE_INFO - " Device Model: %s\n" - " FW Version: %s\n" - " Serial Number: %s\n" - " Flash Size: %s\n" + " Device Model: %s\n" + " FW Version: %s\n" + " Serial Number: %s\n" + " Flash Size: %s\n" + " Max queue age: %u ms\n" + " Startup override: %u ms\n", #endif // USE_NEXTION_CONFIG_DUMP_DEVICE_INFO #ifdef USE_NEXTION_CONFIG_EXIT_REPARSE_ON_START - " Exit reparse: YES\n" + " Exit reparse: YES\n" #endif // USE_NEXTION_CONFIG_EXIT_REPARSE_ON_START - " Wake On Touch: %s\n" - " Touch Timeout: %" PRIu16, + " Wake On Touch: %s\n" + " Touch Timeout: %" PRIu16, #ifdef USE_NEXTION_CONFIG_DUMP_DEVICE_INFO this->device_model_.c_str(), this->firmware_version_.c_str(), this->serial_number_.c_str(), - this->flash_size_.c_str(), + this->flash_size_.c_str(), this->max_q_age_ms_, + this->startup_override_ms_ #endif // USE_NEXTION_CONFIG_DUMP_DEVICE_INFO - YESNO(this->connection_state_.auto_wake_on_touch_), this->touch_sleep_timeout_); + YESNO(this->connection_state_.auto_wake_on_touch_), + this->touch_sleep_timeout_); #endif // USE_NEXTION_CONFIG_SKIP_CONNECTION_HANDSHAKE #ifdef USE_NEXTION_MAX_COMMANDS_PER_LOOP @@ -174,21 +178,21 @@ void Nextion::dump_config() { #endif // USE_NEXTION_MAX_COMMANDS_PER_LOOP if (this->wake_up_page_ != 255) { - ESP_LOGCONFIG(TAG, " Wake Up Page: %u", this->wake_up_page_); + ESP_LOGCONFIG(TAG, " Wake Up Page: %u", this->wake_up_page_); } #ifdef USE_NEXTION_CONF_START_UP_PAGE if (this->start_up_page_ != 255) { - ESP_LOGCONFIG(TAG, " Start Up Page: %u", this->start_up_page_); + ESP_LOGCONFIG(TAG, " Start Up Page: %u", this->start_up_page_); } #endif // USE_NEXTION_CONF_START_UP_PAGE #ifdef USE_NEXTION_COMMAND_SPACING - ESP_LOGCONFIG(TAG, " Cmd spacing: %u ms", this->command_pacer_.get_spacing()); + ESP_LOGCONFIG(TAG, " Cmd spacing: %u ms", this->command_pacer_.get_spacing()); #endif // USE_NEXTION_COMMAND_SPACING #ifdef USE_NEXTION_MAX_QUEUE_SIZE - ESP_LOGCONFIG(TAG, " Max queue size: %zu", this->max_queue_size_); + ESP_LOGCONFIG(TAG, " Max queue size: %zu", this->max_queue_size_); #endif } @@ -336,7 +340,8 @@ void Nextion::loop() { if (this->started_ms_ == 0) this->started_ms_ = App.get_loop_component_start_time(); - if (this->started_ms_ + this->startup_override_ms_ < App.get_loop_component_start_time()) { + if (this->startup_override_ms_ > 0 && + this->started_ms_ + this->startup_override_ms_ < App.get_loop_component_start_time()) { ESP_LOGV(TAG, "Manual ready set"); this->connection_state_.nextion_reports_is_setup_ = true; } @@ -845,7 +850,8 @@ void Nextion::process_nextion_commands_() { const uint32_t ms = App.get_loop_component_start_time(); - if (!this->nextion_queue_.empty() && this->nextion_queue_.front()->queue_time + this->max_q_age_ms_ < ms) { + if (this->max_q_age_ms_ > 0 && !this->nextion_queue_.empty() && + this->nextion_queue_.front()->queue_time + this->max_q_age_ms_ < ms) { for (size_t i = 0; i < this->nextion_queue_.size(); i++) { NextionComponentBase *component = this->nextion_queue_[i]->component; if (this->nextion_queue_[i]->queue_time + this->max_q_age_ms_ < ms) { diff --git a/esphome/components/nextion/nextion.h b/esphome/components/nextion/nextion.h index 331e901578..c543e14bfe 100644 --- a/esphome/components/nextion/nextion.h +++ b/esphome/components/nextion/nextion.h @@ -1309,6 +1309,30 @@ class Nextion : public NextionBase, public PollingComponent, public uart::UARTDe */ bool is_connected() { return this->connection_state_.is_connected_; } + /** + * @brief Set the maximum age for queue items + * @param age_ms Maximum age in milliseconds before queue items are removed + */ + inline void set_max_queue_age(uint16_t age_ms) { this->max_q_age_ms_ = age_ms; } + + /** + * @brief Get the maximum age for queue items + * @return Maximum age in milliseconds + */ + inline uint16_t get_max_queue_age() const { return this->max_q_age_ms_; } + + /** + * @brief Set the startup override timeout + * @param timeout_ms Time in milliseconds to wait before forcing setup complete + */ + inline void set_startup_override_ms(uint16_t timeout_ms) { this->startup_override_ms_ = timeout_ms; } + + /** + * @brief Get the startup override timeout + * @return Startup override timeout in milliseconds + */ + inline uint16_t get_startup_override_ms() const { return this->startup_override_ms_; } + protected: #ifdef USE_NEXTION_MAX_COMMANDS_PER_LOOP uint16_t max_commands_per_loop_{1000}; @@ -1479,9 +1503,10 @@ class Nextion : public NextionBase, public PollingComponent, public uart::UARTDe void reset_(bool reset_nextion = true); std::string command_data_; - const uint16_t startup_override_ms_ = 8000; - const uint16_t max_q_age_ms_ = 8000; uint32_t started_ms_ = 0; + + uint16_t startup_override_ms_ = 8000; ///< Timeout before forcing setup complete + uint16_t max_q_age_ms_ = 8000; ///< Maximum age for queue items in ms }; } // namespace nextion diff --git a/tests/components/nextion/common.yaml b/tests/components/nextion/common.yaml index f5ee12a51c..48a7292f43 100644 --- a/tests/components/nextion/common.yaml +++ b/tests/components/nextion/common.yaml @@ -277,6 +277,8 @@ display: command_spacing: 5ms max_commands_per_loop: 20 max_queue_size: 50 + startup_override_ms: 10000ms # Wait 10s for display ready + max_queue_age: 5000ms # Remove queue items after 5s on_sleep: then: lambda: 'ESP_LOGD("display","Display went to sleep");'