Caldav configuration

Like many components in HA, the documentation for CalDav is still pretty vague.

I still don’t understand how or what to put in the optional calendars variable.

calendar:
  - platform: caldav
    url: !secret caldav_url
    username: !secret caldav_username
    password: !secret caldav_password
    calendars: ????

I’ve tried a lot of configuration changes and I cannot figure this one out.

I can’t set calendars or custom_calendars sections.

If I don’t, I get 2 calendars components, one named after the calendar name (‘calendar.events’), the other after the user name (‘calendar.Me_calendar’), and a calendar group.
I have a Davical server at home on an ubuntu VM, configuration looks like this :

calendar:
  - platform: caldav
    url: http://192.168.1.1:81/caldav.php/
    username: me
    password: mypass
    cert_path: false

If I add a “calendars” list or a custom_calendars list, it fails, I see nothing and it hasn’t a log error.
I was expecting this configuration to create 2 sensors, one for “home office” and one for “holiday” :

 calendar:
  - platform: caldav
    url: http://192.168.1.1:81/caldav.php/
    username: me
    password: mypass
    cert_path: false
    custom_calendars:
      - name: 'Home Office'
        calendar: 'events'
        search: 'home'
      - name: 'DayOff'
        calendar: 'events'
        search: 'Holiday'

For the “calendars” section, I’ve tried several syntaxes, none proved useful :

  • calendars: ‘events’
  • calendars :
    - name: ‘events’
  • or the same structure as ‘custom_calendars’

First 2 do nothing at all, latter breaks the calendar entries

I get this error when I start HomeAssistant and there is an event going on in the calendar :

Sun Jan 07 2018 13:15:44 GMT+0100 (CET)

Error while setting up platform caldav

Traceback (most recent call last):
  File "/usr/homeassistant/lib/python3.5/site-packages/vobject/base.py", line 529, in __getattr__
    return self.contents[toVName(name)][0]
KeyError: 'dtend'

During handling of the above exception, another exception occurred:

Traceback (most recent call last):
  File "/usr/homeassistant/lib/python3.5/site-packages/homeassistant/helpers/entity_component.py", line 171, in _async_setup_platform
    SLOW_SETUP_MAX_WAIT, loop=self.hass.loop)
  File "/usr/lib/python3.5/asyncio/tasks.py", line 392, in wait_for
    return fut.result()
  File "/usr/lib/python3.5/asyncio/futures.py", line 274, in result
    raise self._exception
  File "/usr/lib/python3.5/concurrent/futures/thread.py", line 55, in run
    result = self.fn(*self.args, **self.kwargs)
  File "/usr/homeassistant/lib/python3.5/site-packages/homeassistant/components/calendar/caldav.py", line 102, in setup_platform
    WebDavCalendarEventDevice(hass, device_data, calendar)
  File "/usr/homeassistant/lib/python3.5/site-packages/homeassistant/components/calendar/caldav.py", line 120, in __init__
    super().__init__(hass, device_data)
  File "/usr/homeassistant/lib/python3.5/site-packages/homeassistant/components/calendar/__init__.py", line 72, in __init__
    self.update()
  File "/usr/homeassistant/lib/python3.5/site-packages/homeassistant/components/calendar/__init__.py", line 138, in update
    if not self.data or not self.data.update():
  File "/usr/homeassistant/lib/python3.5/site-packages/homeassistant/util/__init__.py", line 306, in wrapper
    result = method(*args, **kwargs)
  File "/usr/homeassistant/lib/python3.5/site-packages/homeassistant/components/calendar/caldav.py", line 164, in update
    and not self.is_over(event.instance.vevent))), None)
  File "/usr/homeassistant/lib/python3.5/site-packages/homeassistant/components/calendar/caldav.py", line 164, in <genexpr>
    and not self.is_over(event.instance.vevent))), None)
  File "/usr/homeassistant/lib/python3.5/site-packages/homeassistant/components/calendar/caldav.py", line 208, in is_over
    return dt.now() > WebDavCalendarData.to_datetime(vevent.dtend.value)
  File "/usr/homeassistant/lib/python3.5/site-packages/vobject/base.py", line 531, in __getattr__
    raise AttributeError(name)
