From b313d07669b871b2b6ab345e0078e8113d2deccc Mon Sep 17 00:00:00 2001 From: Nic Limper Date: Sat, 12 Apr 2025 19:51:57 +0200 Subject: [PATCH] added sunrise/sunset/moon phase to date display --- .../data/www/content_cards.json.gz | Bin 4784 -> 4932 bytes ESP32_AP-Flasher/include/contentmanager.h | 3 +- ESP32_AP-Flasher/src/contentmanager.cpp | 79 ++++++++++++++++-- ESP32_AP-Flasher/wwwroot/content_cards.json | 23 ++++- resources/tagtypes/47.json | 13 ++- 5 files changed, 104 insertions(+), 14 deletions(-) diff --git a/ESP32_AP-Flasher/data/www/content_cards.json.gz b/ESP32_AP-Flasher/data/www/content_cards.json.gz index ccac4508d76f6b6623b75e1e5fb6ccf029cc8f38..868b6c541ce1d081c36fdfc346b399754da3a5d5 100644 GIT binary patch delta 4923 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 delta 4776 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 C=^S+c diff --git a/ESP32_AP-Flasher/include/contentmanager.h b/ESP32_AP-Flasher/include/contentmanager.h index f4948a6b..84eb144d 100644 --- a/ESP32_AP-Flasher/include/contentmanager.h +++ b/ESP32_AP-Flasher/include/contentmanager.h @@ -1,6 +1,7 @@ #include #include #include +#include #include "makeimage.h" #include "tag_db.h" @@ -21,7 +22,7 @@ bool updateTagImage(String &filename, const uint8_t *dst, uint16_t nextCheckin, void drawString(TFT_eSprite &spr, String content, int16_t posx, int16_t posy, String font, byte align = 0, uint16_t color = TFT_BLACK, uint16_t size = 30, uint16_t bgcolor = TFT_WHITE); void drawTextBox(TFT_eSprite &spr, String &content, int16_t &posx, int16_t &posy, int16_t boxwidth, int16_t boxheight, String font, uint16_t color = TFT_BLACK, uint16_t bgcolor = TFT_WHITE, float lineheight = 1, byte align = TL_DATUM); void initSprite(TFT_eSprite &spr, int w, int h, imgParam &imageParams); -void drawDate(String &filename, tagRecord *&taginfo, imgParam &imageParams); +void drawDate(String &filename, JsonObject &cfgobj, tagRecord *&taginfo, imgParam &imageParams); void drawNumber(String &filename, int32_t count, int32_t thresholdred, tagRecord *&taginfo, imgParam &imageParams); void drawWeather(String &filename, JsonObject &cfgobj, const tagRecord *taginfo, imgParam &imageParams); void drawForecast(String &filename, JsonObject &cfgobj, const tagRecord *taginfo, imgParam &imageParams); diff --git a/ESP32_AP-Flasher/src/contentmanager.cpp b/ESP32_AP-Flasher/src/contentmanager.cpp index 29f860d1..a5578ed5 100644 --- a/ESP32_AP-Flasher/src/contentmanager.cpp +++ b/ESP32_AP-Flasher/src/contentmanager.cpp @@ -336,7 +336,7 @@ void drawNew(const uint8_t mac[8], tagRecord *&taginfo) { case 1: // Today - drawDate(filename, taginfo, imageParams); + drawDate(filename, cfgobj, taginfo, imageParams); taginfo->nextupdate = util::getMidnightTime(); updateTagImage(filename, mac, (taginfo->nextupdate - now) / 60 - 10, taginfo, imageParams); break; @@ -790,7 +790,41 @@ void initSprite(TFT_eSprite &spr, int w, int h, imgParam &imageParams) { spr.fillSprite(TFT_WHITE); } -void drawDate(String &filename, tagRecord *&taginfo, imgParam &imageParams) { +String utf8FromCodepoint(uint16_t cp) { + char buf[4] = {0}; + if (cp < 0x80) { + buf[0] = cp; + } else if (cp < 0x800) { + buf[0] = 0xC0 | (cp >> 6); + buf[1] = 0x80 | (cp & 0x3F); + } else { + buf[0] = 0xE0 | ((cp >> 12) & 0x0F); + buf[1] = 0x80 | ((cp >> 6) & 0x3F); + buf[2] = 0x80 | (cp & 0x3F); + } + return String(buf); +} + +String formatUtcToLocal(const String &s) { + int h, m, ss = 0; + if (sscanf(s.c_str(), "%d:%d:%d", &h, &m, &ss) < 2 || h > 23 || m > 59 || ss > 59) + return "-"; + + time_t n = time(nullptr); + struct tm tm = *localtime(&n); + tm.tm_hour = h; + tm.tm_min = m; + tm.tm_sec = ss; + + time_t utc = mktime(&tm) - _timezone + (tm.tm_isdst ? 3600 : 0); + localtime_r(&utc, &tm); + + char buf[6]; + snprintf(buf, 6, "%02d:%02d", tm.tm_hour, tm.tm_min); + return buf; +} + +void drawDate(String &filename, JsonObject &cfgobj, tagRecord *&taginfo, imgParam &imageParams) { time_t now; time(&now); struct tm timeinfo; @@ -811,19 +845,48 @@ void drawDate(String &filename, tagRecord *&taginfo, imgParam &imageParams) { TFT_eSprite spr = TFT_eSprite(&tft); initSprite(spr, imageParams.width, imageParams.height, imageParams); - const auto &date = loc["date"]; - const auto &weekday = loc["weekday"]; - if (date) { + auto date = loc["date"]; + auto weekday = loc["weekday"]; + const auto &month = loc["month"]; + const auto &day = loc["day"]; + + if (cfgobj["location"]) { + const String lat = cfgobj["#lat"]; + const String lon = cfgobj["#lon"]; + JsonDocument doc; + + const bool success = util::httpGetJson("https://api.farmsense.net/v1/daylengths/?d=" + String(now) + "&lat=" + lat + "&lon=" + lon + "&tz=UTC", doc, 5000); + if (success && loc["sunrise"].is()) { + String sunrise = formatUtcToLocal(doc[0]["Sunrise"]); + String sunset = formatUtcToLocal(doc[0]["Sunset"]); + const auto &sunriseicon = loc["sunrise"]; + const auto &sunseticon = loc["sunset"]; + drawString(spr, String("\uF046 "), sunriseicon[0], sunriseicon[1].as(), "/fonts/weathericons.ttf", TR_DATUM, TFT_BLACK, sunriseicon[3]); + drawString(spr, String("\uF047 "), sunseticon[0], sunseticon[1].as(), "/fonts/weathericons.ttf", TR_DATUM, TFT_BLACK, sunseticon[3]); + drawString(spr, sunrise, sunriseicon[0], sunriseicon[1], sunriseicon[2], TL_DATUM, TFT_BLACK, sunriseicon[3]); + drawString(spr, sunset, sunseticon[0], sunseticon[1], sunseticon[2], TL_DATUM, TFT_BLACK, sunseticon[3]); + + const bool success = util::httpGetJson("https://api.farmsense.net/v1/moonphases/?d=" + String(now), doc, 5000); + if (success && loc["moonicon"].is()) { + uint8_t moonage = doc[0]["Index"].as(); + const auto &moonicon = loc["moonicon"]; + uint16_t moonIconId = 0xf095 + moonage; + String moonIcon = utf8FromCodepoint(moonIconId); + drawString(spr, moonIcon, moonicon[0], moonicon[1], "/fonts/weathericons.ttf", TC_DATUM, TFT_BLACK, moonicon[2]); + } + + date = loc["altdate"]; + weekday = loc["altweekday"]; + } + } + if (date.is()) { drawString(spr, languageDays[timeinfo.tm_wday], weekday[0], weekday[1], weekday[2], TC_DATUM, imageParams.highlightColor, weekday[3]); drawString(spr, String(timeinfo.tm_mday) + " " + languageMonth[timeinfo.tm_mon], date[0], date[1], date[2], TC_DATUM, TFT_BLACK, date[3]); } else { - const auto &month = loc["month"]; - const auto &day = loc["day"]; drawString(spr, languageDays[timeinfo.tm_wday], weekday[0], weekday[1], weekday[2], TC_DATUM, TFT_BLACK, weekday[3]); drawString(spr, String(languageMonth[timeinfo.tm_mon]), month[0], month[1], month[2], TC_DATUM, TFT_BLACK, month[3]); drawString(spr, String(timeinfo.tm_mday), day[0], day[1], day[2], TC_DATUM, imageParams.highlightColor, day[3]); } - spr2buffer(spr, filename, imageParams); spr.deleteSprite(); } diff --git a/ESP32_AP-Flasher/wwwroot/content_cards.json b/ESP32_AP-Flasher/wwwroot/content_cards.json index 00af7db6..14836c02 100644 --- a/ESP32_AP-Flasher/wwwroot/content_cards.json +++ b/ESP32_AP-Flasher/wwwroot/content_cards.json @@ -44,8 +44,27 @@ { "id": 1, "name": "Current date", - "desc": "Shows the current date", - "param": [ ] + "desc": "Shows the current date. In some templates, the sunrise and sunset times are shown as well, when you fill in your location.", + "param": [ + { + "key": "location", + "name": "Location", + "desc": "Name of the city. This is used to lookup the lat/long data, and to display as the title", + "type": "geoselect" + }, + { + "key": "#lat", + "name": "Lat", + "desc": "Latitude (set automatic when generating image)", + "type": "ro" + }, + { + "key": "#lon", + "name": "Lon", + "desc": "Longitude (set automatic when generating image)", + "type": "ro" + } + ] }, { "id": 2, diff --git a/resources/tagtypes/47.json b/resources/tagtypes/47.json index 9bc101a9..a48902aa 100644 --- a/resources/tagtypes/47.json +++ b/resources/tagtypes/47.json @@ -1,5 +1,5 @@ { - "version": 3, + "version": 4, "name": "M3 2.7\"", "width": 300, "height": 200, @@ -16,8 +16,15 @@ "contentids": [ 22, 23, 1, 2, 3, 4, 5, 7, 8, 9, 10, 11, 17, 18, 19, 20, 21, 27 ], "template": { "1": { - "weekday": [ 150, 25, "Signika-SB.ttf", 60 ], - "date": [ 150, 100, "Signika-SB.ttf", 48 ] + "weekday": [ 150, -5, "Signika-SB.ttf", 60 ], + "day": [ 150, 37, "Signika-SB.ttf", 100 ], + "month": [ 150, 125, "Signika-SB.ttf", 60 ], + + "altweekday": [ 150, -5, "Signika-SB.ttf", 60 ], + "altdate": [ 150, 65, "Signika-SB.ttf", 54 ], + "moonicon": [ 150, 115, 62 ], + "sunrise": [ 50, 140, "Signika-SB.ttf", 28 ], + "sunset": [ 220, 140, "Signika-SB.ttf", 28 ] }, "2": { "fonts": [ "Signika-SB.ttf", 200, 200, 170, 120, 100, 80 ],