Small Guide to icalendar

Tags: #<Tag:0x00007fc9165d63a8> #<Tag:0x00007fc9165d5778> #<Tag:0x00007fc9165d5548>

As many users seem to use the icalendar plugin as replacement for caldav and some just need some basic help where to start i thought a small guide could help.

What is iCalendar and for what this binding could be used?

The iCalendar-standard is normally a offline-to-use standard file format for describing calendars. It has itself many features and allows to describe events, appointments, away times etc. The icalendar binding focuses on events and uses only a small subset of the whole standard. The standard does not define how to transmit a calendar (caldav does), as the web uses literally everywhere http, it’s here done also.

For which use-cases icalendar can be used?
• Getting a simple overview about some events like garbage collections
• Switching items based on events

For all previous caldav-users: Please note that it is not fully possible to replace all caldav-personal features using this plugin (and also it’s not intended to). E.g. the recording feature is technically not possible as the convention (in fact there is no real registered standard for transmitting calendars outside of DAV) only implements read-only access. Also there is no code shared between caldav and icalendar – so they are simply completely different.

How to

First of all, you need the iCal-URL. It‘s a http(s) URL where an iCalendar is retrievable. Using different sources, different methods are available for getting the URL.

URL in Nextcloud

A simple example is Nextcloud. For retrieving the URL a way is to get the download link from inside the web interface (desktop browser typically support to copy the link by right-clicking on it). Use your login as authentication data. You can also create an app-specific password inside the user settings for more secure access.


Another example is SOGo. Retrieve the URL use the menu and there „Links to this Calendar“ and then copy the WebDAV-ICS-URL (either public or private as you prefer). Using the private URL, the authentication is done by your normal login data.

URL in iCloud

iCloud also allows to share a calendar, but only without authentication.

Your calendar solution may gives you an URL beginning with „webcal://“ (like iCloud). In that case, just try to get a result in your browser by replacing „webcal://“ with „https://“ or „http://“ and use the working URL. Comparing to a caldav-URL, most cases the URLs are quite similar e.g. Nextcloud just adds an „?export“ in most cases (not always).

Configuring icalendar Bridge

Next step is to enter the information to iCalendar Binding. Using the GUI, this can look as follows:

Please think about the retrieval interval. Some cloud providers seem to limit the interval and also, there is no need to poll the calendar every minute if you usually enter items a day before begin into the calendar. E.g. It might be sufficient if the interval is once a day for garbage collection calendars as this is no usual subject of change. If you don‘t trust the source fully, use a random authorization code to ensure, potential unwanted commands are not executed.

Create items using the Bridges channels (here done with „Create Points from Thing“):

The bridge only supports a presence switch and shows begin, end and subject of the current and next event.

Configuring event filters

You can also retrieve other events begin, end and subject by using event filters. For using them, the icalendar bridge must already exist. Create a new thing and select the calendar as bridge. First, think about how much results you expect and how often the result set needs to be updated. After that use the text or time based filter to get only some events. You can combine both (but both filters have to match).

The time-based filter allows to get only events in a specific time frame. Note that zero is „now“ or the rounded value of „now“. If you select „round to unit“ the begin and end will be rounded down to the selected unit. E.g. if unit is day and begin is set to 0, the timeframe to search from would be today at 0:00. Disabling the selection it would be exactly now. Here is a example where tomorrows events are retrieved:

If the date filter is not set, the earliest events in your calendar are shown!

The text filter allows to retrieve events by their contents. The easier mode is to use the simple text filter. If the event contains in the selected field your text, it will be shown. Here you can also use regular expressions. Note that if you use regular expressions, your expression has to match the whole string. Here is an example for specially titled events:

I hope this guide, which is now longer than it has been planned, is a good start. Please feel free to comment further cool things you have done with it.


Nice tutorial =)

I recently wrote a post on how to trigger actions in openHAB from a calendar. Maybe someone will find it useful.

1 Like

