diff --git a/esphome/components/nextion/automation.h b/esphome/components/nextion/automation.h index 5f4219acb1..210d7b2e2b 100644 --- a/esphome/components/nextion/automation.h +++ b/esphome/components/nextion/automation.h @@ -26,5 +26,12 @@ class WakeTrigger : public Trigger<> { } }; +class PageTrigger : public Trigger { + public: + explicit PageTrigger(Nextion *nextion) { + nextion->add_new_page_callback([this](const uint8_t page_id) { this->trigger(page_id); }); + } +}; + } // namespace nextion } // namespace esphome diff --git a/esphome/components/nextion/base_component.py b/esphome/components/nextion/base_component.py index 75694ee4b2..06216e9ce0 100644 --- a/esphome/components/nextion/base_component.py +++ b/esphome/components/nextion/base_component.py @@ -18,6 +18,7 @@ CONF_TFT_URL = "tft_url" CONF_ON_SLEEP = "on_sleep" CONF_ON_WAKE = "on_wake" CONF_ON_SETUP = "on_setup" +CONF_ON_PAGE = "on_page" CONF_TOUCH_SLEEP_TIMEOUT = "touch_sleep_timeout" CONF_WAKE_UP_PAGE = "wake_up_page" CONF_AUTO_WAKE_ON_TOUCH = "auto_wake_on_touch" diff --git a/esphome/components/nextion/display.py b/esphome/components/nextion/display.py index d95810bfbe..c6372fbaf0 100644 --- a/esphome/components/nextion/display.py +++ b/esphome/components/nextion/display.py @@ -14,6 +14,7 @@ from .base_component import ( CONF_ON_SLEEP, CONF_ON_WAKE, CONF_ON_SETUP, + CONF_ON_PAGE, CONF_TFT_URL, CONF_TOUCH_SLEEP_TIMEOUT, CONF_WAKE_UP_PAGE, @@ -28,6 +29,7 @@ AUTO_LOAD = ["binary_sensor", "switch", "sensor", "text_sensor"] SetupTrigger = nextion_ns.class_("SetupTrigger", automation.Trigger.template()) SleepTrigger = nextion_ns.class_("SleepTrigger", automation.Trigger.template()) WakeTrigger = nextion_ns.class_("WakeTrigger", automation.Trigger.template()) +PageTrigger = nextion_ns.class_("PageTrigger", automation.Trigger.template()) CONFIG_SCHEMA = ( display.BASIC_DISPLAY_SCHEMA.extend( @@ -50,6 +52,11 @@ CONFIG_SCHEMA = ( 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_TOUCH_SLEEP_TIMEOUT): cv.int_range(min=3, max=65535), cv.Optional(CONF_WAKE_UP_PAGE): cv.positive_int, cv.Optional(CONF_AUTO_WAKE_ON_TOUCH, default=True): cv.boolean, @@ -102,3 +109,7 @@ async def to_code(config): for conf in config.get(CONF_ON_WAKE, []): trigger = cg.new_Pvariable(conf[CONF_TRIGGER_ID], var) await automation.build_automation(trigger, [], conf) + + for conf in config.get(CONF_ON_PAGE, []): + trigger = cg.new_Pvariable(conf[CONF_TRIGGER_ID], var) + await automation.build_automation(trigger, [(cg.uint8, "x")], conf) diff --git a/esphome/components/nextion/nextion.cpp b/esphome/components/nextion/nextion.cpp index 46c063e5ee..5dfff4327c 100644 --- a/esphome/components/nextion/nextion.cpp +++ b/esphome/components/nextion/nextion.cpp @@ -152,6 +152,10 @@ void Nextion::add_setup_state_callback(std::function &&callback) { this->setup_callback_.add(std::move(callback)); } +void Nextion::add_new_page_callback(std::function &&callback) { + this->page_callback_.add(std::move(callback)); +} + void Nextion::update_all_components() { if ((!this->is_setup() && !this->ignore_is_setup_) || this->is_sleeping()) return; @@ -390,7 +394,6 @@ void Nextion::process_nextion_commands_() { case 0x1A: // variable name invalid ESP_LOGW(TAG, "Nextion reported variable name invalid!"); this->remove_from_q_(); - break; case 0x1B: // variable operation invalid ESP_LOGW(TAG, "Nextion reported variable operation invalid!"); @@ -417,7 +420,6 @@ void Nextion::process_nextion_commands_() { case 0x23: // too long variable name ESP_LOGW(TAG, "Nextion reported too long variable name!"); this->remove_from_q_(); - break; case 0x24: // Serial Buffer overflow occurs ESP_LOGW(TAG, "Nextion reported Serial Buffer overflow!"); @@ -425,9 +427,9 @@ void Nextion::process_nextion_commands_() { case 0x65: { // touch event return data if (to_process_length != 3) { ESP_LOGW(TAG, "Touch event data is expecting 3, received %zu", to_process_length); - break; } + uint8_t page_id = to_process[0]; uint8_t component_id = to_process[1]; uint8_t touch_event = to_process[2]; // 0 -> release, 1 -> press @@ -438,6 +440,18 @@ void Nextion::process_nextion_commands_() { } break; } + case 0x66: { // Nextion initiated new page event return data. + // Also is used for sendme command which we never explicitly initiate + if (to_process_length != 1) { + ESP_LOGW(TAG, "New page event data is expecting 1, received %zu", to_process_length); + break; + } + + uint8_t page_id = to_process[0]; + ESP_LOGD(TAG, "Got new page=%u", page_id); + this->page_callback_.call(page_id); + break; + } case 0x67: { // Touch Coordinate (awake) break; } @@ -455,9 +469,6 @@ void Nextion::process_nextion_commands_() { ESP_LOGD(TAG, "Got touch at x=%u y=%u type=%s", x, y, touch_event ? "PRESS" : "RELEASE"); break; } - case 0x66: { - break; - } // sendme page id // 0x70 0x61 0x62 0x31 0x32 0x33 0xFF 0xFF 0xFF // Returned when using get command for a string. diff --git a/esphome/components/nextion/nextion.h b/esphome/components/nextion/nextion.h index 285b3ac9a3..ad696d0e83 100644 --- a/esphome/components/nextion/nextion.h +++ b/esphome/components/nextion/nextion.h @@ -689,6 +689,12 @@ class Nextion : public NextionBase, public PollingComponent, public uart::UARTDe */ void add_setup_state_callback(std::function &&callback); + /** Add a callback to be notified when the nextion changes pages. + * + * @param callback The void(std::string) callback. + */ + void add_new_page_callback(std::function &&callback); + void update_all_components(); /** @@ -813,6 +819,7 @@ class Nextion : public NextionBase, public PollingComponent, public uart::UARTDe CallbackManager setup_callback_{}; CallbackManager sleep_callback_{}; CallbackManager wake_callback_{}; + CallbackManager page_callback_{}; optional writer_; float brightness_{1.0}; diff --git a/tests/test3.yaml b/tests/test3.yaml index 1a862b515e..1abbee8dc5 100644 --- a/tests/test3.yaml +++ b/tests/test3.yaml @@ -1438,6 +1438,13 @@ display: on_wake: then: lambda: 'ESP_LOGD("display","Display woke up");' + on_setup: + then: + lambda: 'ESP_LOGD("display","Display setup completed");' + on_page: + then: + lambda: 'ESP_LOGD("display","Display shows new page %u", x);' + http_request: useragent: esphome/device