Parse data for waste collection

I am trying to come up with a way how to parse data and create calendar events accordingly based on waste type.
My local garbage company has android app to notify for waste collection. Basically there are 3 types of garbage. I intercepted android app and it calls this URL to get the schedule:

https://vylozsmeti.kabernet.sk/api/public/schedule?locationId=99&year=2024

This contains all events for year 2024. Basically what matters is wasteId and date - I just can’t figure out how to properly store the array and run calendar action for all array fields. Any help would be appreciated.

You can use a REST command to retrieve the data.

#configuration.yaml
rest_command:
  get_waste_data:
    url: "https://vylozsmeti.kabernet.sk/api/public/schedule?locationId=99&year={{now().year}}"
    method: GET

Then use the response data in an automation or sensor. To populate the whole year’s events you can use a Repeat for Each action to iterate over all the items that are returned so they supply the data for the calendar.create_event action. Here’s a basic outline of the action sequence that would go in an automation or script:

...
  - action: rest_command.get_waste_data
    response_variable: waste
  - repeat:
      for_each: "{{ waste.content }}"
      sequence: 
        - variables:
            type: "{{ repeat.item.wasteType}}"  #Should this return the type number or a description?
            date: "{{ repeat.item.date | as_datetime }}"
        - action: calendar.create_event
          target:
            entity_id: calendar.EXAMPLE
          data:
            summary: "{{ type }}" 
        #    Do you want all-day events or not?

        - delay: 2  #To keep the repeat from spamming the Calendar integration
....

If you can give a more specific description of how you want to construct the calendar events, we can give you more specific help with the automation.

I use a similar script for my trash calendar, though our collection company does not provide the dates so the templating is more complex. FWIW, I have a couple examples on my github (https://gist.github.com/Didgeridrew/491fa955ef2fe7c4f16bc503ac121db8) if you want to take a look at them.

Keep in mind that this doesn’t have any anti-duplication built in, so if you run it multiple times you will end up with multiple calendar events. Anti-duplication could be added by using the calendar.get_events action and then comparing dates, but I haven’t found it to be a problem with my instance.

This helped a lot. I moved a little further. I am OK with adding all day events, so I templated start and end date. This works fine and populates desired dates. However I would like to substitute wasteId with type, there are only 3 types:

2 - Generic Waste
5 - Paper
7 - Plastic

My script looks as follows, but it does not subsitute summary - I guess I am doing something stupid here:

alias: Waste
sequence:
  - action: rest_command.get_waste_data
    response_variable: waste
    data: {}
  - repeat:
      for_each: "{{ waste.content }}"
      sequence:
        - variables:
            type: "{{ repeat.item.wasteId}}"
            date: "{{ repeat.item.date }}"
        - action: calendar.create_event
          target:
            entity_id: calendar.waste
          data:
            summary: >-
              {% if type == '2' %}
              General Waste
              {% elif type == '5' %}
              Paper
              {% elif type == '7' %}
              Plastic
              {% endif %}
            start_date: "{{as_timestamp(date) | timestamp_custom('%Y-%m-%d')}}"
            end_date: >-
              {{(as_timestamp(date) + (24*3600)) | timestamp_custom('%Y-%m-%d')
              }}
        - delay: 1

wasteId is an integer so you need to use integers, not strings, in your if/then. Remove the quote marks around the values:

...
            summary: >-
              {% if type == 2 %}
              General Waste
              {% elif type == 5 %}
              Paper
              {% elif type == 7 %}
              Plastic
              {% endif %}
....

Thank you. I figured I need few more variables - whether schedule is biweekly or monthly. So I have added new variables:

...
        - variables:
            type: "{{ repeat.item.wasteId}}"
            date: "{{ repeat.item.date }}"
            isbiweekly: "{{ repeat.item.isBiweekly }}"
            ismonthly: "{{ repeat.item.isMonthly }}"
...

And I have created dropdown entity that defines what schedule I want to populate.
I have tried creating additional if-then condition:

        - if:
            - condition: state
              entity_id: input_select.waste_frequency
              state: Bi-Weekly
          then:
            - if:
                - condition: template
                  value_template: "{{isbiweekly}}==true"
              then:
                - action: calendar.create_event
                  target:
                    entity_id: calendar.waste
                  data:
                    summary: >-
                      {% if type == 2 %} General Waste {% elif type == 5 %}
                      Paper {% elif type == 7 %} Plastic {% endif %}
                    start_date: "{{as_timestamp(date) | timestamp_custom('%Y-%m-%d')}}"
                    end_date: >-
                      {{(as_timestamp(date) + (24*3600)) |
                      timestamp_custom('%Y-%m-%d')}}

I see in a trace that variables are picked up properly:

Iteration 1

repeat:
  first: true
  index: 1
  last: false
  item:
    scheduleId: 73894
    wasteId: 2
    wasteType: 1
    date: '2024-01-02T00:00:00+01:00'
    isBiweekly: true
    isMonthly: false
type: 2
date: '2024-01-02T00:00:00+01:00'
isbiweekly: true
ismonthly: false

But I am failing at comparing those in my condition - it always fails. I am not sure if template is the correct one. Idea is to only add event to calendar if it is matching my frequency (that I can define via dropdown).

There’s also GitHub - mampfes/hacs_waste_collection_schedule: Home Assistant integration framework for (garbage collection) schedules which basically does exactly this.

You’re not actually performing a comparison because the operator and second arg are outside the delimiters, they would need to be inside like:

            - if:
                - condition: template
                  value_template: "{{isbiweekly == true}}"

… but since the variable returns a boolean, you don’t actually need the equality comparison:

            - if:
                - condition: template
                  value_template: "{{isbiweekly}}"

My country is not listed, and I am not sure that static mode supports this?

In that case you can request it here: Sign in to GitHub · GitHub at “Source Request - Request that a municipality or region is supported”. It’s good that it’s a JSON API instead of some more complicated source (some garbage collection companies only offer rendered HTML pages).

I did request it now.

Thanks again. This worked. I am going to try to create a logic for not adding duplicates, I will post here in case I succeed or fail.