Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

2023.9.1: Advanced clock #165

Merged
merged 6 commits into from
Dec 1, 2023
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
8 changes: 8 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -39,6 +39,7 @@
- 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
- Added `vertical_scroll` to ehmtxv2 config.
- Added Advanced clock mode `advanced_clock`, [More info](https://github.com/lubeda/EspHoMaTriXv2/issues/164)

### EspHoMaTriX 2023.9.0
- Added the ability to display graph as defined in the YAML file
Expand Down Expand Up @@ -622,6 +623,7 @@ This component is highly customizable.
ehmtxv2:
  id: rgb8x32
  show_seconds: true
advanced_clock: false
  matrix_component: ehmtx_display
  time_component: ehmtx_time
  icons2html: true
Expand Down Expand Up @@ -652,6 +654,10 @@ ehmtxv2:

**time_format** (optional, string): formats the date display with [strftime syntax](https://esphome.io/components/time.html?highlight=strftime), defaults `"%H:%M"` (use `"%I:%M%p"` for the US)

**time_format_big** (optional, string): formats the date display with [strftime syntax](https://esphome.io/components/time.html?highlight=strftime), defaults `"%H:%M:%S"`, work only in **advanced_clock** mode and sets the time format for a screen with a clock without an icon

**advanced_clock** (optional, boolean): Enables or disables advanced clock mode. (default: false) [More info](https://github.com/lubeda/EspHoMaTriXv2/issues/164)

**default_font_yoffset** (optional, pixel): yoffset the text is aligned BASELINE_LEFT, the baseline defaults to `6`

**default_font_xoffset** (optional, pixel): xoffset the text is aligned BASELINE_LEFT, the left defaults to `1`
Expand Down Expand Up @@ -783,6 +789,8 @@ Numerous features are accessible with services from home assistant and lambdas t
|`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|
|`set_adv_clock_color`|"hr", "hg", "hb", "mr", "mg", "mb", "sr", "sg", "sb"|available only in **advanced clock mode** `advanced_clock: true`, allows you to set the color for the Hours (hr, hg, hb), Minutes (mr, mg, mb) and Spacer (sr, sg, sb), color is set by analogy with `r,g,b`. If the color is set as `black`, the standard color is used (see `set_clock_color`).|
|`set_clock_infotext_color`|"left_r", "left_g", "left_b", "right_r", "right_g", "right_b","default_font","y_offset"|set the special color for left and right char on info text on `icon clock` screen, work only in **advanced clock mode**|

#### Parameter description

Expand Down
97 changes: 97 additions & 0 deletions components/ehmtxv2/EHMTX.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@
#include <vector>
#include <algorithm>
#include <string>
#include <regex>

namespace esphome
{
Expand Down Expand Up @@ -32,6 +33,14 @@ namespace esphome
this->vertical_scroll = false;
#endif

#ifdef EHMTXv2_ADV_CLOCK
this->info_clock_lcolor = Color(CG_GREY, CG_GREY, CG_GREY);
this->info_clock_rcolor = Color(CG_GREY * 2, CG_GREY * 2, CG_GREY * 2);

this->set_clock_color();
this->set_adv_clock_color();
#endif

for (uint8_t i = 0; i < MAXQUEUE; i++)
{
this->queue[i] = new EHMTX_queue(this);
Expand Down Expand Up @@ -664,6 +673,11 @@ namespace esphome
register_service(&EHMTX::fire_screen, "fire_screen", {"lifetime", "screen_time"});
#endif

#ifdef EHMTXv2_ADV_CLOCK
register_service(&EHMTX::set_clock_infotext_color, "set_clock_infotext_color", {"left_r", "left_g", "left_b", "right_r", "right_g", "right_b", "default_font", "y_offset"});
register_service(&EHMTX::set_adv_clock_color, "set_adv_clock_color", {"hr", "hg", "hb", "mr", "mg", "mb", "sr", "sg", "sb"});
#endif

register_service(&EHMTX::text_screen_progress, "text_screen_progress", {"text", "value", "progress", "lifetime", "screen_time", "default_font", "value_color_as_progress", "r", "g", "b"});
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"});
Expand Down Expand Up @@ -2070,6 +2084,89 @@ namespace esphome
}
}

#ifdef EHMTXv2_ADV_CLOCK
void EHMTX::set_clock_infotext_color(int lr, int lg, int lb, int rr, int rg, int rb, bool df, int y_offset)
{
this->info_clock_lcolor = Color((uint8_t)lr, (uint8_t)lg, (uint8_t)lb);
this->info_clock_rcolor = Color((uint8_t)rr, (uint8_t)rg, (uint8_t)rb);
this->info_clock_font = df;
this->info_clock_y_offset = y_offset;
ESP_LOGD(TAG, "info clock text color left: r: %d g: %d b: %d right: r: %d g: %d b: %d y_offset %d", lr, lg, lb, rr, rg, rb, y_offset);
}

void EHMTX::set_adv_clock_color(int hr, int hg, int hb, int mr, int mg, int mb, int sr, int sg, int sb)
{
this->hour_color = Color((uint8_t)hr, (uint8_t)hg, (uint8_t)hb);
this->minutes_color = Color((uint8_t)mr, (uint8_t)mg, (uint8_t)mb);
this->spacer_color = Color((uint8_t)sr, (uint8_t)sg, (uint8_t)sb);
ESP_LOGD(TAG, "advanced clock color hour: r: %d g: %d b: %d minutes: r: %d g: %d b: %d spacer: r: %d g: %d b: %d", hr, hg, hb, mr, mg, mb, sr, sg, sb);
}

bool EHMTX::draw_clock(std::string format, esphome::display::BaseFont *font, Color color, int xpos, int ypos)
{
std::regex rgx {"^(%[HI])(.)(%M)(.)?(%S|%p)?$"};
std::smatch match;
if (!std::regex_search(format, match, rgx))
return false;

std::vector<std::string> parts;
std::vector<uint8_t> len;
std::string sep = "";

uint8_t full_length = 0;

for (int i = 1; i < match.length(); i++)
{
std::string output = match[i].str();

if (output.length() > 0)
{
if (output.find("%") != std::string::npos)
{
if (output == "%p" && this->replace_time_date_active) // check for replace active
{
output = this->clock->now().strftime(output);
output = this->replace_time_date(output);
}
else
{
output = this->clock->now().strftime(output);
}
}
else if (sep == "")
{
sep = output;
}

parts.push_back(output);
len.push_back(output.length() > 0 ? this->GetTextWidth(font, "%s", output.c_str()) : 0);
full_length += len.back();
}
}

uint8_t x = xpos - full_length / 2;
for (int i = 0; i < parts.size(); i++)
{
if (parts.at(i).length() > 0)
{
if (!(this->show_seconds && parts.at(i) == sep && (this->clock->now().second % 2 == 1)))
{
Color c_ = i == 0 ? this->hour_color : i == 2 ? this->minutes_color : parts.at(i) == sep ? this->spacer_color : color;
if (c_.r + c_.g + c_.b == C_BLACK)
{
c_ = color;
}

this->display->printf(x, ypos, font, c_, display::TextAlign::BASELINE_LEFT, "%s", parts.at(i).c_str());
}
x += len.at(i);
}
}

return true;
}
#endif

void EHMTX::set_weekday_char_count(uint8_t i)
{
this->weekday_char_count = i;
Expand Down
17 changes: 16 additions & 1 deletion components/ehmtxv2/EHMTX.h
Original file line number Diff line number Diff line change
Expand Up @@ -108,17 +108,27 @@ namespace esphome
void dump_config();
bool info_font = true;
int8_t info_y_offset = 0;
#ifdef EHMTXv2_ADV_CLOCK
bool info_clock_font = true;
int8_t info_clock_y_offset = 0;
#endif
#ifdef USE_ESP32
PROGMEM Color text_color, alarm_color, rindicator_color, lindicator_color, today_color, weekday_color, rainbow_color, clock_color, info_lcolor, info_rcolor;
PROGMEM Color bitmap[256];
PROGMEM Color cgauge[8];
PROGMEM EHMTX_Icon *icons[MAXICONS];
#ifdef EHMTXv2_ADV_CLOCK
PROGMEM Color hour_color, minutes_color, spacer_color, info_clock_lcolor, info_clock_rcolor;
#endif
#endif

#ifdef USE_ESP8266
Color text_color, alarm_color, gauge_color, gauge_bgcolor,rindicator_color,lindicator_color, today_color, weekday_color, rainbow_color, clock_color, info_lcolor, info_rcolor;
EHMTX_Icon *icons[MAXICONS];
uint8_t gauge_value;
#ifdef EHMTXv2_ADV_CLOCK
Color hour_color, minutes_color, spacer_color, info_clock_lcolor, info_clock_rcolor;
#endif
#endif
display::BaseFont *default_font;
display::BaseFont *special_font;
Expand Down Expand Up @@ -166,7 +176,7 @@ namespace esphome
uint8_t find_icon(std::string name);
uint8_t find_last_clock();
bool string_has_ending(std::string const &fullString, std::string const &ending);
void draw_day_of_week(int ypos = 0, bool small=false);
void draw_day_of_week(int ypos = 0, bool small = false);
void show_all_icons();
float get_tick();
void tick();
Expand Down Expand Up @@ -200,6 +210,11 @@ namespace esphome
void set_weekday_color(int r = CD_RED, int g = CD_GREEN, int b = CD_BLUE);
void set_clock_color(int r = C_RED, int g = C_GREEN, int b = C_BLUE);
void set_infotext_color(int lr = CG_GREY, int lg = CG_GREY, int lb = CG_GREY, int rr = CG_GREY, int rg = CG_GREY, int rb = CG_GREY, bool info_font = true, int y_offset = 0);
#ifdef EHMTXv2_ADV_CLOCK
void set_clock_infotext_color(int lr = CG_GREY, int lg = CG_GREY, int lb = CG_GREY, int rr = CG_GREY, int rg = CG_GREY, int rb = CG_GREY, bool info_font = true, int y_offset = 0);
void set_adv_clock_color(int hr = C_BLACK, int hg = C_BLACK, int hb = C_BLACK, int mr = C_BLACK, int mg = C_BLACK, int mb = C_BLACK, int sr = C_BLACK, int sg = C_BLACK, int sb = C_BLACK);
bool draw_clock(std::string format, esphome::display::BaseFont *font, Color color, int xpos = 0, int ypos = 0);
#endif

void show_alarm(int r = CA_RED, int g = CA_GREEN, int b = CA_BLUE, int s = 2);
void show_gauge(int v, int r = C_RED, int g = C_GREEN, int b = C_BLUE,int bgr = CG_GREY, int bgg = CG_GREY, int bgb = CG_GREY); // int because of register_service
Expand Down
89 changes: 62 additions & 27 deletions components/ehmtxv2/EHMTX_queue.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -523,19 +523,28 @@ namespace esphome
{
color_ = (this->mode == MODE_RAINBOW_CLOCK) ? this->config_->rainbow_color : this->text_color;
time_t ts = this->config_->clock->now().timestamp;
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, this->ypos() + yoffset, font, color_, display::TextAlign::BASELINE_CENTER, "%s", time_new.c_str());
} else {
this->config_->display->strftime(xoffset + 15, this->ypos() + 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)
#ifdef EHMTXv2_ADV_CLOCK
if (!this->config_->draw_clock(EHMTXv2_TIME_FORMAT_BIG, font, color_, xoffset + 15, this->ypos() + yoffset))
{
this->config_->display->draw_pixel_at(0, 0, color_);
#endif
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, this->ypos() + yoffset, font, color_, display::TextAlign::BASELINE_CENTER, "%s", time_new.c_str());
}
else
{
this->config_->display->strftime(xoffset + 15, this->ypos() + yoffset, font, color_, display::TextAlign::BASELINE_CENTER, EHMTXv2_TIME_FORMAT,
this->config_->clock->now());
}
if (this->config_->show_seconds && (this->config_->clock->now().second % 2 == 0))
{
this->config_->display->draw_pixel_at(0, 0, color_);
}
#ifdef EHMTXv2_ADV_CLOCK
}
#endif
if (this->mode != MODE_RAINBOW_CLOCK)
{
this->config_->draw_day_of_week(this->ypos());
Expand Down Expand Up @@ -587,27 +596,39 @@ namespace esphome
{
color_ = this->text_color;
time_t ts = this->config_->clock->now().timestamp;

if (this->mode == MODE_ICON_CLOCK)
{
if (this->config_->replace_time_date_active) // check for replace active
#ifdef EHMTXv2_ADV_CLOCK
if (!this->config_->draw_clock(EHMTXv2_TIME_FORMAT, font, color_, xoffset + 20, this->ypos() + yoffset))
{
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 + 19, this->ypos() + yoffset, font, color_, display::TextAlign::BASELINE_CENTER, "%s", time_new.c_str());
} else {
this->config_->display->strftime(xoffset + 19, this->ypos() + yoffset, font, color_, display::TextAlign::BASELINE_CENTER, EHMTXv2_TIME_FORMAT,
this->config_->clock->now());
#endif
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 + 20, this->ypos() + yoffset, font, color_, display::TextAlign::BASELINE_CENTER, "%s", time_new.c_str());
}
else
{
this->config_->display->strftime(xoffset + 20, this->ypos() + yoffset, font, color_, display::TextAlign::BASELINE_CENTER, EHMTXv2_TIME_FORMAT,
this->config_->clock->now());
}
#ifdef EHMTXv2_ADV_CLOCK
}
#endif
}
else
{
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 + 19, this->ypos() + yoffset, font, color_, display::TextAlign::BASELINE_CENTER, "%s", time_new.c_str());
} else {
this->config_->display->strftime(xoffset + 19, this->ypos() + yoffset, font, color_, display::TextAlign::BASELINE_CENTER, EHMTXv2_DATE_FORMAT,
this->config_->display->printf(xoffset + 20, this->ypos() + yoffset, font, color_, display::TextAlign::BASELINE_CENTER, "%s", time_new.c_str());
}
else
{
this->config_->display->strftime(xoffset + 20, this->ypos() + yoffset, font, color_, display::TextAlign::BASELINE_CENTER, EHMTXv2_DATE_FORMAT,
this->config_->clock->now());
}
}
Expand All @@ -619,6 +640,20 @@ namespace esphome

if (this->icon_name.find("day") != std::string::npos || this->icon_name.find("weekday") != std::string::npos)
{
int8_t i_y_offset = this->config_->info_y_offset;
Color i_lcolor = this->config_->info_rcolor;
Color i_rcolor = this->config_->info_rcolor;

#ifdef EHMTXv2_ADV_CLOCK
if (this->mode == MODE_ICON_CLOCK)
{
i_y_offset = this->config_->info_clock_y_offset;
i_lcolor = this->config_->info_clock_rcolor;
i_rcolor = this->config_->info_clock_rcolor;
info_font = this->config_->info_clock_font ? this->config_->default_font : this->config_->special_font;
}
#endif

int mode = 0;
std::size_t pos = icon_name.find("#");
if (pos != std::string::npos)
Expand Down Expand Up @@ -666,12 +701,12 @@ namespace esphome
if (mode == 5 && (d < 10))
{
x_right = 4 - (r_width - 1) / 2;
this->config_->display->printf(x_right, this->ypos() + yoffset + this->config_->info_y_offset, info_font, this->config_->info_rcolor, display::TextAlign::BASELINE_LEFT, "%d", d % 10);
this->config_->display->printf(x_right, this->ypos() + yoffset + i_y_offset, info_font, i_rcolor, display::TextAlign::BASELINE_LEFT, "%d", d % 10);
}
else
{
this->config_->display->printf(x_left, this->ypos() + yoffset + this->config_->info_y_offset - (mode != 3 ? 0 : 1), info_font, this->config_->info_lcolor, display::TextAlign::BASELINE_LEFT, "%d", d / 10 % 10);
this->config_->display->printf(x_right, this->ypos() + yoffset + this->config_->info_y_offset - (mode != 4 ? 0 : 1), info_font, this->config_->info_rcolor, display::TextAlign::BASELINE_LEFT, "%d", d % 10);
this->config_->display->printf(x_left, this->ypos() + yoffset + i_y_offset - (mode != 3 ? 0 : 1), info_font, i_lcolor, display::TextAlign::BASELINE_LEFT, "%d", d / 10 % 10);
this->config_->display->printf(x_right, this->ypos() + yoffset + i_y_offset - (mode != 4 ? 0 : 1), info_font, i_rcolor, display::TextAlign::BASELINE_LEFT, "%d", d % 10);
}
}
else // if (this->icon_name.rfind("weekday", 0) == 0)
Expand Down Expand Up @@ -708,8 +743,8 @@ namespace esphome
x_right = x_right - r_width;
break;
}
this->config_->display->printf(x_left, this->ypos() + yoffset + this->config_->info_y_offset - (mode != 3 ? 0 : 1), info_font, this->config_->info_lcolor, display::TextAlign::BASELINE_LEFT, "%s", left.c_str());
this->config_->display->printf(x_right, this->ypos() + yoffset + this->config_->info_y_offset - (mode != 4 ? 0 : 1), info_font, this->config_->info_rcolor, display::TextAlign::BASELINE_LEFT, "%s", right.c_str());
this->config_->display->printf(x_left, this->ypos() + yoffset + i_y_offset - (mode != 3 ? 0 : 1), info_font, i_lcolor, display::TextAlign::BASELINE_LEFT, "%s", left.c_str());
this->config_->display->printf(x_right, this->ypos() + yoffset + i_y_offset - (mode != 4 ? 0 : 1), info_font, i_rcolor, display::TextAlign::BASELINE_LEFT, "%s", right.c_str());
}
else
{
Expand All @@ -718,7 +753,7 @@ namespace esphome
// The symbol consists of a visible part, and an empty area to the right with a width of one point.
uint8_t c_width = this->config_->GetTextWidth(info_font, "%s", weekday.c_str());
x_left = 4 - (c_width - 1) / 2;
this->config_->display->printf(x_left, this->ypos() + yoffset + this->config_->info_y_offset, info_font, this->config_->info_lcolor, display::TextAlign::BASELINE_LEFT, "%s", weekday.c_str());
this->config_->display->printf(x_left, this->ypos() + yoffset + i_y_offset, info_font, i_lcolor, display::TextAlign::BASELINE_LEFT, "%s", weekday.c_str());
}
}
}
Expand Down
Loading