From 37460d9b765980c045845998e3cbcb0a456bd386 Mon Sep 17 00:00:00 2001 From: LuBeDa Date: Sat, 29 Apr 2023 20:28:38 +0200 Subject: [PATCH 01/12] beta --- CHANGELOG.md | 46 ++-------------------------------- components/ehmtxv2/EHMTX.h | 2 +- components/ehmtxv2/__init__.py | 3 +-- 3 files changed, 4 insertions(+), 47 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 11c20f2..43a80fa 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,47 +1,5 @@ # Changelog -## 2023.4.1 -- breaking: removed show_icons +## 2023.5.0 -## 2023.4.0 -- new: set_screen_color service to set color for a screen (service & action) -- breaking: all settings and parameters are named more consistant -- changed: center small text instead of left aligned -- removed: select component - -## 2023.3.5 -- new: show_seconds indicator top left corner -- breaking: removed automatic scaling of images -- new: support 8x32 icons without text -- breaking: added status,display_on,display_off as default service => remove these from your yaml -- breaking: added indicator_on/off as default service => remove these from your yaml -- breaking: added alarm_color,text_color,clock_color as default service => remove these from your yaml -- breaking: gauge is also schown while the clock is displayed but without moving the screen to the right -- breaking: show_icons as default service => remove from yaml - -## 2023.3.4 - -- added: option to not display clock/date #53 -- added: dynamic set_show_clock -- added: on_next_clock trigger - -## 2023.3.3 - -- fixed: force_screen skips imediatly to the selected screen -- added: hold_time configurable - -## 2023.3.2 - -- added: hold_screen for 20 additional seconds - -## 2023.3.1 - -- added: del_screen with wildcards -- changed: maximum icons to 80 -- fixed: skip_next -- fixed: show_all_icons on boot - -## 2023.3.0 - -see README.md for features -e.g. Service **display_on** / **display_off** +- beta release \ No newline at end of file diff --git a/components/ehmtxv2/EHMTX.h b/components/ehmtxv2/EHMTX.h index 1773ef7..7cfc6d6 100644 --- a/components/ehmtxv2/EHMTX.h +++ b/components/ehmtxv2/EHMTX.h @@ -21,7 +21,7 @@ const uint8_t TEXTSCROLLSTART = 8; const uint8_t TEXTSTARTOFFSET = (32 - 8); const uint16_t TICKINTERVAL = 1000; // each 1000ms -static const char *const EHMTX_VERSION = "Version: 2023.5.0"; +static const char *const EHMTX_VERSION = "Version: 2023.5.0 beta"; static const char *const TAG = "EHMTXv2"; enum show_mode : uint8_t { MODE_EMPTY = 0,MODE_BLANK = 1, MODE_CLOCK = 2, MODE_DATE = 3, MODE_FULL_SCREEN = 4, MODE_ICONSCREEN = 5, MODE_TEXT = 6 , MODE_RAINBOW_ICON = 7,MODE_RAINBOW_TEXT = 8, MODE_RAINBOW_CLOCK = 9 }; diff --git a/components/ehmtxv2/__init__.py b/components/ehmtxv2/__init__.py index 7680922..c4ecd0e 100644 --- a/components/ehmtxv2/__init__.py +++ b/components/ehmtxv2/__init__.py @@ -27,8 +27,7 @@ SVG_FULL_SCREEN_START = '' SVG_END = "" logging.warning(f"") -logging.warning(f"If you are upgrading EsphoMaTrix from a version before 2023.5.0,") -logging.warning(f"you should read the manual https://github.com/lubeda/EspHoMaTriXv2 for tips.") +logging.warning(f"This is a beta version of https://github.com/lubeda/EspHoMaTriXv2") logging.warning(f"") def rgb565_svg(x,y,r,g,b): From ca9106be4e716152d3dc5c21b5bcf95b30a5a1fd Mon Sep 17 00:00:00 2001 From: LuBeDa Date: Sat, 29 Apr 2023 20:48:55 +0200 Subject: [PATCH 02/12] docu --- README.md | 114 +++++++++++++++++++++++++++--------------------------- 1 file changed, 57 insertions(+), 57 deletions(-) diff --git a/README.md b/README.md index 64bff6e..db85395 100644 --- a/README.md +++ b/README.md @@ -1,20 +1,18 @@ -# This is a work in progress. Don't use it for production! +# EspHoMaTriX version 2 (EHMTXv2) + +## This is a prerelease beta version! ## Important information If you like my work, please donate me a star on github and consider sponsoring me!! -# EspHoMaTriX version 2 (EHMTXv2) +## Introduction -A simple but very flexible DIY status display, built with a flexible 8x32 RGB LED panel implemented with [esphome.io](https://esphome.io) +A simple but very flexible DIY status display, built with a flexible 8x32 RGB LED panel, e.g. the ULANZI TC001 implemented with [esphome.io](https://esphome.io) ![sample image](./images/sample.png) -## Important information - -If you like my work, please donate me a star on github and consider sponsoring me!! - -## Introduction +## Background There are some "RGB-matrices" status displays/clocks out there, the commercial ones from LaMetric and Ulanzi, also some very good DIY-alternatives. @@ -22,33 +20,12 @@ There are some "RGB-matrices" status displays/clocks out there, the commercial o - [Ulanzi TC001](https://www.aliexpress.com/item/1005005008682055.html) commercial ~ €50 - [AWTRIX](https://awtrixdocs.blueforcer.de/#/) (project has been discontinued after more than 4 years now in August 2022) - [Pixel It](https://docs.bastelbunker.de/pixelit/) (project is under active development) -- [AWTRIX-Light](https://github.com/Blueforcer/awtrix-light) From the developer of Awtrix, optimized for the Ulanzi TC001 -Hardware -- [lamatrix](https://github.com/noahwilliamsson/lamatrix/tree/master) micropython based and around 5 years old +- [AWTRIX-Light](https://github.com/Blueforcer/awtrix-light) From the developer of Awtrix, optimized for the Ulanzi TC001 Hardware The solutions have their pros and cons. I tried some and used AwTrix for a long time. But the cons are so big (in my opinion) that I started an esphome.io variant. Targeted to an optimized Home Assistant integration, without paid blueprints and the need of MQTT. But it had to be extensible, e.g. for the use as pool thermometer or as media player. All done by the magical power of esphome. -### EspHoMaTriX in the media - -See this German tutorial video with information on setting up your display [RGB-LED Status Display für Home Assistant mit ESPHome | ESPHoMaTrix](https://www.youtube.com/watch?v=DTd9vAhet9A). - -Another german tutorial video focused at the Ulanzi [Smarte Pixel Clock über Home Assistant steuern - Entitäten / Icons und mehr in der Ulanzi](https://www.youtube.com/watch?v=LgaT0mNbl34) - -See this [nice article](https://blakadder.com/esphome-pixel-clock/) about EsphoMaTrix on a Ulanzi TC001 from [blakadder](https://github.com/blakadder). - -Short video on Instagram [@blak_adder](https://www.insbuiltagram.com/reel/CpYVByRIaSI) - -See this english discussions: -[Share your projects](https://community.home-assistant.io/t/esphomatrix-a-simple-clock-status-display/425325) -[ESPHOME](https://community.home-assistant.io/t/a-simple-diy-status-display-with-an-8x32-rgb-led/379051) - -It was also mentiond in the blog [Building the Open Home](https://building.open-home.io/local-control-is-the-only-way/) and in the home assistant [livestream](https://youtu.be/IGnCGDaXR0M?t=6267) - -Or in german: -[Showroom](https://community.simon42.com/t/8x32-pixel-uhr-mit-homeassistant-anbindung/1076) - ### Features Based on a 8x32 RGB matrix, it displays a clock, the date and up to 24 other 'screens' provided by Home Assistant. Each screen (value/text) can be associated with a 8x8 bit RGB icon or GIF animation (see [installation](#installation)). The values/text can be updated or deleted from the display queue. Each screen has a lifetime, if not refreshed in its lifetime, it will disappear. Even 8x32 GIF animations are possible. You can control nearly everything of the component. @@ -63,11 +40,9 @@ After the [old](https://github.com/lubeda/EsphoMaTrix) component became favorite There is a little hype around the Ulanzi TC001 pixel clock. This hardware can be used with **EspHoMaTriX v2**. -### Steps (easy) - #### Step 1 -Copy these files: +Copy these files from the source folder `copy2esphome`: - ulanzi-simple.yaml - EHMTXv2.ttf @@ -76,11 +51,11 @@ to your esphome directory (usually /config/esphome). In your esphome dashboard, #### Step 2 -connect your ulanzi device to your host with USB-C and flash the firmware. +Connect your ulanzi device to your host with USB-C and flash the firmware. #### Step 3 -Copy `EHMTX_easy_state.yaml` to your blueprint path (usually /config/blueprints/automation/) in a subfolder named `ehmtxv2`. +Copy the blueprints `EHMTX_easy_*.yaml` to your blueprint path (usually /config/blueprints/automation/) in a subfolder named `ehmtxv2`. Reload your automations and have fun after configuring some automations with this blueprint. @@ -98,13 +73,13 @@ If not, check the esphome logs for further investigations. ### The funny but more elaborate way -This is for the more advanced users. If you understand the concept of esphome, you can display nearly everything with this component. +This is for the more advanced users. If you understand the concept of esphome, you can display nearly everything with this component. You are also able to create your own customized esphome based display with multiple sensors or even use it as microphone for the new [voice assist](https://esphome.io/components/voice_assistant.html) feature from home assistant. #### Concept You can add screens to a queue and all these screens are displayed one after another. ![timing](./images/timingv2.png) -Each screen can display different information or is of a different kind. They all have a lifetime, if a screen isn't refreshed during its lifetime it will be removed from the queue. If there is nothing left in the queue, the date and time screens are displayed. Some screens can show additional features like an alarm or indicator see [elements](#elements). +Each screen can display different information or is of a different kind. They all have a lifetime, if a screen isn't refreshed during its lifetime it will be removed from the queue. If there is nothing left in the queue, the date and time screens are displayed. Some screens can show additional features like an alarm or indicator see [elements](#display_elements). You can add screens from home assistant with services or from esphome via YAML. #### Screen types @@ -113,19 +88,25 @@ You can add screens from home assistant with services or from esphome via YAML. ![clock screen](./images/clock_screen.png) -###### Service +###### Service via API + +You can call this from e.g. the [developer tools service](https://my.home-assistant.io/redirect/developer_services/) ```c clock_screen => {"lifetime", "screen_time", "default_font", "r", "g", "b"} +rainbow_clock_screen 0> {"lifetime", "screen_time", "default_font"} date_screen => {"lifetime", "screen_time", "default_font", "r", "g", "b"} ``` -###### API +###### Lambda + +You cann use these in [lambdas](https://esphome.io/guides/automations.html?highlight=lambda#lambda-action) in your esphome YAML. all parameters have a default value. ```c void clock_screen(int lifetime=D_LIFETIME, int screen_time=D_SCREEN_TIME,bool default_font=true,int r=C_RED, int g=C_GREEN, int b=C_BLUE); +void rainbow_clock_screen(int lifetime=D_LIFETIME, int screen_time=D_SCREEN_TIME, bool default_font=true); void date_screen(int lifetime=D_LIFETIME, int screen_time=D_SCREEN_TIME,bool default_font=true, int r=C_RED, int g=C_GREEN, int b=C_BLUE); ``` @@ -133,16 +114,18 @@ void date_screen(int lifetime=D_LIFETIME, int screen_time=D_SCREEN_TIME,bool def ![icon screen](./images/icon_screen.png) -###### service +###### Service via API ```c icon_screen => {"icon_name", "text", "lifetime", "screen_time", "default_font", "r", "g", "b"} +rainbow_icon_screen => {"icon_name", "text", "lifetime", "screen_time", "default_font"} ``` -###### api +###### Lambda ```c void icon_screen(std::string icon, std::string text, int lifetime=D_LIFETIME, int screen_time=D_SCREEN_TIME,bool default_font=true,int r=C_RED, int g=C_GREEN, int b=C_BLUE); +void rainbow_icon_screen(std::string icon, std::string text, int lifetime=D_LIFETIME, int screen_time=D_SCREEN_TIME,bool default_font=true); ``` ##### full_screen @@ -151,39 +134,40 @@ For 8x32 icons or animations ![full_screen](./images/fullscreen.png) -###### service +###### service via API ```c full_screen => {"icon_name", "lifetime", "screen_time"} ``` -###### api +###### Lambda ```c -void EHMTX::full_screen(std::string iconname, int lifetime, int screen_time) +void full_screen(string iconname, int =D_LIFETIME, int screen_time=D_SCREEN_TIME); ``` -#### Elements +#### Display Elements ![elements](./images/elements.png) ##### alarm -The alarm is displayed in the upper right corner at all screen types! You can set its color. +The alarm is displayed in the upper right corner at all screen types! You can set its color and its size. ###### service ```c -show_alarm => { "r", "g", "b","s"} +show_alarm => { "r", "g", "b","size"} ``` ###### api ```c -void EHMTX::show_alarm(int r, int g, int b, int s=2); +void EHMTX::show_alarm(int r, int g, int b, int size=2); ``` r,g,b: 0-255 color components +size: 1-3 To remove it, call: @@ -196,7 +180,7 @@ hide_alarm => no parameter ###### API ```c -void EHMTX::hide_alarm(); +void hide_alarm(); ``` ##### Indicator @@ -206,16 +190,17 @@ The indicator is in the lower left corner, but not displayed in fullscreen 8x32 ###### Service ```c -show_indicator => { "r", "g", "b","s"} +show_indicator => { "r", "g", "b","size"} ``` ###### API ```c -void EHMTX::show_indicator(int r, int g, int ,int s=3); +void show_indicator(int r, int g, int ,int size=3); ``` r,g,b: 0-255 color components +size: 1-3 To remove it, call: @@ -228,7 +213,7 @@ hide_indicator => no parameter ###### API ```c -void EHMTX::hide_indicator(); +void hide_indicator(); ``` ##### gauge @@ -244,10 +229,10 @@ show_gauge => {"value","r", "g", "b"} ###### api ```c -void EHMTX::show_gauge(int value, int r, int g, int b); +void show_gauge(int percent, int r, int g, int b); ``` -value: 0-100 (resolution: one pixel per 12,5%) +percent: 0-100 (resolution: one pixel per 12,5%) r,g,b: 0-255 color components To remove it call: @@ -261,7 +246,7 @@ hide_gauge => no parameter ###### api ```c -void EHMTX::hide_gauge(); +void hide_gauge(); ``` #### Installation @@ -960,9 +945,24 @@ sensor: **nothing yet, since it is new** -## Usage +## EspHoMaTriX in the media + +See this German tutorial video with information on setting up your display [RGB-LED Status Display für Home Assistant mit ESPHome | ESPHoMaTrix](https://www.youtube.com/watch?v=DTd9vAhet9A). + +Another german tutorial video focused at the Ulanzi [Smarte Pixel Clock über Home Assistant steuern - Entitäten / Icons und mehr in der Ulanzi](https://www.youtube.com/watch?v=LgaT0mNbl34) + +See this [nice article](https://blakadder.com/esphome-pixel-clock/) about EsphoMaTrix on a Ulanzi TC001 from [blakadder](https://github.com/blakadder). -The integration works with the Home Assistant API so, after boot of the device, it takes a few seconds until the service calls start working. If you see a growing green rectangle after boot, you have to wait a bit until the API is connected etc. +Short video on Instagram [@blak_adder](https://www.insbuiltagram.com/reel/CpYVByRIaSI) + +See this english discussions: +[Share your projects](https://community.home-assistant.io/t/esphomatrix-a-simple-clock-status-display/425325) +[ESPHOME](https://community.home-assistant.io/t/a-simple-diy-status-display-with-an-8x32-rgb-led/379051) + +It was also mentiond in the blog [Building the Open Home](https://building.open-home.io/local-control-is-the-only-way/) and in the home assistant [livestream](https://youtu.be/IGnCGDaXR0M?t=6267) + +Or in german: +[Showroom](https://community.simon42.com/t/8x32-pixel-uhr-mit-homeassistant-anbindung/1076) ## Disclaimer From 8626fafa0c601bd52a49b5de02deb8298803eac1 Mon Sep 17 00:00:00 2001 From: LuBeDa Date: Sun, 30 Apr 2023 18:59:29 +0200 Subject: [PATCH 03/12] docu --- README.md | 60 +++++++++---------- components/ehmtxv2/EHMTX.cpp | 18 ++++-- components/ehmtxv2/EHMTX.h | 4 +- components/ehmtxv2/__init__.py | 2 - .../{Ulanzi-simple.yaml => ulanzi-easy.yaml} | 60 ++++++++++++++----- 5 files changed, 91 insertions(+), 53 deletions(-) rename copy2esphome/{Ulanzi-simple.yaml => ulanzi-easy.yaml} (80%) diff --git a/README.md b/README.md index db85395..b17268e 100644 --- a/README.md +++ b/README.md @@ -38,7 +38,9 @@ After the [old](https://github.com/lubeda/EsphoMaTrix) component became favorite ### The easy way -There is a little hype around the Ulanzi TC001 pixel clock. This hardware can be used with **EspHoMaTriX v2**. +There is a little hype around the Ulanzi TC001 pixel clock. The easy way works with the Ulanzi TC001 hardware. For more customization and other hardware look [here](#the-funny-but-more-elaborate-way). + +In easy mode you'll have a clock with auto brightness control and after step 3 you can send states to the display an toggle on or off additional screen elements. #### Step 1 @@ -47,7 +49,7 @@ Copy these files from the source folder `copy2esphome`: - ulanzi-simple.yaml - EHMTXv2.ttf -to your esphome directory (usually /config/esphome). In your esphome dashboard, you will find a new device named `ulanzi-simple`. +to your esphome directory (usually /config/esphome). In your esphome dashboard, you will find a new device named `ulanzi-easy`. #### Step 2 @@ -55,7 +57,7 @@ Connect your ulanzi device to your host with USB-C and flash the firmware. #### Step 3 -Copy the blueprints `EHMTX_easy_*.yaml` to your blueprint path (usually /config/blueprints/automation/) in a subfolder named `ehmtxv2`. +Copy the blueprints `EHMTX_easy_*.yaml` to your blueprint path (usually /config/blueprints/automation/) in a subfolder named `ehmtxv2`. Reload your automations and have fun after configuring some automations with this blueprint. @@ -65,7 +67,7 @@ The device should boot ![boot](images/booting.png) -and after a while (~30 seconds) it should display the correct time +and after a while (~30 seconds) it should display the correct time. ![clock screen](images/clock_screen.png). @@ -79,10 +81,10 @@ This is for the more advanced users. If you understand the concept of esphome, y You can add screens to a queue and all these screens are displayed one after another. ![timing](./images/timingv2.png) -Each screen can display different information or is of a different kind. They all have a lifetime, if a screen isn't refreshed during its lifetime it will be removed from the queue. If there is nothing left in the queue, the date and time screens are displayed. Some screens can show additional features like an alarm or indicator see [elements](#display_elements). -You can add screens from home assistant with services or from esphome via YAML. +Each screen can display different information or animation or text, even in rainbox color. They all have a lifetime, if a screen isn't refreshed during its lifetime it will be removed from the queue. If there is nothing left in the queue, the date and time screens are displayed. Some screens can show additional features like an alarm or indicator see [elements](#display-elements). +You can add screens from home assistant with service-calls or from esphome via lambdas in your YAML. -#### Screen types +#### Screen types a.k.a. what is possible ##### Date/Time screen @@ -94,7 +96,7 @@ You can call this from e.g. the [developer tools service](https://my.home-assist ```c clock_screen => {"lifetime", "screen_time", "default_font", "r", "g", "b"} -rainbow_clock_screen 0> {"lifetime", "screen_time", "default_font"} +rainbow_clock_screen => {"lifetime", "screen_time", "default_font"} date_screen => {"lifetime", "screen_time", "default_font", "r", "g", "b"} ``` @@ -167,7 +169,7 @@ void EHMTX::show_alarm(int r, int g, int b, int size=2); ``` r,g,b: 0-255 color components -size: 1-3 +size: 0-3 (zero turns it off) To remove it, call: @@ -177,7 +179,7 @@ To remove it, call: hide_alarm => no parameter ``` -###### API +###### Lambda ```c void hide_alarm(); @@ -200,7 +202,7 @@ void show_indicator(int r, int g, int ,int size=3); ``` r,g,b: 0-255 color components -size: 1-3 +size: 0-3 (zero turns it off) To remove it, call: @@ -210,7 +212,7 @@ To remove it, call: hide_indicator => no parameter ``` -###### API +###### Lambda ```c void hide_indicator(); @@ -249,13 +251,11 @@ hide_gauge => no parameter void hide_gauge(); ``` -#### Installation - -##### **EspHoMaTriXv2** custom component +#### Installation of **EspHoMaTriXv2** custom component **EspHoMaTriXv2** is a custom component, you have to include it in your YAML configuration. To always use the newest features you should use the repo, to use a stable version, you copy a working version to your esphome installation. -###### local use +##### use of local copy If you download the components-folder from the repo and install it in your esphome you have a stable installation. But if there are new features, you won't see them. If needed, customize the YAML to your folder structure. @@ -275,10 +275,10 @@ external_components: - source: type: git url: https://github.com/lubeda/EspHoMaTriXv2 - ref: release # optional select a special branch or tag + ref: stable # optional select a special branch or tag ``` -##### Addressable_light component +#### Addressable_light component The **EspHoMaTriXv2** component requires a 8x32 pixel addressable_light, it is referenced by the id `matrix_component`. @@ -286,7 +286,7 @@ See the default [options](https://esphome.io/components/display/index.html) There are some different matrices-types on the market, to adapt them to **EspHoMaTriXv2** you have to find the proper pixel mapper. If there is garbage on your display, try the other `pixel_mapper`. Here are the most common types for flexible 8x32 matrices: -#### Type 1 +##### Type 1 Common for 8x32 RGB flexible matrices. @@ -304,7 +304,7 @@ display: ..... ``` -#### Type 2 (e.g. Ulanzi TC001) +##### Type 2 (e.g. Ulanzi TC001) Under the display tag, specify this pixel mapper: @@ -320,7 +320,7 @@ display: ..... ``` -#### Type 3 (daisy chained 8x8 panels) +##### Type 3 (daisy chained 8x8 panels) ```yaml display: @@ -331,7 +331,7 @@ display: ..... ``` -#### How to configure the pixel_mapper +##### How to configure the pixel_mapper You have to configure this `lambda` under the `display:` section to use the **EspHoMaTriXv2** component @@ -391,6 +391,8 @@ You can configure two fonts if you like. DarkPoet78 is also providing special fonts for 8x32 matrices in his [repo](https://github.com/darkpoet78/MatrixClockFonts) +For european starters you can use the font EHMTXv2.ttf of the copy2esphome folder. + ```yaml font: - file: EHMTXv2.ttf @@ -402,7 +404,7 @@ font: #### Icons and Animations -Download and install all needed icons (.jpg/.png) and animations (.GIF) under the `ehmtx:` key. All icons have to be 8x8 or 8x32 pixels in size. If necessary, scale them with gimp, check "as animation" for GIFs. +Download and install all needed icons (.jpg/.png) and animations (.GIF) under the `ehmtxv2:` key. All icons have to be 8x8 or 8x32 pixels in size. If necessary, scale them with gimp, check "as animation" for GIFs. You can also specify a URL to directly download the image file. The URLs will only be downloaded once at compile time, so there is no additional traffic on the hosting website. @@ -423,8 +425,11 @@ emhtx: - id: yoga file: icons/yoga-bridge.GIF pingpong: true + - id: jackshome + url: https://awtrix.blueforcer.de/animations/JackHomePage + resize: 32x8 - id: garage - file: garage.GIF + lameid: 1234 duration: 100 - id: homeassistant url: https://github.com/home-assistant/assets/raw/master/logo/logo-special.png @@ -451,8 +456,6 @@ This component is highly customizable. ```yaml ehmtxv2: id: rgb8x32 - clock_time: 7 - screen_time: 9 show_seconds: true matrix_component: ehmtx_display time_component: ehmtx_time @@ -476,10 +479,6 @@ ehmtxv2: **id** (required, ID): Manually specify the ID used for code generation and in service definitions. -**clock_time** (optional, seconds): duration to display the clock after this time the date is displayed until the next "show_screen". If `show_date` is false and `clock_time` > 0 the clock will be display as long as a normal screen! Setting `clock_time` to 0 will not show the clock or date. If there are no screens ind the queue, the display will be blank until the next screen is sent. - -**screen_time** (optional, seconds): default duration to display a screen or a clock/date sequence, a long text will be scrolled at least `scroll_count` times (default: 10 seconds). This may be overwritten by the add_screen service. - **hold_time** (optional, seconds): extends the display time of the current screen in seconds (default=20). Used in services or automations, see `hold_screen` **date_format** (optional, string): formats the date display with [strftime syntax](https://esphome.io/components/time.html?highlight=strftime), defaults `"%d.%m."` (use `"%m.%d."` for the US) @@ -978,6 +977,7 @@ THE SOFTWARE IS PROVIDED "AS IS", use at your own risk! - **[ofirsnb](https://github.com/ofirsnb)** for his contributions - **[darkpoet78](https://github.com/darkpoet78/MatrixClockFonts)** for his work on optimized fonts - **[pplucky](https://user-images.githubusercontent.com/16407309/224850723-634c9b2d-55d9-44f2-9f93-765c0485b090.GIF)** for his 8x32 GIF animation +- **[dennisse](https://github.com/dennisse)** Auto brightness for the Ulanzi - ** everbody that found bugs/issues and reported them! ## Special thanks to all sponsors diff --git a/components/ehmtxv2/EHMTX.cpp b/components/ehmtxv2/EHMTX.cpp index 7fdc7e5..7f697ca 100644 --- a/components/ehmtxv2/EHMTX.cpp +++ b/components/ehmtxv2/EHMTX.cpp @@ -8,6 +8,7 @@ namespace esphome this->display_gauge = false; this->display_indicator = 0; this->display_alarm = 0; + this->clock_time = 10; this->icon_count = 0; this->hue_ = 0; this->text_color = Color(C_RED, C_GREEN, C_BLUE); @@ -38,9 +39,14 @@ namespace esphome void EHMTX::show_indicator(int r, int g, int b, int size) { - this->indicator_color = Color((uint8_t)r & 248, (uint8_t)g & 252, (uint8_t)b & 248); - this->display_indicator = size; + if (size > 0 ) { + this->indicator_color = Color((uint8_t)r & 248, (uint8_t)g & 252, (uint8_t)b & 248); + this->display_indicator = size & 3; ESP_LOGD(TAG, "show indicator size: %d r: %d g: %d b: %d", size, r, g, b); + } else { + this->hide_indicator(); + } + } void EHMTX::hide_indicator() @@ -183,9 +189,13 @@ namespace esphome void EHMTX::show_alarm(int r, int g, int b, int size) { - this->alarm_color = Color((uint8_t)r & 248, (uint8_t)g & 252, (uint8_t)b & 248); - this->display_alarm = size; + if (size > 0){ + this->alarm_color = Color((uint8_t)r & 248, (uint8_t)g & 252, (uint8_t)b & 248); + this->display_alarm = size & 3; ESP_LOGD(TAG, "show alarm size: %d color r: %d g: %d b: %d", size, r, g, b); + } else { + this->hide_alarm(); + } } void EHMTX::hide_alarm() diff --git a/components/ehmtxv2/EHMTX.h b/components/ehmtxv2/EHMTX.h index 7cfc6d6..e32c1ab 100644 --- a/components/ehmtxv2/EHMTX.h +++ b/components/ehmtxv2/EHMTX.h @@ -102,8 +102,8 @@ namespace esphome void hold_screen(); void set_display(addressable_light::AddressableLightDisplay *disp); - void set_hold_time(uint16_t t); - void set_clock_time(uint16_t t); + void set_hold_time(uint16_t t=30); + void set_clock_time(uint16_t t=10); void set_show_day_of_week(bool b); void set_show_seconds(bool b); void set_show_date(bool b); diff --git a/components/ehmtxv2/__init__.py b/components/ehmtxv2/__init__.py index c4ecd0e..f919e21 100644 --- a/components/ehmtxv2/__init__.py +++ b/components/ehmtxv2/__init__.py @@ -49,7 +49,6 @@ NextClockTrigger = ehmtx_ns.class_( "EHMTXNextClockTrigger", automation.Trigger.template(cg.std_string) ) -CONF_CLOCKTIME = "clock_time" CONF_EHMTX = "ehmtx" CONF_URL = "url" CONF_FLAG = "flag" @@ -391,7 +390,6 @@ async def to_code(config): ehmtxtime = await cg.get_variable(config[CONF_TIMECOMPONENT]) cg.add(var.set_clock(ehmtxtime)) - cg.add(var.set_clock_time(config[CONF_CLOCKTIME])) cg.add(var.set_brightness(config[CONF_BRIGHTNESS])) cg.add(var.set_scroll_interval(config[CONF_SCROLLINTERVAL])) cg.add(var.set_rainbow_interval(config[CONF_SCROLLINTERVAL])) diff --git a/copy2esphome/Ulanzi-simple.yaml b/copy2esphome/ulanzi-easy.yaml similarity index 80% rename from copy2esphome/Ulanzi-simple.yaml rename to copy2esphome/ulanzi-easy.yaml index b6553b8..cf45ba9 100644 --- a/copy2esphome/Ulanzi-simple.yaml +++ b/copy2esphome/ulanzi-easy.yaml @@ -15,6 +15,40 @@ substitutions: scl_pin: GPIO22 sda_pin: GPIO21 +- platform: template + name: "Auto-Adjust Brightness" + id: switch_autobrightness + icon: mdi:brightness-auto + restore_mode: RESTORE_DEFAULT_ON + lambda: |- + if (id(aab_enable)) { + return true; + } else { + return false; + } + turn_on_action: + lambda: |- + id(aab_enable) = true; + turn_off_action: + lambda: |- + id(aab_enable) = false; + +globals: + # aab = auto-adjustable brightness + - id: aab_enable + type: "bool" + restore_value: true + initial_value: "true" + - id: aab_add + type: int + initial_value: '10' + - id: aab_max + type: int + initial_value: '220' + - id: aab_min + type: int + initial_value: '20' + external_components: - source: type: git @@ -111,19 +145,17 @@ sensor: filters: - lambda: |- return (x / 10000.0) * 2000000.0 - 15 ; - on_value_range: - - below: 100.0 - then: - lambda: |- - id(rgb8x32)->set_brightness(20); - - below: 250.0 - then: - lambda: |- - id(rgb8x32)->set_brightness(40); - - above: 250.0 - then: - lambda: |- - id(rgb8x32)->set_brightness(80); + on_value: + then: + - lambda: |- + if ( id(aab_enable) ) { + int n = x / 4 + id(aab_add); // new_value + if (n > id(aab_max)) n = id(aab_max); + if (n < id(aab_min)) n = id(aab_min); + int c = id(rgb8x32)->get_brightness(); // current value + int d = (n - c) * 100 / c; // diff in % + if ( abs(d) > 2 ) id(rgb8x32)->set_brightness(n); + } ota: password: !secret ota_password @@ -190,8 +222,6 @@ display: ehmtxv2: id: rgb8x32 - clock_time: 10 - screen_time: 10 hold_time: 30 icons2html: true default_font_yoffset: 6 From 29a42904c6dfa415778a5a308b20f516b7d0c93a Mon Sep 17 00:00:00 2001 From: LuBeDa Date: Sun, 30 Apr 2023 19:00:04 +0200 Subject: [PATCH 04/12] docu --- components/ehmtxv2/__init__.py | 2 -- 1 file changed, 2 deletions(-) diff --git a/components/ehmtxv2/__init__.py b/components/ehmtxv2/__init__.py index f919e21..18dd774 100644 --- a/components/ehmtxv2/__init__.py +++ b/components/ehmtxv2/__init__.py @@ -231,8 +231,6 @@ async def ehmtx_set_week_color_action_to_code(config, action_id, template_arg, a return var - - CODEOWNERS = ["@lubeda"] async def to_code(config): From 91f5dd959aace95b1010e96a5954a2ca989cb364 Mon Sep 17 00:00:00 2001 From: LuBeDa Date: Sun, 30 Apr 2023 19:01:43 +0200 Subject: [PATCH 05/12] removed clock Time --- components/ehmtxv2/__init__.py | 3 --- 1 file changed, 3 deletions(-) diff --git a/components/ehmtxv2/__init__.py b/components/ehmtxv2/__init__.py index 18dd774..f6a5b06 100644 --- a/components/ehmtxv2/__init__.py +++ b/components/ehmtxv2/__init__.py @@ -91,9 +91,6 @@ EHMTX_SCHEMA = cv.Schema({ cv.Required(CONF_MATRIXCOMPONENT): cv.use_id(display), cv.Required(CONF_DEFAULT_FONT_ID): cv.use_id(font), cv.Required(CONF_special_FONT_ID): cv.use_id(font), - cv.Optional( - CONF_CLOCKTIME, default="5" - ): cv.templatable(cv.positive_int), cv.Optional( CONF_HTML, default=False ): cv.boolean, From 8a5616de3b6fa0655d6eb17a10c22d795d1dff38 Mon Sep 17 00:00:00 2001 From: LuBeDa Date: Sun, 30 Apr 2023 19:56:48 +0200 Subject: [PATCH 06/12] docu --- README.md | 45 ++++++++++++++++++++++++++--- components/ehmtxv2/EHMTX.cpp | 11 +++---- components/ehmtxv2/EHMTX.h | 4 +-- components/ehmtxv2/EHMTX_queue.cpp | 11 +++++-- components/ehmtxv2/__init__.py | 5 ---- copy2esphome/ulanzi-easy.yaml | 1 - images/events.png | Bin 0 -> 26616 bytes 7 files changed, 56 insertions(+), 21 deletions(-) create mode 100644 images/events.png diff --git a/README.md b/README.md index b17268e..ffb4a5f 100644 --- a/README.md +++ b/README.md @@ -98,6 +98,7 @@ You can call this from e.g. the [developer tools service](https://my.home-assist clock_screen => {"lifetime", "screen_time", "default_font", "r", "g", "b"} rainbow_clock_screen => {"lifetime", "screen_time", "default_font"} date_screen => {"lifetime", "screen_time", "default_font", "r", "g", "b"} +rainbow_date_screen => {"lifetime", "screen_time", "default_font"} ``` ###### Lambda @@ -479,8 +480,6 @@ ehmtxv2: **id** (required, ID): Manually specify the ID used for code generation and in service definitions. -**hold_time** (optional, seconds): extends the display time of the current screen in seconds (default=20). Used in services or automations, see `hold_screen` - **date_format** (optional, string): formats the date display with [strftime syntax](https://esphome.io/components/time.html?highlight=strftime), defaults `"%d.%m."` (use `"%m.%d."` for the US) **show_seconds** (optional, boolean): toggle an indicator for seconds while the clock is displayed (default: false) @@ -542,6 +541,38 @@ See [icon details](#icons-and-animations) A lot of features are accessible with actions, you can use in your YAML. +### Public functions/services + |service|parameter|result| + |---|---|---|---| + `status`|none|write some status information to the esphome logs| + `display_on`|none|turn display off| + `display_off`|none|turn display on| + `hold_screen`|none|show the screen that is currently displayed for the number of seconds longer| + `hide_indicator`|none|hides the indicator| + `hide_gauge`|none|hides the gauge| + `hide_alarm`|none|hides the alarm| + `show_gauge"`|"percent", "r", "g", "b"|set the heught of the gauge according to the percentage in the given color| + `show_alarm`|"r", "g", "b", "size"|shows the color with the given size in the upper right corner| + `show_indicator`|"r", "g", "b", "size"|shows the color with the given size in the lower right corner| + + `clock_color`|"r", "g", "b"|set the default color for the clock/date display| + `today_color"`|"r", "g", "b"|set the special color for today in the day of week line| + `weekday_color"`|"r", "g", "b"|set the default color in the day of week line| + + `del_screen`|"icon_name", "mode"|deletes the specified icon screen from the queue, the [mode](#modes) is a filter| + `force_screen`|"icon_name", "mode"|displayes the seleted the specified icon screen from the queue, the [mode](#modes) is a filter| + + `full_screen`|"icon_name", "lifetime", "screen_time"|show the specified icon as fullscreen| + `icon_screen`|"icon_name", "text", "lifetime", "screen_time", "default_font", "r", "g", "b"|show the specified icon with text| + `rainbow_icon_screen`|"icon_name", "text", "lifetime", "screen_time", "default_font"|show the specified icon with text in rainbow color| + `text_screen`|"text", "lifetime", "screen_time", "default_font", "r", "g", "b"|show the specified text| + `rainbow_text_screen`|"text", "lifetime", "screen_time", "default_font"|show the specified text in rainbow colors| + `clock_screen`|"lifetime", "screen_time", "default_font", "r", "g", "b"|show the clock| + `rainbow_clock_screen`|"lifetime", "screen_time", "default_font"|show the clock in rainbow color| + `blank_screen`|"lifetime", "screen_time"|"show" an empty screen| + `date_screen`|"lifetime", "screen_time", "default_font", "r", "g", "b"|show the date| + `brightness`|"value"|set the display brightness| + ### Local actions/lambdas #### Add screen to your display queue @@ -681,6 +712,8 @@ For example, if you have multiple icons named weather_sunny, weather_rain & weat - ```icon_name```: Icon `id` defined in the YAML (see installation) - ```mode```: The mode is for internal purposes use `5` for icon_screen +##### modes + |mode|value| |----|----| |MODE_BLANK|1| @@ -689,6 +722,10 @@ For example, if you have multiple icons named weather_sunny, weather_rain & weat | MODE_FULL_SCREEN | 4| |MODE_ICONSCREEN | 5| |MODE_TEXT | 6| +|MODE_RAINBOW_ICON | 7| +|MODE_RAINBOW_TEXT |8| +| MODE_RAINBOW_CLOCK | 9| +| MODE_RAINBOW_DATE | 10| **(D)** Service **display_on** / **display_off** @@ -733,7 +770,7 @@ binary_sensor: Service **hold_screen** -Displays the current screen for a configured amount (see **hold_time**) (default=20) seconds longer. +Displays the current screen for a configured amount (see **hold_time**) (default=30) seconds longer. e.g. on the Ulanzi TC001 @@ -745,7 +782,7 @@ binary_sensor: inverted: true on_press: lambda: - id(rgb8x32)->hold_screen(); + id(rgb8x32)->hold_screen(120); ``` **(D)** Service **status** diff --git a/components/ehmtxv2/EHMTX.cpp b/components/ehmtxv2/EHMTX.cpp index 7f697ca..e6fa054 100644 --- a/components/ehmtxv2/EHMTX.cpp +++ b/components/ehmtxv2/EHMTX.cpp @@ -9,6 +9,7 @@ namespace esphome this->display_indicator = 0; this->display_alarm = 0; this->clock_time = 10; + this->hold_time = 10; this->icon_count = 0; this->hue_ = 0; this->text_color = Color(C_RED, C_GREEN, C_BLUE); @@ -158,7 +159,7 @@ namespace esphome register_service(&EHMTX::get_status, "status"); register_service(&EHMTX::set_display_on, "display_on"); register_service(&EHMTX::set_display_off, "display_off"); - register_service(&EHMTX::hold_screen, "hold_screen"); + register_service(&EHMTX::hold_screen, "hold_screen", {"time"}); register_service(&EHMTX::hide_indicator, "hide_indicator"); register_service(&EHMTX::hide_gauge, "hide_gauge"); register_service(&EHMTX::hide_alarm, "hide_alarm"); @@ -385,9 +386,10 @@ namespace esphome this->next_action_time = this->clock->now().timestamp - 1; } - void EHMTX::hold_screen() + void EHMTX::hold_screen(int time) { this->next_action_time += this->hold_time; + this->hold_time = time; } void EHMTX::get_status() @@ -765,11 +767,6 @@ namespace esphome this->clock_time = t; } - void EHMTX::set_hold_time(uint16_t t) - { - this->hold_time = t; - } - void EHMTX::set_scroll_count(uint8_t c) { this->scroll_count = c; diff --git a/components/ehmtxv2/EHMTX.h b/components/ehmtxv2/EHMTX.h index e32c1ab..8abf226 100644 --- a/components/ehmtxv2/EHMTX.h +++ b/components/ehmtxv2/EHMTX.h @@ -23,7 +23,7 @@ const uint8_t TEXTSTARTOFFSET = (32 - 8); const uint16_t TICKINTERVAL = 1000; // each 1000ms static const char *const EHMTX_VERSION = "Version: 2023.5.0 beta"; static const char *const TAG = "EHMTXv2"; -enum show_mode : uint8_t { MODE_EMPTY = 0,MODE_BLANK = 1, MODE_CLOCK = 2, MODE_DATE = 3, MODE_FULL_SCREEN = 4, MODE_ICONSCREEN = 5, MODE_TEXT = 6 , MODE_RAINBOW_ICON = 7,MODE_RAINBOW_TEXT = 8, MODE_RAINBOW_CLOCK = 9 }; +enum show_mode : uint8_t { MODE_EMPTY = 0,MODE_BLANK = 1, MODE_CLOCK = 2, MODE_DATE = 3, MODE_FULL_SCREEN = 4, MODE_ICONSCREEN = 5, MODE_TEXT = 6 , MODE_RAINBOW_ICON = 7,MODE_RAINBOW_TEXT = 8, MODE_RAINBOW_CLOCK = 9,MODE_RAINBOW_DATE=10 }; namespace esphome { @@ -99,7 +99,7 @@ namespace esphome void get_status(); void queue_status(); void skip_screen(); - void hold_screen(); + void hold_screen(int t=30); void set_display(addressable_light::AddressableLightDisplay *disp); void set_hold_time(uint16_t t=30); diff --git a/components/ehmtxv2/EHMTX_queue.cpp b/components/ehmtxv2/EHMTX_queue.cpp index 32c1173..c3eeec7 100644 --- a/components/ehmtxv2/EHMTX_queue.cpp +++ b/components/ehmtxv2/EHMTX_queue.cpp @@ -52,6 +52,9 @@ namespace esphome case MODE_RAINBOW_CLOCK: ESP_LOGD(TAG, "queue: clock for %d sec", this->screen_time); break; + case MODE_RAINBOW_DATE: + ESP_LOGD(TAG, "queue: date for %d sec", this->screen_time); + break; default: ESP_LOGD(TAG, "queue: UPPS"); break; @@ -141,17 +144,21 @@ namespace esphome this->config_->display->print(15 + xoffset, yoffset, font, this->config_->alarm_color, display::TextAlign::BASELINE_CENTER, "!t!"); } break; + case MODE_RAINBOW_DATE: case MODE_DATE: if (this->config_->clock->now().timestamp > 6000) // valid time { + color_ = (this->mode == MODE_RAINBOW_DATE) ? this->config_->rainbow_color : this->text_color; time_t ts = this->config_->clock->now().timestamp; - this->config_->display->strftime(xoffset + 15, yoffset, font, this->text_color, display::TextAlign::BASELINE_CENTER, this->config_->date_fmt.c_str(), + this->config_->display->strftime(xoffset + 15, yoffset, font, color_, display::TextAlign::BASELINE_CENTER, this->config_->date_fmt.c_str(), this->config_->clock->now()); if ((this->config_->clock->now().second % 2 == 0) && this->config_->show_seconds) { this->config_->display->draw_pixel_at(0, 0, this->config_->clock_color); } - this->config_->draw_day_of_week(); + if (this->mode != MODE_RAINBOW_DATE){ + this->config_->draw_day_of_week(); + } } else { diff --git a/components/ehmtxv2/__init__.py b/components/ehmtxv2/__init__.py index f6a5b06..6d5bbe9 100644 --- a/components/ehmtxv2/__init__.py +++ b/components/ehmtxv2/__init__.py @@ -59,7 +59,6 @@ CONF_ICONS = "icons" CONF_SHOWDOW = "show_dow" CONF_SHOWDATE = "show_date" CONF_FRAMEDURATION = "frame_duration" -CONF_HOLD_TIME = "hold_time" CONF_SCROLLCOUNT = "scroll_count" CONF_MATRIXCOMPONENT = "matrix_component" CONF_HTML = "icons2html" @@ -127,9 +126,6 @@ EHMTX_SCHEMA = cv.Schema({ cv.Optional( CONF_special_FONT_YOFFSET, default="6" ): cv.templatable(cv.int_range(min=-32, max=32)), - cv.Optional( - CONF_HOLD_TIME, default="20" - ): cv.templatable(cv.int_range(min=0, max=3600)), cv.Optional(CONF_SCROLLINTERVAL, default="80" ): cv.templatable(cv.positive_int), cv.Optional(CONF_RAINBOWINTERVAL, default="32" @@ -394,7 +390,6 @@ async def to_code(config): cg.add(var.set_time_format(config[CONF_TIME_FORMAT])) cg.add(var.set_date_format(config[CONF_DATE_FORMAT])) cg.add(var.set_show_day_of_week(config[CONF_SHOWDOW])) - cg.add(var.set_hold_time(config[CONF_HOLD_TIME])) cg.add(var.set_show_date(config[CONF_SHOWDATE])) cg.add(var.set_show_seconds(config[CONF_SHOW_SECONDS])) cg.add(var.set_default_font_offset(config[CONF_DEFAULT_FONT_XOFFSET], config[CONF_DEFAULT_FONT_YOFFSET] )) diff --git a/copy2esphome/ulanzi-easy.yaml b/copy2esphome/ulanzi-easy.yaml index cf45ba9..a890794 100644 --- a/copy2esphome/ulanzi-easy.yaml +++ b/copy2esphome/ulanzi-easy.yaml @@ -222,7 +222,6 @@ display: ehmtxv2: id: rgb8x32 - hold_time: 30 icons2html: true default_font_yoffset: 6 matrix_component: ehmtx_display diff --git a/images/events.png b/images/events.png new file mode 100644 index 0000000000000000000000000000000000000000..43bb5f843801d3da47b1d955853fd81b88770b40 GIT binary patch literal 26616 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

