Read the statement by Michael Teeuw here.
MM Calendar error connecting
-
Platform: Raspberry Pi 4
Node Version: v20.17.0
MagicMirror Version: 2.28.0 (running in docker)I’m using the built-in magic mirror module for CalDav integration, but the mirror just shows “Error in the Calendar module, check the logs for more info”. Logs are below (personal info scrubbed).
MagicMirrorServer | [2024-09-07 12:59:32.931] [ERROR] Calendar Error. Could not fetch calendar: https://radicale.mydomain.com/MyUser/CalendarUUID/ Error: Forbidden MagicMirrorServer | at NodeHelper.checkFetchStatus (/opt/magic_mirror/js/node_helper.js:110:9) MagicMirrorServer | at process.processTicksAndRejections (node:internal/process/task_queues:95:5)
My setup for Caldav is Nginx reverse proxy using Basic Auth -> Radicale instance. Auth is disabled on Radicale. I’ve triple-checked the password in the MagicMirror config is correct (even copy-pasted). When I manually browse the calendar URL, I get a Basic auth prompt, then I’m able to download the calendar as an ICS file.
Perhaps this
wget
log will help?wget --user MyUser --ask-password https://radicale.MyDomain.com/MyUser/CalendarUUID/ Password for user ‘MyUser’: --2024-09-07 13:36:56-- https://radicale.MyDomain.com/MyUser/CalendarUUID/ Loaded CA certificate '/etc/ssl/certs/ca-certificates.crt' Resolving radicale.MyDomain.com (radicale.MyDomain.com)... 192.168.-.-- Connecting to radicale.MyDomain.com (radicale.MyDomain.com)|192.168.-.--|:443... connected. HTTP request sent, awaiting response... 401 Unauthorized Authentication selected: Basic realm="Radicale - Password Required" Reusing existing connection to radicale.MyDomain.com:443. HTTP request sent, awaiting response... 200 OK Length: 269670 (263K) [text/calendar] Saving to: ‘index.html’
Configuration:
{ module: "calendar", header: "Events", position: "top_left", config: { calendars: [ { fetchInterval: 60 * 60 * 1000, symbol: "calendar-check", url: "https://radicale.MyDomain.com/MyUser/CalendarUUID/", auth: { user: "-----", pass: "-----", method: "basic" } } ] } }
-
@Amenity4882 as i understand it, we don’t read Caldav directly, as it doesnt provide data in ical format.
you would use a module like MMM-CalDAV, which creates an intermediate service that converts to ical format on the fly
-
@sdetweil The URL I specified in the module will return an iCal file. It doesn’t have a filename in the url (which is confusing). Maybe I don’t understand CalDav/WebDav enough to explain it well enough. Or maybe this is a Radicale quirk.
-
@Amenity4882 can you use curl on the url and redirect the content to a file
and then for test , and make a url for that file
( it needs to be inside the MagicMirror folder tree) -
@sdetweil I’m not sure what you mean by “inside the MagicMirror folder”, but I created a manual location in Nginx that points to an ICS file downloaded from Radicale. Then I updated MM to point to this custom URL. Used Wget to confirm I can download using the custom URL. Same issue…
Then I removed the authentication from Radicale entirely, same issue…
Then I replaced the ICS file downloaded from Radicale with the ICS file from this repo. Same issue…MagicMirrorServer | [2024-09-08 09:25:30.190] [ERROR] Calendar Error. Could not fetch calendar: https://radicale.MyDomain.com/MyUser/main.ics Error: Forbidden MagicMirrorServer | at NodeHelper.checkFetchStatus (/opt/magic_mirror/js/node_helper.js:110:9) MagicMirrorServer | at process.processTicksAndRejections (node:internal/process/task_queues:95:5)
-
@Amenity4882 if you use an actual file, and want MagicMirror to load it, you have to use the MagicMirror web server that is rooted at ~/MagicMirror
so
http://localhost:mm_port/…path to file
the file must be found in the MagicMirror folder tree( altho you can play games with linking)
if you have a server on another system or port then you can do whatever
so is you nginx server really serving https?
-
@sdetweil Ah, so that was just to use the internal MM web server.
Yes I use Nginx for reverse proxying and I use a LetsEncrypt cert to add https. The https portion is working fine and I’ve tested the custom URL pointing to the ICS file using
wget
. -
@Amenity4882 ok, lets see if we can figure out which error is what
here is a clone of the calendar fetch code as a standalone app
copy paste that to test_fetch.js whereever you like on the MM system .
(in user home, or a separate temp folder… )const https = require("node:https"); let auth = null let url = process.argv[2] console.log("url=",url) if(process.argv.length>3){ console.log("auth info=", process.argv[3]) auth = JSON.parse(process.argv[3]) } const nodeVersion = Number(process.version.match(/^v(\d+\.\d+)/)[1]); let httpsAgent = null; let headers = { "User-Agent": `Mozilla/5.0 (Node.js ${nodeVersion}) MagicMirror/2.28` }; if (auth) { if (auth.method === "bearer") { headers.Authorization = `Bearer ${auth.pass}`; } else { headers.Authorization = `Basic ${Buffer.from(`${auth.user}:${auth.pass}`).toString("base64")}`; } } fetch(url, { headers: headers, agent: httpsAgent }) .then((response) => response.text()) .then((responseData) => { let data = []; try { console.log("ical data="+responseData) } catch (error) { console.log("ical data error=",error) } }) .catch((error) => { console.log("ical fetch failed=",error); });
then on the terminal window , execute it like this
node test_fetch.js url optional_auth_info
an example from my local system, running MM and fetching a test ics from the modules/defaults/calendar folder thru the MM web server
node test_fetch.js http://localhost:8090/modules/default/calendar/testbalkan.ics "{\"method\":\"basic\",\"user\":\"sam\",\"pass\":\"fribble\"}"
note the auth_info requires quotes around each word thing… with \ in front of each and quotes around the whole thing…
one of my successful test runs , just dumps out the text of the ics file
node test_fetch.js http://localhost:8090/modules/default/calendar/testbalkan.ics url= http://localhost:8090/modules/default/calendar/testbalkan.ics ical data=BEGIN:VCALENDAR BEGIN:VEVENT CREATED:20240109T161646Z DTEND;TZID=Europe/London:20240110T170000 DTSTAMP:20240109T161647Z DTSTART;TZID=Europe/London:20240110T160000 LAST-MODIFIED:20240109T161646Z SEQUENCE:0 SUMMARY:test54321 TRANSP:OPAQUE UID:156ED8F1-9BDA-43D2-BE7C-DDEFE18E95EF URL;VALUE=URI: X-APPLE-CREATOR-IDENTITY:com.apple.mobilecal X-APPLE-CREATOR-TEAM-IDENTITY:0000000000 END:VEVENT END:VCALENDAR
I ‘wonder’ if the problem is the useragent string…
as a test after you get failures, edit line 14 and remove the trailing
MagicMirror/2.28
leave the backtick thothen repeat some failures…
-
@sdetweil Oh my god, I’m so sorry I have to say this. It was all my fault. I had added an option to Nginx to limit connections to specific IP ranges at some point, and that took effect only after I restarted my server recently. My docker IP range was the only thing not listed, so everything else inside my network was working fine.
But anyway, thank you for helping troubleshoot, especially with your latest comment with all the debug! That was actually what helped me discover the issue, just not the way you probably intended!
All is good now. Thank you again 😭
-
@Amenity4882 its solved
glad you found it