Add calendar Parsing

This commit is contained in:
Fred Boniface 2025-02-10 21:35:15 +00:00
parent 64057258b9
commit 4e5e016d2c
3 changed files with 94 additions and 14 deletions

View File

@ -58,6 +58,7 @@ SPIClass hspi(HSPI);
Config conf;
ActiveFeatures activeFeatures;
int loopIteration = 0;
std::vector<Calendar> cals; // Contains Calendar data
void setup()
{
@ -123,11 +124,7 @@ void setup()
activeFeatures.weather = false;
}
text_y += line_height;
// Check Nextcloud reachable here
// Nextcloud dev check:
StartEnd timestamp = calculateStartEnd();
String cal_test = downloadICSFile(conf.calUrls[0], String(timestamp.start), String(timestamp.end), conf.calUser, conf.calKey);
Serial.println(cal_test);
activeFeatures.calendar = true;
displayActiveFeatures(activeFeatures);
bootMsg("Weather Icons sourced from flaticon.com", text_y);
text_y += 2 * line_height;
@ -156,7 +153,12 @@ void loop() {
// Fetch calendar data if it is active
if (activeFeatures.calendar) {
// FETCH CALENDAR DATA HERE
StartEnd se = calculateStartEnd();
cals = std::vector<Calendar>(); // Clear the vector
for (const String& url : conf.calUrls) {
Calendar cal = downloadICSFile(url, String(se.start), String(se.end), conf.calUser, conf.calKey);
cals.push_back(cal);
}
}
Serial.printf("Loop iteration %d\n", loopIteration);
@ -169,8 +171,8 @@ void loop() {
if (activeFeatures.weather && weather.latitude != 0 && weather.longitude != 0) {
displayWeather(weather);
}
if (!activeFeatures.calendar) { // Temporarily inverse the statenment during tests
displayCalendar(timeinfo);
if (activeFeatures.calendar) { // Temporarily inverse the statenment during tests
displayCalendar(timeinfo, cals);
}
} while (display.nextPage());
}
@ -458,7 +460,7 @@ void displayFullScreenArt() {
while (display.nextPage());
}
void displayCalendar(struct tm timeinfo) {
void displayCalendar(struct tm timeinfo, std::vector<Calendar> cals) {
const int cal_y = 80;
const int cal_head = 30;
const int cal_margin = 30;
@ -489,4 +491,26 @@ void displayCalendar(struct tm timeinfo) {
display.setCursor(3, cal_head + i * 74 + 96);
display.print(weekDays[dayOfWk]);
}
// Print Calendar Data
if (!cals.empty()) {
Calendar firstCal = cals[0];
int eventCount = 0;
int cursorY = 150;
int cursorX = 50;
for (const VEvent& event : firstCal.events) {
if (eventCount >= 2) break;
display.setCursor(cursorX, cursorY);
display.print(event.dtstamp);
display.setCursor(cursorX, cursorY + 20);
display.print(event.dtstart);
display.setCursor(cursorX, cursorY + 40);
display.print(event.dtend);
display.setCursor(cursorX, cursorY + 60);
display.print(event.summary);
eventCount++;
cursorX = cursorX + 300;
}
}
}

View File

@ -6,7 +6,7 @@
#include "nextcloud_cal.h"
#include "tls_certificates.h"
String downloadICSFile(const String& url, const String& startTime, const String& endTime, const String& username, const String& password) {
Calendar downloadICSFile(const String& url, const String& startTime, const String& endTime, const String& username, const String& password) {
WiFiClientSecure client;
client.setCACert(letsencrypt_root_ca);
@ -24,7 +24,7 @@ String downloadICSFile(const String& url, const String& startTime, const String&
Serial.println("Connection failed!");
Serial.print("Host: ");
Serial.println(host);
return "";
return Calendar{};
}
// Encode credentials in Base64
@ -54,10 +54,10 @@ String downloadICSFile(const String& url, const String& startTime, const String&
if (headerEnd != -1) {
response = response.substring(headerEnd + 4);
}
return response;
return parseVCalendar(response);
} else {
Serial.println("Failed to fetch: " + String(statusCode));
return "";
return Calendar{};
}
}
@ -85,3 +85,44 @@ StartEnd calculateStartEnd() {
StartEnd result = {startTimestamp, endTimestamp};
return result;
}
Calendar parseVCalendar(String vcalData) {
Calendar calendar;
VEvent currentEvent;
bool inEvent = false;
int startPos = 0;
while (startPos < vcalData.length()) {
int endPos = vcalData.indexOf("\n", startPos);
if (endPos == -1) endPos = vcalData.length();
String line = vcalData.substring(startPos, endPos);
line.trim();
if (line.startsWith("X-WR-CALNAME:")) {
calendar.name = line.substring(13);
} else if (line.startsWith("X-APPLE-CALENDAR-COLOR:")) {
calendar.color = line.substring(25);
} else if (line.startsWith("BEGIN:VEVENT")) {
inEvent = true;
currentEvent = VEvent();
} else if (line.startsWith("END:VEVENT")) {
inEvent = false;
calendar.events.push_back(currentEvent);
} else if (inEvent) {
if (line.startsWith("DTSTAMP:")) {
currentEvent.dtstamp = line.substring(8);
} else if (line.startsWith("DTSTART:")) {
currentEvent.dtstart = line.substring(8);
} else if (line.startsWith("DTEND:")) {
currentEvent.dtend = line.substring(6);
} else if (line.startsWith("SUMMARY:")) {
currentEvent.summary = line.substring(8);
}
}
startPos = endPos + 1;
}
return calendar;
}

View File

@ -9,7 +9,22 @@ struct StartEnd {
time_t end;
};
struct VEvent {
String dtstamp;
String dtstart;
String dtend;
String summary;
};
struct Calendar {
String name;
String color;
std::vector<VEvent> events;
};
struct StartEnd calculateStartEnd();
String downloadICSFile(const String& url, const String& startTime, const String& endTime, const String& username, const String& password);
Calendar downloadICSFile(const String& url, const String& startTime, const String& endTime, const String& username, const String& password);
Calendar parseVCalendar(String vcalData);
#endif