mirror of
https://github.com/esphome/esphome.git
synced 2025-07-29 06:36:45 +00:00
[nextion] Add configurable limit for commands processed per loop (#8972)
Co-authored-by: Keith Burzinski <kbx81x@gmail.com>
This commit is contained in:
parent
3174f7ae86
commit
94848e4811
@ -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_COMMANDS_PER_LOOP = "max_commands_per_loop"
|
||||||
CONF_MAX_QUEUE_SIZE = "max_queue_size"
|
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"
|
||||||
|
@ -16,11 +16,12 @@ 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_COMMANDS_PER_LOOP,
|
||||||
CONF_MAX_QUEUE_SIZE,
|
CONF_MAX_QUEUE_SIZE,
|
||||||
CONF_ON_BUFFER_OVERFLOW,
|
CONF_ON_BUFFER_OVERFLOW,
|
||||||
|
CONF_ON_PAGE,
|
||||||
CONF_ON_SETUP,
|
CONF_ON_SETUP,
|
||||||
CONF_ON_SLEEP,
|
CONF_ON_SLEEP,
|
||||||
CONF_ON_PAGE,
|
|
||||||
CONF_ON_WAKE,
|
CONF_ON_WAKE,
|
||||||
CONF_SKIP_CONNECTION_HANDSHAKE,
|
CONF_SKIP_CONNECTION_HANDSHAKE,
|
||||||
CONF_START_UP_PAGE,
|
CONF_START_UP_PAGE,
|
||||||
@ -50,8 +51,27 @@ CONFIG_SCHEMA = (
|
|||||||
display.BASIC_DISPLAY_SCHEMA.extend(
|
display.BASIC_DISPLAY_SCHEMA.extend(
|
||||||
{
|
{
|
||||||
cv.GenerateID(): cv.declare_id(Nextion),
|
cv.GenerateID(): cv.declare_id(Nextion),
|
||||||
cv.Optional(CONF_TFT_URL): cv.url,
|
cv.Optional(CONF_AUTO_WAKE_ON_TOUCH, default=True): cv.boolean,
|
||||||
cv.Optional(CONF_BRIGHTNESS): cv.percentage,
|
cv.Optional(CONF_BRIGHTNESS): cv.percentage,
|
||||||
|
cv.Optional(CONF_COMMAND_SPACING): cv.All(
|
||||||
|
cv.positive_time_period_milliseconds,
|
||||||
|
cv.Range(max=TimePeriod(milliseconds=255)),
|
||||||
|
),
|
||||||
|
cv.Optional(CONF_EXIT_REPARSE_ON_START, default=False): cv.boolean,
|
||||||
|
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(
|
||||||
|
{
|
||||||
|
cv.GenerateID(CONF_TRIGGER_ID): cv.declare_id(
|
||||||
|
BufferOverflowTrigger
|
||||||
|
),
|
||||||
|
}
|
||||||
|
),
|
||||||
|
cv.Optional(CONF_ON_PAGE): automation.validate_automation(
|
||||||
|
{
|
||||||
|
cv.GenerateID(CONF_TRIGGER_ID): cv.declare_id(PageTrigger),
|
||||||
|
}
|
||||||
|
),
|
||||||
cv.Optional(CONF_ON_SETUP): automation.validate_automation(
|
cv.Optional(CONF_ON_SETUP): automation.validate_automation(
|
||||||
{
|
{
|
||||||
cv.GenerateID(CONF_TRIGGER_ID): cv.declare_id(SetupTrigger),
|
cv.GenerateID(CONF_TRIGGER_ID): cv.declare_id(SetupTrigger),
|
||||||
@ -62,39 +82,21 @@ CONFIG_SCHEMA = (
|
|||||||
cv.GenerateID(CONF_TRIGGER_ID): cv.declare_id(SleepTrigger),
|
cv.GenerateID(CONF_TRIGGER_ID): cv.declare_id(SleepTrigger),
|
||||||
}
|
}
|
||||||
),
|
),
|
||||||
cv.Optional(CONF_ON_WAKE): automation.validate_automation(
|
|
||||||
{
|
|
||||||
cv.GenerateID(CONF_TRIGGER_ID): cv.declare_id(WakeTrigger),
|
|
||||||
}
|
|
||||||
),
|
|
||||||
cv.Optional(CONF_ON_PAGE): automation.validate_automation(
|
|
||||||
{
|
|
||||||
cv.GenerateID(CONF_TRIGGER_ID): cv.declare_id(PageTrigger),
|
|
||||||
}
|
|
||||||
),
|
|
||||||
cv.Optional(CONF_ON_TOUCH): automation.validate_automation(
|
cv.Optional(CONF_ON_TOUCH): automation.validate_automation(
|
||||||
{
|
{
|
||||||
cv.GenerateID(CONF_TRIGGER_ID): cv.declare_id(TouchTrigger),
|
cv.GenerateID(CONF_TRIGGER_ID): cv.declare_id(TouchTrigger),
|
||||||
}
|
}
|
||||||
),
|
),
|
||||||
cv.Optional(CONF_ON_BUFFER_OVERFLOW): automation.validate_automation(
|
cv.Optional(CONF_ON_WAKE): automation.validate_automation(
|
||||||
{
|
{
|
||||||
cv.GenerateID(CONF_TRIGGER_ID): cv.declare_id(
|
cv.GenerateID(CONF_TRIGGER_ID): cv.declare_id(WakeTrigger),
|
||||||
BufferOverflowTrigger
|
|
||||||
),
|
|
||||||
}
|
}
|
||||||
),
|
),
|
||||||
|
cv.Optional(CONF_SKIP_CONNECTION_HANDSHAKE, default=False): cv.boolean,
|
||||||
|
cv.Optional(CONF_START_UP_PAGE): cv.uint8_t,
|
||||||
|
cv.Optional(CONF_TFT_URL): cv.url,
|
||||||
cv.Optional(CONF_TOUCH_SLEEP_TIMEOUT): cv.int_range(min=3, max=65535),
|
cv.Optional(CONF_TOUCH_SLEEP_TIMEOUT): cv.int_range(min=3, max=65535),
|
||||||
cv.Optional(CONF_WAKE_UP_PAGE): cv.uint8_t,
|
cv.Optional(CONF_WAKE_UP_PAGE): cv.uint8_t,
|
||||||
cv.Optional(CONF_START_UP_PAGE): cv.uint8_t,
|
|
||||||
cv.Optional(CONF_AUTO_WAKE_ON_TOUCH, default=True): cv.boolean,
|
|
||||||
cv.Optional(CONF_EXIT_REPARSE_ON_START, default=False): cv.boolean,
|
|
||||||
cv.Optional(CONF_SKIP_CONNECTION_HANDSHAKE, default=False): cv.boolean,
|
|
||||||
cv.Optional(CONF_COMMAND_SPACING): cv.All(
|
|
||||||
cv.positive_time_period_milliseconds,
|
|
||||||
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"))
|
||||||
@ -173,6 +175,10 @@ async def to_code(config):
|
|||||||
|
|
||||||
cg.add(var.set_skip_connection_handshake(config[CONF_SKIP_CONNECTION_HANDSHAKE]))
|
cg.add(var.set_skip_connection_handshake(config[CONF_SKIP_CONNECTION_HANDSHAKE]))
|
||||||
|
|
||||||
|
if max_commands_per_loop := config.get(CONF_MAX_COMMANDS_PER_LOOP):
|
||||||
|
cg.add_define("USE_NEXTION_MAX_COMMANDS_PER_LOOP")
|
||||||
|
cg.add(var.set_max_commands_per_loop(max_commands_per_loop))
|
||||||
|
|
||||||
await display.register_display(var, config)
|
await display.register_display(var, config)
|
||||||
|
|
||||||
for conf in config.get(CONF_ON_SETUP, []):
|
for conf in config.get(CONF_ON_SETUP, []):
|
||||||
|
@ -162,21 +162,24 @@ void Nextion::dump_config() {
|
|||||||
" Wake On Touch: %s\n"
|
" Wake On Touch: %s\n"
|
||||||
" Exit reparse: %s",
|
" Exit reparse: %s",
|
||||||
YESNO(this->auto_wake_on_touch_), YESNO(this->exit_reparse_on_start_));
|
YESNO(this->auto_wake_on_touch_), YESNO(this->exit_reparse_on_start_));
|
||||||
|
#ifdef USE_NEXTION_MAX_COMMANDS_PER_LOOP
|
||||||
|
ESP_LOGCONFIG(TAG, " Max commands per loop: %u", this->max_commands_per_loop_);
|
||||||
|
#endif // USE_NEXTION_MAX_COMMANDS_PER_LOOP
|
||||||
|
|
||||||
if (this->touch_sleep_timeout_ != 0) {
|
if (this->touch_sleep_timeout_ != 0) {
|
||||||
ESP_LOGCONFIG(TAG, " Touch Timeout: %" PRIu32, this->touch_sleep_timeout_);
|
ESP_LOGCONFIG(TAG, " Touch Timeout: %" PRIu32, this->touch_sleep_timeout_);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (this->wake_up_page_ != -1) {
|
if (this->wake_up_page_ != -1) {
|
||||||
ESP_LOGCONFIG(TAG, " Wake Up Page: %" PRId16, this->wake_up_page_);
|
ESP_LOGCONFIG(TAG, " Wake Up Page: %d", this->wake_up_page_);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (this->start_up_page_ != -1) {
|
if (this->start_up_page_ != -1) {
|
||||||
ESP_LOGCONFIG(TAG, " Start Up Page: %" PRId16, this->start_up_page_);
|
ESP_LOGCONFIG(TAG, " Start Up Page: %d", this->start_up_page_);
|
||||||
}
|
}
|
||||||
|
|
||||||
#ifdef USE_NEXTION_COMMAND_SPACING
|
#ifdef USE_NEXTION_COMMAND_SPACING
|
||||||
ESP_LOGCONFIG(TAG, " Cmd spacing: %" PRIu8 "ms", this->command_pacer_.get_spacing());
|
ESP_LOGCONFIG(TAG, " Cmd spacing: %u ms", this->command_pacer_.get_spacing());
|
||||||
#endif // USE_NEXTION_COMMAND_SPACING
|
#endif // USE_NEXTION_COMMAND_SPACING
|
||||||
|
|
||||||
#ifdef USE_NEXTION_MAX_QUEUE_SIZE
|
#ifdef USE_NEXTION_MAX_QUEUE_SIZE
|
||||||
@ -370,6 +373,10 @@ void Nextion::process_nextion_commands_() {
|
|||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#ifdef USE_NEXTION_MAX_COMMANDS_PER_LOOP
|
||||||
|
size_t commands_processed = 0;
|
||||||
|
#endif // USE_NEXTION_MAX_COMMANDS_PER_LOOP
|
||||||
|
|
||||||
#ifdef USE_NEXTION_COMMAND_SPACING
|
#ifdef USE_NEXTION_COMMAND_SPACING
|
||||||
if (!this->command_pacer_.can_send()) {
|
if (!this->command_pacer_.can_send()) {
|
||||||
return; // Will try again in next loop iteration
|
return; // Will try again in next loop iteration
|
||||||
@ -384,6 +391,12 @@ void Nextion::process_nextion_commands_() {
|
|||||||
this->print_queue_members_();
|
this->print_queue_members_();
|
||||||
#endif
|
#endif
|
||||||
while ((to_process_length = this->command_data_.find(COMMAND_DELIMITER)) != std::string::npos) {
|
while ((to_process_length = this->command_data_.find(COMMAND_DELIMITER)) != std::string::npos) {
|
||||||
|
#ifdef USE_NEXTION_MAX_COMMANDS_PER_LOOP
|
||||||
|
if (++commands_processed > this->max_commands_per_loop_) {
|
||||||
|
ESP_LOGW(TAG, "Command processing limit exceeded");
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
#endif // USE_NEXTION_MAX_COMMANDS_PER_LOOP
|
||||||
ESP_LOGN(TAG, "queue size: %zu", this->nextion_queue_.size());
|
ESP_LOGN(TAG, "queue size: %zu", this->nextion_queue_.size());
|
||||||
while (to_process_length + COMMAND_DELIMITER.length() < this->command_data_.length() &&
|
while (to_process_length + COMMAND_DELIMITER.length() < this->command_data_.length() &&
|
||||||
static_cast<uint8_t>(this->command_data_[to_process_length + COMMAND_DELIMITER.length()]) == 0xFF) {
|
static_cast<uint8_t>(this->command_data_[to_process_length + COMMAND_DELIMITER.length()]) == 0xFF) {
|
||||||
@ -798,8 +811,6 @@ void Nextion::process_nextion_commands_() {
|
|||||||
|
|
||||||
// ESP_LOGN(TAG, "nextion_event_ deleting from 0 to %d", to_process_length + COMMAND_DELIMITER.length() + 1);
|
// ESP_LOGN(TAG, "nextion_event_ deleting from 0 to %d", to_process_length + COMMAND_DELIMITER.length() + 1);
|
||||||
this->command_data_.erase(0, to_process_length + COMMAND_DELIMITER.length() + 1);
|
this->command_data_.erase(0, to_process_length + COMMAND_DELIMITER.length() + 1);
|
||||||
// App.feed_wdt(); Remove before master merge
|
|
||||||
this->process_serial_();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
uint32_t ms = millis();
|
uint32_t ms = millis();
|
||||||
@ -840,7 +851,7 @@ void Nextion::process_nextion_commands_() {
|
|||||||
ESP_LOGN(TAG, "Loop end");
|
ESP_LOGN(TAG, "Loop end");
|
||||||
// App.feed_wdt(); Remove before master merge
|
// App.feed_wdt(); Remove before master merge
|
||||||
this->process_serial_();
|
this->process_serial_();
|
||||||
} // namespace nextion
|
} // Nextion::process_nextion_commands_()
|
||||||
|
|
||||||
void Nextion::set_nextion_sensor_state(int queue_type, const std::string &name, float state) {
|
void Nextion::set_nextion_sensor_state(int queue_type, const std::string &name, float state) {
|
||||||
this->set_nextion_sensor_state(static_cast<NextionQueueType>(queue_type), name, state);
|
this->set_nextion_sensor_state(static_cast<NextionQueueType>(queue_type), name, state);
|
||||||
|
@ -75,6 +75,22 @@ 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_COMMANDS_PER_LOOP
|
||||||
|
/**
|
||||||
|
* @brief Set the maximum number of commands to process in each loop iteration
|
||||||
|
* @param value Maximum number of commands (default: 20)
|
||||||
|
*
|
||||||
|
* Limiting the number of commands per loop helps prevent stack overflows
|
||||||
|
* when a large number of commands are queued at once, especially during boot.
|
||||||
|
*/
|
||||||
|
inline void set_max_commands_per_loop(uint16_t value) { this->max_commands_per_loop_ = value; }
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief Get the current maximum number of commands allowed per loop iteration
|
||||||
|
* @return Configured command limit per loop
|
||||||
|
*/
|
||||||
|
inline uint16_t get_max_commands_per_loop() const { return this->max_commands_per_loop_; }
|
||||||
|
#endif // USE_NEXTION_MAX_COMMANDS_PER_LOOP
|
||||||
#ifdef USE_NEXTION_MAX_QUEUE_SIZE
|
#ifdef USE_NEXTION_MAX_QUEUE_SIZE
|
||||||
/**
|
/**
|
||||||
* @brief Set the maximum allowed queue size
|
* @brief Set the maximum allowed queue size
|
||||||
@ -1287,6 +1303,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_COMMANDS_PER_LOOP
|
||||||
|
uint16_t max_commands_per_loop_{1000};
|
||||||
|
#endif // USE_NEXTION_MAX_COMMANDS_PER_LOOP
|
||||||
#ifdef USE_NEXTION_MAX_QUEUE_SIZE
|
#ifdef USE_NEXTION_MAX_QUEUE_SIZE
|
||||||
size_t max_queue_size_{0};
|
size_t max_queue_size_{0};
|
||||||
#endif // USE_NEXTION_MAX_QUEUE_SIZE
|
#endif // USE_NEXTION_MAX_QUEUE_SIZE
|
||||||
|
@ -281,6 +281,7 @@ display:
|
|||||||
id: main_lcd
|
id: main_lcd
|
||||||
update_interval: 5s
|
update_interval: 5s
|
||||||
command_spacing: 5ms
|
command_spacing: 5ms
|
||||||
|
max_commands_per_loop: 20
|
||||||
max_queue_size: 50
|
max_queue_size: 50
|
||||||
on_sleep:
|
on_sleep:
|
||||||
then:
|
then:
|
||||||
|
Loading…
x
Reference in New Issue
Block a user