Public Access
Add Interstellar and Your Name pages
Interstellar: Gargantua with a time dilation clock (Earth today vs. Miller's planet), TARS with his settings and remarks about the house, the Endurance spinning at a solar-driven RPM while a Ranger docks, and the tesseract's bookshelf with the time in binary dust and the Message's first word in Morse on a watch. Your Name: comet Tiamat splitting over Itomori's lake, and kataware-doki, a countdown to sunset from sun.sun where two silhouettes stand on the crater rim during the twilight hour. HomeData gains sunset, sunrise and sun elevation (with an ISO time parser); wrap() and typed() move to el512_pages.h. Share Tech Mono 22 gets the full Latin set. All pages are in the renderer, checked with normal, busy and empty data. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
This commit is contained in:
1 parent
a4ce97d744
commit
f46f7ab6c5
22 files changed
+1159
-110
No files matched your search
@@ -9,7 +9,9 @@
|
||||
#include <cstdint>
|
||||
#include <cstdio>
|
||||
#include <string>
|
||||
#include <vector>
|
||||
|
||||
#include "el512_helpers.h"
|
||||
#include "esphome/components/display/display.h"
|
||||
#include "esphome/core/time.h"
|
||||
|
||||
@@ -34,6 +36,9 @@ struct HomeData {
|
||||
std::string agenda; // sensor.el512_agenda events: "day|time|title;..."
|
||||
std::string message; // the panel's Message text
|
||||
std::string printer; // 3D printer state (Moonraker: printing, paused, error, ...)
|
||||
int64_t sunset{0}; // next sunset, Unix time (sun.sun next_setting); 0 = unknown
|
||||
int64_t sunrise{0}; // next sunrise, Unix time (sun.sun next_rising); 0 = unknown
|
||||
float sun_elevation{NAN}; // degrees above the horizon
|
||||
Reading rooms[4];
|
||||
|
||||
// Today's solar power in 15-minute slots (highest value seen per slot; -1 =
|
||||
@@ -96,6 +101,30 @@ inline std::string upper(std::string s) {
|
||||
return s;
|
||||
}
|
||||
|
||||
// Days since 1970-01-01 for a civil date (Howard Hinnant's algorithm).
|
||||
inline int64_t days_from_civil(int y, int m, int d) {
|
||||
y -= m <= 2;
|
||||
const int era = (y >= 0 ? y : y - 399) / 400;
|
||||
const int yoe = y - era * 400;
|
||||
const int doy = (153 * (m + (m > 2 ? -3 : 9)) + 2) / 5 + d - 1;
|
||||
const int doe = yoe * 365 + yoe / 4 - yoe / 100 + doy;
|
||||
return (int64_t) era * 146097 + doe - 719468;
|
||||
}
|
||||
|
||||
// "2026-10-19T16:32:10.123+00:00" (as Home Assistant sends datetimes) to Unix
|
||||
// time; 0 if it doesn't parse.
|
||||
inline int64_t parse_iso_utc(const std::string &s) {
|
||||
int y, mo, d, h, mi, se;
|
||||
if (sscanf(s.c_str(), "%d-%d-%dT%d:%d:%d", &y, &mo, &d, &h, &mi, &se) != 6)
|
||||
return 0;
|
||||
int64_t t = days_from_civil(y, mo, d) * 86400 + h * 3600 + mi * 60 + se;
|
||||
const size_t p = s.find_first_of("+-", 19);
|
||||
int oh, om;
|
||||
if (p != std::string::npos && sscanf(s.c_str() + p + 1, "%d:%d", &oh, &om) == 2)
|
||||
t -= (s[p] == '+' ? 1 : -1) * (int64_t) (oh * 3600 + om * 60);
|
||||
return t;
|
||||
}
|
||||
|
||||
inline std::string lower(std::string s) {
|
||||
for (auto &c : s)
|
||||
c = (char) tolower((unsigned char) c);
|
||||
@@ -108,6 +137,43 @@ inline int text_width(display::Display &it, display::BaseFont *font, const char
|
||||
return w;
|
||||
}
|
||||
|
||||
// Greedy word wrap into at most max_lines lines of `width` pixels; the last
|
||||
// line ends in "..." when text is left over.
|
||||
inline std::vector<std::string> wrap(display::Display &it, display::BaseFont *font, const std::string &text, int width,
|
||||
size_t max_lines) {
|
||||
std::vector<std::string> lines;
|
||||
std::string line;
|
||||
size_t i = 0;
|
||||
while (i <= text.size()) {
|
||||
size_t j = text.find(' ', i);
|
||||
if (j == std::string::npos)
|
||||
j = text.size();
|
||||
const std::string word = text.substr(i, j - i);
|
||||
const std::string joined = line.empty() ? word : line + " " + word;
|
||||
if (!line.empty() && text_width(it, font, joined.c_str()) > width) {
|
||||
lines.push_back(line);
|
||||
line = word;
|
||||
} else {
|
||||
line = joined;
|
||||
}
|
||||
i = j + 1;
|
||||
}
|
||||
if (!line.empty())
|
||||
lines.push_back(line);
|
||||
if (lines.size() > max_lines) {
|
||||
lines.resize(max_lines);
|
||||
lines.back() += "...";
|
||||
}
|
||||
for (auto &l : lines)
|
||||
l = fit(font, l, width);
|
||||
return lines;
|
||||
}
|
||||
|
||||
// The part of `s` typed so far at `cps` characters per second.
|
||||
inline std::string typed(const std::string &s, uint32_t t, int cps) {
|
||||
return s.substr(0, std::min<size_t>(s.size(), (size_t) t * cps / 1000));
|
||||
}
|
||||
|
||||
// Draw a sprite (optionally only its first `rows` rows), scaled up in blocks.
|
||||
inline void sprite(display::Display &it, const Sprite &s, int x, int y, int scale = 1, int rows = -1,
|
||||
Color color = display::COLOR_ON) {
|
||||
|
||||
Reference in new issue
Block a user