From fcdfb2da69e09a9f1cfab6dbf5b01bb6054b20a7 Mon Sep 17 00:00:00 2001 From: autinerd <27780930+autinerd@users.noreply.github.com> Date: Fri, 9 Jul 2021 17:58:26 +0200 Subject: [PATCH 1/8] add awido integration --- .../source/awido_cubefour_de.py | 59 +++++++++++++++++++ 1 file changed, 59 insertions(+) create mode 100644 custom_components/waste_collection_schedule/waste_collection_schedule/source/awido_cubefour_de.py diff --git a/custom_components/waste_collection_schedule/waste_collection_schedule/source/awido_cubefour_de.py b/custom_components/waste_collection_schedule/waste_collection_schedule/source/awido_cubefour_de.py new file mode 100644 index 000000000..48cc65462 --- /dev/null +++ b/custom_components/waste_collection_schedule/waste_collection_schedule/source/awido_cubefour_de.py @@ -0,0 +1,59 @@ +import datetime +import requests +import json + +from waste_collection_schedule import Collection # type: ignore[attr-defined] +from waste_collection_schedule.service.ICS import ICS + +TITLE = "Cubefour AWIDO" +DESCRIPTION = "Source for waste collections hosted by Cubefour." +URL = "https://www.awido-online.de/" + +class Source: + def __init__(self, customer, fraktionen, city, street, housenumber): + self._customer = customer + self._fractions = fractions + self._city = city + self._street = street + self._housenumber = housenumber + + def fetch(self): + # Retrieve list of places + places = json.loads(requests.get(f'https://awido.cubefour.de//WebServices/Awido.Service.svc/secure/getPlaces/client={self._customer}').text) + + # Check if given place is in the list + found_places = [(place['key'], place['value']) for place in places if place['value'] == self._city] + if len(found_places) != 1: + return [] + place_oid = found_places[0][0] + + streets = json.loads(requests.get(f'https://awido.cubefour.de//WebServices/Awido.Service.svc/secure/getGroupedStreets/{place_oid}?client={self._customer}').text) + found_streets = [(street['key'], street['value']) for street in streets if self._street in street['value']] + if len(found_streets) != 1: + return [] + # If Housenumber is already in found street, oid is already found, if not, check for housenumber + if self._street != found_streets[0][1]: + oid = found_streets[0][0] + else: + street_oid = found_streets[0][0] + housenumbers = json.loads(requests.get(f'https://awido.cubefour.de//WebServices/Awido.Service.svc/secure/getStreetAddons/{street_oid}?client={self._customer}').text) + found_housenumbers = [(hn['key'], hn['value']) for hn in housenumbers if self._housenumber == hn['value']] + if len(found_housenumbers) == 0: + return [] + oid = found_housenumbers[0][0] + + cal_json = json.loads(requests.get(f'https://awido.cubefour.de//WebServices/Awido.Service.svc/secure/getData/{oid}?fractions={fraktionen}&client={self._customer}')) + calendar = [item for item in cal_json['calendar'] if item['ad'] is not None] + fracts = cal_json['fracts'] + fractions = {} + for fract in fracts: + fractions[fract['snm']] = fract['nm'] + + entries = [] + for calitem in calendar: + date = datetime.date(int(calitem['dt'][0:4]), int(calitem['dt'][4:6]), int(calitem['dt'][6:8])) + for i, fracitem in calitem['fr']: + typ = fractions[fracitem] + entries.append(Collection(date, typ)) + + return entries \ No newline at end of file From fb85b5d68b6e8cee45e046fecca5532c9a087a7d Mon Sep 17 00:00:00 2001 From: autinerd <27780930+autinerd@users.noreply.github.com> Date: Fri, 9 Jul 2021 19:01:25 +0200 Subject: [PATCH 2/8] add test-cases and documentation for awido --- .../source/awido_cubefour_de.py | 66 +++++++++---- doc/source/awido_cubefour_de.md | 96 +++++++++++++++++++ 2 files changed, 143 insertions(+), 19 deletions(-) create mode 100644 doc/source/awido_cubefour_de.md diff --git a/custom_components/waste_collection_schedule/waste_collection_schedule/source/awido_cubefour_de.py b/custom_components/waste_collection_schedule/waste_collection_schedule/source/awido_cubefour_de.py index 48cc65462..6aa6ced43 100644 --- a/custom_components/waste_collection_schedule/waste_collection_schedule/source/awido_cubefour_de.py +++ b/custom_components/waste_collection_schedule/waste_collection_schedule/source/awido_cubefour_de.py @@ -3,16 +3,41 @@ import json from waste_collection_schedule import Collection # type: ignore[attr-defined] -from waste_collection_schedule.service.ICS import ICS TITLE = "Cubefour AWIDO" DESCRIPTION = "Source for waste collections hosted by Cubefour." URL = "https://www.awido-online.de/" +TEST_CASES = { + "Schorndorf, Raingrund 21": { + "customer": "rmk", + "city": "Schorndorf", + "street": "Raingrund", + "housenumber": "21", + "fraktionen": "1" + }, + "Altomünster, Maisbrunn": { + "customer": "lra-dah", + "city": "Altomünster", + "street": "Maisbrunn", + "fraktionen": "1,3" + }, + "SOK-Alsmannsdorf": { + "customer": "zaso", + "city": "SOK-Alsmannsdorf", + "fraktionen": "1,2,3,10" + }, + "Kaufbeuren, Rehgrund": { + "customer": "kaufbeuren", + "city": "Kaufbeuren", + "street": "Rehgrund", + "fraktionen": "1,3,4" + } +} class Source: - def __init__(self, customer, fraktionen, city, street, housenumber): + def __init__(self, customer, fraktionen=None, city, street=None, housenumber=None): self._customer = customer - self._fractions = fractions + self._fraktionen = fraktionen self._city = city self._street = street self._housenumber = housenumber @@ -25,24 +50,27 @@ def fetch(self): found_places = [(place['key'], place['value']) for place in places if place['value'] == self._city] if len(found_places) != 1: return [] - place_oid = found_places[0][0] - - streets = json.loads(requests.get(f'https://awido.cubefour.de//WebServices/Awido.Service.svc/secure/getGroupedStreets/{place_oid}?client={self._customer}').text) - found_streets = [(street['key'], street['value']) for street in streets if self._street in street['value']] - if len(found_streets) != 1: - return [] - # If Housenumber is already in found street, oid is already found, if not, check for housenumber - if self._street != found_streets[0][1]: - oid = found_streets[0][0] + if self._street is None: + oid = found_places[0][0] else: - street_oid = found_streets[0][0] - housenumbers = json.loads(requests.get(f'https://awido.cubefour.de//WebServices/Awido.Service.svc/secure/getStreetAddons/{street_oid}?client={self._customer}').text) - found_housenumbers = [(hn['key'], hn['value']) for hn in housenumbers if self._housenumber == hn['value']] - if len(found_housenumbers) == 0: + place_oid = found_places[0][0] + + streets = json.loads(requests.get(f'https://awido.cubefour.de//WebServices/Awido.Service.svc/secure/getGroupedStreets/{place_oid}?client={self._customer}').text) + found_streets = [(street['key'], street['value']) for street in streets if self._street in street['value']] + if len(found_streets) != 1: return [] - oid = found_housenumbers[0][0] + # If Housenumber is already in found street, oid is already found, if not, check for housenumber + if self._street != found_streets[0][1] or self._housenumber is None: + oid = found_streets[0][0] + else: + street_oid = found_streets[0][0] + housenumbers = json.loads(requests.get(f'https://awido.cubefour.de//WebServices/Awido.Service.svc/secure/getStreetAddons/{street_oid}?client={self._customer}').text) + found_housenumbers = [(hn['key'], hn['value']) for hn in housenumbers if str(self._housenumber) == hn['value']] + if len(found_housenumbers) == 0: + return [] + oid = found_housenumbers[0][0] - cal_json = json.loads(requests.get(f'https://awido.cubefour.de//WebServices/Awido.Service.svc/secure/getData/{oid}?fractions={fraktionen}&client={self._customer}')) + cal_json = json.loads(requests.get(f'https://awido.cubefour.de//WebServices/Awido.Service.svc/secure/getData/{oid}?fractions={str(self._fraktionen) if self._fraktionen is not None else ""}&client={self._customer}').text) calendar = [item for item in cal_json['calendar'] if item['ad'] is not None] fracts = cal_json['fracts'] fractions = {} @@ -52,7 +80,7 @@ def fetch(self): entries = [] for calitem in calendar: date = datetime.date(int(calitem['dt'][0:4]), int(calitem['dt'][4:6]), int(calitem['dt'][6:8])) - for i, fracitem in calitem['fr']: + for fracitem in calitem['fr']: typ = fractions[fracitem] entries.append(Collection(date, typ)) diff --git a/doc/source/awido_cubefour_de.md b/doc/source/awido_cubefour_de.md new file mode 100644 index 000000000..1e60bbe25 --- /dev/null +++ b/doc/source/awido_cubefour_de.md @@ -0,0 +1,96 @@ +# Cubefour AWIDO-based services + +Cubefour AWIDO is a platform for waste schedules, which has several German cities and districts as customers. The homepage of the company is https://www.awido-online.de/. + +## Configuration via configuration.yaml + +```yaml +waste_collection_schedule: + sources: + - name: awido_cubefour_de + args: + customer: customer + city: city + street: street + housenumber: 2 + fraktionen: 2,3,4 +``` + +### Configuration Variables + +**customer**
+*(string) (required)* + +**city**
+*(string) (required)* + +**street**
+*(integer) (depend on customer)* + +**housenumber**
+*(integer) (depend on customer)* + +**fraktionen**
+*(string) (optional)* + +## Example + +```yaml +waste_collection_schedule: + sources: + - name: awido_cubefour_de + args: + customer: rmk + city: Waiblingen + street: Benzstr. + housenumber: 14 + fraktionen: 2,3 +``` + +## How to get the source arguments + +### customer + +List of customers (2021-07-09): +- `rmk`: AWG des Rems-Murr-Kreises mbH +- `lra-schweinfurt`: Landkreis Schweinfurt +- `gotha`: Landkreis Gotha +- `zaso`: Zweckverband Abfallwirtschaft Saale-Orla +- `unterhaching`: Gemeinde Unterhaching +- `kaufbeuren`: Stadt Kaufbeuren +- `bgl`: Landkreis Berchtesgadener Land +- `pullach`: Pullach im Isartal +- `ffb`: Landkreis Fürstenfeldbruck +- `unterschleissheim`: Stadt Unterschleißheim +- `kreis-tir`: Landkreis Tirschenreuth +- `rosenheim`: Landkreis Rosenheim +- `tuebingen`: Landkreis Tübingen +- `kronach`: Landkreis Kronach +- `erding`: Landkreis Erding +- `zv-muc-so`: Zweckverband München-Südost +- `coburg`: Landkreis Coburg +- `ansbach`: Landkreis Ansbach +- `awb-duerkheim`: AWB Landkreis Bad Dürkheim +- `aic-fdb`: Landratsamt Aichach-Friedberg +- `wgv`: WGV Recycling GmbH +- `neustadt`: Neustadt a.d. Waldnaab +- `kelheim`: Landkreis Kelheim +- `kaw-guenzburg`: Landkreis Günzburg +- `memmingen`: Stadt Memmingen +- `eww-suew`: Landkreis Südliche Weinstraße +- `lra-dah`: Landratsamt Dachau +- `landkreisbetriebe`: Landkreisbetriebe Neuburg-Schrobenhausen +- `awb-ak`: Abfallwirtschaftsbetrieb Landkreis Altenkirchen +- `awld`: Abfallwirtschaft des Lahn-Dill-Kreises +- `azv-hef-rof`: Abfallwirtschafts-Zweckverband des Landkreises Hersfeld-Rotenburg +- `awv-nordschwaben`: Abfall-Wirtschafts-Verband Nordschwaben + +### fraktionen + +Go to your calender at `https://awido.cubefour.de/Customer//v2/Calendar2.aspx`, select a city, street and housenumber and then select the types of waste you want to have. Afterwards enter this in the address bar and press Enter: `javascript:alert(document.querySelector('#Content_SelectedFractions').value)` + +Copy the value which is shown in the alert dialog and paste it as the argument fraktionen in the config. + +### city, street etc. + +Go to your calender at `https://awido.cubefour.de/Customer//v2/Calendar2.aspx`. The first entry is the `city` (except for single-city customers, then the parameter `city` is the city), then the `street` and depending on the customer then the `housenumber`. From 238db707222e7d800f2eb5afc250e75fadc987f6 Mon Sep 17 00:00:00 2001 From: autinerd <27780930+autinerd@users.noreply.github.com> Date: Sat, 10 Jul 2021 13:59:01 +0200 Subject: [PATCH 3/8] bugfix --- .../waste_collection_schedule/source/awido_cubefour_de.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/custom_components/waste_collection_schedule/waste_collection_schedule/source/awido_cubefour_de.py b/custom_components/waste_collection_schedule/waste_collection_schedule/source/awido_cubefour_de.py index 6aa6ced43..820ca8f01 100644 --- a/custom_components/waste_collection_schedule/waste_collection_schedule/source/awido_cubefour_de.py +++ b/custom_components/waste_collection_schedule/waste_collection_schedule/source/awido_cubefour_de.py @@ -35,7 +35,7 @@ } class Source: - def __init__(self, customer, fraktionen=None, city, street=None, housenumber=None): + def __init__(self, customer, city, street=None, housenumber=None, fraktionen=None): self._customer = customer self._fraktionen = fraktionen self._city = city From b06626e77cc47f96872c3e34a55af4a6f3648904 Mon Sep 17 00:00:00 2001 From: mampfes Date: Tue, 20 Jul 2021 07:37:36 +0200 Subject: [PATCH 4/8] reduce nested statements to improve readability --- .../source/awido_cubefour_de.py | 49 +++++++++++-------- 1 file changed, 28 insertions(+), 21 deletions(-) diff --git a/custom_components/waste_collection_schedule/waste_collection_schedule/source/awido_cubefour_de.py b/custom_components/waste_collection_schedule/waste_collection_schedule/source/awido_cubefour_de.py index 820ca8f01..d16c0bfad 100644 --- a/custom_components/waste_collection_schedule/waste_collection_schedule/source/awido_cubefour_de.py +++ b/custom_components/waste_collection_schedule/waste_collection_schedule/source/awido_cubefour_de.py @@ -15,23 +15,23 @@ "housenumber": "21", "fraktionen": "1" }, - "Altomünster, Maisbrunn": { - "customer": "lra-dah", - "city": "Altomünster", - "street": "Maisbrunn", - "fraktionen": "1,3" - }, - "SOK-Alsmannsdorf": { - "customer": "zaso", - "city": "SOK-Alsmannsdorf", - "fraktionen": "1,2,3,10" - }, - "Kaufbeuren, Rehgrund": { - "customer": "kaufbeuren", - "city": "Kaufbeuren", - "street": "Rehgrund", - "fraktionen": "1,3,4" - } +# "Altomünster, Maisbrunn": { +# "customer": "lra-dah", +# "city": "Altomünster", +# "street": "Maisbrunn", +# "fraktionen": "1,3" +# }, +# "SOK-Alsmannsdorf": { +# "customer": "zaso", +# "city": "SOK-Alsmannsdorf", +# "fraktionen": "1,2,3,10" +# }, +# "Kaufbeuren, Rehgrund": { +# "customer": "kaufbeuren", +# "city": "Kaufbeuren", +# "street": "Rehgrund", +# "fraktionen": "1,3,4" +# } } class Source: @@ -44,7 +44,8 @@ def __init__(self, customer, city, street=None, housenumber=None, fraktionen=Non def fetch(self): # Retrieve list of places - places = json.loads(requests.get(f'https://awido.cubefour.de//WebServices/Awido.Service.svc/secure/getPlaces/client={self._customer}').text) + r = requests.get(f'https://awido.cubefour.de/WebServices/Awido.Service.svc/secure/getPlaces/client={self._customer}') + places = json.loads(r.text) # Check if given place is in the list found_places = [(place['key'], place['value']) for place in places if place['value'] == self._city] @@ -55,7 +56,9 @@ def fetch(self): else: place_oid = found_places[0][0] - streets = json.loads(requests.get(f'https://awido.cubefour.de//WebServices/Awido.Service.svc/secure/getGroupedStreets/{place_oid}?client={self._customer}').text) + r = requests.get(f'https://awido.cubefour.de/WebServices/Awido.Service.svc/secure/getGroupedStreets/{place_oid}', params={"client":self._customer}) + streets = json.loads(r.text) + found_streets = [(street['key'], street['value']) for street in streets if self._street in street['value']] if len(found_streets) != 1: return [] @@ -64,13 +67,17 @@ def fetch(self): oid = found_streets[0][0] else: street_oid = found_streets[0][0] - housenumbers = json.loads(requests.get(f'https://awido.cubefour.de//WebServices/Awido.Service.svc/secure/getStreetAddons/{street_oid}?client={self._customer}').text) + r = requests.get(f'https://awido.cubefour.de/WebServices/Awido.Service.svc/secure/getStreetAddons/{street_oid}', params={"client":self._customer}) + housenumbers = json.loads(r.text) found_housenumbers = [(hn['key'], hn['value']) for hn in housenumbers if str(self._housenumber) == hn['value']] if len(found_housenumbers) == 0: return [] oid = found_housenumbers[0][0] - cal_json = json.loads(requests.get(f'https://awido.cubefour.de//WebServices/Awido.Service.svc/secure/getData/{oid}?fractions={str(self._fraktionen) if self._fraktionen is not None else ""}&client={self._customer}').text) + r = requests.get(f'https://awido.cubefour.de/WebServices/Awido.Service.svc/secure/getData/{oid}', params={ + "fractions": str(self._fraktionen) if self._fraktionen is not None else "", + "client":self._customer}) + cal_json = json.loads(r.text) calendar = [item for item in cal_json['calendar'] if item['ad'] is not None] fracts = cal_json['fracts'] fractions = {} From d9eb1a2b2b40fbde0cbdb3cce7d33a980a0235db Mon Sep 17 00:00:00 2001 From: mampfes Date: Tue, 20 Jul 2021 07:38:32 +0200 Subject: [PATCH 5/8] remove support to filter for fractions A source should always return all available waste types. --- .../source/awido_cubefour_de.py | 17 ++++++----------- 1 file changed, 6 insertions(+), 11 deletions(-) diff --git a/custom_components/waste_collection_schedule/waste_collection_schedule/source/awido_cubefour_de.py b/custom_components/waste_collection_schedule/waste_collection_schedule/source/awido_cubefour_de.py index d16c0bfad..5a402b50b 100644 --- a/custom_components/waste_collection_schedule/waste_collection_schedule/source/awido_cubefour_de.py +++ b/custom_components/waste_collection_schedule/waste_collection_schedule/source/awido_cubefour_de.py @@ -12,32 +12,27 @@ "customer": "rmk", "city": "Schorndorf", "street": "Raingrund", - "housenumber": "21", - "fraktionen": "1" + "housenumber": "21" }, # "Altomünster, Maisbrunn": { # "customer": "lra-dah", # "city": "Altomünster", -# "street": "Maisbrunn", -# "fraktionen": "1,3" +# "street": "Maisbrunn" # }, # "SOK-Alsmannsdorf": { # "customer": "zaso", -# "city": "SOK-Alsmannsdorf", -# "fraktionen": "1,2,3,10" +# "city": "SOK-Alsmannsdorf" # }, # "Kaufbeuren, Rehgrund": { # "customer": "kaufbeuren", # "city": "Kaufbeuren", -# "street": "Rehgrund", -# "fraktionen": "1,3,4" +# "street": "Rehgrund" # } } class Source: - def __init__(self, customer, city, street=None, housenumber=None, fraktionen=None): + def __init__(self, customer, city, street=None, housenumber=None): self._customer = customer - self._fraktionen = fraktionen self._city = city self._street = street self._housenumber = housenumber @@ -75,7 +70,7 @@ def fetch(self): oid = found_housenumbers[0][0] r = requests.get(f'https://awido.cubefour.de/WebServices/Awido.Service.svc/secure/getData/{oid}', params={ - "fractions": str(self._fraktionen) if self._fraktionen is not None else "", + "fractions": "", "client":self._customer}) cal_json = json.loads(r.text) calendar = [item for item in cal_json['calendar'] if item['ad'] is not None] From ab8b2f558ee298812337000d2dc95d9e608e5090 Mon Sep 17 00:00:00 2001 From: mampfes Date: Tue, 20 Jul 2021 07:39:18 +0200 Subject: [PATCH 6/8] improve error logging in case of config option mismatch --- .../source/awido_cubefour_de.py | 106 ++++++++++-------- 1 file changed, 61 insertions(+), 45 deletions(-) diff --git a/custom_components/waste_collection_schedule/waste_collection_schedule/source/awido_cubefour_de.py b/custom_components/waste_collection_schedule/waste_collection_schedule/source/awido_cubefour_de.py index 5a402b50b..1a2f3c32c 100644 --- a/custom_components/waste_collection_schedule/waste_collection_schedule/source/awido_cubefour_de.py +++ b/custom_components/waste_collection_schedule/waste_collection_schedule/source/awido_cubefour_de.py @@ -1,6 +1,7 @@ import datetime import requests import json +import logging from waste_collection_schedule import Collection # type: ignore[attr-defined] @@ -8,28 +9,31 @@ DESCRIPTION = "Source for waste collections hosted by Cubefour." URL = "https://www.awido-online.de/" TEST_CASES = { - "Schorndorf, Raingrund 21": { + "Schorndorf, Miedelsbacher Straße 30 /1": { "customer": "rmk", "city": "Schorndorf", - "street": "Raingrund", - "housenumber": "21" + "street": "Miedelsbacher Straße", + "housenumber": "30 /1" }, -# "Altomünster, Maisbrunn": { -# "customer": "lra-dah", -# "city": "Altomünster", -# "street": "Maisbrunn" -# }, -# "SOK-Alsmannsdorf": { -# "customer": "zaso", -# "city": "SOK-Alsmannsdorf" -# }, -# "Kaufbeuren, Rehgrund": { -# "customer": "kaufbeuren", -# "city": "Kaufbeuren", -# "street": "Rehgrund" -# } + "Altomünster, Maisbrunn": { + "customer": "lra-dah", + "city": "Altomünster", + "street": "Maisbrunn" + }, + "SOK-Alsmannsdorf": { + "customer": "zaso", + "city": "SOK-Alsmannsdorf" + }, + "Kaufbeuren, Rehgrund": { + "customer": "kaufbeuren", + "city": "Kaufbeuren", + "street": "Rehgrund" + } } +_LOGGER = logging.getLogger(__name__) + + class Source: def __init__(self, customer, city, street=None, housenumber=None): self._customer = customer @@ -42,48 +46,60 @@ def fetch(self): r = requests.get(f'https://awido.cubefour.de/WebServices/Awido.Service.svc/secure/getPlaces/client={self._customer}') places = json.loads(r.text) - # Check if given place is in the list - found_places = [(place['key'], place['value']) for place in places if place['value'] == self._city] - if len(found_places) != 1: + # create city to key map from retrieved places + city_to_oid = {place["value"].strip():place["key"] for (place) in places} + + if self._city not in city_to_oid: + _LOGGER.error(f"city not found: {self._city}") return [] - if self._street is None: - oid = found_places[0][0] - else: - place_oid = found_places[0][0] - r = requests.get(f'https://awido.cubefour.de/WebServices/Awido.Service.svc/secure/getGroupedStreets/{place_oid}', params={"client":self._customer}) + oid = city_to_oid[self._city] + + if self._street is not None: + r = requests.get(f'https://awido.cubefour.de/WebServices/Awido.Service.svc/secure/getGroupedStreets/{oid}', params={"client":self._customer}) streets = json.loads(r.text) - found_streets = [(street['key'], street['value']) for street in streets if self._street in street['value']] - if len(found_streets) != 1: + # create street to key map from retrieved places + street_to_oid = {street["value"].strip():street["key"] for (street) in streets} + + if self._street not in street_to_oid: + _LOGGER.error(f"street not found: {self._street}") return [] - # If Housenumber is already in found street, oid is already found, if not, check for housenumber - if self._street != found_streets[0][1] or self._housenumber is None: - oid = found_streets[0][0] - else: - street_oid = found_streets[0][0] - r = requests.get(f'https://awido.cubefour.de/WebServices/Awido.Service.svc/secure/getStreetAddons/{street_oid}', params={"client":self._customer}) - housenumbers = json.loads(r.text) - found_housenumbers = [(hn['key'], hn['value']) for hn in housenumbers if str(self._housenumber) == hn['value']] - if len(found_housenumbers) == 0: + + oid = street_to_oid[self._street] + + if self._housenumber is not None: + r = requests.get(f'https://awido.cubefour.de/WebServices/Awido.Service.svc/secure/getStreetAddons/{oid}', params={"client":self._customer}) + hsnbrs = json.loads(r.text) + + # create housenumber to key map from retrieved places + hsnbr_to_oid = {hsnbr["value"].strip():hsnbr["key"] for (hsnbr) in hsnbrs} + + if self._housenumber not in hsnbr_to_oid: + _LOGGER.error(f"housenumber not found: {self._housenumber}") return [] - oid = found_housenumbers[0][0] + oid = hsnbr_to_oid[self._housenumber] + + # get calendar data r = requests.get(f'https://awido.cubefour.de/WebServices/Awido.Service.svc/secure/getData/{oid}', params={ "fractions": "", - "client":self._customer}) + "client": self._customer}) cal_json = json.loads(r.text) + + # map fraction code to fraction name + fractions = {fract["snm"]:fract["nm"] for (fract) in cal_json["fracts"]} + + # calendar also contains public holidays. In this case, 'ad' is None calendar = [item for item in cal_json['calendar'] if item['ad'] is not None] - fracts = cal_json['fracts'] - fractions = {} - for fract in fracts: - fractions[fract['snm']] = fract['nm'] entries = [] for calitem in calendar: - date = datetime.date(int(calitem['dt'][0:4]), int(calitem['dt'][4:6]), int(calitem['dt'][6:8])) + date = datetime.datetime.strptime(calitem["dt"], "%Y%m%d").date() + + # add all fractions for this date for fracitem in calitem['fr']: - typ = fractions[fracitem] - entries.append(Collection(date, typ)) + waste_type = fractions[fracitem] + entries.append(Collection(date, waste_type)) return entries \ No newline at end of file From 22a422b17997dbc0f1bec27c864efce9392224a5 Mon Sep 17 00:00:00 2001 From: mampfes Date: Tue, 20 Jul 2021 07:58:17 +0200 Subject: [PATCH 7/8] add documentation for awido_de --- README.md | 1 + .../{awido_cubefour_de.py => awido_de.py} | 4 +-- .../{awido_cubefour_de.md => awido_de.md} | 28 +++++++------------ info.md | 1 + 4 files changed, 14 insertions(+), 20 deletions(-) rename custom_components/waste_collection_schedule/waste_collection_schedule/source/{awido_cubefour_de.py => awido_de.py} (97%) rename doc/source/{awido_cubefour_de.md => awido_de.md} (67%) diff --git a/README.md b/README.md index 52db56883..3c49c3a57 100644 --- a/README.md +++ b/README.md @@ -62,6 +62,7 @@ Currently the following service providers are supported: - [AbfallNavi.de (RegioIT.de)](./doc/source/abfallnavi_de.md) - [Abfallwirtschaft Stuttgart](./doc/source/stuttgart_de.md) - [AWBKoeln.de](./doc/source/awbkoeln_de.md) +- [AWIDO-online.de](./doc/source/awido_de.md) - [BSR.de / Berliner Stadtreinigungsbetriebe](./doc/source/bsr_de.md) - [Jumomind.de](./doc/source/jumomind_de.md) - [Muellmax.de](./doc/source/muellmax_de.md) diff --git a/custom_components/waste_collection_schedule/waste_collection_schedule/source/awido_cubefour_de.py b/custom_components/waste_collection_schedule/waste_collection_schedule/source/awido_de.py similarity index 97% rename from custom_components/waste_collection_schedule/waste_collection_schedule/source/awido_cubefour_de.py rename to custom_components/waste_collection_schedule/waste_collection_schedule/source/awido_de.py index 1a2f3c32c..30efefa8d 100644 --- a/custom_components/waste_collection_schedule/waste_collection_schedule/source/awido_cubefour_de.py +++ b/custom_components/waste_collection_schedule/waste_collection_schedule/source/awido_de.py @@ -5,8 +5,8 @@ from waste_collection_schedule import Collection # type: ignore[attr-defined] -TITLE = "Cubefour AWIDO" -DESCRIPTION = "Source for waste collections hosted by Cubefour." +TITLE = "AWIDO" +DESCRIPTION = "Source for AWIDO waste collection." URL = "https://www.awido-online.de/" TEST_CASES = { "Schorndorf, Miedelsbacher Straße 30 /1": { diff --git a/doc/source/awido_cubefour_de.md b/doc/source/awido_de.md similarity index 67% rename from doc/source/awido_cubefour_de.md rename to doc/source/awido_de.md index 1e60bbe25..52312f121 100644 --- a/doc/source/awido_cubefour_de.md +++ b/doc/source/awido_de.md @@ -1,4 +1,4 @@ -# Cubefour AWIDO-based services +# AWIDO based services Cubefour AWIDO is a platform for waste schedules, which has several German cities and districts as customers. The homepage of the company is https://www.awido-online.de/. @@ -7,13 +7,12 @@ Cubefour AWIDO is a platform for waste schedules, which has several German citie ```yaml waste_collection_schedule: sources: - - name: awido_cubefour_de + - name: awido_de args: customer: customer city: city street: street housenumber: 2 - fraktionen: 2,3,4 ``` ### Configuration Variables @@ -25,26 +24,22 @@ waste_collection_schedule: *(string) (required)* **street**
-*(integer) (depend on customer)* +*(integer) (optinal, depends on customer)* **housenumber**
-*(integer) (depend on customer)* - -**fraktionen**
-*(string) (optional)* +*(integer) (optional, depends on customer)* ## Example ```yaml waste_collection_schedule: sources: - - name: awido_cubefour_de + - name: awido_de args: customer: rmk city: Waiblingen street: Benzstr. housenumber: 14 - fraktionen: 2,3 ``` ## How to get the source arguments @@ -85,12 +80,9 @@ List of customers (2021-07-09): - `azv-hef-rof`: Abfallwirtschafts-Zweckverband des Landkreises Hersfeld-Rotenburg - `awv-nordschwaben`: Abfall-Wirtschafts-Verband Nordschwaben -### fraktionen - -Go to your calender at `https://awido.cubefour.de/Customer//v2/Calendar2.aspx`, select a city, street and housenumber and then select the types of waste you want to have. Afterwards enter this in the address bar and press Enter: `javascript:alert(document.querySelector('#Content_SelectedFractions').value)` - -Copy the value which is shown in the alert dialog and paste it as the argument fraktionen in the config. - -### city, street etc. +### city, street, house number -Go to your calender at `https://awido.cubefour.de/Customer//v2/Calendar2.aspx`. The first entry is the `city` (except for single-city customers, then the parameter `city` is the city), then the `street` and depending on the customer then the `housenumber`. +- Go to your calender at `https://awido.cubefour.de/Customer//v2/Calendar2.aspx`. Replace `` with the one of the keys listed above. +- Enter your city name from the first page into the `city` field, except for single-city customers, then the parameter `city` is the city. +- If you have to enter a street or district, enter the name into the street` field. +- If you have to enter a house number, enter the house number into the `housenumber` field. diff --git a/info.md b/info.md index 20d461e60..6f8673e3f 100644 --- a/info.md +++ b/info.md @@ -50,6 +50,7 @@ Currently the following service providers are supported: - [AbfallNavi.de (RegioIT.de)](https://github.com/mampfes/hacs_waste_collection_schedule/blob/master/doc/source/abfallnavi_de.md) - [Abfallwirtschaft Stuttgart](https://github.com/mampfes/hacs_waste_collection_schedule/blob/master/doc/source/stuttgart_de.md) - [AWBKoeln.de](https://github.com/mampfes/hacs_waste_collection_schedule/blob/master/doc/source/awbkoeln_de.md) +- [AWIDO-online.de](./doc/source/awido_de.md) - [BSR.de / Berliner Stadtreinigungsbetriebe](https://github.com/mampfes/hacs_waste_collection_schedule/blob/master/doc/source/bsr_de.md) - [Jumomind.de](https://github.com/mampfes/hacs_waste_collection_schedule/blob/master/doc/source/jumomind_de.md) - [Muellmax.de](https://github.com/mampfes/hacs_waste_collection_schedule/blob/master/doc/source/muellmax_de.md) From e5dd44de53ab49f7d4d277043e4301c4b4892394 Mon Sep 17 00:00:00 2001 From: mampfes Date: Tue, 20 Jul 2021 08:08:04 +0200 Subject: [PATCH 8/8] fix black, pylint, ... warnings --- .../source/awido_de.py | 60 +++++++++++-------- 1 file changed, 35 insertions(+), 25 deletions(-) diff --git a/custom_components/waste_collection_schedule/waste_collection_schedule/source/awido_de.py b/custom_components/waste_collection_schedule/waste_collection_schedule/source/awido_de.py index 30efefa8d..fa71bf824 100644 --- a/custom_components/waste_collection_schedule/waste_collection_schedule/source/awido_de.py +++ b/custom_components/waste_collection_schedule/waste_collection_schedule/source/awido_de.py @@ -1,8 +1,8 @@ import datetime -import requests import json import logging +import requests from waste_collection_schedule import Collection # type: ignore[attr-defined] TITLE = "AWIDO" @@ -13,22 +13,19 @@ "customer": "rmk", "city": "Schorndorf", "street": "Miedelsbacher Straße", - "housenumber": "30 /1" + "housenumber": "30 /1", }, "Altomünster, Maisbrunn": { "customer": "lra-dah", "city": "Altomünster", - "street": "Maisbrunn" - }, - "SOK-Alsmannsdorf": { - "customer": "zaso", - "city": "SOK-Alsmannsdorf" + "street": "Maisbrunn", }, + "SOK-Alsmannsdorf": {"customer": "zaso", "city": "SOK-Alsmannsdorf"}, "Kaufbeuren, Rehgrund": { "customer": "kaufbeuren", "city": "Kaufbeuren", - "street": "Rehgrund" - } + "street": "Rehgrund", + }, } _LOGGER = logging.getLogger(__name__) @@ -43,11 +40,13 @@ def __init__(self, customer, city, street=None, housenumber=None): def fetch(self): # Retrieve list of places - r = requests.get(f'https://awido.cubefour.de/WebServices/Awido.Service.svc/secure/getPlaces/client={self._customer}') + r = requests.get( + f"https://awido.cubefour.de/WebServices/Awido.Service.svc/secure/getPlaces/client={self._customer}" + ) places = json.loads(r.text) # create city to key map from retrieved places - city_to_oid = {place["value"].strip():place["key"] for (place) in places} + city_to_oid = {place["value"].strip(): place["key"] for (place) in places} if self._city not in city_to_oid: _LOGGER.error(f"city not found: {self._city}") @@ -56,11 +55,16 @@ def fetch(self): oid = city_to_oid[self._city] if self._street is not None: - r = requests.get(f'https://awido.cubefour.de/WebServices/Awido.Service.svc/secure/getGroupedStreets/{oid}', params={"client":self._customer}) + r = requests.get( + f"https://awido.cubefour.de/WebServices/Awido.Service.svc/secure/getGroupedStreets/{oid}", + params={"client": self._customer}, + ) streets = json.loads(r.text) # create street to key map from retrieved places - street_to_oid = {street["value"].strip():street["key"] for (street) in streets} + street_to_oid = { + street["value"].strip(): street["key"] for (street) in streets + } if self._street not in street_to_oid: _LOGGER.error(f"street not found: {self._street}") @@ -69,37 +73,43 @@ def fetch(self): oid = street_to_oid[self._street] if self._housenumber is not None: - r = requests.get(f'https://awido.cubefour.de/WebServices/Awido.Service.svc/secure/getStreetAddons/{oid}', params={"client":self._customer}) + r = requests.get( + f"https://awido.cubefour.de/WebServices/Awido.Service.svc/secure/getStreetAddons/{oid}", + params={"client": self._customer}, + ) hsnbrs = json.loads(r.text) # create housenumber to key map from retrieved places - hsnbr_to_oid = {hsnbr["value"].strip():hsnbr["key"] for (hsnbr) in hsnbrs} + hsnbr_to_oid = { + hsnbr["value"].strip(): hsnbr["key"] for (hsnbr) in hsnbrs + } if self._housenumber not in hsnbr_to_oid: _LOGGER.error(f"housenumber not found: {self._housenumber}") return [] oid = hsnbr_to_oid[self._housenumber] - + # get calendar data - r = requests.get(f'https://awido.cubefour.de/WebServices/Awido.Service.svc/secure/getData/{oid}', params={ - "fractions": "", - "client": self._customer}) + r = requests.get( + f"https://awido.cubefour.de/WebServices/Awido.Service.svc/secure/getData/{oid}", + params={"fractions": "", "client": self._customer}, + ) cal_json = json.loads(r.text) # map fraction code to fraction name - fractions = {fract["snm"]:fract["nm"] for (fract) in cal_json["fracts"]} + fractions = {fract["snm"]: fract["nm"] for (fract) in cal_json["fracts"]} # calendar also contains public holidays. In this case, 'ad' is None - calendar = [item for item in cal_json['calendar'] if item['ad'] is not None] - + calendar = [item for item in cal_json["calendar"] if item["ad"] is not None] + entries = [] for calitem in calendar: date = datetime.datetime.strptime(calitem["dt"], "%Y%m%d").date() # add all fractions for this date - for fracitem in calitem['fr']: + for fracitem in calitem["fr"]: waste_type = fractions[fracitem] entries.append(Collection(date, waste_type)) - - return entries \ No newline at end of file + + return entries