diff --git a/README.md b/README.md index 10f12f0f..a28caf1a 100644 --- a/README.md +++ b/README.md @@ -21,9 +21,9 @@ - Example for **weekdays**: - `weekdays: "일월화수목금토"` - `weekdays: "НДПНВТСРЧТПТСБ"` - - Added a screen with the ability to display a progress bar, progress value `(-100..100)` - `icon_screen_progress(iconname, text, progress, lifetime, screen_time, default_font, r, g, b)` +- Added `replace_time_date_to:` and `replace_time_date_from:` which allow replacing the system date & time text (anything!) ### EspHoMaTriX 2023.9.0 - Added the ability to display graph as defined in the YAML file @@ -38,7 +38,7 @@ ### EspHoMaTriX 2023.8.0 -A lot of users asked for special behavior, e.g. display date but no time or vice versa. Display nothing at all e.g. during night. I like to implement a lot of the requestes but ist hard to keep the known default behaviour. In this version i will provide a YAML with the default behaviour but there will be less hardcoded by me, instead you have your freedom to do all in your YAML. +A lot of users asked for special behavior, e.g. display date but no time or vice versa. Display nothing at all e.g. during night. I like to implement a lot of the requests but it's hard to keep the known default behaviour. In this version i will provide a YAML with the default behaviour but there will be less hardcoded by me, instead you have your freedom to do all in your YAML. For the old default behavior use this trigger in your YAML: diff --git a/components/ehmtxv2/EHMTX.cpp b/components/ehmtxv2/EHMTX.cpp index a8c409e4..08b0627c 100644 --- a/components/ehmtxv2/EHMTX.cpp +++ b/components/ehmtxv2/EHMTX.cpp @@ -1,5 +1,7 @@ #include "esphome.h" #include +#include +#include namespace esphome { @@ -772,6 +774,59 @@ namespace esphome this->special_font = font; } + void EHMTX::set_replace_time_date_active(bool b) + { + this->replace_time_date_active = b; + if (b) + { + ESP_LOGI(TAG, "replace_time_date on"); + } + else + { + ESP_LOGI(TAG, "replace_time_date off"); + } + } + + std::string EHMTX::replace_time_date(std::string time_date) // Replace Time Date Strings / Trip5 + { + std::string replace_from_string = EHMTXv2_REPLACE_TIME_DATE_FROM; + std::string replace_to_string = EHMTXv2_REPLACE_TIME_DATE_TO; + std::string replace_from_arr[50]; // AM + PM + 7 Days + 12 Months = 21 but 50 to be super-safe + std::string replace_to_arr[50]; + std::string replace_from; + std::string replace_to; + uint16_t replace_arr_n; + if (replace_from_string != "" && replace_to_string != "") + { + std::istringstream iss_from(replace_from_string); + std::vector replace_from_arr; + for(std::string s_from;iss_from>>s_from;) + replace_from_arr.push_back(s_from); + replace_arr_n = replace_from_arr.size(); + std::istringstream iss_to(replace_to_string); + std::vector replace_to_arr; + for(std::string s_to;iss_to>>s_to;) + replace_to_arr.push_back(s_to); + if (replace_to_arr.size() < replace_arr_n) { replace_arr_n = replace_to_arr.size(); } + uint16_t k = 0; + do + { + std::vector data(time_date.begin(), time_date.end()); + std::vector pattern(replace_from_arr[k].begin(), replace_from_arr[k].end()); + std::vector replaceData(replace_to_arr[k].begin(), replace_to_arr[k].end()); + std::vector::iterator itr; + while((itr = std::search(data.begin(), data.end(), pattern.begin(), pattern.end())) != data.end()) + { + data.erase(itr, itr + pattern.size()); + data.insert(itr, replaceData.begin(), replaceData.end()); + } + time_date = std::string(data.begin(), data.end()); + k++; + } while (k < replace_arr_n); + } + return time_date; + } + void EHMTX::del_screen(std::string icon_name, int mode) { for (uint8_t i = 0; i < MAXQUEUE; i++) @@ -1506,7 +1561,6 @@ namespace esphome this->icon_count++; } - void EHMTX::draw_alarm() { if (this->display_alarm > 2) diff --git a/components/ehmtxv2/EHMTX.h b/components/ehmtxv2/EHMTX.h index ad7fc10e..3f670c02 100644 --- a/components/ehmtxv2/EHMTX.h +++ b/components/ehmtxv2/EHMTX.h @@ -168,6 +168,7 @@ namespace esphome #endif void set_default_font(display::BaseFont *font); void set_special_font(display::BaseFont *font); + void show_rindicator(int r = C_RED, int g = C_GREEN, int b = C_BLUE, int s = 3); void show_lindicator(int r = C_RED, int g = C_GREEN, int b = C_BLUE, int s = 3); void set_text_color(int r = C_RED, int g = C_GREEN, int b = C_BLUE); @@ -208,6 +209,9 @@ namespace esphome void draw_rindicator(); void draw_lindicator(); + void set_replace_time_date_active(bool b=false); + bool replace_time_date_active; + std::string replace_time_date(std::string time_date); int GetWeekdayCharCount(); std::string GetWeekdayChar(int position); diff --git a/components/ehmtxv2/EHMTX_queue.cpp b/components/ehmtxv2/EHMTX_queue.cpp index 2427100c..cc06e61a 100644 --- a/components/ehmtxv2/EHMTX_queue.cpp +++ b/components/ehmtxv2/EHMTX_queue.cpp @@ -315,8 +315,15 @@ namespace esphome { color_ = (this->mode == MODE_RAINBOW_CLOCK) ? this->config_->rainbow_color : this->text_color; time_t ts = this->config_->clock->now().timestamp; - this->config_->display->strftime(xoffset + 15, yoffset, font, color_, display::TextAlign::BASELINE_CENTER, EHMTXv2_TIME_FORMAT, - this->config_->clock->now()); + if (this->config_->replace_time_date_active) // check for replace active + { + std::string time_new = this->config_->clock->now().strftime(EHMTXv2_TIME_FORMAT).c_str(); + time_new = this->config_->replace_time_date(time_new); + this->config_->display->printf(xoffset + 15, yoffset, font, color_, display::TextAlign::BASELINE_CENTER, "%s", time_new.c_str()); + } else { + this->config_->display->strftime(xoffset + 15, yoffset, font, color_, display::TextAlign::BASELINE_CENTER, EHMTXv2_TIME_FORMAT, + this->config_->clock->now()); + } if ((this->config_->clock->now().second % 2 == 0) && this->config_->show_seconds) { this->config_->display->draw_pixel_at(0, 0, color_); @@ -338,8 +345,15 @@ namespace esphome { 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, color_, display::TextAlign::BASELINE_CENTER, EHMTXv2_DATE_FORMAT, - this->config_->clock->now()); + if (this->config_->replace_time_date_active) // check for replace active + { + std::string time_new = this->config_->clock->now().strftime(EHMTXv2_DATE_FORMAT).c_str(); + time_new = this->config_->replace_time_date(time_new); + this->config_->display->printf(xoffset + 15, yoffset, font, color_, display::TextAlign::BASELINE_CENTER, "%s", time_new.c_str()); + } else { + this->config_->display->strftime(xoffset + 15, yoffset, font, color_, display::TextAlign::BASELINE_CENTER, EHMTXv2_DATE_FORMAT, + this->config_->clock->now()); + } if ((this->config_->clock->now().second % 2 == 0) && this->config_->show_seconds) { this->config_->display->draw_pixel_at(0, 0, color_); @@ -367,13 +381,27 @@ namespace esphome time_t ts = this->config_->clock->now().timestamp; if (this->mode == MODE_ICON_CLOCK) { - this->config_->display->strftime(xoffset + 19, yoffset, font, color_, display::TextAlign::BASELINE_CENTER, EHMTXv2_TIME_FORMAT, - this->config_->clock->now()); + if (this->config_->replace_time_date_active) // check for replace active + { + std::string time_new = this->config_->clock->now().strftime(EHMTXv2_TIME_FORMAT).c_str(); + time_new = this->config_->replace_time_date(time_new); + this->config_->display->printf(xoffset + 15, yoffset, font, color_, display::TextAlign::BASELINE_CENTER, "%s", time_new.c_str()); + } else { + this->config_->display->strftime(xoffset + 19, yoffset, font, color_, display::TextAlign::BASELINE_CENTER, EHMTXv2_TIME_FORMAT, + this->config_->clock->now()); + } } else { - this->config_->display->strftime(xoffset + 19, yoffset, font, color_, display::TextAlign::BASELINE_CENTER, EHMTXv2_DATE_FORMAT, - this->config_->clock->now()); + if (this->config_->replace_time_date_active) // check for replace active + { + std::string time_new = this->config_->clock->now().strftime(EHMTXv2_DATE_FORMAT).c_str(); + time_new = this->config_->replace_time_date(time_new); + this->config_->display->printf(xoffset + 15, yoffset, font, color_, display::TextAlign::BASELINE_CENTER, "%s", time_new.c_str()); + } else { + this->config_->display->strftime(xoffset + 19, yoffset, font, color_, display::TextAlign::BASELINE_CENTER, EHMTXv2_DATE_FORMAT, + this->config_->clock->now()); + } } this->config_->display->image(0, 0, this->config_->icons[this->icon]); this->config_->draw_day_of_week(true); @@ -699,4 +727,7 @@ namespace esphome ESP_LOGD(TAG, "calc_scroll_time: mode: %d text: \"%s\" pixels %d calculated: %d defined: %d max_steps: %d", this->mode, text.c_str(), this->pixels_, this->screen_time_, screen_time, this->scroll_reset); } + } + + diff --git a/components/ehmtxv2/__init__.py b/components/ehmtxv2/__init__.py index 5806d51e..c1a05351 100644 --- a/components/ehmtxv2/__init__.py +++ b/components/ehmtxv2/__init__.py @@ -109,6 +109,8 @@ def rgb565_888(v565): CONF_ON_ICON_ERROR = "on_icon_error" CONF_ON_ADD_SCREEN = "on_add_screen" CONF_WEEKDAYTEXT = "weekdays" +CONF_REPLACE_TIME_DATE_FROM = "replace_time_date_from" +CONF_REPLACE_TIME_DATE_TO = "replace_time_date_to" CONF_ON_EXPIRED_SCREEN= "on_expired_screen" CONF_SHOW_SECONDS = "show_seconds" CONF_SCROLL_SMALL_TEXT = "scroll_small_text" @@ -151,6 +153,12 @@ def rgb565_888(v565): cv.Optional( CONF_WEEKDAYTEXT, default="SOMODIMIDOFRSA" ): cv.string, + cv.Optional( + CONF_REPLACE_TIME_DATE_FROM, default="" + ): cv.string, + cv.Optional( + CONF_REPLACE_TIME_DATE_TO, default="" + ): cv.string, cv.Optional( CONF_ALWAYS_SHOW_RLINDICATORS, default=False ): cv.boolean, @@ -430,6 +438,27 @@ def thumbnails(frames): if config[CONF_WEEKDAYTEXT]: cg.add_define("EHMTXv2_WEEKDAYTEXT",config[CONF_WEEKDAYTEXT]) + cg.add_define("EHMTXv2_REPLACE_TIME_DATE_TO",config[CONF_REPLACE_TIME_DATE_TO]) + cg.add_define("EHMTXv2_REPLACE_TIME_DATE_FROM",config[CONF_REPLACE_TIME_DATE_FROM]) + + if config[CONF_REPLACE_TIME_DATE_FROM] and config[CONF_REPLACE_TIME_DATE_TO]: + if (len(config[CONF_REPLACE_TIME_DATE_FROM].split())) != (len(config[CONF_REPLACE_TIME_DATE_TO].split())): + logging.warning(f"replace_time_date_from: and replace_time_date_to: do not have matching pairs! (not using replacements)\n\r") + cg.add(var.set_replace_time_date_active(False)) + else: + if (len(config[CONF_REPLACE_TIME_DATE_FROM].split())) > 50: + logging.warning(f"replace_time_date_from: and replace_time_date_to: exceeds 30! (not using replacements)\n\r") + cg.add(var.set_replace_time_date_active(False)) + else: + logging.info(f"replace_time_date_from: and replace_time_date_to: defined (using replacements)\n\r") + cg.add(var.set_replace_time_date_active(True)) + else: + cg.add(var.set_replace_time_date_active(False)) + if config[CONF_REPLACE_TIME_DATE_TO]: + logging.warning(f"replace_time_date_to: defined but no replace_time_date_from:! (not using replacements)\n\r") + if config[CONF_REPLACE_TIME_DATE_FROM]: + logging.warning(f"replace_time_date_from: defined but no replace_time_date_to:! (not using replacements)\n\r") + cg.add_define("EHMTXv2_SCROLL_INTERVALL",config[CONF_SCROLLINTERVAL]) cg.add_define("EHMTXv2_RAINBOW_INTERVALL",config[CONF_RAINBOWINTERVAL]) cg.add_define("EHMTXv2_FRAME_INTERVALL",config[CONF_FRAMEINTERVAL]) diff --git a/wiki/fonts.md b/wiki/fonts.md index ad3b372e..d87a262a 100644 --- a/wiki/fonts.md +++ b/wiki/fonts.md @@ -1,4 +1,4 @@ -# fonts +# Fonts **Skill-level:** all diff --git a/wiki/home.md b/wiki/home.md index c8a02d0c..1d3abb2f 100644 --- a/wiki/home.md +++ b/wiki/home.md @@ -4,20 +4,24 @@ - [Display a timer on your ehmtxv2](display-timer) - [weather display](weather-display) -- [matrix used as "circle"](rotating-text) -## Configuration +## Basic Configuration +- [Fonts for the display](fonts) +- [Time and date display](time-date-display) +- [Time & Date Formats](time-date-format) +- [Set parameter on startup](startup-settings) +- [Special clock and date display duration](special-clock-and-date-display-duration) - [Ulanzi upside-down](rotate-ULANZI-display-180-degrees) -- [Use all icons in your blueprint](use-icons-in-blueprints) -- [Time & Date Formats](time-format) + +## Intermediate & Advanced Configuration + - [Blueprints for easier configuration](blueprints) -- [time and date display](time-date-display) -- [special clock and date display duration](special-clock-and-date-display-duration) -- [set parameter on startup](startup-settings) -- [fonts for the display](fonts) -- [small clock with icon](icon-clock) -- [showing graphs on the display](using-graphs) +- [Use all icons in your blueprint](use-icons-in-blueprints) +- [Matrix used as "circle" (rotating text)](rotating-text) +- [Small clock with icon](icon-clock) +- [Showing graphs on the display](using-graphs) +- [Replacing text in date and time](time-date-replace) ## Problems diff --git a/wiki/special-clock-and-date-display-duration.md b/wiki/special-clock-and-date-display-duration.md index 311a90f5..ec5e8a6b 100644 --- a/wiki/special-clock-and-date-display-duration.md +++ b/wiki/special-clock-and-date-display-duration.md @@ -8,7 +8,7 @@ Set up a timer helper named *eier_timer* I'm using EspHoMaTriXv2 on a Ulanzi TC001. I want to display the time for 55 seconds and the date for 5 seconds in a loop. I don't understand, how I can configure the display times. I tried clock_interval: 55 but it doesn't seem to help. -What's the corerct way? +What's the correct way? I think the easiest way is by a home assistant script like this: diff --git a/wiki/time-date-display.md b/wiki/time-date-display.md index 2e2d80fc..6fa3b789 100644 --- a/wiki/time-date-display.md +++ b/wiki/time-date-display.md @@ -4,7 +4,7 @@ todo => adapt to 2023.8.0 **Skill-level:** low -EspHoMaTriXv2 is a pixel clock. With out any configuration it displays only the time and date. These are "build in", but can be widely configured [format](time-format). If you don't need the date-display, you can disable it with the parameter `show_date: false` in the YAML. Or if you don't want either time or date add `allow_empty_screen: true` to your yaml. +EspHoMaTriXv2 is a pixel clock. Without any configuration it displays only the time and date. These are "build in", but can be widely configured [format](time-date-format). If you don't need the date-display, you can disable it with the parameter `show_date: false` in the YAML. Or if you don't want either time or date add `allow_empty_screen: true` to your yaml. During runtime, you can remove them from the queue with: diff --git a/wiki/time-format.md b/wiki/time-date-format.md similarity index 77% rename from wiki/time-format.md rename to wiki/time-date-format.md index 92d228cd..19a33593 100644 --- a/wiki/time-format.md +++ b/wiki/time-date-format.md @@ -1,4 +1,4 @@ -# introduction +# Introduction **Skill-level:** low @@ -57,3 +57,8 @@ Abbreviated Day and Date (Tue 08) ```yaml time_format: "%l:%M%p" ``` +## Localized Time and Date + +Unfortunately, ESPHome does not seem capable of passing on localized time and date formats so that you can get time formats in your own language easily. + +But you can still do it with a special function: [time-date-replace](time-date-replace). \ No newline at end of file diff --git a/wiki/time-date-replace.md b/wiki/time-date-replace.md new file mode 100644 index 00000000..59871044 --- /dev/null +++ b/wiki/time-date-replace.md @@ -0,0 +1,45 @@ +# Introduction + +**Skill-level:** intermediate + +In the ehmtxv2: section of your yaml, you can change the [time date format](time-date-format). + +Unfortunately, ESPHome does not seem capable of passing on localized time and date formats through compilation. + +Using the replace function you can replace various elements of date and time formats completely which can help localize or customize your display. + +## Date formats + +Normal time and date function to get: `4:30PM` and `Oct 11`: + +```yaml + time_format: "%l:%M%p" + date_format: "%b d%" +``` + +An example to get Korean date and time like `4:30오후` and `10월11일`: + +```yaml + time_format: "%l:%M%p" + date_format: "%b%d일" + replace_time_date_from: "AM PM Sun Mon Tue Wed Thu Fri Sat Jan Feb Mar Apr May Jun Jul Aug Sep Oct Nov Dec" + replace_time_date_to: "오전 오후 일 월 화 수 목 금 토 1월 2월 3월 4월 5월 6월 7월 8월 9월 10월 11월 12월" +``` + +Here is an example to get Ukrainian `Жовт 11`: + +```yaml + date_format: "%b %d" + replace_time_date_from: "Sun Mon Tue Wed Thu Fri Sat Jan Feb Mar Apr May Jun Jul Aug Sep Oct Nov Dec" + replace_time_date_to: "ПН ВТ СР ЧТ ПТ СБ ВС Сiч Лют Бер Квiт Трав Черв Лип Серп Вер Жовт Лист Груд" +``` + +These are just a few examples. You can replace almost any element you want, except spaces (this includes special Unicode spaces like thin spaces). +Yes, that means you can even replace numbers and the colon with other characters. Use emojis, if you like! + +Keep an eye on the ESPHome output when using this. You should see a message if the replace is deactivated due to some error. +Note there is also a 50 pair limit. Using too many pairs may cause slowdowns. Although tested well with the Korean pair above, using more is considered experimental. + +Please note also that input for `time_format` and `date_format` may be limited. Experiment! + +### Don't forget to include matching glyphs in your font section! \ No newline at end of file