From 21ddeca107195187ca7da6293651d7cddbb900f7 Mon Sep 17 00:00:00 2001 From: mniejo Date: Thu, 26 Dec 2024 17:39:29 +0100 Subject: [PATCH] Added support for OLO, Slovakia suource --- .gitignore | 4 +- README.md | 1 + .../waste_collection_schedule/sources.json | 6 + .../translations/de.json | 20 +++ .../translations/en.json | 23 +++ .../translations/it.json | 20 +++ .../source/olo_sk.py | 166 ++++++++++++++++++ doc/source/olo_sk.md | 37 ++++ info.md | 2 +- 9 files changed, 277 insertions(+), 2 deletions(-) create mode 100644 custom_components/waste_collection_schedule/waste_collection_schedule/source/olo_sk.py create mode 100644 doc/source/olo_sk.md diff --git a/.gitignore b/.gitignore index c9d578304..f110c4029 100644 --- a/.gitignore +++ b/.gitignore @@ -8,4 +8,6 @@ custom_components/waste_collection_schedule/waste_collection_schedule/test/secre .DS_Store .venv/ .idea/ -.python-version \ No newline at end of file +.python-version +hello.py +pyproject.toml diff --git a/README.md b/README.md index d0b06a834..ee22ec6ec 100644 --- a/README.md +++ b/README.md @@ -1848,6 +1848,7 @@ If your service provider is not listed, feel free to open a [source request issu Slovakia - [fcc Environment](/doc/source/fcc_group_eu.md) / fcc-group.eu +- [OLO](/doc/source/olo_sk.md) / olo.sk
diff --git a/custom_components/waste_collection_schedule/sources.json b/custom_components/waste_collection_schedule/sources.json index 9f657d1d8..1ed214058 100644 --- a/custom_components/waste_collection_schedule/sources.json +++ b/custom_components/waste_collection_schedule/sources.json @@ -11758,6 +11758,12 @@ "module": "fcc_group_eu", "default_params": {}, "id": "fcc_group_eu" + }, + { + "title": "OLO", + "module": "olo_sk", + "default_params": {}, + "id": "olo_sk" } ], "Slovenia": [ diff --git a/custom_components/waste_collection_schedule/translations/de.json b/custom_components/waste_collection_schedule/translations/de.json index adca0aaf9..731390fb8 100644 --- a/custom_components/waste_collection_schedule/translations/de.json +++ b/custom_components/waste_collection_schedule/translations/de.json @@ -10688,6 +10688,26 @@ }, "data_description": {} }, + "args_olo_sk": { + "title": "Quelle konfigurieren", + "description": "Konfiguriere deinen Service Provider. \n\nHOW TO GET ARGUMENTS DESCRIPTION\n\nMehr details: https://github.com/mampfes/hacs_waste_collection_schedule/blob/master/doc/source/olo_sk.md", + "data": { + "calendar_title": "Kalender Titel", + "street": "Straße" + }, + "data_description": { + "calendar_title": "Ein lesbarerer oder benutzerfreundlicherer Name für den Müllkalender. Wenn nichts angegeben wird, wird der Name der Quelle verwendet." + } + }, + "reconfigure_olo_sk": { + "title": "Quelle Neu Konfigurieren", + "description": "Konfiguriere deinen Service Provider. \n\nHOW TO GET ARGUMENTS DESCRIPTION\n\nMehr details: https://github.com/mampfes/hacs_waste_collection_schedule/blob/master/doc/source/olo_sk.md", + "data": { + "calendar_title": "Kalender Titel", + "street": "Straße" + }, + "data_description": {} + }, "args_mojiodpadki_si": { "title": "Quelle konfigurieren", "description": "Konfiguriere deinen Service Provider. Mehr details: https://github.com/mampfes/hacs_waste_collection_schedule/blob/master/doc/source/mojiodpadki_si.md", diff --git a/custom_components/waste_collection_schedule/translations/en.json b/custom_components/waste_collection_schedule/translations/en.json index 7aeb8bd52..d4df001e2 100644 --- a/custom_components/waste_collection_schedule/translations/en.json +++ b/custom_components/waste_collection_schedule/translations/en.json @@ -10697,6 +10697,29 @@ }, "data_description": {} }, + "args_olo_sk": { + "title": "Configure Source", + "description": "Configure your service provider. \n\nHOW TO GET ARGUMENTS DESCRIPTION\n\nMore details: https://github.com/mampfes/hacs_waste_collection_schedule/blob/master/doc/source/olo_sk.md.", + "data": { + "calendar_title": "Calendar Title", + "street": "Enter street name" + }, + "data_description": { + "calendar_title": "A more readable, or user-friendly, name for the waste calendar. If nothing is provided, the name returned by the source will be used.", + "street": "Street name" + } + }, + "reconfigure_olo_sk": { + "title": "Reconfigure Source", + "description": "Configure your service provider. \n\nHOW TO GET ARGUMENTS DESCRIPTION\n\nMore details: https://github.com/mampfes/hacs_waste_collection_schedule/blob/master/doc/source/olo_sk.md.", + "data": { + "calendar_title": "Calendar Title", + "street": "Enter street name" + }, + "data_description": { + "street": "Street name" + } + }, "args_mojiodpadki_si": { "title": "Configure Source", "description": "Configure your service provider. More details: https://github.com/mampfes/hacs_waste_collection_schedule/blob/master/doc/source/mojiodpadki_si.md.", diff --git a/custom_components/waste_collection_schedule/translations/it.json b/custom_components/waste_collection_schedule/translations/it.json index 3ffa230ad..43fc7a5ec 100644 --- a/custom_components/waste_collection_schedule/translations/it.json +++ b/custom_components/waste_collection_schedule/translations/it.json @@ -10670,6 +10670,26 @@ }, "data_description": {} }, + "args_olo_sk": { + "title": "Configurazione Sorgente", + "description": "Compila i campi per ottenere le informazioni sul tuo servizio di raccolta. \n\nHOW TO GET ARGUMENTS DESCRIPTION\n\nMaggiori informazioni: https://github.com/mampfes/hacs_waste_collection_schedule/blob/master/doc/source/olo_sk.md.", + "data": { + "calendar_title": "Nome Calendario", + "street": "Strada" + }, + "data_description": { + "calendar_title": "Puoi cambiare il nome del calendario della raccolta dei rifiuti, altrimenti di default verra' utilizzato il nome del tuo fornitore di servizi." + } + }, + "reconfigure_olo_sk": { + "title": "Riconfigurazione Sorgente", + "description": "Compila i campi per ottenere le informazioni sul tuo servizio di raccolta. \n\nHOW TO GET ARGUMENTS DESCRIPTION\n\nPer maggiori informazioni: https://github.com/mampfes/hacs_waste_collection_schedule/blob/master/doc/source/olo_sk.md.", + "data": { + "calendar_title": "Nome Calendario", + "street": "Strada" + }, + "data_description": {} + }, "args_mojiodpadki_si": { "title": "Configurazione Sorgente", "description": "Compila i campi per ottenere le informazioni sul tuo servizio di raccolta. Maggiori informazioni: https://github.com/mampfes/hacs_waste_collection_schedule/blob/master/doc/source/mojiodpadki_si.md.", diff --git a/custom_components/waste_collection_schedule/waste_collection_schedule/source/olo_sk.py b/custom_components/waste_collection_schedule/waste_collection_schedule/source/olo_sk.py new file mode 100644 index 000000000..57bb137a0 --- /dev/null +++ b/custom_components/waste_collection_schedule/waste_collection_schedule/source/olo_sk.py @@ -0,0 +1,166 @@ +import datetime +from waste_collection_schedule import Collection +import requests + +TITLE = "OLO" # Title will show up in README.md and info.md +DESCRIPTION = "Source script for olo.sk" # Describe your source +# Insert url to service homepage. URL will show up in README.md and info.md +URL = "https://www.olo.sk" +TEST_CASES = { # Insert arguments for test cases to be used by test_sources.py script + "Jantarova 47": {"street": 'Jantarova 47', "registrationNumber": '2441788'}, + "Jasovska 8": {"street": 'Jasovska 8', "registrationNumber": '1353013'}, + "Rovniankova 5": {"street": 'Rovniankova 5', "registrationNumber": ''}, +} + +API_URL = "https://olo-strapi-meilisearch.bratislava.sk/indexes/waste-collection-day/search" +ICON_MAP = { # Optional: Dict of waste types and suitable mdi icons + "DOMESTIC": "mdi:trash-can", + "RECYCLE": "mdi:recycle", + "KITCHEN": "mdi:coutertop", +} + +WEKDAYS = { + "pondelok": "Monday", + "utorok": "Tuesday", + "streda": "Wednesday", + "štvrtok": "Thursday", + "piatok": "Friday", + "sobota": "Saturday", + "nedeľa": "Sunday" +} + +#### Arguments affecting the configuration GUI #### + +HOW_TO_GET_ARGUMENTS_DESCRIPTION = { # Optional dictionary to describe how to get the arguments, will be shown in the GUI configuration form above the input fields, does not need to be translated in all languages + "en": "HOW TO GET ARGUMENTS DESCRIPTION" +} + +PARAM_DESCRIPTIONS = { # Optional dict to describe the arguments, will be shown in the GUI configuration below the respective input field + "en": { + "street": "Street name", + "registrationNumber": "Registration number" + } +} + +PARAM_TRANSLATIONS = { # Optional dict to translate the arguments, will be shown in the GUI configuration form as placeholder text + "en": { + "street": "Enter street name", + "registrationNumber": "Enter registration number" + } +} + +#### End of arguments affecting the configuration GUI #### + + +class Source: + # argX correspond to the args dict in the source configuration + def __init__(self, street: str, registrationNumber: str): + self._street = street + self._registrationNumber = registrationNumber + + def parseDates(self, dates_str: str) -> list[datetime.date]: + dates = dates_str.split(";") + dates = [date.strip() for date in dates] + dates = [date for date in dates if date] + return [datetime.datetime.strptime(date, "%d.%m.%Y").date() for date in dates] + + def fetchWasteType(self, waste_type: str) -> str: + headers = { + "Content-Type": "application/json", + "Accept": "application/json", + "authorization": "Bearer ae84ae0982c2162a81eb253765ceaa8593abd9105c71954cf5c9620b0178cbb6" + } + + params = { + "q": self._street, + "limit": 100, + "offset": 0, + "sort": ["waste-collection-day.address:asc"], + "filter": ["type = \"waste-collection-day\"", "waste-collection-day.type = \"" + waste_type + "\""] + } + + response = requests.post(API_URL, json=params, headers=headers) + response.raise_for_status() # Raise an error for bad status codes + data = response.json() + items = data.get("hits", []) + return [item.get("waste-collection-day", {}) for item in items] + + def getRecycableWaste(self) -> list[Collection]: + items = self.fetchWasteType("vrecovyZ") + if not items: + return [] + + first_item = items[0] + + collection_dates_str = first_item.get("collectionDates") + if not collection_dates_str: + return [] + + collection_dates = self.parseDates(collection_dates_str) + + return [Collection( + date=date, + t="Recycable Waste", + icon=ICON_MAP.get("RECYCLE") + ) for date in collection_dates] + + def generate_dates(self, weekdays: list[str], is_even_week: bool) -> list[datetime.date]: + today = datetime.date.today() + end_date = today + datetime.timedelta(days=90) + dates = [] + + current_date = today + while current_date <= end_date: + week_number = current_date.isocalendar()[1] + if (is_even_week and week_number % 2 == 0) or (not is_even_week and week_number % 2 != 0): + if current_date.strftime("%A") in weekdays: + dates.append(current_date) + current_date += datetime.timedelta(days=1) + return dates + + def getDomesticWaste(self) -> list[Collection]: + items = self.fetchWasteType("zkoD") + if not items: + return [] + + if self._registrationNumber: + items = [item for item in items if item.get( + "registrationNumber") == self._registrationNumber] + if not items: + return [] + + first_item = items[0] + + evenWeek_str = first_item.get("evenWeek", "") + oddWeek_str = first_item.get("oddWeek", "") + + evenWeek = [day.strip() + for day in evenWeek_str.split(",") if day.strip()] + oddWeek = [day.strip() + for day in oddWeek_str.split(",") if day.strip()] + + evenWeek = [WEKDAYS[day] for day in evenWeek] + oddWeek = [WEKDAYS[day] for day in oddWeek] + + evenWeek_dates = self.generate_dates(evenWeek, True) + oddWeek_dates = self.generate_dates(oddWeek, False) + + collection_dates = evenWeek_dates + oddWeek_dates + collection_dates.sort() + + return [Collection( + date=date, + t="Domestic Waste", + icon=ICON_MAP.get("DOMESTIC") + ) for date in collection_dates] + + def fetch(self) -> list[Collection]: + recycable_waste = self.getRecycableWaste() + domestic_waste = self.getDomesticWaste() + + entries = recycable_waste + domestic_waste + + if not entries: + raise Exception("No waste data found") + + return entries diff --git a/doc/source/olo_sk.md b/doc/source/olo_sk.md new file mode 100644 index 000000000..25c1fed47 --- /dev/null +++ b/doc/source/olo_sk.md @@ -0,0 +1,37 @@ +# fcc Environment (VYLOŽ SMETI APP) + +Support for schedules provided by [OLO Bratislava](https://www.olo.sk/), serving in Bratislava in Slovakia. + +## Configuration via configuration.yaml + +```yaml +waste_collection_schedule: + sources: + - name: olo_sk + args: + street: STREET + +``` + +### Configuration Variables + +**street** +*(String) (required)* + +## Example + +```yaml +waste_collection_schedule: + sources: + - name: olo_sk + args: + street: Jantarova 47 +``` + +```yaml +waste_collection_schedule: + sources: + - name: olo_sk + args: + city: Jasovska 8 +``` \ No newline at end of file diff --git a/info.md b/info.md index dad120553..d1985333d 100644 --- a/info.md +++ b/info.md @@ -34,7 +34,7 @@ Waste collection schedules from service provider web sites are updated daily, de | New Zealand | Auckland Council, Christchurch City Council, Dunedin District Council, Gore, Invercargill & Southland, Hamilton City Council, Horowhenua District Council, Hutt City Council, Napier City Council, Porirua City, Rotorua Lakes Council, Tauranga City Council, Waipa District Council, Wellington City Council | | Norway | BIR (Bergensområdets Interkommunale Renovasjonsselskap), Fosen Renovasjon, IRiS, Min Renovasjon, Movar IKS, Oslo Kommune, ReMidt Orkland muni, Sandnes Kommune, Stavanger Kommune, Trondheim | | Poland | App Moje Odpady, Bydgoszcz Pronatura, Czerwonak, Murowana Goślina, Oborniki, Ecoharmonogram, Gmina Miękinia, Koziegłowy/Objezierze/Oborniki, MPGK Katowice, Poznań, Warsaw, Wrocław | -| Slovakia | fcc Environment | +| Slovakia | fcc Environment, OLO | | Slovenia | Moji odpadki, Ljubljana, Snaga Maribor | | Sweden | Affärsverken, Avfallsapp.se - Multi Source, Boden, Borås Energi och Miljö, EDPEvent - Multi Source, Gästrike Återvinnare, Jönköping - June Avfall & Miljö, Kretslopp Sydost, Kristianstad Renhållning, Landskrona - Svalövs Renhållning, Lerum Vatten och Avlopp, Linköping - Tekniska Verken, Luleå, Lund Waste Collection, Mölndal, Norrtalje Vatten & Avfall, North / Middle Bohuslän - Rambo AB, Region Gotland, Ronneby Miljöteknik, Roslagsvatten, Samverkan Återvinning Miljö (SÅM), Skellefteå, SRV Återvinning, SSAM (Deprecated), SSAM Södra Smalånds Avfall & Miljö, Sysav Sophämntning, Söderköping, Uppsala Vatten, Uppsala Vatten och Avfall AB (Deprecated), VA Syd Sophämntning, VIVAB Sophämtning, Västervik Miljö & Energi | | Switzerland | A-Region, Alchenstorf, Andwil, Appenzell, Berg, Bühler, Canton of Zürich, Eggersriet, Gais, Gaiserwald, Gasel, Goldach, Grosswangen, Grub, Heiden, Herisau, Horn, Hundwil, Häggenschwil, Köniz, Köniz, Liebefeld, Lindau, Lutzenberg, Mittelhäusern, Muolen, Mörschwil, Münchenstein, Münsingen BE, Switzerland, Nieder-/Oberscherli, Niederwangen, Oberwangen, Rapperswil, Real Luzern, Real Luzern, Rehetobel, Rorschach, Rorschacherberg, Sammelkalender.ch, Schliern, Schwellbrunn, Schönengrund, Seon, Speicher, Spiegel, Stadt Bülach, Stein, Steinach, Teufen, Thal, Thörishaus, Trogen, Tübach, Untereggen, Urnäsch, Wabern, Wald, Waldkirch, Waldstatt, Winterthur, Wittenbach, Wolfhalden, ZAKU Entsorgung, Zeba, ZKRI |