From b3556eb4a703cf3fbd9fdee0f6bfa57a7fed6b65 Mon Sep 17 00:00:00 2001 From: "Andrew J.Swan" Date: Fri, 17 Nov 2023 16:01:30 +0200 Subject: [PATCH 1/3] 2023.9.1-149: Add Icon Prognosis screen --- components/ehmtxv2/EHMTX.cpp | 131 ++++++++++++++++++++++++----- components/ehmtxv2/EHMTX.h | 6 +- components/ehmtxv2/EHMTX_queue.cpp | 22 +++++ components/ehmtxv2/__init__.py | 2 +- 4 files changed, 138 insertions(+), 23 deletions(-) diff --git a/components/ehmtxv2/EHMTX.cpp b/components/ehmtxv2/EHMTX.cpp index 17736821..cd677258 100644 --- a/components/ehmtxv2/EHMTX.cpp +++ b/components/ehmtxv2/EHMTX.cpp @@ -661,6 +661,9 @@ namespace esphome register_service(&EHMTX::icon_screen_progress, "icon_screen_progress", {"icon_name", "text", "progress", "lifetime", "screen_time", "default_font", "r", "g", "b"}); register_service(&EHMTX::set_progressbar_color, "set_progressbar_color", {"icon_name", "mode", "r", "g", "b", "bg_r", "bg_g", "bg_b"}); + register_service(&EHMTX::icon_prognosis_screen, "icon_prognosis_screen", {"icon_name", "text", "prognosis", "lifetime", "screen_time", "default_font"}); + register_service(&EHMTX::icon_prognosis_screen_rgb, "icon_prognosis_screen_rgb", {"icon_name", "text", "prognosis", "lifetime", "screen_time", "default_font", "r", "g", "b"}); + ESP_LOGD(TAG, "Setup and running!"); } @@ -745,15 +748,16 @@ namespace esphome if (this->queue[i]->mode == mode) { bool force = true; - if ((mode == MODE_ICON_SCREEN) || - (mode == MODE_ICON_CLOCK) || - (mode == MODE_ICON_DATE) || - (mode == MODE_FULL_SCREEN) || - (mode == MODE_RAINBOW_ICON) || - (mode == MODE_ICON_PROGRESS) || - (mode == MODE_ICON_TEXT_SCREEN) || - (mode == MODE_RAINBOW_ICON_TEXT_SCREEN) || - (mode == MODE_TEXT_PROGRESS)) + if ( (mode == MODE_ICON_SCREEN) || + (mode == MODE_ICON_CLOCK) || + (mode == MODE_ICON_DATE) || + (mode == MODE_FULL_SCREEN) || + (mode == MODE_RAINBOW_ICON) || + (mode == MODE_ICON_PROGRESS) || + (mode == MODE_ICON_TEXT_SCREEN) || + (mode == MODE_RAINBOW_ICON_TEXT_SCREEN) || + (mode == MODE_TEXT_PROGRESS) || + (mode == MODE_PROGNOSIS_SCREEN) ) { if (strcmp(this->queue[i]->icon_name.c_str(), icon_name.c_str()) != 0) { @@ -910,6 +914,7 @@ namespace esphome case MODE_ICON_TEXT_SCREEN: case MODE_RAINBOW_ICON_TEXT_SCREEN: case MODE_TEXT_PROGRESS: + case MODE_PROGNOSIS_SCREEN: infotext = this->queue[i]->icon_name.c_str(); break; case MODE_RAINBOW_TEXT: @@ -1207,15 +1212,16 @@ namespace esphome { bool force = true; ESP_LOGD(TAG, "del_screen: icon %s in position: %s mode %d", icon_name.c_str(), this->queue[i]->icon_name.c_str(), mode); - if ((mode == MODE_ICON_SCREEN) || - (mode == MODE_ICON_CLOCK) || - (mode == MODE_ICON_DATE) || - (mode == MODE_FULL_SCREEN) || - (mode == MODE_RAINBOW_ICON) || - (mode == MODE_ICON_PROGRESS) || - (mode == MODE_ICON_TEXT_SCREEN) || - (mode == MODE_RAINBOW_ICON_TEXT_SCREEN) || - (mode == MODE_TEXT_PROGRESS)) + if ( (mode == MODE_ICON_SCREEN) || + (mode == MODE_ICON_CLOCK) || + (mode == MODE_ICON_DATE) || + (mode == MODE_FULL_SCREEN) || + (mode == MODE_RAINBOW_ICON) || + (mode == MODE_ICON_PROGRESS) || + (mode == MODE_ICON_TEXT_SCREEN) || + (mode == MODE_RAINBOW_ICON_TEXT_SCREEN) || + (mode == MODE_TEXT_PROGRESS) || + (mode == MODE_PROGNOSIS_SCREEN) ) { if (this->string_has_ending(icon_name, "*")) { @@ -1705,13 +1711,95 @@ namespace esphome screen->status(); } + void EHMTX::icon_prognosis_screen(std::string iconname, std::string text, std::string prognosis, int lifetime, int screen_time, bool default_font) + { + this->icon_prognosis_screen_rgb(iconname, text, prognosis, lifetime, screen_time, default_font, C_BLACK, C_BLACK, C_BLACK); + } + + void EHMTX::icon_prognosis_screen_rgb(std::string iconname, std::string text, std::string prognosis, int lifetime, int screen_time, bool default_font, int r, int g, int b) + { + std::string ic = get_icon_name(iconname); + std::string id = get_screen_id(iconname); + + uint8_t icon = this->find_icon(ic.c_str()); + + if (icon == MAXICONS) + { + ESP_LOGW(TAG, "icon %d/%s not found => default: 0", icon, ic.c_str()); + icon = 0; + for (auto *t : on_icon_error_triggers_) + { + t->process(ic); + } + } + + EHMTX_queue *screen = this->find_mode_icon_queue_element(MODE_PROGNOSIS_SCREEN, id); + + screen->text = text; + screen->text_color = Color(r, g, b); + screen->default_font = default_font; + screen->mode = MODE_PROGNOSIS_SCREEN; + screen->icon_name = id; + screen->icon = icon; + screen->calc_scroll_time(text, screen_time); + screen->endtime = this->get_tick() + (lifetime > 0 ? lifetime * 60000.0 : screen->screen_time_); + + if (screen->sbitmap == NULL) + { + screen->sbitmap = new Color[64]; + } + + const size_t CAPACITY = JSON_ARRAY_SIZE(72); + StaticJsonDocument doc; + deserializeJson(doc, prognosis); + JsonArray array = doc.as(); + // extract the 24 color values + uint8_t red = 0; + uint8_t gre = 0; + uint8_t blu = 0; + + uint16_t i = 0; + for (JsonVariant v : array) + { + if (i % 3 == 0) + { + red = v.as(); + } + if (i % 3 == 1) + { + gre = v.as(); + } + if (i % 3 == 2) + { + blu = v.as(); + + screen->sbitmap[static_cast(i / 3)] = Color(red, gre, blu); + } + + i++; + } + + if (r + g + b == C_BLACK) + { + screen->text_color = screen->sbitmap[0]; + } + + for (auto *t : on_add_screen_triggers_) + { + t->process(screen->icon_name, (uint8_t)screen->mode); + } + ESP_LOGD(TAG, "icon prognosis screen prognosis: %s", prognosis.c_str()); + ESP_LOGD(TAG, "icon prognosis screen icon: %d iconname: %s text: %s prognosis: %d lifetime: %d screen_time: %d", icon, iconname.c_str(), text.c_str(), static_cast(i / 3), lifetime, screen_time); + screen->status(); + } + EHMTX_queue *EHMTX::find_icon_queue_element(uint8_t icon) { for (size_t i = 0; i < MAXQUEUE; i++) { - if ( ((this->queue[i]->mode == MODE_ICON_SCREEN) || - (this->queue[i]->mode == MODE_RAINBOW_ICON) || - (this->queue[i]->mode == MODE_ICON_PROGRESS)) && + if ( ( (this->queue[i]->mode == MODE_ICON_SCREEN) || + (this->queue[i]->mode == MODE_RAINBOW_ICON) || + (this->queue[i]->mode == MODE_ICON_PROGRESS) ) && (this->queue[i]->icon == icon) ) { ESP_LOGD(TAG, "icon_screen: found by icon"); @@ -2132,6 +2220,7 @@ namespace esphome #ifndef EHMTXv2_ALWAYS_SHOW_RLINDICATORS if (this->queue[this->screen_pointer]->mode != MODE_ICON_SCREEN && this->queue[this->screen_pointer]->mode != MODE_RAINBOW_ICON && + this->queue[this->screen_pointer]->mode != MODE_PROGNOSIS_SCREEN && !this->display_gauge) { #endif diff --git a/components/ehmtxv2/EHMTX.h b/components/ehmtxv2/EHMTX.h index d0786653..18fa4871 100644 --- a/components/ehmtxv2/EHMTX.h +++ b/components/ehmtxv2/EHMTX.h @@ -55,7 +55,8 @@ enum show_mode : uint8_t MODE_ICON_TEXT_SCREEN = 21, MODE_RAINBOW_ICON_TEXT_SCREEN = 22, MODE_BITMAP_STACK_SCREEN = 23, - MODE_TEXT_PROGRESS = 24 + MODE_TEXT_PROGRESS = 24, + MODE_PROGNOSIS_SCREEN = 25 }; namespace esphome @@ -222,6 +223,9 @@ namespace esphome void bitmap_stack(std::string icons, int lifetime = D_LIFETIME, int screen_time = D_SCREEN_TIME); + void icon_prognosis_screen(std::string icon, std::string text, std::string prognosis, int lifetime = D_LIFETIME, int screen_time = D_SCREEN_TIME, bool default_font = true); + void icon_prognosis_screen_rgb(std::string icon, std::string text, std::string prognosis, 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 bitmap_screen(std::string text, int lifetime = D_LIFETIME, int screen_time = D_SCREEN_TIME); void color_gauge(std::string text); void bitmap_small(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); diff --git a/components/ehmtxv2/EHMTX_queue.cpp b/components/ehmtxv2/EHMTX_queue.cpp index 703df336..d4617af7 100644 --- a/components/ehmtxv2/EHMTX_queue.cpp +++ b/components/ehmtxv2/EHMTX_queue.cpp @@ -115,6 +115,9 @@ namespace esphome case MODE_ICON_PROGRESS: ESP_LOGD(TAG, "queue: icon progress: \"%s\" text: %s for: %.1f sec", this->icon_name.c_str(), this->text.c_str(), this->screen_time_ / 1000.0); break; + case MODE_PROGNOSIS_SCREEN: + ESP_LOGD(TAG, "queue: icon prognosis screen: \"%s\" text: %s for: %.1f sec", this->icon_name.c_str(), this->text.c_str(), this->screen_time_ / 1000.0); + break; case MODE_TEXT_PROGRESS: ESP_LOGD(TAG, "queue: text progress: \"%s\" text: %s for: %.1f sec", this->icon_name.c_str(), this->text.c_str(), this->screen_time_ / 1000.0); break; @@ -188,6 +191,7 @@ namespace esphome case MODE_ICON_DATE: case MODE_ALERT_SCREEN: case MODE_ICON_PROGRESS: + case MODE_PROGNOSIS_SCREEN: startx = 8; break; case MODE_TEXT_SCREEN: @@ -714,6 +718,7 @@ namespace esphome case MODE_ALERT_SCREEN: case MODE_RAINBOW_ICON: case MODE_ICON_PROGRESS: + case MODE_PROGNOSIS_SCREEN: color_ = (this->mode == MODE_RAINBOW_ICON) ? this->config_->rainbow_color : this->text_color; #ifdef EHMTXv2_USE_RTL this->config_->display->print(this->xpos() + xoffset, yoffset, font, color_, esphome::display::TextAlign::BASELINE_RIGHT, @@ -744,6 +749,22 @@ namespace esphome this->config_->display->line(9, 7, 9 + abs(this->progress) * 22 / 100, 7, color_); } } + else if (this->mode == MODE_PROGNOSIS_SCREEN) + { + if (this->icon != BLANKICON) + { + this->config_->display->line(8, 0, 8, 7, esphome::display::COLOR_OFF); + this->config_->display->image(0, 0, this->config_->icons[this->icon]); + } + + if (this->sbitmap != NULL) + { + for (uint8_t x = 0; x < 24; x++) + { + this->config_->display->draw_pixel_at(8 + x, 7, this->sbitmap[x]); + } + } + } else { if (this->config_->display_gauge) @@ -990,6 +1011,7 @@ namespace esphome case MODE_ICON_SCREEN: case MODE_ALERT_SCREEN: case MODE_ICON_PROGRESS: + case MODE_PROGNOSIS_SCREEN: startx = 8; if (this->pixels_ < 23) { diff --git a/components/ehmtxv2/__init__.py b/components/ehmtxv2/__init__.py index 2a7719bb..768e548d 100644 --- a/components/ehmtxv2/__init__.py +++ b/components/ehmtxv2/__init__.py @@ -252,7 +252,7 @@ def rgb565_888(v565): } ), cv.Optional(CONF_NIGHT_MODE_SCREENS, default=DEFAULT_NIGHT_MODE_SCREENS): cv.All( - cv.ensure_list(cv.one_of(1, 2, 3, 4, 5, 9, 10, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23, 24)), cv.Length(min=1, max=5) + cv.ensure_list(cv.one_of(1, 2, 3, 4, 5, 9, 10, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25)), cv.Length(min=1, max=5) ), cv.Required(CONF_ICONS): cv.All( cv.ensure_list( From d8e52fa4d1026167392aca6bce83f3a667ccad71 Mon Sep 17 00:00:00 2001 From: "Andrew J.Swan" Date: Sun, 19 Nov 2023 17:03:13 +0200 Subject: [PATCH 2/3] 2023.9.1: Change accent color to bright weekday_color --- components/ehmtxv2/EHMTX.cpp | 22 +++++++++++++++++----- 1 file changed, 17 insertions(+), 5 deletions(-) diff --git a/components/ehmtxv2/EHMTX.cpp b/components/ehmtxv2/EHMTX.cpp index 17736821..bfbe3966 100644 --- a/components/ehmtxv2/EHMTX.cpp +++ b/components/ehmtxv2/EHMTX.cpp @@ -1872,11 +1872,21 @@ namespace esphome ESP_LOGD(TAG, "set_clock"); } + #define max3(x,y,z) ( (x) > (y) ? ((x) > (z) ? (x) : (z)) : ((y) > (z) ? (y) : (z)) ) + void EHMTX::draw_day_of_week(bool small) { if (this->show_day_of_week) { auto dow = this->clock->now().day_of_week - 1; // SUN = 0 + + Color accent_color = esphome::display::COLOR_OFF; + if (this->weekday_accent && this->brightness_ < 50) + { + uint8_t max_diff = max3(this->today_color.r, this->today_color.g, this->today_color.b) - max3(this->weekday_color.r, this->weekday_color.g, this->weekday_color.b); + accent_color = this->weekday_color + max_diff; + } + if (! small) { for (uint8_t i = 0; i <= 6; i++) @@ -1889,13 +1899,15 @@ namespace esphome else { this->display->line(2 + i * 4, 7, i * 4 + 4, 7, this->weekday_color); - if (this->weekday_accent && this->brightness_ < 50) + if (accent_color != esphome::display::COLOR_OFF) { - this->display->line(i * 4 + 3, 7, i * 4 + 3, 7, this->today_color); + this->display->line(i * 4 + 3, 7, i * 4 + 3, 7, accent_color); } } } - } else { + } + else + { for (uint8_t i = 0; i <= 6; i++) { if (((!EHMTXv2_WEEK_START) && (dow == i)) || @@ -1906,9 +1918,9 @@ namespace esphome else { this->display->line(10 + i * 3, 7, 11 + i * 3 , 7, this->weekday_color); - if (this->weekday_accent && this->brightness_ < 50) + if (accent_color != esphome::display::COLOR_OFF) { - this->display->line( (i < dow ? 11 : 10) + i * 3, 7, (i < dow ? 11 : 10) + i * 3 , 7, this->today_color); + this->display->line( (i < dow ? 11 : 10) + i * 3, 7, (i < dow ? 11 : 10) + i * 3 , 7, accent_color); } } } From b8257aabc07d251033f5459e3d90da67f9f79c07 Mon Sep 17 00:00:00 2001 From: "Andrew J.Swan" Date: Sun, 19 Nov 2023 17:18:20 +0200 Subject: [PATCH 3/3] 2023.9.1-149: Add Icon Prognosis screen to Readme --- README.md | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/README.md b/README.md index 70088546..d2c2725b 100644 --- a/README.md +++ b/README.md @@ -37,6 +37,7 @@ - Added a screen with the ability to display a progress bar, text, progress value `(-100..100)` - `text_screen_progress(text, value, progress, lifetime, screen_time, default_font, value_color_as_progress, r, g, b)` - Added `set_weekday_accent_on` and `set_weekday_accent_off` Turn on / off small days (accent) of the week when brightness is insufficient. +- Added `icon_prognosis_screen` and `icon_prognosis_screen_rgb` Displays an icon, text, and a prognosis bar consisting of 24 dots of specified colors. https://github.com/lubeda/EspHoMaTriXv2/issues/149 ### EspHoMaTriX 2023.9.0 - Added the ability to display graph as defined in the YAML file @@ -776,6 +777,8 @@ Numerous features are accessible with services from home assistant and lambdas t |`rainbow_icon_text_screen`|"icon_name", "text", "lifetime", "screen_time", "default_font"|show the specified icon with text in rainbow color and scroll icon along with long text| |`bitmap_stack`|"icons", "lifetime", "screen_time"|show or scroll from 1 to 64 icons described in the configuration| |`text_screen_progress`|"text", "value", "progress", "lifetime", "screen_time", "default_font", "value_color_as_progress", "r", "g", "b"|show the specified short text with value and with progress bar on bottom| +|`icon_prognosis_screen`|"icon_name", "text", "prognosis", "lifetime", "screen_time", "default_font"|show an icon, text, and a prognosis bar consisting of 24 dots of specified colors| +|`icon_prognosis_screen_rgb`|"icon_name", "text", "prognosis", "lifetime", "screen_time", "default_font", "r", "g", "b"|show an icon, text, and a prognosis bar consisting of 24 dots of specified colors| #### Parameter description @@ -791,6 +794,7 @@ Numerous features are accessible with services from home assistant and lambdas t - **progress**: сan take a value from -100 to 100, the color of the progress bar is calculated automatically, if no colors are specified in the function `set_progressbar_color`, then if the progress is in the range `0..100`, then `from red to green`, if in the range `-100..0`, then from `green to red`. - **value_color_as_progress**: display the value with the color of the current color on the progress bar - **value**: the brightness 0..255 +- **prognosis**: 24 triplets of digits (72 in total), each triplet, one point on the prognosis bar in the specified color in the triplet color. Like: [200,200,200, ..., 100,100,100] ### Night mode