From f311a1bb302b0acfe32eae58ff31dfdefbfaff5a Mon Sep 17 00:00:00 2001 From: Otto Winter Date: Sun, 17 Feb 2019 00:35:23 +0100 Subject: [PATCH] Add display page abstraction (#435) --- esphome/components/display/__init__.py | 75 ++++++++++++++++++- esphome/components/display/ssd1306_i2c.py | 6 +- esphome/components/display/ssd1306_spi.py | 6 +- .../components/display/waveshare_epaper.py | 5 +- esphome/const.py | 1 + tests/test1.yaml | 18 ++++- 6 files changed, 98 insertions(+), 13 deletions(-) diff --git a/esphome/components/display/__init__.py b/esphome/components/display/__init__.py index dac4984a6a..aa568059c9 100644 --- a/esphome/components/display/__init__.py +++ b/esphome/components/display/__init__.py @@ -1,11 +1,13 @@ # coding=utf-8 import voluptuous as vol +from esphome import core +from esphome.automation import ACTION_REGISTRY, maybe_simple_id import esphome.config_validation as cv -from esphome.const import CONF_LAMBDA, CONF_ROTATION, CONF_UPDATE_INTERVAL +from esphome.const import CONF_LAMBDA, CONF_ROTATION, CONF_UPDATE_INTERVAL, CONF_PAGES, CONF_ID from esphome.core import CORE -from esphome.cpp_generator import add -from esphome.cpp_types import esphome_ns +from esphome.cpp_generator import add, process_lambda, Pvariable, templatable, get_variable +from esphome.cpp_types import esphome_ns, void, Action PLATFORM_SCHEMA = cv.PLATFORM_SCHEMA.extend({ @@ -13,7 +15,12 @@ PLATFORM_SCHEMA = cv.PLATFORM_SCHEMA.extend({ display_ns = esphome_ns.namespace('display') DisplayBuffer = display_ns.class_('DisplayBuffer') +DisplayPage = display_ns.class_('DisplayPage') +DisplayPagePtr = DisplayPage.operator('ptr') DisplayBufferRef = DisplayBuffer.operator('ref') +DisplayPageShowAction = display_ns.class_('DisplayPageShowAction', Action) +DisplayPageShowNextAction = display_ns.class_('DisplayPageShowNextAction', Action) +DisplayPageShowPrevAction = display_ns.class_('DisplayPageShowPrevAction', Action) DISPLAY_ROTATIONS = { 0: display_ns.DISPLAY_ROTATION_0_DEGREES, @@ -41,6 +48,10 @@ BASIC_DISPLAY_PLATFORM_SCHEMA = PLATFORM_SCHEMA.extend({ FULL_DISPLAY_PLATFORM_SCHEMA = BASIC_DISPLAY_PLATFORM_SCHEMA.extend({ vol.Optional(CONF_ROTATION): validate_rotation, + vol.Optional(CONF_PAGES): vol.All(cv.ensure_list({ + cv.GenerateID(): cv.declare_variable_id(DisplayPage), + vol.Required(CONF_LAMBDA): cv.lambda_, + }), vol.Length(min=1)), }) @@ -49,6 +60,64 @@ def setup_display_core_(display_var, config): add(display_var.set_update_interval(config[CONF_UPDATE_INTERVAL])) if CONF_ROTATION in config: add(display_var.set_rotation(DISPLAY_ROTATIONS[config[CONF_ROTATION]])) + if CONF_PAGES in config: + pages = [] + for conf in config[CONF_PAGES]: + for lambda_ in process_lambda(conf[CONF_LAMBDA], [(DisplayBufferRef, 'it')], + return_type=void): + yield + var = Pvariable(conf[CONF_ID], DisplayPage.new(lambda_)) + pages.append(var) + add(display_var.set_pages(pages)) + + +CONF_DISPLAY_PAGE_SHOW = 'display.page.show' +DISPLAY_PAGE_SHOW_ACTION_SCHEMA = maybe_simple_id({ + vol.Required(CONF_ID): cv.templatable(cv.use_variable_id(DisplayPage)), +}) + + +@ACTION_REGISTRY.register(CONF_DISPLAY_PAGE_SHOW, DISPLAY_PAGE_SHOW_ACTION_SCHEMA) +def display_page_show_to_code(config, action_id, arg_type, template_arg): + type = DisplayPageShowAction.template(arg_type) + action = Pvariable(action_id, type.new(), type=type) + if isinstance(config[CONF_ID], core.Lambda): + for template_ in templatable(config[CONF_ID], arg_type, DisplayPagePtr): + yield None + add(action.set_page(template_)) + else: + for var in get_variable(config[CONF_ID]): + yield None + add(action.set_page(var)) + yield action + + +CONF_DISPLAY_PAGE_SHOW_NEXT = 'display.page.show_next' +DISPLAY_PAGE_SHOW_NEXT_ACTION_SCHEMA = maybe_simple_id({ + vol.Required(CONF_ID): cv.templatable(cv.use_variable_id(DisplayBuffer)), +}) + + +@ACTION_REGISTRY.register(CONF_DISPLAY_PAGE_SHOW_NEXT, DISPLAY_PAGE_SHOW_NEXT_ACTION_SCHEMA) +def display_page_show_next_to_code(config, action_id, arg_type, template_arg): + for var in get_variable(config[CONF_ID]): + yield None + type = DisplayPageShowNextAction.template(arg_type) + yield Pvariable(action_id, type.new(var), type=type) + + +CONF_DISPLAY_PAGE_SHOW_PREVIOUS = 'display.page.show_previous' +DISPLAY_PAGE_SHOW_PREVIOUS_ACTION_SCHEMA = maybe_simple_id({ + vol.Required(CONF_ID): cv.templatable(cv.use_variable_id(DisplayBuffer)), +}) + + +@ACTION_REGISTRY.register(CONF_DISPLAY_PAGE_SHOW_PREVIOUS, DISPLAY_PAGE_SHOW_PREVIOUS_ACTION_SCHEMA) +def display_page_show_previous_to_code(config, action_id, arg_type, template_arg): + for var in get_variable(config[CONF_ID]): + yield None + type = DisplayPageShowPrevAction.template(arg_type) + yield Pvariable(action_id, type.new(var), type=type) def setup_display(display_var, config): diff --git a/esphome/components/display/ssd1306_i2c.py b/esphome/components/display/ssd1306_i2c.py index 1d2cddb54e..0daaa1b868 100644 --- a/esphome/components/display/ssd1306_i2c.py +++ b/esphome/components/display/ssd1306_i2c.py @@ -5,7 +5,7 @@ from esphome.components import display from esphome.components.display import ssd1306_spi import esphome.config_validation as cv from esphome.const import CONF_ADDRESS, CONF_EXTERNAL_VCC, CONF_ID, CONF_LAMBDA, CONF_MODEL, \ - CONF_RESET_PIN + CONF_PAGES, CONF_RESET_PIN from esphome.cpp_generator import Pvariable, add, process_lambda from esphome.cpp_helpers import gpio_output_pin_expression, setup_component from esphome.cpp_types import App, void @@ -14,13 +14,13 @@ DEPENDENCIES = ['i2c'] I2CSSD1306 = display.display_ns.class_('I2CSSD1306', ssd1306_spi.SSD1306) -PLATFORM_SCHEMA = display.FULL_DISPLAY_PLATFORM_SCHEMA.extend({ +PLATFORM_SCHEMA = vol.All(display.FULL_DISPLAY_PLATFORM_SCHEMA.extend({ cv.GenerateID(): cv.declare_variable_id(I2CSSD1306), vol.Required(CONF_MODEL): ssd1306_spi.SSD1306_MODEL, vol.Optional(CONF_RESET_PIN): pins.gpio_output_pin_schema, vol.Optional(CONF_EXTERNAL_VCC): cv.boolean, vol.Optional(CONF_ADDRESS): cv.i2c_address, -}).extend(cv.COMPONENT_SCHEMA.schema) +}).extend(cv.COMPONENT_SCHEMA.schema), cv.has_at_most_one_key(CONF_PAGES, CONF_LAMBDA)) def to_code(config): diff --git a/esphome/components/display/ssd1306_spi.py b/esphome/components/display/ssd1306_spi.py index a6b6a67274..f8fe14127e 100644 --- a/esphome/components/display/ssd1306_spi.py +++ b/esphome/components/display/ssd1306_spi.py @@ -5,7 +5,7 @@ from esphome.components import display, spi from esphome.components.spi import SPIComponent import esphome.config_validation as cv from esphome.const import CONF_CS_PIN, CONF_DC_PIN, CONF_EXTERNAL_VCC, CONF_ID, CONF_LAMBDA, \ - CONF_MODEL, CONF_RESET_PIN, CONF_SPI_ID + CONF_MODEL, CONF_RESET_PIN, CONF_SPI_ID, CONF_PAGES from esphome.cpp_generator import Pvariable, add, get_variable, process_lambda from esphome.cpp_helpers import gpio_output_pin_expression, setup_component from esphome.cpp_types import App, PollingComponent, void @@ -29,7 +29,7 @@ MODELS = { SSD1306_MODEL = cv.one_of(*MODELS, upper=True, space="_") -PLATFORM_SCHEMA = display.FULL_DISPLAY_PLATFORM_SCHEMA.extend({ +PLATFORM_SCHEMA = vol.All(display.FULL_DISPLAY_PLATFORM_SCHEMA.extend({ cv.GenerateID(): cv.declare_variable_id(SPISSD1306), cv.GenerateID(CONF_SPI_ID): cv.use_variable_id(SPIComponent), vol.Required(CONF_CS_PIN): pins.gpio_output_pin_schema, @@ -37,7 +37,7 @@ PLATFORM_SCHEMA = display.FULL_DISPLAY_PLATFORM_SCHEMA.extend({ vol.Required(CONF_MODEL): SSD1306_MODEL, vol.Optional(CONF_RESET_PIN): pins.gpio_output_pin_schema, vol.Optional(CONF_EXTERNAL_VCC): cv.boolean, -}).extend(cv.COMPONENT_SCHEMA.schema) +}).extend(cv.COMPONENT_SCHEMA.schema), cv.has_at_most_one_key(CONF_PAGES, CONF_LAMBDA)) def to_code(config): diff --git a/esphome/components/display/waveshare_epaper.py b/esphome/components/display/waveshare_epaper.py index 4c1bc0e0ec..b1058eb9da 100644 --- a/esphome/components/display/waveshare_epaper.py +++ b/esphome/components/display/waveshare_epaper.py @@ -5,7 +5,7 @@ from esphome.components import display, spi from esphome.components.spi import SPIComponent import esphome.config_validation as cv from esphome.const import CONF_BUSY_PIN, CONF_CS_PIN, CONF_DC_PIN, CONF_FULL_UPDATE_EVERY, \ - CONF_ID, CONF_LAMBDA, CONF_MODEL, CONF_RESET_PIN, CONF_SPI_ID + CONF_ID, CONF_LAMBDA, CONF_MODEL, CONF_PAGES, CONF_RESET_PIN, CONF_SPI_ID from esphome.cpp_generator import Pvariable, add, get_variable, process_lambda from esphome.cpp_helpers import gpio_input_pin_expression, gpio_output_pin_expression, \ setup_component @@ -48,7 +48,8 @@ PLATFORM_SCHEMA = vol.All(display.FULL_DISPLAY_PLATFORM_SCHEMA.extend({ vol.Optional(CONF_RESET_PIN): pins.gpio_output_pin_schema, vol.Optional(CONF_BUSY_PIN): pins.gpio_input_pin_schema, vol.Optional(CONF_FULL_UPDATE_EVERY): cv.uint32_t, -}).extend(cv.COMPONENT_SCHEMA.schema), validate_full_update_every_only_type_a) +}).extend(cv.COMPONENT_SCHEMA.schema), validate_full_update_every_only_type_a, + cv.has_at_most_one_key(CONF_PAGES, CONF_LAMBDA)) def to_code(config): diff --git a/esphome/const.py b/esphome/const.py index 244097f318..99632c2f26 100644 --- a/esphome/const.py +++ b/esphome/const.py @@ -336,6 +336,7 @@ CONF_CHANGE_MODE_EVERY = 'change_mode_every' CONF_PAGE_ID = 'page_id' CONF_COMPONENT_ID = 'component_id' CONF_COLD_WHITE = 'cold_white' +CONF_PAGES = 'pages' CONF_WARM_WHITE = 'warm_white' CONF_COLD_WHITE_COLOR_TEMPERATURE = 'cold_white_color_temperature' CONF_WARM_WHITE_COLOR_TEMPERATURE = 'warm_white_color_temperature' diff --git a/tests/test1.yaml b/tests/test1.yaml index ff7b6f8168..cd9526f50d 100644 --- a/tests/test1.yaml +++ b/tests/test1.yaml @@ -1007,6 +1007,14 @@ fan: medium: 0.75 high: 1.0 +interval: + - interval: 10s + then: + - display.page.show: !lambda |- + if (true) return id(page1); else return id(page2); + - display.page.show_next: display + - display.page.show_previous: display + display: - platform: lcd_gpio dimensions: 18x4 @@ -1037,8 +1045,14 @@ display: model: "SSD1306 128x64" reset_pin: GPIO23 address: 0x3C - lambda: |- - it.rectangle(0, 0, it.get_width(), it.get_height()); + id: display + pages: + - id: page1 + lambda: |- + it.rectangle(0, 0, it.get_width(), it.get_height()); + - id: page2 + lambda: |- + // Nothing - platform: ssd1306_spi model: "SSD1306 128x64" cs_pin: GPIO23