Homeassistant Track Dates

I want to have the next waste disposal dates in Homeassistant. There is an all-solved-solution (hacs_waste_collection_schedule) that also supports the city I live in. But this is a lot of code to copy around when not using Home Assistant Community Store, which I try no to use.

A while ago I wrote a bit of code to parse the ical for waste dates from the city of Stuttgart and documented it in a post. Let us modify this script to generate the json we need for template webhook upload in homeassistant.

But first the homeassistant configuration that is needed:

template:
  - trigger:
      - platform: webhook
        webhook_id: !secret waste-disposal
        allowed_methods:
          - POST
        local_only: true
    unique_id: "waste"
    sensor:
      - name: "residual_waste"
        state: "{{ trigger.json.residual_waste }}"
        device_class: date
        unique_id: "residual_waste"
      - name: "waste_paper"
        state: "{{ trigger.json.waste_paper }}"
        device_class: date
        unique_id: "waste_paper"
      - name: "yellow bag"
        state: "{{ trigger.json.yellow_bag }}"
        device_class: date
        unique_id: "yellow_bag"

The script to upload will run on the same host as the homeassistant, so local_only can be true.

Now the script that downloads the calendar and uploads to home assistant:

import datetime
import json
import sys
from pathlib import Path
import requests


def parse(stream):
    ds = {}
    for line in stream.split("\n"):
        if line.strip() == "BEGIN:VEVENT" and ds:
            yield ds
            ds = {}
        if line.startswith("DTSTART"):
            ds["date"] = str(
                datetime.datetime.strptime(
                    line.split(":")[-1].split("T")[0], "%Y%m%d"
                ).date()
            )
        if line.startswith("SUMMARY"):
            ds["summary"] = line.split(":")[-1].strip()


if __name__ == "__main__":
    # copy webhook secret into file .secret
    secret = (Path(__file__).parent / ".secret").open().read().strip()

    # url is set in the first commandline argument
    r = requests.get(url=sys.argv[1])
    key_map = {
        "Restmüll 02-wöchentl.": "residual_waste",
        "Altpapier 03-wöchentl.": "waste_paper",
        "Gelber Sack 03-wöchentl.": "yellow_bag",
    }
    dataset = {}
    for item in parse(r.text):
        _k = item.get("summary")
        if _k in key_map:
            dataset[key_map[_k]] = item.get("date")
            del key_map[_k]

    r = requests.post(f"http://localhost:8123/api/webhook/{secret}", json=dataset)
    assert r.status_code == 200

The modifications to the original version in the blogpost are: - using requests -- because it is already installed - the addition of a key_map to name the keys to the same keys expected by the sensor template - code to push to homeassistant

The result in homeassistant looks like this:

screenshot of waste collection dates in homeassistant dashboard