Repository: mampfes/hacs_waste_collection_schedule

Issue:
[Source Request]: tonnenleerung.de
### Municipality / Region

Langenmosen Germany

### Collection Calendar Webpage

https://tonnenleerung.de/nd-sob/langenmosen/

### Example Address

Streetname 10, 86571 Langenmosen

### Collection Data Format

As ICS/ICAL file, As html on a webpage

### Additional Information

_No response_


Discussion:
There is already a solution available: [Awido source](https://github.com/mampfes/hacs_waste_collection_schedule/blob/master/doc/source/awido_de.md)

Configuration example:
```
waste_collection_schedule:
  sources:
    - name: awido_de
      args:
        customer: landkreisbetriebe
        city: Langenmosen
        street: Am Sommerfeld
```

Hello,

 

ist only a partial solution as all waste except “paper”/”Blauetonne” is available in awido_de.

The “paper”/”Blauetonne” needs to be added from https://tonnenleerung.de/nd-sob/langenmosen/

 

Thanks!

 

From: Rene Nulsch ***@***.***> 
Sent: Monday, 5 February 2024 12:16
To: mampfes/hacs_waste_collection_schedule ***@***.***>
Cc: xaquib666 ***@***.***>; Author ***@***.***>
Subject: Re: [mampfes/hacs_waste_collection_schedule] [Source Request]: (Issue #1767)

 

There is already a solution available: Awido source <https://github.com/mampfes/hacs_waste_collection_schedule/blob/master/doc/source/awido_de.md> 

Configuration example:

    - name: awido_de
      args:
        customer: landkreisbetriebe
        city: Langenmosen
        street: Am Sommerfeld

—
Reply to this email directly, view it on GitHub <https://github.com/mampfes/hacs_waste_collection_schedule/issues/1767#issuecomment-1926747428> , or unsubscribe <https://github.com/notifications/unsubscribe-auth/A3ZWCVUVPEPT5J2LVRLD343YSC5PVAVCNFSM6AAAAABCZZQAV2VHI2DSMVQWIX3LMV43OSLTON2WKQ3PNVWWK3TUHMYTSMRWG42DONBSHA> .
You are receiving this because you authored the thread.  <https://github.com/notifications/beacon/A3ZWCVQ6PDOCOGI63K2JPHDYSC5PVA5CNFSM6AAAAABCZZQAV2WGG33NNVSW45C7OR4XAZNMJFZXG5LFINXW23LFNZ2KUY3PNVWWK3TUL5UWJTTS27KSI.gif> Message ID: ***@***.*** ***@***.***> >



Resolving patch:
diff --git a/custom_components/waste_collection_schedule/waste_collection_schedule/source/tonnenleerung_de.py b/custom_components/waste_collection_schedule/waste_collection_schedule/source/tonnenleerung_de.py
new file mode 100644
--- /dev/null
+++ b/custom_components/waste_collection_schedule/waste_collection_schedule/source/tonnenleerung_de.py
@@ -0,0 +1,88 @@
+import json
+import re
+from datetime import datetime
+
+import requests
+from waste_collection_schedule import Collection  # type: ignore[attr-defined]
+
+TITLE = "tonnenleerung.de LK Aichach-Friedberg + Neuburg-Schrobenhausen"
+DESCRIPTION = (
+    "Source for tonnenleerung.de LK Aichach-Friedberg + Neuburg-Schrobenhausen."
+)
+URL = "https://tonnenleerung.de"
+TEST_CASES = {
+    "nd-sob/neuburg-donau/abbevillestrasse/": {
+        "url": "nd-sob/neuburg-donau/abbevillestrasse/"
+    },
+    "aic-fdb/affing/": {"url": "https://tonnenleerung.de/aic-fdb/affing"},
+    "nd-sob/schrobenhausen/albertus-magnus-weg/": {
+        "url": "/nd-sob/schrobenhausen/albertus-magnus-weg/"
+    },
+}
+
+
+ICON_MAP = {
+    "grau4": "mdi:trash-can",
+    "grau": "mdi:trash-can",
+    "Bio": "mdi:leaf",
+    "blau": "mdi:package-variant",
+    "gelb": "mdi:recycle",
+}
+
+
+API_URL = "https://tonnenleerung.de/{url}"
+
+EXTRA_INFO = [
+    {
+        "name": "LK Aichach-Friedberg",
+        "url": "https://tonnenleerung.de/aic-fdb/",
+    },
+    {
+        "name": "LK Neuburg-Schrobenhausen",
+        "url": "https://tonnenleerung.de/nd-sob/",
+    },
+]
+
+
+# Array names included in the html file
+ARRAY_NAMES = ["blauArray", "gelbArray", "grauArray", "braunArray", "grau4Array"]
+
+REGEX_TEMPLATE = r"{array_name}\s?=\s?\[[,\"\-\d]*\]"
+
+# Array names to names shown on the frontend
+NAME_2_TYPE = {
+    "blauArray": "blau",
+    "gelbArray": "gelb",
+    "grauArray": "grau",
+    "braunArray": "Bio",
+    "grau4Array": "grau4",
+}
+
+
+class Source:
+    def __init__(self, url: str):
+        self._url: str = url
+        if "tonnenleerung.de" in self._url:
+            self._url = self._url.split("tonnenleerung.de")[1]
+        if self._url.startswith("/"):
+            self._url = self._url[1:]
+
+    def fetch(self):
+        # get json file
+        r = requests.get(API_URL.format(url=self._url))
+        r.raise_for_status()
+
+        entries = []
+
+        for array_name in ARRAY_NAMES:
+            array = re.search(REGEX_TEMPLATE.format(array_name=array_name), r.text)
+            if not array:
+                continue
+            bin_type = NAME_2_TYPE[array_name]
+            dates = json.loads(array.group(0).split("=")[1])
+            for date_str in dates:
+                date = datetime.strptime(date_str, "%Y-%m-%d").date()
+                icon = ICON_MAP.get(bin_type)  # Collection icon
+
+                entries.append(Collection(date=date, t=bin_type, icon=icon))
+        return entries


Test patch: