Skip to content

Instantly share code, notes, and snippets.

@jterrace
Last active April 15, 2024 18:48
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save jterrace/f412fdfac90687719cf3016ff968cc0b to your computer and use it in GitHub Desktop.
Save jterrace/f412fdfac90687719cf3016ff968cc0b to your computer and use it in GitHub Desktop.
node-red code to pull calendar and push to eink
// Formats the given Date and returns map with format string parts.
const makeTimeFormatMap = function(date) {
const tz = Intl.DateTimeFormat().resolvedOptions().locale;
const dateTimeFormat = new Intl.DateTimeFormat(tz, {
month: 'short',
day: 'numeric',
weekday: 'short',
hour: 'numeric',
minute: 'numeric',
hour12: true,
});
const partsMap = {};
dateTimeFormat.formatToParts(date).map(({type, value}) => {
partsMap[type] = value
})
partsMap.dayPeriod = partsMap.dayPeriod[0].toLowerCase();
return partsMap;
};
// Makes a Date from a date/time string.
const makeDate = function(dateString) {
if (dateString.includes("T")) {
return new Date(dateString);
}
// All day events just show up as "YYYY-MM-DD" with no
// time zone, so parse manually to make sure it's in "local"
// time zone.
var b = dateString.split(/\D/);
return new Date(b[0], b[1]-1, b[2]);
};
// Returns an array of dates between the two time strings.
const getDaysArray = function (start, end) {
const days = [];
for (var dt = makeDate(start); dt <= makeDate(end); dt.setDate(dt.getDate() + 1)) {
days.push(new Date(dt));
}
return days;
};
const cal = msg.payload["calendar.terrace_household"];
if (cal === undefined) return null;
const by_date = {}
for (const event of cal.events) {
const days = getDaysArray(event.start, event.end);
if (days.length == 1) {
const ts = days[0];
const formatParts = makeTimeFormatMap(ts);
const dateStr = `${formatParts.weekday} ${formatParts.month} ${formatParts.day}`;
const timeStr = `${formatParts.hour}:${formatParts.minute}${formatParts.dayPeriod}`;
by_date[dateStr] = by_date[dateStr] || [];
by_date[dateStr].push(timeStr + ' ' + event.summary);
continue;
}
// Multi day events end at midnight the day after, lop it off.
days.pop();
for (const day of days) {
const formatParts = makeTimeFormatMap(day);
const dateStr = `${formatParts.weekday} ${formatParts.month} ${formatParts.day}`;
by_date[dateStr] = by_date[dateStr] || [];
by_date[dateStr].push(event.summary);
}
}
const drawPayloads = [];
var largeSize = 30;
for (const [dateString, events] of Object.entries(by_date)) {
drawPayloads.push(
{
type: "text",
value: dateString,
font: "ppb.ttf",
x: 5,
size: largeSize,
color: "red"
});
largeSize = 25;
drawPayloads.push(
{
type: "multiline",
value: events.join('|'),
delimiter: '|',
font: "ppb.ttf",
offset_y: 30,
x: 10,
size: 20,
y_padding: 5,
color: "black"
});
}
return {payload: drawPayloads };
@samuelcomplex
Copy link

Wondering if I could get some help getting this going. Changing const cal = msg.payload["calendar.terrace_household"]; to the name of my calendar doesn't seem to work. It's not fetching any data.

@jterrace
Copy link
Author

Are you calling calendar.get_events? Try piping the output to a debug node with "complete msg object" as the output so you can see what the JSON object looks like on the right side debug message panel.

@samuelcomplex
Copy link

In the "Fetch Calendar Items" service node I've selected "calendar" as domain and "get_events" as service. I've also selected the correct calendar as entity. In the data field I entered the "start_date_time" line you shared on your blog.

Debug node isn't giving any error messages. I've played around with it quite a bit and as far as I can tell the issue is that the fetch isn't getting any events from the calendar.

@jterrace
Copy link
Author

If you go to Developer Tools -> Services and call calendar.get_events there, does it return anything? If not, maybe your calendar isn't being fetched properly?

@samuelcomplex
Copy link

samuelcomplex commented Apr 14, 2024

That works, I get 2 events for the same timeline. However I still can't get the service call to fetch any events. If I use a current state node it shows 2 events, and shows what they are. I've tried multiple calendars and with start and end time as well as the snippet that's written on the blog.

image
This is what the call service node looks like, just to clarify.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment