mirror of
https://github.com/sascha-hemi/hacs_waste_collection_schedule.git
synced 2026-03-21 04:06:03 +01:00
add source for stadtreinigung.hamburg
This commit is contained in:
@@ -31,6 +31,7 @@ Currently the following service providers are supported:
|
||||
- [AbfallPlus.de / Abfall.IO](./doc/source/abfall_io.md)
|
||||
- [AWBKoeln.de](./doc/source/awbkoeln_de.md)
|
||||
- [Jumomind.de](./doc/source/jumomind_de.md)
|
||||
- [Stadtreinigung.Hamburg](./doc/source/stadtreinigung_hamburg.md)
|
||||
|
||||
## Configuration via configuration.yaml
|
||||
|
||||
|
||||
@@ -0,0 +1,56 @@
|
||||
import re
|
||||
import requests
|
||||
import datetime
|
||||
import icalendar
|
||||
from collections import OrderedDict
|
||||
|
||||
from ..helpers import CollectionAppointment
|
||||
|
||||
|
||||
DESCRIPTION = "Source for Stadtreinigung.Hamburg based services."
|
||||
URL = "https://www.stadtreinigung.hamburg"
|
||||
TEST_CASES = OrderedDict(
|
||||
[
|
||||
(
|
||||
"Hamburg",
|
||||
{
|
||||
"asId": 5087,
|
||||
"hnId": 113084,
|
||||
},
|
||||
),
|
||||
]
|
||||
)
|
||||
|
||||
|
||||
class Source:
|
||||
def __init__(self, asId, hnId):
|
||||
self._asId = asId
|
||||
self._hnId = hnId
|
||||
|
||||
def fetch(self):
|
||||
args = {"asId": self._asId, "hnId": self._hnId, "adresse": "MeineAdresse"}
|
||||
|
||||
# get ics file
|
||||
r = requests.post(
|
||||
f"https://www.stadtreinigung.hamburg/privatkunden/abfuhrkalender/Abfuhrtermin.ics",
|
||||
data=args,
|
||||
)
|
||||
|
||||
# parse ics file
|
||||
calender = icalendar.Calendar.from_ical(r.text)
|
||||
|
||||
# Summary text contains a lot of blabla. This reg-ex tries to extract the waste type.
|
||||
regex = re.compile("Erinnerung: Abfuhr (.*) morgen")
|
||||
|
||||
entries = []
|
||||
for e in calender.walk():
|
||||
if e.name == "VEVENT":
|
||||
summary = str(e.get("summary"))
|
||||
match = regex.match(summary)
|
||||
if match:
|
||||
summary = match.group(1)
|
||||
dtstart = e.get("dtstart").dt.date() + datetime.timedelta(days=1) # events are reported 1 day before
|
||||
summary = summary
|
||||
entries.append(CollectionAppointment(dtstart, summary))
|
||||
|
||||
return entries
|
||||
@@ -0,0 +1,112 @@
|
||||
#!/usr/bin/python3
|
||||
|
||||
import inquirer
|
||||
import requests
|
||||
import json
|
||||
from html.parser import HTMLParser
|
||||
|
||||
|
||||
# Parser for HTML option list
|
||||
class OptionParser(HTMLParser):
|
||||
def __init__(self, select_name):
|
||||
super().__init__()
|
||||
self._select_name = select_name
|
||||
self._within_select = False
|
||||
self._within_option = False
|
||||
self._option_name = ""
|
||||
self._option_value = "-1"
|
||||
self._choices = []
|
||||
|
||||
@property
|
||||
def choices(self):
|
||||
return self._choices
|
||||
|
||||
def handle_starttag(self, tag, attrs):
|
||||
if tag == "select":
|
||||
for attr in attrs:
|
||||
if attr[0] == "name" and attr[1] == self._select_name:
|
||||
self._within_select = True
|
||||
break
|
||||
elif tag == "option" and self._within_select:
|
||||
self._within_option = True
|
||||
for attr in attrs:
|
||||
if attr[0] == "value":
|
||||
self._option_value = attr[1]
|
||||
|
||||
def handle_endtag(self, tag):
|
||||
if tag == "select":
|
||||
self._within_select = False
|
||||
elif tag == "option":
|
||||
if (
|
||||
self._within_select
|
||||
and self._within_option
|
||||
and len(self._option_name) > 0
|
||||
and self._option_value != ""
|
||||
):
|
||||
self._choices.append((self._option_name, self._option_value))
|
||||
self._within_option = False
|
||||
self._option_name = ""
|
||||
self._option_value = "-1"
|
||||
|
||||
def handle_data(self, data):
|
||||
if self._within_option:
|
||||
self._option_name += data
|
||||
|
||||
|
||||
def main():
|
||||
# search for street
|
||||
questions = [
|
||||
inquirer.Text("strasse", message="Enter search string for street name"),
|
||||
# inquirer.Text("hausnummer", message="Enter search string for building number"),
|
||||
]
|
||||
answers = inquirer.prompt(questions)
|
||||
|
||||
args = answers
|
||||
args["hausnummer"] = ""
|
||||
args["bestaetigung"] = "true"
|
||||
args["mode"] = "search"
|
||||
|
||||
r = requests.post(
|
||||
"https://www.stadtreinigung.hamburg/privatkunden/abfuhrkalender/index.html",
|
||||
data=args,
|
||||
)
|
||||
|
||||
# parser HTML option list
|
||||
parser = OptionParser(select_name="asId")
|
||||
parser.feed(r.text)
|
||||
|
||||
questions = [inquirer.List("asId", choices=parser.choices, message="Select street")]
|
||||
answers = inquirer.prompt(questions)
|
||||
|
||||
# search for building number
|
||||
args = answers.copy()
|
||||
args["hausnummer"] = ""
|
||||
args["bestaetigung"] = "true"
|
||||
args["mode"] = "search"
|
||||
|
||||
r = requests.post(
|
||||
"https://www.stadtreinigung.hamburg/privatkunden/abfuhrkalender/index.html",
|
||||
data=args,
|
||||
)
|
||||
|
||||
# parser HTML option list
|
||||
parser = OptionParser(select_name="hnId")
|
||||
parser.feed(r.text)
|
||||
|
||||
questions = [
|
||||
inquirer.List("hnId", choices=parser.choices, message="Select house number")
|
||||
]
|
||||
answers.update(inquirer.prompt(questions))
|
||||
|
||||
print("Copy the following statements into your configuration.yaml:\n")
|
||||
print("# waste_collection_schedule source configuration")
|
||||
print("waste_collection_schedule:")
|
||||
print(" sources:")
|
||||
print(" - name: stadtreinigung_hamburg")
|
||||
print(" args:")
|
||||
print(f" asId: {answers['asId']}")
|
||||
print(f" hnId: {answers['hnId']}")
|
||||
|
||||
|
||||
if __name__ == "__main__":
|
||||
main()
|
||||
41
doc/source/stadtreinigung_hamburg.md
Normal file
41
doc/source/stadtreinigung_hamburg.md
Normal file
@@ -0,0 +1,41 @@
|
||||
# Stadtreinigung.Hamburg
|
||||
|
||||
Add support for schedules provided by `Stadtreinigung.Hamburg`.
|
||||
|
||||
## Configuration via configuration.yaml
|
||||
|
||||
```yaml
|
||||
waste_collection_schedule:
|
||||
sources:
|
||||
- name: stadtreinigung_hamburg
|
||||
args:
|
||||
asId: ASID
|
||||
hnId: HNID
|
||||
```
|
||||
|
||||
### Configuration Variables
|
||||
|
||||
**asId**<br>
|
||||
*(string) (required)*
|
||||
|
||||
**hnId**<br>
|
||||
*(string) (required)*
|
||||
|
||||
## Example
|
||||
|
||||
```yaml
|
||||
waste_collection_schedule:
|
||||
sources:
|
||||
- name: stadtreinigung_hamburg
|
||||
args:
|
||||
asId: 5087
|
||||
hnId: 113084
|
||||
```
|
||||
|
||||
## How to get the source arguments
|
||||
|
||||
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/package/wizard/stadtreinigung_hamburg.py](https://github.com/mampfes/hacs_waste_collection_schedule/blob/master/custom_components/waste_collection_schedule/package/wizard/stadtreinigung_hamburg.py).
|
||||
|
||||
Just run this script from a shell and answer the questions.
|
||||
Reference in New Issue
Block a user