mirror of
https://github.com/sascha-hemi/hacs_waste_collection_schedule.git
synced 2026-03-21 04:06:03 +01:00
Adding renoweb_dk (#1795)
* Added renoweb.dk
* README.md updated
* info.md updated
* requested modifications
* requested modifications
* reformatting
---------
Co-authored-by: Rune <{ID}+{username}@users.noreply.github.com>
Co-authored-by: 5ila5 <5ila5@users.noreply.github.com>
This commit is contained in:
@@ -498,6 +498,7 @@ Waste collection schedules in the following formats and countries are supported.
|
||||
<summary>Denmark</summary>
|
||||
|
||||
- [Renosyd](/doc/source/renosyd_dk.md) / renosyd.dk
|
||||
- [RenoWeb](/doc/source/renoweb_dk.md) / renoweb.dk
|
||||
</details>
|
||||
|
||||
<details>
|
||||
|
||||
@@ -0,0 +1,134 @@
|
||||
"""Support for Renoweb waste collection schedule."""
|
||||
|
||||
import json
|
||||
import logging
|
||||
import re
|
||||
from datetime import datetime
|
||||
from typing import List
|
||||
|
||||
import requests
|
||||
from waste_collection_schedule import Collection # type: ignore[attr-defined]
|
||||
|
||||
TITLE = "RenoWeb"
|
||||
DESCRIPTION = "RenoWeb collections"
|
||||
URL = "https://renoweb.dk"
|
||||
API_URL = "https://{municipality}.renoweb.dk/Legacy/JService.asmx/{{endpoint}}"
|
||||
|
||||
TEST_CASES = {
|
||||
"test_01": {
|
||||
"municipality": "frederiksberg",
|
||||
"address": "Roskildevej 40",
|
||||
},
|
||||
"test_02": {
|
||||
"municipality": "htk",
|
||||
"address_id": 45149,
|
||||
},
|
||||
"test_03": {
|
||||
"municipality": "rudersdal",
|
||||
"address": "Stationsvej 38",
|
||||
},
|
||||
}
|
||||
|
||||
_LOGGER = logging.getLogger("waste_collection_schedule.renoweb_dk")
|
||||
|
||||
|
||||
class Source:
|
||||
"""Source class for RenoWeb."""
|
||||
|
||||
_api_url: str
|
||||
__address_id: int
|
||||
|
||||
def __init__(
|
||||
self,
|
||||
municipality: str,
|
||||
address: str | None = None,
|
||||
address_id: int | None = None,
|
||||
):
|
||||
_LOGGER.debug(
|
||||
"Source.__init__(); municipality=%s, address_id=%s, address=%s",
|
||||
municipality,
|
||||
address_id,
|
||||
address,
|
||||
)
|
||||
|
||||
self._api_url = API_URL.format(municipality=municipality.lower())
|
||||
|
||||
if address_id:
|
||||
self.__address_id = address_id
|
||||
|
||||
elif address:
|
||||
self._address = address
|
||||
|
||||
else:
|
||||
raise ValueError("Either address or address_id must be provided")
|
||||
|
||||
self._session = requests.Session()
|
||||
self._session.headers = {
|
||||
"User-Agent": "Mozilla/5.0 (Windows NT 10.0; Win64; x64; rv:109.0) "
|
||||
+ "Gecko/20100101 Firefox/115.0",
|
||||
"Accept-Encoding": "gzip, deflate",
|
||||
"Accept": "*/*",
|
||||
"Connection": "keep-alive",
|
||||
}
|
||||
|
||||
def _get_address_id(self) -> None:
|
||||
"""Get the address id."""
|
||||
response = self._session.post(
|
||||
url=self._api_url.format(endpoint="Adresse_SearchByString"),
|
||||
json={"searchterm": f"{self._address},", "addresswithmateriel": 3},
|
||||
)
|
||||
|
||||
response.raise_for_status()
|
||||
|
||||
_LOGGER.debug(
|
||||
"Address '%s'; id %s",
|
||||
json.loads(response.json()["d"])["list"][0]["label"],
|
||||
json.loads(response.json()["d"])["list"][0]["value"],
|
||||
)
|
||||
|
||||
self.__address_id = json.loads(response.json()["d"])["list"][0]["value"]
|
||||
|
||||
@property
|
||||
def _address_id(self) -> int:
|
||||
"""Return the address id."""
|
||||
if not hasattr(self, "__address_id"):
|
||||
self._get_address_id()
|
||||
|
||||
return self.__address_id
|
||||
|
||||
def fetch(self) -> List[Collection]:
|
||||
"""Fetch data from RenoWeb."""
|
||||
_LOGGER.debug("Source.fetch()")
|
||||
|
||||
entries: list[Collection] = []
|
||||
|
||||
response = self._session.post(
|
||||
url=self._api_url.format(endpoint="GetAffaldsplanMateriel_mitAffald"),
|
||||
json={"adrid": self._address_id, "common": False},
|
||||
)
|
||||
|
||||
response.raise_for_status()
|
||||
|
||||
# For some reason the response is a JSON structure inside a JSON string
|
||||
for entry in json.loads(response.json()["d"])["list"]:
|
||||
if not entry["afhentningsbestillingmateriel"] and re.search(
|
||||
r"dag den \d{2}-\d{2}-\d{4}", entry["toemningsdato"]
|
||||
):
|
||||
response = self._session.post(
|
||||
url=self._api_url.format(endpoint="GetCalender_mitAffald"),
|
||||
json={"materialid": entry["id"]},
|
||||
)
|
||||
|
||||
response.raise_for_status()
|
||||
|
||||
entry["name"] = " - ".join(
|
||||
[entry["ordningnavn"], entry["materielnavn"]]
|
||||
)
|
||||
|
||||
for date in [
|
||||
datetime.strptime(date_string.split()[-1], "%d-%m-%Y").date()
|
||||
for date_string in json.loads(response.json()["d"])["list"]
|
||||
]:
|
||||
entries.append(Collection(date=date, t=entry["name"]))
|
||||
|
||||
return entries
|
||||
76
doc/source/renoweb_dk.md
Normal file
76
doc/source/renoweb_dk.md
Normal file
@@ -0,0 +1,76 @@
|
||||
# Renoweb
|
||||
|
||||
Support for schedules provided by Sweco's [RenoWeb](https://renoweb.dk/), serving many Danish municipalities.
|
||||
|
||||
## Configuration via configuration.yaml
|
||||
|
||||
```yaml
|
||||
waste_collection_schedule:
|
||||
sources:
|
||||
- name: renoweb_dk
|
||||
args:
|
||||
municipality: MUNICIPALITY
|
||||
address: ADDRESS
|
||||
address_id: ADDRESS_ID
|
||||
```
|
||||
|
||||
### Configuration Variables
|
||||
|
||||
**municipality**
|
||||
_(String) (required)_
|
||||
|
||||
The name of the municipality as it appears in the URL. E.g. https://htk.renoweb.dk/Legacy/selvbetjening/mit_affald.aspx where "htk" is for Høje-Taastrup municipality.
|
||||
|
||||
**address**
|
||||
_(String) (required)_
|
||||
|
||||
The address to look up. It should be exactly as it is on the website until the comma between the street address and the postal code.
|
||||
|
||||
**address_id**
|
||||
_(Int) (optional)_
|
||||
|
||||
Use address_id if the address lookup fails.
|
||||
|
||||
## Example
|
||||
|
||||
```yaml
|
||||
waste_collection_schedule:
|
||||
sources:
|
||||
- name: renoweb_dk
|
||||
args:
|
||||
municipality: frederiksberg
|
||||
address: "Roskildevej 40"
|
||||
customize:
|
||||
- type: "Haveaffald - Haveaffald henteordning (1 stk.)"
|
||||
alias: "Haveaffald"
|
||||
```
|
||||
|
||||
## How to find the address_id
|
||||
|
||||
Go to the RenoWeb site for your municipality, e.g. https://htk.renoweb.dk/Legacy/selvbetjening/mit_affald.aspx if you are lucky enough to live in Høje-Taastrup.
|
||||
|
||||
Open the developer console in your browser.
|
||||
|
||||
Enter your address and select it in the dropdown menu. (Note that the Ejd.nr. in the dropdown is _not_ the ID we are looking for).
|
||||
|
||||
In the Network tab in the browser console, find the latest URL ending in **Adresse_SearchByString** and look in under Response, where you should see a chunk of JSON-ish data. The ID you need to use for adress_id is in the "value" field.
|
||||
|
||||
```json
|
||||
d: '{"list":[{"value":"45149","label":"Rådhusstræde 1, 2630 Taastrup (Ejd.nr. 186783)"}],"status":{"id":0,"status":"Ok","msg":""}}'
|
||||
```
|
||||
|
||||
### Customizing Waste Types
|
||||
|
||||
Customizing waste types is a feature of the Waste Collection Schedule component and is very useful here, since the waste types in RenoWeb are often long and not very consistent.
|
||||
|
||||
```yaml
|
||||
waste_collection_schedule:
|
||||
sources:
|
||||
- name: renoweb_dk
|
||||
args:
|
||||
municipality: frederiksberg
|
||||
address: "Roskildevej 40"
|
||||
customize:
|
||||
- type: "Haveaffald - Haveaffald henteordning (1 stk.)"
|
||||
alias: "Haveaffald"
|
||||
```
|
||||
Reference in New Issue
Block a user