thanks for the tutorial!
Now I’m able to switch items via command tags out of my main gmail account.
I do have “sub-calendars” for garbage, birthdays and school holidays. unfortunately I`m not able to integrate them into iCalendar binding.

Download of calendar timed out (waited too long for headers)

thats the only message I receive in logs, the Kalender thing itself reports an offline state.
Any idea how to solve this?

Can you please show us the configuration of the calendar thing. If you look into my tutorial there is a example setup of a calendar thing.

I also use iCal with Google’s calendar, and have a dedicated calendar for school schedules. In the settings click on the other calendar and on the right side scroll to the bottom there is a private iCal URL, I pasted that into the Bridge and created the channels/items.

I tried both the public and private ical URL. I also enabled “share publicity” to test it.

Here a bit general advise (not only for Google Calendar):

First of all, please try to retrieve the calendar using the URL you have in a browser using a different internet connection e.g. via your mobile.

If that not works, please check the URL. Are there any typos or invisible symbols (like spaces etc.) inside?

If it works please check your providers limits. People especially using the Google Calendar had issues with too short intervals. In your case this interval at the broken calendar is set to 5 Minutes, the working has an interval of 120 Minutes. If you are hosting your calendar yourself (so you are not using any public cloud), please check the Server Logs. Please check also the connectivity of your OpenHAB instance.

You message sounds like the server is not able (or unwilling) to respond. This really sounds like a connectivity issue or hit limit. In the latter case i would expect a different message but i don’t know how it’s implemented at google and even great providers may behave strange.

when I call the ical URL in a webbrowser, I get a basic.ics file downloaded. opening this file I can see the calender events. however, I do not find a basic.ics file downloaded to OH, should that file exist somewhere?
I also tried another gmail account, some result.
btw. I use the same calender account in OH2.5 with caldav without any problems. (but caldav does not use ical)

I enabled debugging in karaf and do see further events when I add the calender:
2021-01-02 19:54:44.765 [INFO ] [ab.event.ThingStatusInfoChangedEvent] - Thing ‘icalendar:calendar:fd5330ae37’ changed from UNINITIALIZED to INITIALIZING

==> /var/log/openhab/openhab.log <==

2021-01-02 19:54:44.773 [DEBUG] [ar.internal.handler.ICalendarHandler] - The calendar is currently offline as no local copy exists. It will go online as soon as a valid valid calendar is retrieved.

==> /var/log/openhab/events.log <==

2021-01-02 19:54:44.776 [INFO ] [ab.event.ThingStatusInfoChangedEvent] - Thing 'icalendar:calendar:fd5330ae37' changed from INITIALIZING to OFFLINE

==> /var/log/openhab/openhab.log <==

2021-01-02 19:55:44.776 [WARN ] [g.icalendar.internal.handler.PullJob] - Download of calendar timed out (waited too long for headers).

2021-01-02 19:55:44.778 [DEBUG] [g.icalendar.internal.handler.PullJob] - TimeoutException message is: null

2021-01-02 19:55:57.025 [DEBUG] [ar.internal.handler.ICalendarHandler] - The calendar is currently offline as no local copy exists. It will go online as soon as a valid valid calendar is retrieved.

its located in the openHAB-userdata folder:

thanks, but I can confirm that there is no ical file found

matthias@openhab3:~$ sudo find / -name *.ical
matthias@openhab3:~$ ls /var/lib/openhab
cache  config  etc  jsondb  openhabcloud  persistence  secrets  tmp  uuid

checking the thing again after a couple of days I can confirm that the ical binding is working now… it’s kinda selfhealing :laughing:
however, thanks for the tutorial!

how do you show up your calender in the UI? I created them as equipment, but its mixed up with all other “equipment” tagged things. wouldn’t it be nice to have a separate “calendar” card instead of one for all generic equipements? how do you present a calendar?

I had set up a calendar where I put events in specific rooms. The room is specified in the location item from the calendar. When an event ocur in a specific room, the heating in that room need to be turned on (some time before so it is warm at the given time), when the event ends the heating will set off.

So I made an eventfilter that get the current and future events in a specific location. So based on time 0, without rounding before. The events earlier that day not interest me for this sollution.

It works fine for the future event, but from the moment the event start, it disapear from the eventfilter. I was expecting that it shoud removed from the event filter after the event was ended, so that the current event is also visible. This is now a problem because the systemen start the heating, but when the event start, the item is removed from the filter and so the heating will be stopped again.

In the binding event you have the current event, but not the location information what I need to know for what room it is and I can have several at the same time in different rooms, so that is not helping also.

So do you know how the eventfilter can be configured that he shows as well the current envents and not only the future events?
The configuration of the event filter I’m using now is for example:
UID: icalendar:eventfilter:10dcede027:62b4d9e48c
label: Afspraken kamer Dagmar
thingTypeUID: icalendar:eventfilter
maxEvents: 3
textValueType: TEXT
datetimeEnd: 1
refreshTime: 15
datetimeStart: 0
textEventValue: Dagmar
textEventField: LOCATION
datetimeUnit: DAY
bridgeUID: icalendar:calendar:10dcede027
location: Dagmar

This is currently not possible using eventfilter. The simplest way would be to use different calendars and use no filter.

OK thanks… would be nice when this is a feature that can be added in the future.
7 extra calenders is also a lot to manage so I will try to find out an other way to do it, but will be indeed much more complex.

Thanks for the guide it was very helpful!
I got the calendar connection working and I get updates on the normal current/next event channels. But I just can’t get eventfilters working… No matter what I try, just nothing happens.

I’m using OH 2.5.11 and calendars from Nextcloud.

I tried configuring through PaperUI or things file, I tried text filters (my initial goal), but also timebased filters… I get updates on the calendar thing itself, so it’s generally working. But no response from eventfilter things.Not even an error log, nothing…
Strange thing is that I can’t find any reference to the eventfilter things in the Things DB or anywhere… It looks like they are completely ignored…
What could be wrong?


Bridge icalendar:calendar:deadbeef    "My calendar" @ "Internet" [ url="http://nextcloud/remote.php/dav/calendars/foobar/personal?export", username="...", password="...", refreshTime=4 ]
Thing  icalendar:eventfilter:feedd1d1 "Away Events C" (icalendar:calendar:deadbeef) [ maxEvents=1, refreshTime=5, textEventField="DESCRIPTION", textEventValue="away", textValueType="TEXT"]
Thing  icalendar:eventfilter:feedd2d2 "Away Events E" (icalendar:calendar:deadbeef) [ maxEvents=1, refreshTime=5, datetimeUnit="DAY", datetimeStart=1, datetimeEnd=2, datetimeRound=true]


// gets updates
String   next_event_name "next event [%s]"                      <calendar> { channel="icalendar:calendar:deadbeef:next_title" }

// nothing happens...
String   away_event_name_tomorrow "away event [%s]"                         <calendar> { channel="icalendar:eventfilter:feedd1d1:result_0#title" }
String   first_event_name_tomorrow "first event [%s]"                         <calendar> { channel="icalendar:eventfilter:feedd2d2:result_0#title" }

Sorry, the event filter is not included in 2.5.x and i won’t support 2.5.x anymore. I’m also pretty sure the event filter was not backported to 2.5 as it was merged into 3.0.

Oh, too bad. Thanks, then I can at least stop searching. I already thought something like that. A comment in the docs might have saved me some hours… :sweat_smile:

This topic was automatically closed 41 days after the last reply. New replies are no longer allowed.