Repository: mampfes/hacs_waste_collection_schedule

Issue:
data.umweltprofis.at: iCal service retired
I had to change the interval in my data.umweltprofis.at waste schedule when I noticed that the server throws an error when requesting a new iCal link at https://data.umweltprofis.at/opendata/AppointmentService/index.aspx

I contacted their support and they told me that this service is not going to be fixed because they are currently working on (another?) app.

Should this integration be marked as broken for the time being? Existing iCal URLs continue to work, at least for the time being.


Discussion:
@andyboeh i'm also having the same problem, wrote to them some weeks ago but didn't get an answer.
 did you manage to find a workaround? or do we have to wait?
Unfortunately, I don't know more than what I already wrote above. I'm not aware of any newer app either, but I didn't research that further.

At the same page where you request the iCal link you can also request data in XML format. The link contains a key and I'm unsure for how long this key is valid or if it ever changes. Parsing the XML data shouldn't be too difficult. BUT: The data contained therein starts in November 2021 and ends in December 2022. I'm unsure if that data is going to be updated.

There is also the GEM2GO app that can display this schedule, but I did not further investigate where they get their data from.
ok, i see... thanks for reply... maybe theres a solution with a self created calendar and wast collection schedule...

Resolving patch:
diff --git a/custom_components/waste_collection_schedule/waste_collection_schedule/source/data_umweltprofis_at.py b/custom_components/waste_collection_schedule/waste_collection_schedule/source/data_umweltprofis_at.py
--- a/custom_components/waste_collection_schedule/waste_collection_schedule/source/data_umweltprofis_at.py
+++ b/custom_components/waste_collection_schedule/waste_collection_schedule/source/data_umweltprofis_at.py
@@ -1,5 +1,7 @@
 import logging
 import requests
+from datetime import datetime
+from xml.dom.minidom import parseString
 from waste_collection_schedule import Collection  # type: ignore[attr-defined]
 from waste_collection_schedule.service.ICS import ICS
 
@@ -8,17 +10,33 @@
 URL = "https://www.umweltprofis.at"
 TEST_CASES = {
     "Ebensee": {"url": "https://data.umweltprofis.at/OpenData/AppointmentService/AppointmentService.asmx/GetIcalWastePickupCalendar?key=KXX_K0bIXDdk0NrTkk3xWqLM9-bsNgIVBE6FMXDObTqxmp9S39nIqwhf9LTIAX9shrlpfCYU7TG_8pS9NjkAJnM_ruQ1SYm3V9YXVRfLRws1"},
+    "Rohrbach": {"xmlurl": "https://data.umweltprofis.at/opendata/AppointmentService/AppointmentService.asmx/GetTermineForLocationSecured?Key=TEMPKeyabvvMKVCic0cMcmsTEMPKey&StreetNr=118213&HouseNr=Alle&intervall=Alle"},
 }
 
 _LOGGER = logging.getLogger(__name__)
 
+def getText(element):
+    s = ""
+    for e in element.childNodes:
+        if e.nodeType == e.TEXT_NODE:
+            s += e.nodeValue
+    return s
 
 class Source:
-    def __init__(self, url):
+    def __init__(self, url=None, xmlurl=None):
         self._url = url
+        self._xmlurl = xmlurl
         self._ics = ICS()
+        if url is None and xmlurl is None:
+            raise Exception("either url or xmlurl needs to be specified")
 
     def fetch(self):
+        if self._url is not None:
+            return self.fetch_ics()
+        elif self._xmlurl is not None:
+            return self.fetch_xml()
+
+    def fetch_ics(self):
         r = requests.get(self._url)
         if r.status_code != 200:
             _LOGGER.error("Error querying calendar data")
@@ -32,3 +50,18 @@ def fetch(self):
         for d in dates:
             entries.append(Collection(d[0], d[1]))
         return entries
+
+    def fetch_xml(self):
+        r = requests.get(self._xmlurl)
+        r.raise_for_status()
+
+        doc = parseString(r.text)
+        appointments = doc.getElementsByTagName("AppointmentEntry")
+
+        entries = []
+        for a in appointments:
+            date_string = getText(a.getElementsByTagName("Datum")[0])
+            date = datetime.fromisoformat(date_string).date()
+            waste_type = getText(a.getElementsByTagName("WasteType")[0])
+            entries.append(Collection(date, waste_type))
+        return entries


Test patch: