Request for CalDAV Calendar Component

thanks. but i have tried both places; custom_components and /usr/local/lib/python3.4/dist-packages/homeassistant/components/calendar and still not working. I have upgraded to HA 0.49.0 and still no luck.

Try
pip3 install caldav

thanks. but still not successful. i saw few reds during installation process. The errors are basically the same one in the HA log.

OK. Somehow I managed to solve this by executing theseā€¦

sudo apt-get update
sudo apt-get install -t jessie python-dev
sudo apt-get install libxml2-dev libxslt-dev
sudo pip3 install caldav

I can confirm that it works. However, the behavior is a bit different from the Google Calendar component.

In google calendar, the entity attributes always show the upcoming event in the calendar with state off. The state will become on when the event time reach.

However in this component, the entity attributes show null with the state off when there is no event during that moment. When the event time is reach, the state will change to on and the attributes of that event will be displayed.

Is that normal?

It works for me as well. I just get this message in the logs

/home/graham/.virtualenvs/homeassistant/lib/python3.5/site-packages/requests/packages/urllib3/connectionpool.py:852: InsecureRequestWarning: Unverified HTTPS request is being made. Adding certificate verification is strongly advised. See: https://urllib3.readthedocs.io/en/latest/advanced-usage.html#ssl-warnings
  InsecureRequestWarning)

which is presumably because I have cert_path: False. How do I obtain or locate a certificate that would remove the warning?

Iā€™m glad you could solve the issues regarding the installation of caldav, Iā€™m sorry I couldnā€™t write earlier.

I think this issue is already fixed. I did some improvements to the caldav components yesterday evening (around 22:30 CEST). Just download it again.

I will (re)investigate the issue this evening and let you know in case of any progress. As previously mentioned, the component is still under active development and itā€™s my first contribution to home-assistant so I do not have much experience in regard to its code.

Thanks for testing and reporting!

1 Like

Yes this is because cert_path is set to False. This will encrypt your connection but a man-in-the-middle attack would still be possible because your certificate is not verified.

If you have a certificate installed which is signed by a root CA (like letā€™s encrypt) you can simply set cert_path: True. If you use a self-signed certificate, set the cert_path=/path/to/public_key.pem.

Maybe cert_path is not the best name for this setting, I might have to change thatā€¦ :upside_down:

This is the intended behaviour. Itā€™s the same with the google calendar. To have another behaviour the underlying base calss has to be adapted.

This is not the goal of my current implementation, but it looks like other people might take care of this feature.

Thank you so much for your contribution. You just made my dream come true. I hope this will made it into official component soon.

Anyway, if itā€™s not too much to ask for, maybe you can improve the component further by having extra option in the config to specify the duration to check for events. It will list down the upcoming events that is within the duration. Perhaps as a new sensor component.

Iā€™m trying to create my own Jarvis. When I ask, ā€œJarvis, what do I have for today?ā€, It will reply ā€œToday you have 3 events. First event is meeting with John at 9am. Second event is call Mark at 12 noon and the last one is get a gift for Sara.ā€. At the moment, it canā€™t do that.

I finally realized (I think) that what you mean is that the server running the calendar has a certificate signed by a root CA. So I set cert_path: True and the message went away.

Iā€™ll give my best to make an official component ASAP.

As already mentioned in this comment it is required to update the underlying base class. This brings a lot of changes and the Google Calendar component must be updated, too. This is currently not my plan, although some small changes might come afterwards. :slight_smile:

IMO the use-case which you described shouldnā€™t also be part of home assistant since home assistant is a software to control and automate your home and is not like a personal assistant. As long as there are no users, I donā€™t think such a feature will become useful, since my sister doesnā€™t care about my appointments and vice versa.

If you plan to build your personal assistant with Jasper it might be the best solution to implement such a behaviour as a Jasper Module. I do not have much experience with Jasper, but the documentation looks pretty straightforward. Depending on your programming knowledge it might be quite easy to convert my home assistant component into a Jasper module.

To give you an easy start here are the steps required for conversion:

  1. Create a new module as described here
  2. Update the handle function to load the calendar data (some code snippets bellow)
from caldav import DAVClient

# Create a DAVClient
client = DAVClient("caldav_url",
                   username="username",
                   password="password",
                   ssl_verify_cert=True)  # or False or path to self signed cert
principal = client.principal()

# Get all calendars
calendars = principal.calendars()

my_cal = None
for cal in calendars:
    if cal.name == 'calendar_name':
        my_cal = cal  # my_cal contains your calendar

# Search for events
events = my_cal.date_search(datetime.utcnow(),
                            datetime.utcnow() + timedelta(days=1))

# Loop trough all events
for event in events:
    cal = Calendar.from_ical(event.data)
    for e in cal.walk('vevent'):
        summary = e.get('SUMMARY', '')
        start = e.get('DTSTART', '').dt
  1. Patch the information gathered together in a string and return it (it will be handled by Jasper)
1 Like

Agree with your point. it is more suitable for AI. Thanks for your sample.

@mblaettler

I updated my test machine to HA 0.55 this evening, and I now get this error with the caldav component

2017-10-09 19:27:13 ERROR (MainThread) [homeassistant.components.calendar] Error while setting up platform caldav
Traceback (most recent call last):
  File "/srv/homeassistant/lib/python3.5/site-packages/homeassistant/helpers/entity_component.py", line 164, in _async_setup_platform
    SLOW_SETUP_MAX_WAIT, loop=self.hass.loop)
  File "/usr/lib/python3.5/asyncio/tasks.py", line 400, in wait_for
    return fut.result()
  File "/usr/lib/python3.5/asyncio/futures.py", line 293, 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 "/home/homeassistant/.homeassistant/custom_components/calendar/caldav.py", line 70, in setup_platform
    principal = client.principal()
  File "/srv/homeassistant/lib/python3.5/site-packages/caldav/davclient.py", line 113, in principal
    return Principal(self)
  File "/srv/homeassistant/lib/python3.5/site-packages/caldav/objects.py", line 316, in __init__
    cup = self.get_properties([dav.CurrentUserPrincipal()])
  File "/srv/homeassistant/lib/python3.5/site-packages/caldav/objects.py", line 182, in get_properties
    response = self._query_properties(props, depth)
  File "/srv/homeassistant/lib/python3.5/site-packages/caldav/objects.py", line 109, in _query_properties
    return self._query(root, depth)
  File "/srv/homeassistant/lib/python3.5/site-packages/caldav/objects.py", line 127, in _query
    url, body, depth)
  File "/srv/homeassistant/lib/python3.5/site-packages/caldav/davclient.py", line 127, in propfind
    return self.request(url or self.url, "PROPFIND", props, {'Depth': str(depth)})
  File "/srv/homeassistant/lib/python3.5/site-packages/caldav/davclient.py", line 227, in request
    r = requests.request(method, url, data=to_wire(body), headers=combined_headers, proxies=proxies, auth=auth, verify=self.ssl_verify_cert)
  File "/srv/homeassistant/lib/python3.5/site-packages/requests/api.py", line 58, in request
    return session.request(method=method, url=url, **kwargs)
  File "/srv/homeassistant/lib/python3.5/site-packages/requests/sessions.py", line 518, in request
    resp = self.send(prep, **send_kwargs)
  File "/srv/homeassistant/lib/python3.5/site-packages/requests/sessions.py", line 639, in send
    r = adapter.send(request, **kwargs)
  File "/srv/homeassistant/lib/python3.5/site-packages/requests/adapters.py", line 405, in send
    self.cert_verify(conn, request.url, verify, cert)
  File "/srv/homeassistant/lib/python3.5/site-packages/requests/adapters.py", line 225, in cert_verify
    "invalid path: {0}".format(cert_loc))
