mirror of
https://github.com/OpenEPaperLink/OpenEPaperLink.git
synced 2026-03-21 05:06:39 +01:00
added content: google calendar
via google apps script, see /data/calendar.txt
This commit is contained in:
46
ESP32_AP-Flasher/data/calendar.txt
Normal file
46
ESP32_AP-Flasher/data/calendar.txt
Normal file
@@ -0,0 +1,46 @@
|
||||
To use Google Apps Script to get all events for the next day and return them via JSON in a web app, you can follow these steps:
|
||||
|
||||
Create a new Google Apps Script project by going to https://script.google.com and clicking on "New project".
|
||||
|
||||
In the script editor, create a new function called "getEventsForNextDay" that will fetch all events for the next day and return them in JSON format:
|
||||
|
||||
function getEventsForNextDay() {
|
||||
var start = new Date();
|
||||
var end = new Date();
|
||||
end.setDate(end.getDate() + 1);
|
||||
var calendars = CalendarApp.getAllCalendars();
|
||||
var events = [];
|
||||
for (var i = 0; i < calendars.length; i++) {
|
||||
var calendar = calendars[i];
|
||||
var eventsInCalendar = calendar.getEvents(start, end);
|
||||
for (var j = 0; j < eventsInCalendar.length; j++) {
|
||||
var event = eventsInCalendar[j];
|
||||
events.push({
|
||||
title: event.getTitle(),
|
||||
start: Math.floor(event.getStartTime().getTime() / 1000),
|
||||
end: Math.floor(event.getEndTime().getTime() / 1000),
|
||||
location: event.getLocation(),
|
||||
description: event.getDescription()
|
||||
});
|
||||
}
|
||||
}
|
||||
// Sort events by start date/time
|
||||
events.sort(function(a, b) {
|
||||
return a.start - b.start;
|
||||
});
|
||||
return JSON.stringify(events);
|
||||
}
|
||||
|
||||
function doGet() {
|
||||
var content = getEventsForNextDay();
|
||||
var output = ContentService.createTextOutput(content);
|
||||
output.setMimeType(ContentService.MimeType.JSON);
|
||||
return output;
|
||||
}
|
||||
|
||||
|
||||
This function calls the getEventsForNextDay() function to get the events in JSON format, creates a text output with the JSON content, sets the MIME type to JSON, and returns the output.
|
||||
|
||||
Deploy the web app by clicking on "Deploy > New Deployment" in the script editor. Choose "Web app" as the deployment type, set the access to "Anyone, even anonymous", and click on "Deploy". Make sure to take note of the web app URL generated by Google.
|
||||
|
||||
Test the web app by visiting the web app URL in a web browser. You should see the events for the next day in JSON format.
|
||||
@@ -35,6 +35,7 @@
|
||||
<option value="6">memo text</option>
|
||||
<option value="7">image url</option>
|
||||
<option value="10">qr code</option>
|
||||
<option value="11">google calendar</option>
|
||||
<option value="5">firmware update</option>
|
||||
</select>
|
||||
</p>
|
||||
|
||||
@@ -8,7 +8,7 @@ const WAKEUP_REASON_FIRSTBOOT = 0xFC;
|
||||
const WAKEUP_REASON_NETWORK_SCAN = 0xFD;
|
||||
const WAKEUP_REASON_WDT_RESET = 0xFE;
|
||||
|
||||
const contentModes = ["Static image", "Current date", "Counting days", "Counting hours", "Current weather", "Firmware update", "Memo text", "Image url", "Weather forecast", "RSS feed", "QR code"];
|
||||
const contentModes = ["Static image", "Current date", "Counting days", "Counting hours", "Current weather", "Firmware update", "Memo text", "Image url", "Weather forecast", "RSS feed", "QR code", "Calendar"];
|
||||
const models = ["1.54\" 152x152px", "2.9\" 296x128px", "4.2\" 400x300px"];
|
||||
const displaySizeLookup = { 0: [152, 152], 1: [128, 296], 2: [400, 300] };
|
||||
const colorTable = { 0: [255, 255, 255], 1: [0, 0, 0], 2: [255, 0, 0], 3: [255, 0, 0] };
|
||||
@@ -24,6 +24,7 @@ contentModeOptions[7] = ["url","interval"];
|
||||
contentModeOptions[8] = ["location"];
|
||||
contentModeOptions[9] = ["title", "url", "interval"];
|
||||
contentModeOptions[10] = ["title", "qr-content"];
|
||||
contentModeOptions[11] = ["title", "apps_script_url", "interval"];
|
||||
|
||||
const imageQueue = [];
|
||||
let isProcessing = false;
|
||||
|
||||
@@ -26,7 +26,8 @@ void drawWeather(String &filename, String location, tagRecord *&taginfo, imgPara
|
||||
void drawForecast(String &filename, String location, tagRecord *&taginfo, imgParam &imageParams);
|
||||
void drawIdentify(String &filename, tagRecord *&taginfo, imgParam &imageParams);
|
||||
bool getImgURL(String &filename, String URL, time_t fetched, imgParam &imageParams);
|
||||
bool getRSSfeed(String &filename, String URL, String title, tagRecord *&taginfo, imgParam &imageParams);
|
||||
bool getRssFeed(String &filename, String URL, String title, tagRecord *&taginfo, imgParam &imageParams);
|
||||
bool getCalFeed(String &filename, String URL, String title, tagRecord *&taginfo, imgParam &imageParams);
|
||||
void drawQR(String &filename, String qrcontent, String title, tagRecord *&taginfo, imgParam &imageParams);
|
||||
char *formatHttpDate(time_t t);
|
||||
String urlEncode(const char *msg);
|
||||
|
||||
@@ -79,5 +79,5 @@ monitor_port = COM21
|
||||
build_flags =
|
||||
-D SIMPLE_AP=2
|
||||
-D PINOUT=SIMPLE_AP
|
||||
src_filter =
|
||||
build_src_filter =
|
||||
+<*>-<usbflasher.cpp>
|
||||
|
||||
@@ -31,6 +31,7 @@ enum contentModes {
|
||||
Forecast,
|
||||
RSSFeed,
|
||||
QRcode,
|
||||
Calendar,
|
||||
};
|
||||
|
||||
void contentRunner() {
|
||||
@@ -180,7 +181,7 @@ void drawNew(uint8_t mac[8], bool buttonPressed, tagRecord *&taginfo) {
|
||||
|
||||
case RSSFeed:
|
||||
|
||||
if (getRSSfeed(filename, cfgobj["url"], cfgobj["title"], taginfo, imageParams)) {
|
||||
if (getRssFeed(filename, cfgobj["url"], cfgobj["title"], taginfo, imageParams)) {
|
||||
taginfo->nextupdate = now + 60 * (cfgobj["interval"].as<int>() < 5 ? 5 : cfgobj["interval"].as<int>());
|
||||
updateTagImage(filename, mac, cfgobj["interval"].as<int>(), imageParams);
|
||||
} else {
|
||||
@@ -194,6 +195,17 @@ void drawNew(uint8_t mac[8], bool buttonPressed, tagRecord *&taginfo) {
|
||||
taginfo->nextupdate = now + 12 * 3600;
|
||||
updateTagImage(filename, mac, 0, imageParams);
|
||||
break;
|
||||
|
||||
case Calendar:
|
||||
|
||||
if (getCalFeed(filename, cfgobj["apps_script_url"], cfgobj["title"], taginfo, imageParams)) {
|
||||
taginfo->nextupdate = now + 60 * (cfgobj["interval"].as<int>() < 5 ? 5 : cfgobj["interval"].as<int>());
|
||||
updateTagImage(filename, mac, cfgobj["interval"].as<int>(), imageParams);
|
||||
} else {
|
||||
taginfo->nextupdate = now + 300;
|
||||
}
|
||||
break;
|
||||
|
||||
}
|
||||
|
||||
taginfo->modeConfigJson = doc.as<String>();
|
||||
@@ -595,7 +607,7 @@ bool getImgURL(String &filename, String URL, time_t fetched, imgParam &imagePara
|
||||
|
||||
rssClass reader;
|
||||
|
||||
bool getRSSfeed(String &filename, String URL, String title, tagRecord *&taginfo, imgParam &imageParams) {
|
||||
bool getRssFeed(String &filename, String URL, String title, tagRecord *&taginfo, imgParam &imageParams) {
|
||||
// https://github.com/garretlab/shoddyxml2
|
||||
|
||||
// http://feeds.feedburner.com/tweakers/nieuws
|
||||
@@ -649,6 +661,108 @@ bool getRSSfeed(String &filename, String URL, String title, tagRecord *&taginfo,
|
||||
return true;
|
||||
}
|
||||
|
||||
char *epoch_to_display(time_t utc) {
|
||||
static char display[6];
|
||||
struct tm local_tm;
|
||||
localtime_r(&utc, &local_tm);
|
||||
time_t now;
|
||||
time(&now);
|
||||
struct tm now_tm;
|
||||
localtime_r(&now, &now_tm);
|
||||
if (local_tm.tm_year < now_tm.tm_year ||
|
||||
(local_tm.tm_year == now_tm.tm_year && local_tm.tm_mon < now_tm.tm_mon) ||
|
||||
(local_tm.tm_year == now_tm.tm_year && local_tm.tm_mon == now_tm.tm_mon && local_tm.tm_mday < now_tm.tm_mday) ||
|
||||
(local_tm.tm_hour == 0 && local_tm.tm_min == 0)) {
|
||||
strftime(display, sizeof(display), "%d-%m", &local_tm);
|
||||
} else {
|
||||
strftime(display, sizeof(display), "%H:%M", &local_tm);
|
||||
}
|
||||
return display;
|
||||
}
|
||||
|
||||
bool getCalFeed(String &filename, String URL, String title, tagRecord *&taginfo, imgParam &imageParams) {
|
||||
// google apps scripts method to retrieve calendar
|
||||
// see /data/calendar.txt for description
|
||||
|
||||
wsLog("get calendar");
|
||||
|
||||
time_t now;
|
||||
time(&now);
|
||||
struct tm timeinfo;
|
||||
localtime_r(&now, &timeinfo);
|
||||
|
||||
HTTPClient http;
|
||||
http.begin(URL);
|
||||
http.setTimeout(10000); // timeout in ms
|
||||
http.setFollowRedirects(HTTPC_STRICT_FOLLOW_REDIRECTS);
|
||||
int httpCode = http.GET();
|
||||
if (httpCode != 200) {
|
||||
wsErr("http error " + String(httpCode));
|
||||
return false;
|
||||
}
|
||||
|
||||
DynamicJsonDocument doc(5000);
|
||||
DeserializationError error = deserializeJson(doc, http.getString());
|
||||
if (error) {
|
||||
wsErr(error.c_str());
|
||||
}
|
||||
http.end();
|
||||
|
||||
TFT_eSPI tft = TFT_eSPI();
|
||||
TFT_eSprite spr = TFT_eSprite(&tft);
|
||||
U8g2_for_TFT_eSPI u8f;
|
||||
u8f.begin(spr);
|
||||
|
||||
if (taginfo->hwType == SOLUM_29_033) {
|
||||
initSprite(spr, 296, 128);
|
||||
if (title == "" || title == "null") title = "Calendar";
|
||||
|
||||
u8f.setFont(u8g2_font_t0_22b_tr); // select u8g2 font from here: https://github.com/olikraus/u8g2/wiki/fntlistall
|
||||
u8f.setFontMode(0);
|
||||
u8f.setFontDirection(0);
|
||||
u8f.setForegroundColor(PAL_BLACK);
|
||||
u8f.setBackgroundColor(PAL_WHITE);
|
||||
u8f.setCursor(5, 16);
|
||||
u8f.print(title);
|
||||
|
||||
// u8g2_font_nine_by_five_nbp_tr
|
||||
// u8g2_font_7x14_tr
|
||||
// u8g2_font_crox1h_tr
|
||||
// u8g2_font_miranda_nbp_tr
|
||||
// u8g2_font_glasstown_nbp_tr
|
||||
// select u8g2 font from here: https://github.com/olikraus/u8g2/wiki/fntlistall
|
||||
|
||||
int n = doc.size();
|
||||
if (n>7) n=7;
|
||||
for (int i = 0; i < n; i++) {
|
||||
JsonObject obj = doc[i];
|
||||
String eventtitle = obj["title"];
|
||||
String startz = obj["start"];
|
||||
time_t starttime = obj["start"];
|
||||
time_t endtime = obj["end"];
|
||||
if (starttime<now && endtime>now) {
|
||||
u8f.setFont(u8g2_font_t0_14b_tr);
|
||||
u8f.setForegroundColor(PAL_WHITE);
|
||||
u8f.setBackgroundColor(PAL_RED);
|
||||
spr.fillRect(0, i * 15 + 21, 296, 14, PAL_RED);
|
||||
} else {
|
||||
u8f.setFont(u8g2_font_t0_14_tr);
|
||||
u8f.setForegroundColor(PAL_BLACK);
|
||||
u8f.setBackgroundColor(PAL_WHITE);
|
||||
}
|
||||
u8f.setCursor(5, 32 + i * 15);
|
||||
u8f.print(epoch_to_display(obj["start"]));
|
||||
u8f.setCursor(50, 32 + i * 15);
|
||||
u8f.print(eventtitle);
|
||||
}
|
||||
}
|
||||
|
||||
spr2buffer(spr, filename, imageParams);
|
||||
spr.deleteSprite();
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
void drawQR(String &filename, String qrcontent, String title, tagRecord *&taginfo, imgParam &imageParams) {
|
||||
TFT_eSPI tft = TFT_eSPI();
|
||||
TFT_eSprite spr = TFT_eSprite(&tft);
|
||||
|
||||
Reference in New Issue
Block a user