=wV$8o~e+`&{ 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 literal 0 HcmV?d00001 From 28fc122c3205d388a8de1db874b3932e85dd1085 Mon Sep 17 00:00:00 2001 From: LuBeDa Date: Sun, 30 Apr 2023 20:05:11 +0200 Subject: [PATCH 07/12] templates --- copy2esphome/ehtmxv2-template.yaml | 110 +++++++++++++++++++++++++++++ copy2esphome/ulanzi-easy.yaml | 10 +-- 2 files changed, 113 insertions(+), 7 deletions(-) create mode 100644 copy2esphome/ehtmxv2-template.yaml diff --git a/copy2esphome/ehtmxv2-template.yaml b/copy2esphome/ehtmxv2-template.yaml new file mode 100644 index 0000000..9ba87bb --- /dev/null +++ b/copy2esphome/ehtmxv2-template.yaml @@ -0,0 +1,110 @@ +substitutions: + devicename: ehmtxv2 + friendly_name: LED Matrix + board: esp32dev + matrix_pin: GPIO32 + +external_components: + - source: + type: git + url: https://github.com/lubeda/EspHoMaTriXv2 + ref: release + refresh: 60s + components: [ ehmtxv2 ] + +esphome: + comment: "EHMTXv2 from LuBeDa" + name: $devicename + +esp32: + board: esp32dev + +font: + - file: EHMTXv2.ttf + size: 16 + id: default_font + glyphs: | + !?"%()+*=,-_.:°0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZ abcdefghijklmnÖÄÜöäüopqrstuvwxyz@<>ß§€/ + +binary_sensor: + - platform: status + name: "$devicename Status" + +logger: + level: WARN + +api: + +sensor: + +ota: + password: !secret ota_password + +wifi: + ssid: !secret wifi_ssid + password: !secret wifi_password + +web_server: + +light: + - platform: neopixelbus + id: ehmtx_light + type: GRB + internal: true + variant: WS2812 + pin: $ledpin + num_leds: 256 + color_correct: [30%, 30%, 30%] + gamma_correct: 2.0 + name: "$devicename Light" + restore_mode: ALWAYS_OFF + +time: + - platform: homeassistant + id: ehmtx_time + +display: + - platform: addressable_light + id: ehmtx_display + addressable_light_id: ehmtx_light + width: 32 + height: 8 + pixel_mapper: |- + if (y % 2 == 0) { + return (y * 32) + x; + } + return (y * 32) + (31 - x); + rotation: 0° + update_interval: 16ms + auto_clear_enabled: true + lambda: |- + id(rgb8x32)->tick(); + id(rgb8x32)->draw(); + +ehmtxv2: + id: rgb8x32 + icons2html: true + matrix_component: ehmtx_display + time_component: ehmtx_time + time_format: "%H:%M" + date_format: "%d.%m." + show_seconds: false + default_font_id: default_font + special_font_id: default_font + icons: + - id: error + lameid: 40530 + - id: home_assistant + lameid: 47693 + - id: temperature + lameid: 2056 + - id: lightbulb + lameid: 1762 + - id: music + lameid: 45625 + - id: phone + lameid: 1232 + - id: car + lameid: 2819 + - id: sleep8x32 + url: https://user-images.githubusercontent.com/16407309/224850723-634c9b2d-55d9-44f2-9f93-765c0485b090.gif diff --git a/copy2esphome/ulanzi-easy.yaml b/copy2esphome/ulanzi-easy.yaml index a890794..d8ebdc0 100644 --- a/copy2esphome/ulanzi-easy.yaml +++ b/copy2esphome/ulanzi-easy.yaml @@ -1,5 +1,5 @@ substitutions: - devicename: ulanzi-simple + devicename: ledpin: GPIO32 buzzerpin: GPIO15 friendly_name: LED Matrix @@ -55,7 +55,7 @@ external_components: url: https://github.com/lubeda/EspHoMaTriXv2 ref: release refresh: 60s - components: [ ehmtx ] + components: [ ehmtxv2 ] esphome: comment: "EHMTXv2 from LuBeDa" @@ -223,17 +223,13 @@ display: ehmtxv2: id: rgb8x32 icons2html: true - default_font_yoffset: 6 matrix_component: ehmtx_display time_component: ehmtx_time time_format: "%H:%M" date_format: "%d.%m." show_seconds: false default_font_id: default_font - special_font_id: default_font # for starters yust one font - - # used in blueprints - # "error","home_assistant","temperature","lightbulb","music","phone","car","sleep8x32" + special_font_id: default_font icons: - id: error lameid: 40530 From 10567cb3e12e8f4c396bbf85eeabe58b8b41e08c Mon Sep 17 00:00:00 2001 From: LuBeDa Date: Mon, 1 May 2023 13:17:00 +0200 Subject: [PATCH 08/12] almost there --- README.md | 7 +- components/ehmtxv2/EHMTX.cpp | 112 ++++++++++------------------ components/ehmtxv2/EHMTX.h | 10 ++- components/ehmtxv2/EHMTX_queue.cpp | 58 ++++++++++++-- copy2esphome/EHMTX_easy_delete.yaml | 4 +- 5 files changed, 104 insertions(+), 87 deletions(-) diff --git a/README.md b/README.md index ffb4a5f..446e597 100644 --- a/README.md +++ b/README.md @@ -462,15 +462,16 @@ ehmtxv2: time_component: ehmtx_time icons2html: true default_font_id: default_font + default_font_yoffset: 6 special_font_id: special_font special_font_yoffset: 7 - default_font_yoffset: 6 brightness: 80 # percent time_format: "%H:%M" date_format: "%d.%m." week_start_monday: true # false equals sunday scroll_count: 2 # scroll long text at least two times scroll_interval: 80 # milliseconds + rainbow_interval: 32 # milliseconds frame_interval: 192 # milliseconds icons: ..... @@ -720,8 +721,8 @@ For example, if you have multiple icons named weather_sunny, weather_rain & weat |MODE_CLOCK | 2| | MODE_DATE | 3| | MODE_FULL_SCREEN | 4| -|MODE_ICONSCREEN | 5| -|MODE_TEXT | 6| +|MODE_ICON_SCREEN | 5| +|MODE_TEXT_SCREEN | 6| |MODE_RAINBOW_ICON | 7| |MODE_RAINBOW_TEXT |8| | MODE_RAINBOW_CLOCK | 9| diff --git a/components/ehmtxv2/EHMTX.cpp b/components/ehmtxv2/EHMTX.cpp index e6fa054..8ae8e08 100644 --- a/components/ehmtxv2/EHMTX.cpp +++ b/components/ehmtxv2/EHMTX.cpp @@ -2,7 +2,7 @@ namespace esphome { - EHMTX::EHMTX() : PollingComponent(TICKINTERVAL) + EHMTX::EHMTX() : PollingComponent(POLLINGINTERVAL) { this->show_display = true; this->display_gauge = false; @@ -176,13 +176,19 @@ namespace esphome register_service(&EHMTX::full_screen, "full_screen", {"icon_name", "lifetime", "screen_time"}); register_service(&EHMTX::icon_screen, "icon_screen", {"icon_name", "text", "lifetime", "screen_time", "default_font", "r", "g", "b"}); + register_service(&EHMTX::rainbow_icon_screen, "rainbow_icon_screen", {"icon_name", "text", "lifetime", "screen_time", "default_font"}); + register_service(&EHMTX::text_screen, "text_screen", {"text", "lifetime", "screen_time", "default_font", "r", "g", "b"}); + register_service(&EHMTX::rainbow_text_screen, "rainbow_text_screen", {"text", "lifetime", "screen_time", "default_font"}); + register_service(&EHMTX::clock_screen, "clock_screen", {"lifetime", "screen_time", "default_font", "r", "g", "b"}); register_service(&EHMTX::rainbow_clock_screen, "rainbow_clock_screen", {"lifetime", "screen_time", "default_font"}); - register_service(&EHMTX::blank_screen, "blank_screen", {"lifetime", "screen_time"}); + register_service(&EHMTX::date_screen, "date_screen", {"lifetime", "screen_time", "default_font", "r", "g", "b"}); - register_service(&EHMTX::rainbow_icon_screen, "rainbow_icon_screen", {"icon_name", "text", "lifetime", "screen_time", "default_font"}); - register_service(&EHMTX::rainbow_text_screen, "rainbow_text_screen", {"text", "lifetime", "screen_time", "default_font"}); + register_service(&EHMTX::rainbow_date_screen, "rainbow_date_screen", {"lifetime", "screen_time", "default_font"}); + + register_service(&EHMTX::blank_screen, "blank_screen", {"lifetime", "screen_time"}); + register_service(&EHMTX::set_brightness, "brightness", {"value"}); ESP_LOGD(TAG, "Setup and running!"); @@ -215,7 +221,7 @@ namespace esphome void EHMTX::update() // called from polling component { - if (! this->is_running){ + if (!this->is_running){ if (this->clock->now().timestamp > 6000) { ESP_LOGD(TAG, "time sync => starting"); this->is_running = true; @@ -236,7 +242,7 @@ namespace esphome if (this->queue[i]->mode == mode) { bool force = true; - if ((mode == MODE_ICONSCREEN) || (mode == MODE_FULL_SCREEN) || (mode == MODE_RAINBOW_ICON)) + if ((mode == MODE_ICON_SCREEN) || (mode == MODE_FULL_SCREEN) || (mode == MODE_RAINBOW_ICON)) { if (strcmp(this->queue[i]->icon_name.c_str(), icon_name.c_str()) != 0) { @@ -303,12 +309,12 @@ namespace esphome case MODE_FULL_SCREEN: infotext = "full screen " + this->queue[i]->icon_name; break; - case MODE_ICONSCREEN: + case MODE_ICON_SCREEN: case MODE_RAINBOW_ICON: infotext = this->queue[i]->icon_name.c_str(); break; case MODE_RAINBOW_TEXT: - case MODE_TEXT: + case MODE_TEXT_SCREEN: infotext = "TEXT"; break; default: @@ -461,7 +467,7 @@ namespace esphome { bool force = true; ESP_LOGW(TAG, "del_screen: icon %s in position: %d mode %d", icon_name.c_str(), i, mode); - if ((mode == MODE_ICONSCREEN) || (mode == MODE_FULL_SCREEN) || (mode == MODE_RAINBOW_ICON)) + if ((mode == MODE_ICON_SCREEN) || (mode == MODE_FULL_SCREEN) || (mode == MODE_RAINBOW_ICON)) { if (strcmp(this->queue[i]->icon_name.c_str(), icon_name.c_str()) != 0) { @@ -505,7 +511,7 @@ namespace esphome screen->set_text(text, icon, w, lifetime, screen_time); screen->text_color = Color(r, g, b); screen->default_font = default_font; - screen->mode = MODE_ICONSCREEN; + screen->mode = MODE_ICON_SCREEN; screen->icon_name = iconname; ESP_LOGD(TAG, "icon screen icon: %d iconname: %s text: %s lifetime: %d screen_time: %d", icon, iconname.c_str(), text.c_str(), lifetime, screen_time); screen->status(); @@ -523,6 +529,19 @@ namespace esphome screen->status(); } + void EHMTX::rainbow_date_screen(int lifetime, int screen_time, bool default_font) + { + EHMTX_queue *screen = this->find_free_queue_element(); + + ESP_LOGD(TAG, "rainbow_date_screen lifetime: %d screen_time: %d", lifetime, screen_time); + screen->mode = MODE_RAINBOW_DATE; + screen->default_font = default_font; + screen->screen_time = screen_time; + screen->endtime = this->clock->now().timestamp + lifetime * 60; + screen->status(); + } + + void EHMTX::rainbow_icon_screen(std::string iconname, std::string text, int lifetime, int screen_time, bool default_font) { @@ -534,22 +553,13 @@ namespace esphome icon = 0; } EHMTX_queue *screen = this->find_icon_queue_element(icon); - - int x, y, w, h; - if (default_font) - { - this->display->get_text_bounds(0, 0, text.c_str(), this->default_font, display::TextAlign::LEFT, &x, &y, &w, &h); - } - else - { - this->display->get_text_bounds(0, 0, text.c_str(), this->special_font, display::TextAlign::LEFT, &x, &y, &w, &h); - } - screen->set_text(text, icon, w, lifetime, screen_time); - screen->default_font = default_font; + screen->icon_name = iconname; screen->text = text; - screen->pixels_ = w; + screen->endtime = this->clock->now().timestamp + lifetime * 60; + screen->screen_time = screen_time; + screen->default_font = default_font; screen->mode = MODE_RAINBOW_ICON; - screen->icon_name = iconname; + screen->calc_scroll_time(); ESP_LOGD(TAG, "rainbow_icon_screen icon: %d iconname: %s text: %s lifetime: %d screen_time: %d", icon, iconname.c_str(), text.c_str(), lifetime, screen_time); screen->status(); } @@ -558,33 +568,13 @@ namespace esphome { EHMTX_queue *screen = this->find_free_queue_element(); - int x, y, w, h; - if (default_font) - { - this->display->get_text_bounds(0, 0, text.c_str(), this->default_font, display::TextAlign::LEFT, &x, &y, &w, &h); - } - else - { - this->display->get_text_bounds(0, 0, text.c_str(), this->special_font, display::TextAlign::LEFT, &x, &y, &w, &h); - } - screen->text = text; - screen->pixels_ = w; - if (screen->pixels_ < 32) - { - screen->centerx_ = ceil((32 - screen->pixels_) / 2); - } - - screen->shiftx_ = 0; - float display_duration = ceil((this->scroll_count * w * this->scroll_interval) / 1000); - screen->screen_time = (display_duration > screen_time) ? display_duration : screen_time; - ESP_LOGD(TAG, "text_screen text: text: %s pixels %d screen_time: %d lifetime: %d", text.c_str(), w, screen->screen_time, lifetime); screen->endtime = this->clock->now().timestamp + lifetime * 60; - - screen->text_color = Color(r, g, b); + screen->screen_time = screen_time; screen->default_font = default_font; - screen->mode = MODE_TEXT; - + screen->text_color = Color(r, g, b); + screen->mode = MODE_TEXT_SCREEN; + screen->calc_scroll_time(); screen->status(); } @@ -592,32 +582,12 @@ namespace esphome { EHMTX_queue *screen = this->find_free_queue_element(); - int x, y, w, h; - if (default_font) - { - this->display->get_text_bounds(0, 0, text.c_str(), this->default_font, display::TextAlign::LEFT, &x, &y, &w, &h); - } - else - { - this->display->get_text_bounds(0, 0, text.c_str(), this->special_font, display::TextAlign::LEFT, &x, &y, &w, &h); - } - screen->text = text; - screen->pixels_ = w; - if (screen->pixels_ < 32) - { - screen->centerx_ = ceil((32 - screen->pixels_) / 2); - } - - screen->shiftx_ = 0; - float display_duration = ceil((this->scroll_count * w * this->scroll_interval) / 1000); - screen->screen_time = (display_duration > screen_time) ? display_duration : screen_time; - ESP_LOGD(TAG, "text_screen text: text: %s pixels %d screen_time: %d lifetime: %d", text.c_str(), w, screen->screen_time, lifetime); screen->endtime = this->clock->now().timestamp + lifetime * 60; - + screen->screen_time = screen_time; screen->default_font = default_font; screen->mode = MODE_RAINBOW_TEXT; - + screen->calc_scroll_time(); screen->status(); } @@ -671,7 +641,7 @@ namespace esphome { for (size_t i = 0; i < MAXQUEUE; i++) { - if ((this->queue[i]->mode == MODE_ICONSCREEN) && (this->queue[i]->icon == icon)) + if ((this->queue[i]->mode == MODE_ICON_SCREEN) && (this->queue[i]->icon == icon)) { ESP_LOGD(TAG, "free_screen: found by icon"); return this->queue[i]; diff --git a/components/ehmtxv2/EHMTX.h b/components/ehmtxv2/EHMTX.h index 8abf226..1da158b 100644 --- a/components/ehmtxv2/EHMTX.h +++ b/components/ehmtxv2/EHMTX.h @@ -20,10 +20,10 @@ const uint8_t MAXICONS = 90; const uint8_t TEXTSCROLLSTART = 8; const uint8_t TEXTSTARTOFFSET = (32 - 8); -const uint16_t TICKINTERVAL = 1000; // each 1000ms +const uint16_t POLLINGINTERVAL = 800; static const char *const EHMTX_VERSION = "Version: 2023.5.0 beta"; static const char *const TAG = "EHMTXv2"; -enum show_mode : uint8_t { MODE_EMPTY = 0,MODE_BLANK = 1, MODE_CLOCK = 2, MODE_DATE = 3, MODE_FULL_SCREEN = 4, MODE_ICONSCREEN = 5, MODE_TEXT = 6 , MODE_RAINBOW_ICON = 7,MODE_RAINBOW_TEXT = 8, MODE_RAINBOW_CLOCK = 9,MODE_RAINBOW_DATE=10 }; +enum show_mode : uint8_t { MODE_EMPTY = 0,MODE_BLANK = 1, MODE_CLOCK = 2, MODE_DATE = 3, MODE_FULL_SCREEN = 4, MODE_ICON_SCREEN = 5, MODE_TEXT_SCREEN = 6 , MODE_RAINBOW_ICON = 7,MODE_RAINBOW_TEXT = 8, MODE_RAINBOW_CLOCK = 9,MODE_RAINBOW_DATE=10 }; namespace esphome { @@ -69,7 +69,7 @@ namespace esphome void remove_expired_queue_element(); uint8_t find_oldest_queue_element(); uint8_t find_icon_in_queue(std::string); - void force_screen(std::string name,int mode=MODE_ICONSCREEN); + void force_screen(std::string name,int mode=MODE_ICON_SCREEN); EHMTX_Icon *icons[MAXICONS]; EHMTX_queue *queue[MAXQUEUE]; void add_icon(EHMTX_Icon *icon); @@ -142,7 +142,8 @@ namespace esphome void rainbow_icon_screen(std::string icon_name, std::string text, int lifetime=D_LIFETIME, int screen_time=D_SCREEN_TIME, bool default_font=true); void rainbow_text_screen(std::string text, int lifetime=D_LIFETIME, int screen_time=D_SCREEN_TIME, bool default_font=true); void rainbow_clock_screen(int lifetime=D_LIFETIME, int screen_time=D_SCREEN_TIME, bool default_font=true); - void del_screen(std::string icon, int mode=MODE_ICONSCREEN); + void rainbow_date_screen(int lifetime=D_LIFETIME, int screen_time=D_SCREEN_TIME, bool default_font=true); + void del_screen(std::string icon, int mode=MODE_ICON_SCREEN); void draw_gauge(); void draw_alarm(); @@ -186,6 +187,7 @@ namespace esphome void update_screen(); void hold_slot(uint8_t _sec); void set_text(std::string text, uint8_t icon, uint16_t pixel, uint16_t et, uint16_t st); + void calc_scroll_time(); }; class EHMTXNextScreenTrigger : public Trigger diff --git a/components/ehmtxv2/EHMTX_queue.cpp b/components/ehmtxv2/EHMTX_queue.cpp index c3eeec7..143c643 100644 --- a/components/ehmtxv2/EHMTX_queue.cpp +++ b/components/ehmtxv2/EHMTX_queue.cpp @@ -37,10 +37,10 @@ namespace esphome case MODE_FULL_SCREEN: ESP_LOGD(TAG, "queue: full screen: %s for %d sec", this->icon_name.c_str(), this->screen_time); break; - case MODE_ICONSCREEN: + case MODE_ICON_SCREEN: ESP_LOGD(TAG, "queue: icon screen: %s text: %s for %d sec", this->icon_name.c_str(), this->text.c_str(), this->screen_time); break; - case MODE_TEXT: + case MODE_TEXT_SCREEN: ESP_LOGD(TAG, "queue: text text: %s for %d sec", this->text.c_str(), this->screen_time); break; case MODE_RAINBOW_ICON: @@ -76,7 +76,7 @@ namespace esphome this->config_->last_rainbow_time = millis(); } - if ((this->mode == MODE_ICONSCREEN) || (this->mode == MODE_RAINBOW_ICON)) + if ((this->mode == MODE_ICON_SCREEN) || (this->mode == MODE_RAINBOW_ICON)) { if (millis() - this->config_->last_scroll_time >= this->config_->scroll_interval && this->pixels_ > TEXTSTARTOFFSET) { @@ -88,7 +88,7 @@ namespace esphome this->config_->last_scroll_time = millis(); } } - if ((this->mode == MODE_TEXT) || (this->mode == MODE_RAINBOW_TEXT)) + if ((this->mode == MODE_TEXT_SCREEN) || (this->mode == MODE_RAINBOW_TEXT)) { if (millis() - this->config_->last_scroll_time >= this->config_->scroll_interval && this->pixels_ >= 32) { @@ -154,7 +154,7 @@ namespace esphome this->config_->clock->now()); if ((this->config_->clock->now().second % 2 == 0) && this->config_->show_seconds) { - this->config_->display->draw_pixel_at(0, 0, this->config_->clock_color); + this->config_->display->draw_pixel_at(0, 0, color_); } if (this->mode != MODE_RAINBOW_DATE){ this->config_->draw_day_of_week(); @@ -168,7 +168,7 @@ namespace esphome case MODE_FULL_SCREEN: this->config_->display->image(0, 0, this->config_->icons[this->icon]); break; - case MODE_ICONSCREEN: + case MODE_ICON_SCREEN: case MODE_RAINBOW_ICON: { if (this->pixels_ > TEXTSTARTOFFSET) @@ -196,7 +196,7 @@ namespace esphome } } break; - case MODE_TEXT: + case MODE_TEXT_SCREEN: case MODE_RAINBOW_TEXT: if (this->pixels_ > 32) @@ -242,4 +242,48 @@ namespace esphome this->endtime = this->config_->clock->now().timestamp + et * 60; this->icon = icon; } + + void EHMTX_queue::calc_scroll_time() + { + int x, y, w, h; + float display_duration; + if (this->default_font) + { + this->config_->display->get_text_bounds(0, 0, text.c_str(), this->config_->default_font, display::TextAlign::LEFT, &x, &y, &w, &h); + } + else + { + this->config_->display->get_text_bounds(0, 0, text.c_str(), this->config_->special_font, display::TextAlign::LEFT, &x, &y, &w, &h); + } + + this->pixels_ = w; + this->shiftx_ = 0; + + switch (this->mode) + { + case MODE_RAINBOW_TEXT: + case MODE_TEXT_SCREEN: + display_duration = ceil((28+(this->config_->scroll_count * (32 + this->pixels_)) * this->config_->scroll_interval) / 1000); + this->screen_time = (display_duration > this->screen_time) ? display_duration : this->screen_time; + if (this->pixels_ < 32) + { + this->centerx_ = ceil((32 - this->pixels_) / 2); + } + break; + case MODE_RAINBOW_ICON: + case MODE_ICON_SCREEN: + display_duration = ceil(((28-TEXTSTARTOFFSET)+(this->config_->scroll_count * (TEXTSTARTOFFSET + this->pixels_)) * this->config_->scroll_interval) / 1000); + this->screen_time = (display_duration > this->screen_time) ? display_duration : this->screen_time; + if (this->pixels_ < 23) + { + this->centerx_ = ceil((23 - this->pixels_) / 2); + } + break; + default: + break; + } + + this->shiftx_ = 0; + ESP_LOGD(TAG, "display text: %s pixels %d calculated: %d", text.c_str(), this->pixels_, this->screen_time); + } } diff --git a/copy2esphome/EHMTX_easy_delete.yaml b/copy2esphome/EHMTX_easy_delete.yaml index e16d3e9..0fcdedf 100644 --- a/copy2esphome/EHMTX_easy_delete.yaml +++ b/copy2esphome/EHMTX_easy_delete.yaml @@ -22,7 +22,7 @@ blueprint: custom_value: true mode: dropdown options: - - label: MODE_ICONSCREEN + - label: MODE_ICON_SCREEN value: "5" - label: MODE_BLANK value: "1" @@ -32,7 +32,7 @@ blueprint: value: "3" - label: MODE_FULL_SCREEN value: "4" - - label: MODE_TEXT + - label: MODE_TEXT_SCREEN value: "6" - label: MODE_RAINBOW_ICON value: "7" From b3f6e143c4b703b2a03a6d874878b9b41ea5ab03 Mon Sep 17 00:00:00 2001 From: LuBeDa Date: Mon, 1 May 2023 13:19:42 +0200 Subject: [PATCH 09/12] docu --- README.md | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/README.md b/README.md index 446e597..cb31ce9 100644 --- a/README.md +++ b/README.md @@ -540,11 +540,12 @@ See [icon details](#icons-and-animations) ## Control your display -A lot of features are accessible with actions, you can use in your YAML. +A lot of features are accessible with services from home assistant and lambdas you can use in your YAML. ### Public functions/services + |service|parameter|result| - |---|---|---|---| + |---|---|---| `status`|none|write some status information to the esphome logs| `display_on`|none|turn display off| `display_off`|none|turn display on| From a4f22f708d5dfa3062692a564bf9a1e540360621 Mon Sep 17 00:00:00 2001 From: LuBeDa Date: Mon, 1 May 2023 13:21:02 +0200 Subject: [PATCH 10/12] docu --- README.md | 56 +++++++++++++++++++++++++++---------------------------- 1 file changed, 28 insertions(+), 28 deletions(-) diff --git a/README.md b/README.md index cb31ce9..a3956b4 100644 --- a/README.md +++ b/README.md @@ -546,34 +546,34 @@ A lot of features are accessible with services from home assistant and lambdas y |service|parameter|result| |---|---|---| - `status`|none|write some status information to the esphome logs| - `display_on`|none|turn display off| - `display_off`|none|turn display on| - `hold_screen`|none|show the screen that is currently displayed for the number of seconds longer| - `hide_indicator`|none|hides the indicator| - `hide_gauge`|none|hides the gauge| - `hide_alarm`|none|hides the alarm| - `show_gauge"`|"percent", "r", "g", "b"|set the heught of the gauge according to the percentage in the given color| - `show_alarm`|"r", "g", "b", "size"|shows the color with the given size in the upper right corner| - `show_indicator`|"r", "g", "b", "size"|shows the color with the given size in the lower right corner| - - `clock_color`|"r", "g", "b"|set the default color for the clock/date display| - `today_color"`|"r", "g", "b"|set the special color for today in the day of week line| - `weekday_color"`|"r", "g", "b"|set the default color in the day of week line| - - `del_screen`|"icon_name", "mode"|deletes the specified icon screen from the queue, the [mode](#modes) is a filter| - `force_screen`|"icon_name", "mode"|displayes the seleted the specified icon screen from the queue, the [mode](#modes) is a filter| - - `full_screen`|"icon_name", "lifetime", "screen_time"|show the specified icon as fullscreen| - `icon_screen`|"icon_name", "text", "lifetime", "screen_time", "default_font", "r", "g", "b"|show the specified icon with text| - `rainbow_icon_screen`|"icon_name", "text", "lifetime", "screen_time", "default_font"|show the specified icon with text in rainbow color| - `text_screen`|"text", "lifetime", "screen_time", "default_font", "r", "g", "b"|show the specified text| - `rainbow_text_screen`|"text", "lifetime", "screen_time", "default_font"|show the specified text in rainbow colors| - `clock_screen`|"lifetime", "screen_time", "default_font", "r", "g", "b"|show the clock| - `rainbow_clock_screen`|"lifetime", "screen_time", "default_font"|show the clock in rainbow color| - `blank_screen`|"lifetime", "screen_time"|"show" an empty screen| - `date_screen`|"lifetime", "screen_time", "default_font", "r", "g", "b"|show the date| - `brightness`|"value"|set the display brightness| + |`status`|none|write some status information to the esphome logs| + |`display_on`|none|turn display off| + |`display_off`|none|turn display on| + |`hold_screen`|none|show the screen that is currently displayed for the number of seconds longer| + |`hide_indicator`|none|hides the indicator| + |`hide_gauge`|none|hides the gauge| + |`hide_alarm`|none|hides the alarm| + |`show_gauge"`|"percent", "r", "g", "b"|set the heught of the gauge according to the percentage in the given color| + |`show_alarm`|"r", "g", "b", "size"|shows the color with the given size in the upper right corner| + |`show_indicator`|"r", "g", "b", "size"|shows the color with the given size in the lower right corner| + + |`clock_color`|"r", "g", "b"|set the default color for the clock/date display| + |`today_color"`|"r", "g", "b"|set the special color for today in the day of week line| + |`weekday_color"`|"r", "g", "b"|set the default color in the day of week line| + + |`del_screen`|"icon_name", "mode"|deletes the specified icon screen from the queue, the [mode](#modes) is a filter| + |`force_screen`|"icon_name", "mode"|displayes the seleted the specified icon screen from the queue, the [mode](#modes) is a filter| + + |`full_screen`|"icon_name", "lifetime", "screen_time"|show the specified icon as fullscreen| + |`icon_screen`|"icon_name", "text", "lifetime", "screen_time", "default_font", "r", "g", "b"|show the specified icon with text| + |`rainbow_icon_screen`|"icon_name", "text", "lifetime", "screen_time", "default_font"|show the specified icon with text in rainbow color| + |`text_screen`|"text", "lifetime", "screen_time", "default_font", "r", "g", "b"|show the specified text| + |`rainbow_text_screen`|"text", "lifetime", "screen_time", "default_font"|show the specified text in rainbow colors| + |`clock_screen`|"lifetime", "screen_time", "default_font", "r", "g", "b"|show the clock| + |`rainbow_clock_screen`|"lifetime", "screen_time", "default_font"|show the clock in rainbow color| + |`blank_screen`|"lifetime", "screen_time"|"show" an empty screen| + |`date_screen`|"lifetime", "screen_time", "default_font", "r", "g", "b"|show the date| + |`brightness`|"value"|set the display brightness| ### Local actions/lambdas From e73bdb88e9ebb6e7da8da314ac7910f6c4c869bf Mon Sep 17 00:00:00 2001 From: LuBeDa Date: Mon, 1 May 2023 13:23:16 +0200 Subject: [PATCH 11/12] sdf --- README.md | 59 ++++++++++++++++++++++++++----------------------------- 1 file changed, 28 insertions(+), 31 deletions(-) diff --git a/README.md b/README.md index a3956b4..86f2f55 100644 --- a/README.md +++ b/README.md @@ -543,37 +543,34 @@ See [icon details](#icons-and-animations) A lot of features are accessible with services from home assistant and lambdas you can use in your YAML. ### Public functions/services - - |service|parameter|result| - |---|---|---| - |`status`|none|write some status information to the esphome logs| - |`display_on`|none|turn display off| - |`display_off`|none|turn display on| - |`hold_screen`|none|show the screen that is currently displayed for the number of seconds longer| - |`hide_indicator`|none|hides the indicator| - |`hide_gauge`|none|hides the gauge| - |`hide_alarm`|none|hides the alarm| - |`show_gauge"`|"percent", "r", "g", "b"|set the heught of the gauge according to the percentage in the given color| - |`show_alarm`|"r", "g", "b", "size"|shows the color with the given size in the upper right corner| - |`show_indicator`|"r", "g", "b", "size"|shows the color with the given size in the lower right corner| - - |`clock_color`|"r", "g", "b"|set the default color for the clock/date display| - |`today_color"`|"r", "g", "b"|set the special color for today in the day of week line| - |`weekday_color"`|"r", "g", "b"|set the default color in the day of week line| - - |`del_screen`|"icon_name", "mode"|deletes the specified icon screen from the queue, the [mode](#modes) is a filter| - |`force_screen`|"icon_name", "mode"|displayes the seleted the specified icon screen from the queue, the [mode](#modes) is a filter| - - |`full_screen`|"icon_name", "lifetime", "screen_time"|show the specified icon as fullscreen| - |`icon_screen`|"icon_name", "text", "lifetime", "screen_time", "default_font", "r", "g", "b"|show the specified icon with text| - |`rainbow_icon_screen`|"icon_name", "text", "lifetime", "screen_time", "default_font"|show the specified icon with text in rainbow color| - |`text_screen`|"text", "lifetime", "screen_time", "default_font", "r", "g", "b"|show the specified text| - |`rainbow_text_screen`|"text", "lifetime", "screen_time", "default_font"|show the specified text in rainbow colors| - |`clock_screen`|"lifetime", "screen_time", "default_font", "r", "g", "b"|show the clock| - |`rainbow_clock_screen`|"lifetime", "screen_time", "default_font"|show the clock in rainbow color| - |`blank_screen`|"lifetime", "screen_time"|"show" an empty screen| - |`date_screen`|"lifetime", "screen_time", "default_font", "r", "g", "b"|show the date| - |`brightness`|"value"|set the display brightness| + +|service|parameter|result| +|---|---|---| +|`status`|none|write some status information to the esphome logs| +|`display_on`|none|turn display off| +|`display_off`|none|turn display on| +|`hold_screen`|none|show the screen that is currently displayed for the number of seconds longer| +|`hide_indicator`|none|hides the indicator| +|`hide_gauge`|none|hides the gauge| +|`hide_alarm`|none|hides the alarm| +|`show_gauge"`|"percent", "r", "g", "b"|set the heught of the gauge according to the percentage in the given color| +|`show_alarm`|"r", "g", "b", "size"|shows the color with the given size in the upper right corner| +|`show_indicator`|"r", "g", "b", "size"|shows the color with the given size in the lower right corner| +|`clock_color`|"r", "g", "b"|set the default color for the clock/date display| +|`today_color"`|"r", "g", "b"|set the special color for today in the day of week line| +|`weekday_color"`|"r", "g", "b"|set the default color in the day of week line| +|`del_screen`|"icon_name", "mode"|deletes the specified icon screen from the queue, the [mode](#modes) is a filter| +|`force_screen`|"icon_name", "mode"|displayes the seleted the specified icon screen from the queue, the [mode](#modes) is a filter| +|`full_screen`|"icon_name", "lifetime", "screen_time"|show the specified icon as fullscreen| +|`icon_screen`|"icon_name", "text", "lifetime", "screen_time", "default_font", "r", "g", "b"|show the specified icon with text| +|`rainbow_icon_screen`|"icon_name", "text", "lifetime", "screen_time", "default_font"|show the specified icon with text in rainbow color| +|`text_screen`|"text", "lifetime", "screen_time", "default_font", "r", "g", "b"|show the specified text| +|`rainbow_text_screen`|"text", "lifetime", "screen_time", "default_font"|show the specified text in rainbow colors| +|`clock_screen`|"lifetime", "screen_time", "default_font", "r", "g", "b"|show the clock| +|`rainbow_clock_screen`|"lifetime", "screen_time", "default_font"|show the clock in rainbow color| +|`blank_screen`|"lifetime", "screen_time"|"show" an empty screen| +|`date_screen`|"lifetime", "screen_time", "default_font", "r", "g", "b"|show the date| +|`brightness`|"value"|set the display brightness| ### Local actions/lambdas From 45603a03d025628b0b4a4102112ad43b78076adf Mon Sep 17 00:00:00 2001 From: LuBeDa Date: Mon, 1 May 2023 15:03:45 +0200 Subject: [PATCH 12/12] docs --- README.md | 7 +++---- 1 file changed, 3 insertions(+), 4 deletions(-) diff --git a/README.md b/README.md index 86f2f55..fbc0a9b 100644 --- a/README.md +++ b/README.md @@ -561,7 +561,7 @@ A lot of features are accessible with services from home assistant and lambdas y |`weekday_color"`|"r", "g", "b"|set the default color in the day of week line| |`del_screen`|"icon_name", "mode"|deletes the specified icon screen from the queue, the [mode](#modes) is a filter| |`force_screen`|"icon_name", "mode"|displayes the seleted the specified icon screen from the queue, the [mode](#modes) is a filter| -|`full_screen`|"icon_name", "lifetime", "screen_time"|show the specified icon as fullscreen| +|`full_screen`|"icon_name", "lifetime", "screen_time"|show the specified 8x32 icon as fullscreen| |`icon_screen`|"icon_name", "text", "lifetime", "screen_time", "default_font", "r", "g", "b"|show the specified icon with text| |`rainbow_icon_screen`|"icon_name", "text", "lifetime", "screen_time", "default_font"|show the specified icon with text in rainbow color| |`text_screen`|"text", "lifetime", "screen_time", "default_font", "r", "g", "b"|show the specified text| @@ -572,7 +572,7 @@ A lot of features are accessible with services from home assistant and lambdas y |`date_screen`|"lifetime", "screen_time", "default_font", "r", "g", "b"|show the date| |`brightness`|"value"|set the display brightness| -### Local actions/lambdas +### Local lambdas #### Add screen to your display queue @@ -596,7 +596,6 @@ sensor: id(rgb8x32)->icon_screen("sun", text); // uses default values for color etc. ``` -#### Set (alarm/clock/gauge/text/today/weekday) color action ##### Force screen @@ -615,7 +614,7 @@ Experienced programmers can use these public methods: ```c ``` -### Local trigger +### Local triggers To use the display without homeassistant automations, you may use the [advanced functionality](#change-configuration-during-runtime) with triggers. The triggers can be fired by sensors, time or by the ehmtx component.