OSError: Could not find a suitable TLS CA certificate bundle, invalid path: True

It looks like cert_path: True is now being treated as an actual path, rather than a flag :confused:

My config is

calendar:
  - platform: caldav
    url: !secret owndrive_url
    user: !secret owndrive_username
    password: !secret owndrive_password
    cert_path: True
    entities:
      - cal_id: Waste
        sensors:
          - device_id: waste
            name: Waste Pick Up
            track: true

Which has been working on 0.52 for a while now.

Edit 2:
WIth the magic of VirtualBox snapshots, I have been able to track down that the problem actually started in release 0.54, although there doesnā€™t seem to be anything in the release notes that indicate any changes in this sort of area.

Edit 3:
I had some time to play around, and it seems that the ssl_verify_cert parameter now has to be a boolean rather than a string. Iā€™ve tried this code, and it seems to work for me, but == "True" may actually need to != "False" in general, depending on what the local certificates actually represent.

    client = DAVClient(config.get(CONF_CALDAV_URL),
                       username=config.get(CONF_CALDAV_USER),
                       password=config.get(CONF_CALDAV_PASSWORD),
                       ssl_verify_cert=config.get(CONF_CALDAV_CA_PATH, None) == "True"
                       )

Coming from a C++/Java background, I have no idea how Python programs get to last more than a few releases if the type of a parameter can change arbitrarily.

Hi

Sorry for the late response and thanks for your investigation. Due to unplanned events in August and university start in September I was not able to make my component release ready.

Iā€™ll take a look into it by the beginning of November.

2 Likes

Any updates on the development of the CalDav Calendar component? I could really use this component. Iā€™m trying to build an automated bedtime reminder automation that will use calendar events.

The custom component above works fine for me. I use it to remind me to put out the rubbin/recycling/garden waste from a calendar I download from the local council web site.

1 Like

Did some fiddling with the CalDAV component as mentioned earlier. I decided to use the Synology CalDAV service from the Synology Calendar package. Unfortunately I couldnā€™t get it to work so I installed Nextcloud 12 with the Calendar (CalDAV) support. I can confirm this custom component works with HA 0.57.3. Now I can continue my project to build a bedtime automation. The next big hurdle is finding/building a script that checks for the first event the next morning, calculate back to when bedtime should start and add an event to the bedtime calendar. The automation will switch the lights off or dim the lights at bedtime. Maybe switch on some nightstand lights in my bedroomā€¦ :sunglasses:

Just a heads up: Iā€™m currently working on changing the Calendar component, so itā€™s able to hold multiple events attached to it. This allows (currently) to show a list of all events in the UI, and opens the possibility to create an actual calendar later on. You can check the PR here: [Calendar Update](https://github.com/home-assistant/home-assistant/pull/10192)

1 Like

Hi,
Iā€™m considering moving from OpenHab to HomeAssistant to control my central heating system (mostly because itā€™s Python). Controlling the temperature setting through Ć  nextcloud calendar is mandatory for me.
Iā€™ve tried the caldav calendar component and get the same result as 1337hium. The calendar component shows up on the web page but without appointments.
After some hours trying to find out how all that stuff works Iā€™ve come to the conclusion the problem comes from the test line 142 : `

self.event = items[0] if len(items) == 1 else None

Hereā€™s my guessing : the update function retrieves all the events between the actual time and actual time +1 days in the ā€œitemsā€ list (lines 130 to 140).
If thereā€™s more than one event in the list then len(items) will be greater than 1 and self.event will be set to None instead of the next appointment thatā€™ll arise.

Iā€™ve a quick and dirty fix by commenting the test :

self.event = items[0] # if len(items) == 1 else None

And the next appointment appeared as expected.
Of course this fix will have to be enhanced to avoid getting an error if theyā€™re is no appointment in the next day.

Next step : figure out how to set the temperature from the appointment.