AttributeError: dtend

Are you one 0.60.0 or 0.60.1? I have updated my HA to 0.60.1 and have no problem at all except that I have no idea how to make use of the calendars variable. If I put one of the calendars name in it, it will create only one calendar entity in HA. I have 6 calendars in my CalDav account and I want HA to discover only 4 but I have no idea how to do that using the calendars variable.

0.60.1 it failed with 0.60.0.
Now it sort of connects (I see the established/closing sockets in the servers)
I’m trying first with my account, where there are 3 collections (contacts, calendar for events, calendar for tasks). I get the error when I start HA and there is an event, so I guess it can read the ‘events’ collection at least.
If I start when there is no event, I see the calendar objects, but they do nothing and never turn on, even if it reaches an appointment.

calendars entry should be a list, and in the code, it turns the config value into a list, but that doesn’t help as I don’t know how it would need it defined. I’ve since tried calendars: ‘[events]’ or “[‘event’]” and some other python list format but I had no success !

I agree, the documentation of this component requires more details/examples.

I am using SOGo, and could connect using the standard CalDAV URL that appears under ‘Links to this Calendar’.

In the calendars configuration (list of strings) I had to specify the exact name as it appears in the SOGo user interface. In my particular case I access a shared calendar, and its name contains the full name and e-mail address of the sharing user in brackets - all that needs to go into the entry in the calendars configuration.

I was able to specify an entry in custom_calendars. The search entry is apparently a regular expression which tries to match a calendar event’s summary, location or description. I was able to for example find calendar events for garbage collection like this search: 'Garbage.*'. However, I found that only single calendar events match, not series of events. Not sure if this is because series of events are not supported in general, or if they are not supported my CalDAV server. Also, a series of all-day-events doesn’t seem to turn a sensor on.

Can you share your (anonymized) configuration here ?

The SoGo base URL is http://<IP>/SoGo/dav, that’s what you put in the URL field ?
Then the calendar is ‘/Calendar/personal/’ and this is the calendars field ?
You never put the user name that should be in the full URL, it will be built from the fields ?

DaviCal url being http://<IP>/caldav.php/<my user name>/<calendar name>, it should be the same ?

Sure, here we go:

calendar:
  - platform: caldav
    url: https://<server>/SOGo/dav/hass/
    username: hass
    password: !secret caldav_hass_password
    calendars:
      - 'House (Sharing User <[email protected]>)’
    custom_calendars:
      - name: 'Waste Collection'
        calendar: 'House (Sharing User <[email protected]>)'
        search: 'Garbage.*'

I created a user hass in SOGo. The calendar ‘House’ is owned by a different user (named ‘Sharing User’ in the above) and is shared with user hass.

@exxamalte thx thats work for me for my owncloud config

- platform: caldav
  url: https://owncloud_server/remote.php/caldav/calendars/jerome/defaultcalendar
  username: jerome
  password: !secret caldav
  calendars: hass

