Added Insert-IT as a service provider (#1717)

* Added Insert IT

Added Insert IT as a source for all Insert IT based Apps. Therefore deleted Offenbach. Mannheim moved also to Insert IT from Abfall+.

Also added:
- Hattingen
- Herne
- Kassel
- Krefeld

* Updated Readme and info Files

* Tests completed

* fix whitespace

* Added Luebeck and fixed docs

* Readme and info updated with Luebeck

* Added offenbach_de source back for compatibility

* fix deprecated source offenbach_de

---------

Co-authored-by: 5ila5 <5ila5@users.noreply.github.com>
This commit is contained in:
Deniz Celebi
2024-01-26 09:39:00 +01:00
committed by GitHub
parent 1638a98d5f
commit 07e644cee6
12 changed files with 331 additions and 156 deletions

View File

@@ -509,7 +509,13 @@ Waste collection schedules in the following formats and countries are supported.
- [Abfallbehandlungsgesellschaft Havelland mbH (abh)](/doc/ics/abfall_havelland_de.md) / abfall-havelland.de
- [Abfallbewirtschaftung Ostalbkreis](/doc/source/abfall_io.md) / goa-online.de
- [Abfallentsorgung Kreis Kassel](/doc/ics/abfall_kreis_kassel_de.md) / abfall-kreis-kassel.de
- [Abfallkalender Offenbach am Main](/doc/source/offenbach_de.md) / offenbach.de
- [Abfallkalender Hattingen](/doc/source/insert_it_de.md) / insert-it.de/BmsAbfallkalenderHattingen
- [Abfallkalender Herne](/doc/source/insert_it_de.md) / insert-it.de/BmsAbfallkalenderHerne
- [Abfallkalender Kassel](/doc/source/insert_it_de.md) / insert-it.de/BmsAbfallkalenderKassel
- [Abfallkalender Luebeck](/doc/source/insert_it_de.md) / insert-it.de/BmsAbfallkalenderLuebeck
- [Abfallkalender Mannheim](/doc/source/insert_it_de.md) / insert-it.de/BmsAbfallkalenderMannheim
- [Abfallkalender Offenbach](/doc/source/insert_it_de.md) / insert-it.de/BmsAbfallkalenderOffenbach
- [Abfallkalender Offenbach am Main (deprecated)](/doc/source/offenbach_de.md) / offenbach.de
- [Abfallkalender Würzburg](/doc/source/wuerzburg_de.md) / wuerzburg.de
- [AbfallNavi (RegioIT.de)](/doc/source/abfallnavi_de.md) / regioit.de
- [Abfalltermine Forchheim](/doc/source/abfalltermine_forchheim_de.md) / abfalltermine-forchheim.de
@@ -659,6 +665,7 @@ Waste collection schedules in the following formats and countries are supported.
- [Gemeinde Unterhaching](/doc/source/awido_de.md) / unterhaching.de
- [Gipsprojekt](/doc/ics/gipsprojekt_de.md) / gipsprojekt.de
- [Großkrotzenburg (MyMuell App)](/doc/source/jumomind_de.md) / mymuell.de
- [GSAK APP / Krefeld](/doc/source/insert_it_de.md) / insert-it.de/BmsAbfallkalenderKrefeld
- [GWA - Kreis Unna mbH](/doc/source/abfallnavi_de.md) / gwa-online.de
- [Göttinger Entsorgungsbetriebe](/doc/source/abfall_io.md) / geb-goettingen.de
- [Gütersloh](/doc/source/abfallnavi_de.md) / guetersloh.de
@@ -676,6 +683,7 @@ Waste collection schedules in the following formats and countries are supported.
- [Höxter](/doc/source/jumomind_de.md) / abfallservice.kreis-hoexter.de
- [Ilm-Kreis](/doc/source/app_abfallplus_de.md) / Abfall+ App: abfallappik
- [Ingolstadt](/doc/source/jumomind_de.md) / in-kb.de
- [Insert IT Apps](/doc/source/insert_it_de.md) / insert-infotech.de
- [Jumomind](/doc/source/jumomind_de.md) / jumomind.de
- [KAEV Niederlausitz](/doc/source/kaev_niederlausitz.md) / kaev.de
- [Kamp-Lintfort (MyMuell App)](/doc/source/jumomind_de.md) / mymuell.de
@@ -825,7 +833,6 @@ Waste collection schedules in the following formats and countries are supported.
- [mags Mönchengladbacher Abfall-, Grün- und Straßenbetriebe AöR](/doc/source/mags_de.md) / mags.de
- [Main-Kinzig-Kreis](/doc/source/jumomind_de.md) / abfall-mkk.de
- [Main-Kinzig-Kreis (MyMuell App)](/doc/source/jumomind_de.md) / mymuell.de
- [Mannheim](/doc/source/app_abfallplus_de.md) / Abfall+ App: de
- [Mechernich und Kommunen](/doc/source/app_abfallplus_de.md) / Abfall+ App: abfallinfoapp
- [Mein-Abfallkalender.de](/doc/ics/mein_abfallkalender_de.md) / mein-abfallkalender.de
- [Metzingen](/doc/source/app_abfallplus_de.md) / Abfall+ App: abfallappmetz

View File

@@ -206,7 +206,6 @@ SUPPORTED_SERVICES = {
"de.k4systems.abfallappmil": ["Kreis Miltenberg"],
"de.k4systems.abfallsbk": ["Schwarzwald-Baar-Kreis"],
"de.k4systems.wabapp": ["Westerwaldkreis"],
"abfallMA.ucom.de": ["Mannheim"],
"de.k4systems.llabfallapp": ["Kreis Landsberg am Lech"],
"de.k4systems.lkruelzen": ["Kreis Uelzen"],
"de.k4systems.abfallzak": ["Zollernalbkreis"],

View File

@@ -0,0 +1,40 @@
#!/usr/bin/env python3
SERVICE_MAP = [
{
"title": "Abfallkalender Hattingen",
"url": "https://www.insert-it.de/BmsAbfallkalenderHattingen",
"service_id": "BmsAbfallkalenderHattingen",
},
{
"title": "Abfallkalender Herne",
"url": "https://www.insert-it.de/BmsAbfallkalenderHerne",
"service_id": "BmsAbfallkalenderHerne",
},
{
"title": "Abfallkalender Kassel",
"url": "https://www.insert-it.de/BmsAbfallkalenderKassel",
"service_id": "BmsAbfallkalenderKassel",
},
{
"title": "GSAK APP / Krefeld",
"url": "https://www.insert-it.de/BmsAbfallkalenderKrefeld",
"service_id": "BmsAbfallkalenderKrefeld",
},
{
"title": "Abfallkalender Luebeck",
"url": "https://www.insert-it.de/BmsAbfallkalenderLuebeck",
"service_id": "BmsAbfallkalenderLuebeck",
},
{
"title": "Abfallkalender Mannheim",
"url": "https://www.insert-it.de/BmsAbfallkalenderMannheim",
"service_id": "BmsAbfallkalenderMannheim",
},
{
"title": "Abfallkalender Offenbach",
"url": "https://www.insert-it.de/BmsAbfallkalenderOffenbach",
"service_id": "BmsAbfallkalenderOffenbach",
},
]

View File

@@ -0,0 +1,186 @@
import json
import requests
import urllib
from datetime import datetime
from waste_collection_schedule import Collection # type: ignore[attr-defined]
from waste_collection_schedule.service.InsertITDe import SERVICE_MAP
from waste_collection_schedule.service.ICS import ICS
TITLE = "Insert IT Apps"
DESCRIPTION = "Source for Apps by Insert IT"
URL = "https://insert-infotech.de/"
COUNTRY = "de"
def EXTRA_INFO():
return [{"title": s["title"], "url": s["url"]} for s in SERVICE_MAP]
TEST_CASES = {
"Offenbach Address": {
"municipality": "Offenbach",
"street": "Kaiserstraße",
"hnr": 1
},
"Offenbach Location ID": {
"municipality": "Offenbach",
"location_id": 7036
},
"Mannheim Address": {
"municipality": "Mannheim",
"street": "A 3",
"hnr": 1
},
"Mannheim Location ID": {
"municipality": "Mannheim",
"location_id": 430650
}
}
MUNICIPALITIES = {
"Hattingen": "BmsAbfallkalenderHattingen",
"Herne": "BmsAbfallkalenderHerne",
"Kassel": "BmsAbfallkalenderKassel",
"Krefeld": "BmsAbfallkalenderKrefeld",
"Luebeck": "BmsAbfallkalenderLuebeck",
"Mannheim": "BmsAbfallkalenderMannheim",
"Offenbach": "BmsAbfallkalenderOffenbach",
}
ICON_MAP = {
"Offenbach": {
"Restmüll": {"icon": "mdi:trash-can", "name": "Restmüll"},
"Biomüll": {"icon": "mdi:leaf", "name": "Biomüll"},
"DSD": {"icon": "mdi:recycle", "name": "DSD"},
"Altpapier": {"icon": "mdi:package-variant", "name": "Altpapier"},
},
"Mannheim": {
"Rest": {"icon": "mdi:trash-can", "name": "Restmüll"},
"Wertstoff": {"icon": "mdi:recycle", "name": "Sack/Tonne gelb"},
"Bio": {"icon": "mdi:leaf", "name": "Biomüll"},
"Papier": {"icon": "mdi:package-variant", "name": "Altpapier"},
"Grünschnitt": {"icon": "mdi:leaf", "name": "Grünschnitt"},
}
}
REGEX_MAP = {
"Hattingen": r"Leerung:\s+(.*)\s+\(.*\)",
"Herne": r"Leerung:\s+(.*)\s+\(.*\)",
"Kassel": r"Leerung:\s+(.*)\s+\(.*\)",
"Krefeld": r"Leerung:\s+(.*)\s+\(.*\)",
"Luebeck": r"Leerung:\s+(.*)\s+\(.*\)",
"Mannheim": r"Leerung:\s+(.*)",
"Offenbach": r"Leerung:\s+(.*)\s+\(.*\)",
}
class Source:
def __init__(self, municipality, street=None, hnr=None, location_id=None):
self._municipality = municipality
self._street = street
self._hnr = hnr
self._location = location_id
# Check if municipality is in list
municipalities = MUNICIPALITIES
if municipality not in municipalities:
raise Exception(f"municipality '{municipality}' not found")
self._api_url = f"https://www.insert-it.de/{municipalities[municipality]}"
self._ics = ICS(regex=REGEX_MAP.get(municipality))
# Check if at least either location_id is set or both street and hnr are set
if not ((location_id is not None) or (street is not None and hnr is not None)):
raise Exception("At least either location_id should be set or both street and hnr should be set.")
self._uselocation = location_id is not None
def get_street_id(self):
"""Return ID of matching street"""
s = requests.Session()
params = {"text": self._street}
r = s.get(f"{self._api_url}/Main/GetStreets", params=params)
r.raise_for_status()
r.encoding = "utf-8"
result = json.loads(r.text)
if not result:
raise Exception(f"No street found for Street {self._street}")
for element in result:
if element["Name"] == self._street:
street_id = element["ID"]
return street_id
raise Exception(f"Street {self._street} not found")
def get_location_id(self, street_id):
"""Return ID of first matching location"""
s = requests.Session()
params = {"streetId": street_id, "houseNumber": self._hnr}
r = s.get(f"{self._api_url}/Main/GetLocations", params=params)
r.raise_for_status()
r.encoding = "utf-8"
result = json.loads(r.text)
if not result:
raise Exception(f"No locations found for Street ID {street_id} and House number {self._hnr}")
for element in result:
if element["StreetId"] == street_id and element["Text"] == str(self._hnr):
location_id = element["ID"]
return location_id
raise Exception(f"Location for Street ID {street_id} with House number {self._hnr} not found")
def fetch(self):
if not (self._uselocation):
street_id = self.get_street_id()
self._location = self.get_location_id(street_id)
now = datetime.now()
entries = self.fetch_year(now.year)
if now.month == 12:
entries += self.fetch_year(now.year + 1)
return entries
def fetch_year(self, year):
s = requests.Session()
params = {"bmsLocationId": self._location, "year": year}
r = s.get(f"{self._api_url}/Main/Calender", params=params)
r.raise_for_status()
r.encoding = "utf-8"
entries = []
dates = self._ics.convert(r.text)
mapping = ICON_MAP.get(self._municipality, None)
for d in dates:
if mapping is not None and d[1] in mapping:
entries.append(
Collection(
date=d[0],
t=mapping[d[1]]["name"],
icon=mapping[d[1]]["icon"],
)
)
else:
entries.append(Collection(d[0], d[1]))
return entries

View File

@@ -1,52 +1,22 @@
from datetime import datetime
import logging
import requests
from waste_collection_schedule import Collection # type: ignore[attr-defined]
from waste_collection_schedule.service.ICS import ICS
from waste_collection_schedule.source.insert_it_de import \
Source as InsertItSource
TITLE = "Abfallkalender Offenbach am Main"
DESCRIPTION = "Source für Abfallkalender Offenbach"
_LOGGER = logging.getLogger(__name__)
TITLE = "Abfallkalender Offenbach am Main (deprecated)"
DESCRIPTION = "Source für Abfallkalender Offenbach (deprecated)"
URL = "https://www.offenbach.de"
TEST_CASES = {
"offenbach": {"f_id_location": 7036}, # KaiserStraße 1
}
API_URL = "https://www.insert-it.de/BmsAbfallkalenderOffenbach/Main/Calender"
ICON_MAP = {
"Restmüll": "mdi:trash-can",
"Biomüll": "mdi:leaf",
"DSD": "mdi:recycle",
"Altpapier": "mdi:package-variant",
}
class Source:
class Source(InsertItSource):
def __init__(self, f_id_location):
self._location = f_id_location
self._ics = ICS(regex=r"Leerung:\s+(.*)\s+\(.*\)")
def fetch(self):
now = datetime.now()
entries = self.fetch_year(now.year)
if now.month == 12:
entries += self.fetch_year(now.year + 1)
return entries
def fetch_year(self, year):
s = requests.Session()
params = {"bmsLocationId": self._location, "year": year}
r = s.get(API_URL, params=params)
r.raise_for_status()
r.encoding = "utf-8"
entries = []
dates = self._ics.convert(r.text)
for d in dates:
entries.append(Collection(d[0], d[1], icon=ICON_MAP.get(d[1])))
return entries
_LOGGER.warning(
"offenbach_de source is deprecated, please use insert_it_de as new source. More info: https://github.com/mampfes/hacs_waste_collection_schedule/blob/master/doc/source/insert_it_de.md"
)
super().__init__("Offenbach", location_id=f_id_location)

View File

@@ -1,87 +0,0 @@
#!/usr/bin/env python3
import re
import site
import inquirer
import requests
import traceback
s = requests.Session()
def get_streets(answers):
url = "https://www.insert-it.de/BmsAbfallkalenderOffenbach/Main/GetStreets"
params = { "text": answers['street'],
"filter%5Bfilters%5D%5B0%5D%5Bvalue%5D": answers['street'],
"filter%5Bfilters%5D%5B0%5D%5Bfield%5D": "Name",
"filter%5Bfilters%5D%5B0%5D%5Boperator%5D": "contains",
"filter%5Bfilters%5D%5B0%5D%5BignoreCase%5D": "true",
"filter%5Blogic%5D": "and" }
r = s.get(url, params=params)
r.raise_for_status()
return r.json()
def get_numbers(streetname, jdata):
url = "https://www.insert-it.de/BmsAbfallkalenderOffenbach/Main/GetLocations"
streetId = [ i['ID'] for i in jdata if i['Name'] == streetname] [0]
params = {
"streetId": streetId,
"filter[filters][0][field]": "ID",
"filter[filters][0][operator]": "eq",
"filter[filters][0][value]": streetId,
"filter[logic]": "and"
}
r = s.get(url, params=params)
r.raise_for_status()
return r.json()
def main():
questions = [inquirer.Text("street", message="Enter search string for street")]
jdata = []
while not len(jdata):
try:
answers = inquirer.prompt(questions)
jdata = get_streets(answers)
except Exception as e:
traceback.print_exc()
sys.exit()
questions = [
inquirer.List(
"streetname", choices=[i['Name'] for i in jdata], message="Select street"
)
]
try:
answers = inquirer.prompt(questions)
jdata = get_numbers(**answers, jdata=jdata)
except Exception as e:
traceback.print_exc()
sys.exit()
questions = [
inquirer.List(
"streetnumber", choices=[i['Text'] for i in jdata], message="Select number"
)
]
answers = inquirer.prompt(questions)
location_id = [ i['ID'] for i in jdata if i['Text'] == answers['streetnumber']][0]
print("Copy the following statements into your configuration.yaml:\n")
print("# waste_collection_schedule source configuration")
print("waste_collection_schedule:")
print(" sources:")
print(" - name: offenbach_de")
print(" args:")
print(f" f_id_location: {location_id}")
if __name__ == "__main__":
main()

View File

@@ -188,7 +188,6 @@ The app_id can be found from the url of the play store entry: https://play.googl
| de.k4systems.abfallappmil | Kreis Miltenberg |
| de.k4systems.abfallsbk | Schwarzwald-Baar-Kreis |
| de.k4systems.wabapp | Westerwaldkreis |
| abfallMA.ucom.de | Mannheim |
| de.k4systems.llabfallapp | Kreis Landsberg am Lech |
| de.k4systems.lkruelzen | Kreis Uelzen |
| de.k4systems.abfallzak | Zollernalbkreis |

View File

@@ -0,0 +1,80 @@
# Insert IT Apps
Support Apps provided by [Insert IT](https://insert-it.de/). The official homepage is using the URL [Insert Infotech](https://insert-infotech.de/) instead.
```yaml
waste_collection_schedule:
sources:
- name: insert_it_de
args:
municipality: Municipality
street: Street Name
hnr: House Number
location_id: Location ID
```
### Configuration Variables
**municipality**
*(string) (required)*
**street**
*(string) (optional)*
**hnr**
*(integer) (optional)*
**location_id**
*(integer) (optional)*
Either `street` and `hnr` or `location_id` is required. Both could also be set, but `location_id` is prioritized.
If none is set, it will fail.
Currently supported municipalities:
|Region|
|-|
| Hattingen |
| Herne |
| Kassel |
| Krefeld |
| Luebeck |
| Mannheim |
| Offenbach |
## Example
Using Location ID
```yaml
waste_collection_schedule:
sources:
- name: insert_it_de
args:
municipality: Mannheim
location_id: 430650
```
Using Street and House Number
```yaml
waste_collection_schedule:
sources:
- name: insert_it_de
args:
municipality: Offenbach
street: Kaiserstraße
hnr: 1
```
## How to get the source arguments
Easy way to get the `location_id` source argument is to use a (desktop) browser, eg.g Google Chrome:
1. Open the digital abfallkalender, e.g. for Offenbach [https://www.offenbach.de/stadtwerke/stadtservice/Entsorgung/abfallkalender.php](https://www.offenbach.de/stadtwerke/stadtservice/Entsorgung/abfallkalender.php).
2. Enter the street name and the number
3. Right click on the iCalendar link and select "Copy Link Address"
4. Paste somewhere like a notepad to get the full URL. Eg: https://www.insert-it.de/BmsAbfallkalenderOffenbach/Main/Calender?bmsLocationId=7036&year=2024
5. The bmsLocationId argument is the location id that you need to use in the configuration as `location_id`.

View File

@@ -1,6 +1,7 @@
# Offenbach.de
Support for schedules provided by [Offenbach.de](https://www.offenbach.de/stadtwerke/stadtservice/Entsorgung/abfallkalender.php).
## offenbach_de source is deprecated, please use [insert_it_de](https://github.com/mampfes/hacs_waste_collection_schedule/blob/master/doc/source/insert_it_de.md) as new source.
## Configuration via configuration.yaml
@@ -27,23 +28,3 @@ waste_collection_schedule:
args:
f_id_location: 7036
```
## How to get the source arguments
## Simple Variant: Use wizard script
There is a script with an interactive command line interface which generates the required source configuration:
[https://github.com/mampfes/hacs_waste_collection_schedule/blob/master/custom_components/waste_collection_schedule/waste_collection_schedule/wizard/offenbach_de.py](https://github.com/mampfes/hacs_waste_collection_schedule/blob/master/custom_components/waste_collection_schedule/waste_collection_schedule/wizard/offenbach_de.py).
First, install the Python module `inquirer`. Then run this script from a shell and answer the questions.
### Extract arguments from website
Another way get the source arguments is to us a (desktop) browser, e.g. Google Chrome:
1. Open the digital abfallkalender for Offenbach [https://www.offenbach.de/stadtwerke/stadtservice/Entsorgung/abfallkalender.php](https://www.offenbach.de/stadtwerke/stadtservice/Entsorgung/abfallkalender.php).
2. Enter the street name and the number
3. Right click on the iCalendar link and select "Copy Link Address"
4. Paste somewhere like a notepad to get the full URL. Eg: https://www.insert-it.de/BmsAbfallkalenderOffenbach/Main/Calender?bmsLocationId=7036&year=2023
5. The bmsLocationId argument is the location id that you need to use in the configuration as `f_id_location`.

File diff suppressed because one or more lines are too long