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; Config conf;
ActiveFeatures activeFeatures; ActiveFeatures activeFeatures;
int loopIteration = 0; int loopIteration = 0;
std::vector<Calendar> cals; // Contains Calendar data
void setup() void setup()
{ {
@ -123,11 +124,7 @@ void setup()
activeFeatures.weather = false; activeFeatures.weather = false;
} }
text_y += line_height; text_y += line_height;
// Check Nextcloud reachable here activeFeatures.calendar = true;
// 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);
displayActiveFeatures(activeFeatures); displayActiveFeatures(activeFeatures);
bootMsg("Weather Icons sourced from flaticon.com", text_y); bootMsg("Weather Icons sourced from flaticon.com", text_y);
text_y += 2 * line_height; text_y += 2 * line_height;
@ -156,7 +153,12 @@ void loop() {
// Fetch calendar data if it is active // Fetch calendar data if it is active
if (activeFeatures.calendar) { 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); Serial.printf("Loop iteration %d\n", loopIteration);
@ -169,8 +171,8 @@ void loop() {
if (activeFeatures.weather && weather.latitude != 0 && weather.longitude != 0) { if (activeFeatures.weather && weather.latitude != 0 && weather.longitude != 0) {
displayWeather(weather); displayWeather(weather);
} }
if (!activeFeatures.calendar) { // Temporarily inverse the statenment during tests if (activeFeatures.calendar) { // Temporarily inverse the statenment during tests
displayCalendar(timeinfo); displayCalendar(timeinfo, cals);
} }
} while (display.nextPage()); } while (display.nextPage());
} }
@ -458,7 +460,7 @@ void displayFullScreenArt() {
while (display.nextPage()); 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_y = 80;
const int cal_head = 30; const int cal_head = 30;
const int cal_margin = 30; const int cal_margin = 30;
@ -489,4 +491,26 @@ void displayCalendar(struct tm timeinfo) {
display.setCursor(3, cal_head + i * 74 + 96); display.setCursor(3, cal_head + i * 74 + 96);
display.print(weekDays[dayOfWk]); 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 "nextcloud_cal.h"
#include "tls_certificates.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; WiFiClientSecure client;
client.setCACert(letsencrypt_root_ca); client.setCACert(letsencrypt_root_ca);
@ -24,7 +24,7 @@ String downloadICSFile(const String& url, const String& startTime, const String&
Serial.println("Connection failed!"); Serial.println("Connection failed!");
Serial.print("Host: "); Serial.print("Host: ");
Serial.println(host); Serial.println(host);
return ""; return Calendar{};
} }
// Encode credentials in Base64 // Encode credentials in Base64
@ -54,10 +54,10 @@ String downloadICSFile(const String& url, const String& startTime, const String&
if (headerEnd != -1) { if (headerEnd != -1) {
response = response.substring(headerEnd + 4); response = response.substring(headerEnd + 4);
} }
return response; return parseVCalendar(response);
} else { } else {
Serial.println("Failed to fetch: " + String(statusCode)); Serial.println("Failed to fetch: " + String(statusCode));
return ""; return Calendar{};
} }
} }
@ -85,3 +85,44 @@ StartEnd calculateStartEnd() {
StartEnd result = {startTimestamp, endTimestamp}; StartEnd result = {startTimestamp, endTimestamp};
return result; 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; 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(); 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 #endif