diff --git a/esphome/components/display/__init__.py b/esphome/components/display/__init__.py index 5aed998b30..8f48acf2b7 100644 --- a/esphome/components/display/__init__.py +++ b/esphome/components/display/__init__.py @@ -2,7 +2,16 @@ import esphome.codegen as cg import esphome.config_validation as cv from esphome import core, automation from esphome.automation import maybe_simple_id -from esphome.const import CONF_ID, CONF_LAMBDA, CONF_PAGES, CONF_PAGE_ID, CONF_ROTATION +from esphome.const import ( + CONF_ID, + CONF_LAMBDA, + CONF_PAGES, + CONF_PAGE_ID, + CONF_ROTATION, + CONF_FROM, + CONF_TO, + CONF_TRIGGER_ID, +) from esphome.core import coroutine_with_priority IS_PLATFORM_COMPONENT = True @@ -22,6 +31,9 @@ DisplayPageShowPrevAction = display_ns.class_( DisplayIsDisplayingPageCondition = display_ns.class_( "DisplayIsDisplayingPageCondition", automation.Condition ) +DisplayOnPageChangeTrigger = display_ns.class_("DisplayOnPageChangeTrigger") + +CONF_ON_PAGE_CHANGE = "on_page_change" DISPLAY_ROTATIONS = { 0: display_ns.DISPLAY_ROTATION_0_DEGREES, @@ -56,6 +68,15 @@ FULL_DISPLAY_SCHEMA = BASIC_DISPLAY_SCHEMA.extend( ), cv.Length(min=1), ), + cv.Optional(CONF_ON_PAGE_CHANGE): automation.validate_automation( + { + cv.GenerateID(CONF_TRIGGER_ID): cv.declare_id( + DisplayOnPageChangeTrigger + ), + cv.Optional(CONF_FROM): cv.use_id(DisplayPage), + cv.Optional(CONF_TO): cv.use_id(DisplayPage), + } + ), } ) @@ -72,6 +93,17 @@ async def setup_display_core_(var, config): page = cg.new_Pvariable(conf[CONF_ID], lambda_) pages.append(page) cg.add(var.set_pages(pages)) + for conf in config.get(CONF_ON_PAGE_CHANGE, []): + trigger = cg.new_Pvariable(conf[CONF_TRIGGER_ID], var) + if CONF_FROM in conf: + page = await cg.get_variable(conf[CONF_FROM]) + cg.add(trigger.set_from(page)) + if CONF_TO in conf: + page = await cg.get_variable(conf[CONF_TO]) + cg.add(trigger.set_to(page)) + await automation.build_automation( + trigger, [(DisplayPagePtr, "from"), (DisplayPagePtr, "to")], conf + ) async def register_display(var, config): diff --git a/esphome/components/display/display_buffer.cpp b/esphome/components/display/display_buffer.cpp index c66f87a7aa..23f6faccb1 100644 --- a/esphome/components/display/display_buffer.cpp +++ b/esphome/components/display/display_buffer.cpp @@ -315,7 +315,14 @@ void DisplayBuffer::set_pages(std::vector pages) { pages[pages.size() - 1]->set_next(pages[0]); this->show_page(pages[0]); } -void DisplayBuffer::show_page(DisplayPage *page) { this->page_ = page; } +void DisplayBuffer::show_page(DisplayPage *page) { + this->previous_page_ = this->page_; + this->page_ = page; + if (this->previous_page_ != this->page_) { + for (auto *t : on_page_change_triggers_) + t->process(this->previous_page_, this->page_); + } +} void DisplayBuffer::show_next_page() { this->page_->show_next(); } void DisplayBuffer::show_prev_page() { this->page_->show_prev(); } void DisplayBuffer::do_update_() { @@ -326,6 +333,10 @@ void DisplayBuffer::do_update_() { (*this->writer_)(*this); } } +void DisplayOnPageChangeTrigger::process(DisplayPage *from, DisplayPage *to) { + if ((this->from_ == nullptr || this->from_ == from) && (this->to_ == nullptr || this->to_ == to)) + this->trigger(from, to); +} #ifdef USE_TIME void DisplayBuffer::strftime(int x, int y, Font *font, Color color, TextAlign align, const char *format, time::ESPTime time) { diff --git a/esphome/components/display/display_buffer.h b/esphome/components/display/display_buffer.h index 42e3c5871f..0763262d4c 100644 --- a/esphome/components/display/display_buffer.h +++ b/esphome/components/display/display_buffer.h @@ -81,6 +81,7 @@ class Font; class Image; class DisplayBuffer; class DisplayPage; +class DisplayOnPageChangeTrigger; using display_writer_t = std::function; @@ -298,6 +299,8 @@ class DisplayBuffer { const DisplayPage *get_active_page() const { return this->page_; } + void add_on_page_change_trigger(DisplayOnPageChangeTrigger *t) { this->on_page_change_triggers_.push_back(t); } + /// Internal method to set the display rotation with. void set_rotation(DisplayRotation rotation); @@ -318,6 +321,8 @@ class DisplayBuffer { DisplayRotation rotation_{DISPLAY_ROTATION_0_DEGREES}; optional writer_{}; DisplayPage *page_{nullptr}; + DisplayPage *previous_page_{nullptr}; + std::vector on_page_change_triggers_; }; class DisplayPage { @@ -465,5 +470,17 @@ template class DisplayIsDisplayingPageCondition : public Conditi DisplayPage *page_; }; +class DisplayOnPageChangeTrigger : public Trigger { + public: + explicit DisplayOnPageChangeTrigger(DisplayBuffer *parent) { parent->add_on_page_change_trigger(this); } + void process(DisplayPage *from, DisplayPage *to); + void set_from(DisplayPage *p) { this->from_ = p; } + void set_to(DisplayPage *p) { this->to_ = p; } + + protected: + DisplayPage *from_{nullptr}; + DisplayPage *to_{nullptr}; +}; + } // namespace display } // namespace esphome diff --git a/tests/test1.yaml b/tests/test1.yaml index a8633a7067..6f87166490 100644 --- a/tests/test1.yaml +++ b/tests/test1.yaml @@ -1874,6 +1874,12 @@ display: - id: page2 lambda: |- // Nothing + on_page_change: + from: page1 + to: page2 + then: + lambda: |- + ESP_LOGD("display", "1 -> 2"); - platform: ssd1306_spi model: 'SSD1306 128x64' cs_pin: GPIO23