Add switchable clock display page
This commit is contained in:
+103
-7
@@ -149,6 +149,10 @@ globals:
|
||||
type: bool
|
||||
restore_value: true
|
||||
initial_value: 'false'
|
||||
- id: clock_digital_view
|
||||
type: bool
|
||||
restore_value: true
|
||||
initial_value: 'false'
|
||||
- id: device_usage_view
|
||||
type: int
|
||||
restore_value: true
|
||||
@@ -259,20 +263,22 @@ sensor:
|
||||
script:
|
||||
- id: show_previous_page
|
||||
then:
|
||||
- lambda: id(page_index) = (id(page_index) + 2 - 1) % 2;
|
||||
- lambda: id(page_index) = (id(page_index) + 3 - 1) % 3;
|
||||
- component.update: tft
|
||||
- id: toggle_page_mode
|
||||
then:
|
||||
- lambda: |-
|
||||
if (id(page_index) == 0) {
|
||||
id(page_one_gauge_view) = !id(page_one_gauge_view);
|
||||
} else {
|
||||
} else if (id(page_index) == 1) {
|
||||
id(device_usage_view) = (id(device_usage_view) + 1) % 2;
|
||||
} else {
|
||||
id(clock_digital_view) = !id(clock_digital_view);
|
||||
}
|
||||
- component.update: tft
|
||||
- id: show_next_page
|
||||
then:
|
||||
- lambda: id(page_index) = (id(page_index) + 1) % 2;
|
||||
- lambda: id(page_index) = (id(page_index) + 1) % 3;
|
||||
- component.update: tft
|
||||
|
||||
button:
|
||||
@@ -299,7 +305,7 @@ binary_sensor:
|
||||
- platform: wireguard
|
||||
enabled:
|
||||
name: 'WireGuard Enabled'
|
||||
# M5Stack Core button B (middle) toggles the alternate gauge view on page one.
|
||||
# M5Stack Core button B (middle) switches the current page's view.
|
||||
- platform: gpio
|
||||
pin:
|
||||
number: GPIO38
|
||||
@@ -462,7 +468,7 @@ display:
|
||||
} else {
|
||||
it.printf(gauge_center_x, 169, id(font_title), solar_gauge_color, TextAlign::TOP_CENTER, "-- W");
|
||||
}
|
||||
} else {
|
||||
} else if (id(page_index) == 1) {
|
||||
// Page 2 lists nine consumers at once in two columns; button B changes group.
|
||||
const int device_count = 18;
|
||||
const int usage_group = id(device_usage_view);
|
||||
@@ -538,6 +544,93 @@ display:
|
||||
}
|
||||
}
|
||||
|
||||
if (id(page_index) == 2) {
|
||||
const auto now = id(sntp_time).now();
|
||||
const Color accent(143, 190, 223);
|
||||
const Color gold(255, 170, 40);
|
||||
const Color muted(55, 65, 80);
|
||||
it.print(12, 10, id(font_device), accent, "Uhr · Berlin");
|
||||
if (!now.is_valid()) {
|
||||
it.print(160, 100, id(font_title), accent, TextAlign::TOP_CENTER, "--:--:--");
|
||||
it.print(160, 190, id(font_small), Color::WHITE, TextAlign::TOP_CENTER,
|
||||
"Warte auf Zeitsynchronisation");
|
||||
} else {
|
||||
if (!id(clock_digital_view)) {
|
||||
const int cx = 160, cy = 111, radius = 74;
|
||||
const float tau = 6.28318530718f;
|
||||
it.filled_circle(cx, cy, radius, Color(12, 18, 28));
|
||||
it.circle(cx, cy, radius, accent);
|
||||
it.circle(cx, cy, radius - 3, muted);
|
||||
for (int tick = 0; tick < 60; tick++) {
|
||||
const float angle = tick * tau / 60.0f;
|
||||
const int inner = tick % 5 == 0 ? radius - 13 : radius - 8;
|
||||
it.line(cx + lroundf(sinf(angle) * inner), cy - lroundf(cosf(angle) * inner),
|
||||
cx + lroundf(sinf(angle) * (radius - 5)),
|
||||
cy - lroundf(cosf(angle) * (radius - 5)),
|
||||
tick % 5 == 0 ? accent : muted);
|
||||
}
|
||||
it.print(cx, cy - 49, id(font_device), Color::WHITE, TextAlign::CENTER, "12");
|
||||
it.print(cx + 50, cy, id(font_device), Color::WHITE, TextAlign::CENTER, "3");
|
||||
it.print(cx, cy + 49, id(font_device), Color::WHITE, TextAlign::CENTER, "6");
|
||||
it.print(cx - 50, cy, id(font_device), Color::WHITE, TextAlign::CENTER, "9");
|
||||
// Round-ended hands; minutes and hours advance with the seconds.
|
||||
auto hand = [&](float turns, int length, int thickness, Color color) {
|
||||
const float angle = turns * tau;
|
||||
for (int r = 0; r <= length; r++) {
|
||||
it.filled_circle(cx + lroundf(sinf(angle) * r),
|
||||
cy - lroundf(cosf(angle) * r), thickness, color);
|
||||
}
|
||||
};
|
||||
hand((now.hour % 12 + now.minute / 60.0f + now.second / 3600.0f) / 12.0f,
|
||||
34, 3, Color::WHITE);
|
||||
hand((now.minute + now.second / 60.0f) / 60.0f, 51, 2, accent);
|
||||
const float second_angle = now.second * tau / 60.0f;
|
||||
it.line(cx - lroundf(sinf(second_angle) * 12), cy + lroundf(cosf(second_angle) * 12),
|
||||
cx + lroundf(sinf(second_angle) * 60), cy - lroundf(cosf(second_angle) * 60), gold);
|
||||
it.filled_circle(cx, cy, 4, gold);
|
||||
it.filled_circle(cx, cy, 1, Color::BLACK);
|
||||
} else {
|
||||
// Draw seven-segment digits directly, avoiding an extra font dependency.
|
||||
const uint8_t masks[10] = {0x3F, 0x06, 0x5B, 0x4F, 0x66,
|
||||
0x6D, 0x7D, 0x07, 0x7F, 0x6F};
|
||||
const int digits[6] = {now.hour / 10, now.hour % 10, now.minute / 10,
|
||||
now.minute % 10, now.second / 10, now.second % 10};
|
||||
const int positions[6] = {17, 61, 121, 165, 225, 269};
|
||||
const int y = 77;
|
||||
for (int digit = 0; digit < 6; digit++) {
|
||||
const int x = positions[digit];
|
||||
const Color lit = digit < 4 ? accent : gold;
|
||||
for (int segment = 0; segment < 7; segment++) {
|
||||
const Color color = (masks[digits[digit]] & (1 << segment))
|
||||
? lit : Color(20, 27, 36);
|
||||
const bool horizontal = segment == 0 || segment == 3 || segment == 6;
|
||||
const int sx = horizontal ? x + 6 : x + ((segment == 1 || segment == 2) ? 30 : 0);
|
||||
const int sy = y + (segment == 0 ? 0 : segment == 3 ? 72 : segment == 6 ? 36
|
||||
: (segment == 1 || segment == 5) ? 6 : 42);
|
||||
// Taper each segment's ends for the classic LED clock shape.
|
||||
for (int stripe = 0; stripe < 6; stripe++) {
|
||||
const int inset = stripe < 3 ? 2 - stripe : stripe - 3;
|
||||
if (horizontal)
|
||||
it.line(sx + inset, sy + stripe, sx + 23 - inset, sy + stripe, color);
|
||||
else
|
||||
it.line(sx + stripe, sy + inset, sx + stripe, sy + 29 - inset, color);
|
||||
}
|
||||
}
|
||||
}
|
||||
for (int x : {109, 213}) {
|
||||
it.filled_circle(x, y + 24, 3, accent);
|
||||
it.filled_circle(x, y + 54, 3, accent);
|
||||
}
|
||||
it.line(40, 172, 280, 172, muted);
|
||||
}
|
||||
const char *weekdays[] = {"Sonntag", "Montag", "Dienstag", "Mittwoch",
|
||||
"Donnerstag", "Freitag", "Samstag"};
|
||||
it.printf(160, 190, id(font_small), Color::WHITE, TextAlign::TOP_CENTER,
|
||||
"%s, %02d.%02d.%04d", weekdays[now.day_of_week - 1],
|
||||
now.day_of_month, now.month, now.year);
|
||||
}
|
||||
}
|
||||
|
||||
// Labels correspond to the left (A) and right (C) hardware buttons.
|
||||
it.printf(8, 239, id(font_small), Color::WHITE, TextAlign::BOTTOM_LEFT,
|
||||
"< Zurück");
|
||||
@@ -545,8 +638,11 @@ display:
|
||||
"Weiter >");
|
||||
if (id(page_index) == 0) {
|
||||
it.printf(160, 239, id(font_small), Color::WHITE, TextAlign::BOTTOM_CENTER,
|
||||
"Ansicht · 1 / 2");
|
||||
} else {
|
||||
"Ansicht · 1 / 3");
|
||||
} else if (id(page_index) == 1) {
|
||||
it.printf(160, 239, id(font_small), Color::WHITE, TextAlign::BOTTOM_CENTER,
|
||||
"Geräte %d / 2", id(device_usage_view) + 1);
|
||||
} else {
|
||||
it.printf(160, 239, id(font_small), Color::WHITE, TextAlign::BOTTOM_CENTER,
|
||||
"%s · 3 / 3", id(clock_digital_view) ? "Analog" : "Digital");
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user