now just to understand how to get message, probably a template magic that i not find ;-(
normaly it would be {{states(‘calendar.hass_hass_cal.message’)}}, but this give me nothings

Similar to other sensors. If a calendar event is active, something like the following should give you the message:
{{ states.calendar.hass_hass_cal.attributes.message }}.

Ah thanks, there are some progresses here thanks to your conf. I didn’t think I needed the ‘-’ for just one entry, guess it’s the only syntax I didn’t try :roll_eyes:

For my Davical server, I have this configuration :

calendar:
 - platform: caldav
    url: http://192.168.1.1:81/caldav.php/
    username: !secret dav_user
    password: !secret dav_pass
    cert_path: false
    calendars: 
       - 'Events'

In the URL field, I can put only the base URL, or the full one, completed with username/calendar_name.

Now, I get the same error everytime, that there’s something wrong with a DTEND field. (same as I posted 2 days ago).
So I guess configuration is fine now and there’s some bug, either in the caldav component, or in a caldav sync app that I use and there’s something wrong in the server. I have over 7000 events in my shared calendar, could take a while…
If I change the ‘calendars’ entry to point to another collection (I have a ‘My Tasks’ for instance), it starts well but there’s no point there as it’s only tasks, no events !

thanks, that’s works

thanks. somehow it doesn’t work if I combine calendar and custom_calendars in the same platform. I have to split them up like this…

calendar:
  - platform: caldav
    url: !secret caldav_url
    username: !secret caldav_username
    password: !secret caldav_password
    calendars:
      - 'Personal'
      - 'Family'
      - 'Holidays'
      - 'Work'

  - platform: caldav
    url: !secret caldav_url
    username: !secret caldav_username
    password: !secret caldav_password
    custom_calendars:
      - name: 'School Events'
        calendar: 'School'
        search: 'School Events'
      - name: 'School Holiday'
        calendar: 'School'
        search: 'Holiday'
1 Like

It just won’t work with my davical server, even if the caldav 0.5.0 documentation (the base component) says it’s been tested against.
I get the previous error when I start HA.

If I test from the library itself, it fails too, so I’m kinda stuck here :

(homeassistant) homeassistant@services:/usr/homeassistant/lib/python3.5/site-packages/caldav$ python -i davclient.py 

>>> import caldav
>>> client = caldav.DAVClient(' http://192.168.1.1:81/caldav.php/', None, 'user', 'pass')
>>> principal = client.principal()
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
  File "/usr/homeassistant/lib/python3.5/site-packages/caldav/davclient.py", line 113, in principal
    return Principal(self)
  File "/usr/homeassistant/lib/python3.5/site-packages/caldav/objects.py", line 316, in __init__
    cup = self.get_properties([dav.CurrentUserPrincipal()])
  File "/usr/homeassistant/lib/python3.5/site-packages/caldav/objects.py", line 192, in get_properties
    raise Exception("The CalDAV server you are using has "
Exception: The CalDAV server you are using has a problem with path handling.

Same with URL : http://user:[email protected]:81/caldav.php, or with URL http://192.168.1.1:81/caldav.php/user/events/

Now it works with 0.61, I can see the custom_calendars.
But like @masterkenobi, I can’t set the “calendars” and “custom_calendars” fields or it will fail.

Did some debug and I think the problem is in the underlaying library, so I don’t know where to declare the bug ?
Turns out the event in the server doesn’t store a “dtend” field, but instead has a “duration” field along with a “dtstart” field. So the caldav component initialize well when there’s no event going on, but once it hits the event, it fails.

Example of a session :

>>> import caldav
>>> from homeassistant.util import dt
>>> from datetime import datetime, timedelta
>>> cal = caldav.DAVClient('http://mydavicalserver:81/caldav.php/', None, 'Me','mypass')
>>> cals = cal.principal().calendars()
>>>> cals
[Calendar(http://xxxx:81/caldav.php/me/events/), Calendar(http://xxx:81/caldav.php/me/calendar/)]
>>> ev = cals[0]
>>> res = ev.date_search(dt.start_of_local_day(), dt.start_of_local_day() + timedelta(days=1))
>>> res[0].instance
<VCALENDAR| [<VERSION{}2.0>, <PRODID{}-//ddaysoftware.com//NONSGML DDay.iCal 1.0//EN>, <VEVENT| [<UID{}44673fb3-907b-43b7-a9c9-XXXXXXXXXXXX>, <DTSTART{}2018-01-31 12:00:00+00:00>, <DURATION{}2:00:00>, <CLASS{}PUBLIC>, <DTSTAMP{}2018-01-18 16:20:41+00:00>, <LOCATION{}RdC>, <PRIORITY{}5>, <SEQUENCE{}0>, <SUMMARY{}Event>, <TRANSP{}OPAQUE>, <X-MICROSOFT-CDO-BUSYSTATUS{}BUSY>]>]>
>>> res[0].instance.vevent.dtend.value
Traceback (most recent call last):
  File "/usr/homeassistant/lib/python3.5/site-packages/vobject/base.py", line 529, in __getattr__
    return self.contents[toVName(name)][0]
KeyError: 'dtend'

Of course, this calendar structure is correct, any DAV client I tested works fine (Outlook with CalDav Synchronizer, Thunderbird, DaviCal…)

Anyone gotten this working with a Radicale server?

I can’t figure out which URL to use to get it to work successfully.

If I put in http://mydomain.com:5232/ or the URL to a specific calendar, the components loads a list of all my calendars on my server, but they don’t show any information (state “off”).

My logs just say “Set up of calendar is taking over 10 seconds”.

The DTEND issue has been solved here. Shoould be integrated in 0.64, but you can already use it as a custom_component to test.
Now I have the caldav components working, finding all events, and I can filter too.

But as you stated @masterkenobi there’s no way to combine the whole calendar usage with the “calendar:” option, and custom_calendar with a search.
I found a work-around I expect it to cause some charge on the server but it works for me.
Remember that the “search” field uses a regular expression. So :

custom_calendars:
  - name: 'Everything'
    calendar: 'Events'
    search: '.*'

looks for any event that matches any number of any char in title/location/description :wink:

Ok this is driving me crazy. I’m on 0.63.3 and I migrated my CalDAV server to Baikal in an attempt to get this to work, but still nothing.

Error while setting up platform caldav
Traceback (most recent call last):
  File "/usr/lib/python3.6/site-packages/homeassistant/helpers/entity_platform.py", line 84, in async_setup
SLOW_SETUP_MAX_WAIT, loop=hass.loop)
  File "/usr/lib/python3.6/asyncio/tasks.py", line 358, in wait_for
return fut.result()
  File "/usr/lib/python3.6/asyncio/futures.py", line 245, in result
raise self._exception
  File "/usr/lib/python3.6/concurrent/futures/thread.py", line 56, in run
result = self.fn(*self.args, **self.kwargs)
  File "/usr/lib/python3.6/site-packages/homeassistant/components/calendar/caldav.py", line 98, in setup_platform
WebDavCalendarEventDevice(hass, device_data, calendar)
  File "/usr/lib/python3.6/site-packages/homeassistant/components/calendar/caldav.py", line 111, in __init__
super().__init__(hass, device_data)
  File "/usr/lib/python3.6/site-packages/homeassistant/components/calendar/__init__.py", line 72, in __init__
self.update()
  File "/usr/lib/python3.6/site-packages/homeassistant/components/calendar/__init__.py", line 138, in update
if not self.data or not self.data.update():
  File "/usr/lib/python3.6/site-packages/homeassistant/util/__init__.py", line 306, in wrapper
result = method(*args, **kwargs)
  File "/usr/lib/python3.6/site-packages/homeassistant/components/calendar/caldav.py", line 141, in update
dt.start_of_local_day() + timedelta(days=1)
  File "/usr/lib/python3.6/site-packages/caldav/objects.py", line 506, in date_search
response = self._query(root, 1, 'report')
  File "/usr/lib/python3.6/site-packages/caldav/objects.py", line 133, in _query
raise error.exception_by_method[query_method](errmsg(ret))
caldav.lib.error.ReportError: 500 Internal Server Error

b'<?xml version="1.0" encoding="utf-8"?>\n<d:error xmlns:d="DAV:" xmlns:s="http://sabredav.org/ns">\n  <s:sabredav-version>3.1.3</s:sabredav-version>\n  <s:exception>Sabre\\VObject\\EofException</s:exception>\n  <s:message>End of document reached prematurely</s:message>\n</d:error>\n'

I’m using the latest Baikal, with this URL to my ‘personal’ calendar:

http://dav.myhost/cal.php/calendars/brad/personal

Which is exactly the format that the example config is using, so I dunno what to do here. With Radicale server, I could get it to connect and load calendars, but events would not come through. Now, nothing.

The 500 error makes me think the URL isn’t right, but that you can connect to the server (IP and PORT are ok)
I don’t know the specifics for the server you’re using, but with the Davical server, the full URL is http://myserver:port/caldav.php/user/calendar_name
And the url in the configuration is just the server’s : http://myserver:port/caldav.php/

So if I can guess with your server, url could be http://ip:port/cal.php/calendars or just http://ip:port/cal.php/ (I think the former makes sense).
Then your username in the configuration should be “brad”
And then “personal” is the calendar name that’s you’ll use either in the “calendars” list, or as the source calendar (field “calendar:” not “name:” that is the friendly name) of a custom_calendar with a search string.