mirror of
https://github.com/sascha-hemi/hacs_waste_collection_schedule.git
synced 2026-03-21 00:04:11 +01:00
Make use of new Renosyd (DK) API and update devcontainer (#1812)
* Update `devcontainer` to latest structure and images Current source has deprecation message, and simply did not work * Adapt `renosyd_dk` to new API * Remove storskrald It's now sourced on a different endpoint. It's also a service that is ordered, so may make little sense to keep on a schedule. * reformatting * allow integer house_number --------- Co-authored-by: 5ila5 <5ila5@users.noreply.github.com>
This commit is contained in:
@@ -1,33 +1,38 @@
|
||||
// See https://aka.ms/vscode-remote/devcontainer.json for format details.
|
||||
{
|
||||
"name": "Waste Collection Schedule development",
|
||||
"image": "ghcr.io/ludeeus/devcontainer/integration:stable",
|
||||
"context": "..",
|
||||
"image": "mcr.microsoft.com/devcontainers/base:ubuntu",
|
||||
"appPort": [
|
||||
"9123:8123"
|
||||
],
|
||||
"containerEnv": {
|
||||
"TZ": "Europe/Berlin" // Set your local timezone here
|
||||
},
|
||||
"postCreateCommand": "container install",
|
||||
"extensions": [
|
||||
"ms-python.python",
|
||||
"github.vscode-pull-request-github",
|
||||
"ryanluker.vscode-coverage-gutters",
|
||||
"ms-python.vscode-pylance"
|
||||
],
|
||||
"settings": {
|
||||
"files.eol": "\n",
|
||||
"editor.tabSize": 4,
|
||||
"terminal.integrated.shell.linux": "/bin/bash",
|
||||
"python.defaultInterpreterPath": "/usr/bin/python3",
|
||||
"python.analysis.autoSearchPaths": false,
|
||||
"python.linting.pylintEnabled": true,
|
||||
"python.linting.enabled": true,
|
||||
"python.formatting.provider": "black",
|
||||
"editor.formatOnPaste": false,
|
||||
"editor.formatOnSave": true,
|
||||
"editor.formatOnType": true,
|
||||
"files.trimTrailingWhitespace": true
|
||||
"features": {
|
||||
"ghcr.io/devcontainers/features/python:1": {}
|
||||
},
|
||||
"customizations": {
|
||||
"vscode": {
|
||||
"extensions": [
|
||||
"ms-python.python",
|
||||
"github.vscode-pull-request-github",
|
||||
"ryanluker.vscode-coverage-gutters",
|
||||
"ms-python.vscode-pylance"
|
||||
],
|
||||
"settings": {
|
||||
"files.eol": "\n",
|
||||
"editor.tabSize": 4,
|
||||
"terminal.integrated.shell.linux": "/bin/bash",
|
||||
"python.defaultInterpreterPath": "/usr/bin/python3",
|
||||
"python.analysis.autoSearchPaths": false,
|
||||
"python.linting.pylintEnabled": true,
|
||||
"python.linting.enabled": true,
|
||||
"python.formatting.provider": "black",
|
||||
"editor.formatOnPaste": false,
|
||||
"editor.formatOnSave": true,
|
||||
"editor.formatOnType": true,
|
||||
"files.trimTrailingWhitespace": true
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -1,134 +1,59 @@
|
||||
import requests, re, time, datetime
|
||||
from bs4 import BeautifulSoup, NavigableString
|
||||
from dateutil import parser
|
||||
from waste_collection_schedule import Collection # type: ignore[attr-defined]
|
||||
from datetime import datetime
|
||||
from typing import List
|
||||
|
||||
import requests
|
||||
from waste_collection_schedule import Collection # type: ignore[attr-defined]
|
||||
|
||||
TITLE = "Renosyd"
|
||||
DESCRIPTION = "Renosyd collections for Skanderborg and Odder kommunes"
|
||||
URL = "https://renosyd.dk"
|
||||
TEST_CASES = {
|
||||
"TestCase1": {
|
||||
"kommune": "skanderborg",
|
||||
"husnummer": 123000,
|
||||
"house_number": "013000",
|
||||
},
|
||||
"TestCase2": {
|
||||
"kommune": "skanderborg",
|
||||
"husnummer": 186305,
|
||||
"house_number": "012000",
|
||||
},
|
||||
"TestCase3": {
|
||||
"kommune": "odder",
|
||||
"husnummer": 89042,
|
||||
"house_number": 11000,
|
||||
},
|
||||
}
|
||||
|
||||
ICON_MAP = {
|
||||
"RESTAFFALD": "mdi:trash-can",
|
||||
"PAPIR/PAP": "mdi:note-multiple",
|
||||
"PAPIR": "mdi:newspaper",
|
||||
"PAP": "mdi:archive",
|
||||
"EMBALLAGE": "mdi:recycle",
|
||||
"STORSKRALD": "mdi:dump-truck",
|
||||
"HAVEAFFALD": "mdi:leaf", # Uncertain about this name, can't find an example
|
||||
"GLAS": "mdi:bottle-wine",
|
||||
"METAL": "mdi:wrench",
|
||||
"HÅRD PLAST": "mdi:bottle-soda-classic",
|
||||
}
|
||||
|
||||
DANISH_MONTHS = [
|
||||
None,
|
||||
"jan",
|
||||
"feb",
|
||||
"mar",
|
||||
"apr",
|
||||
"maj",
|
||||
"jun",
|
||||
"jul",
|
||||
"aug",
|
||||
"sep",
|
||||
"okt",
|
||||
"nov",
|
||||
"dec",
|
||||
]
|
||||
|
||||
|
||||
class Source:
|
||||
def __init__(self, kommune: str, husnummer: int):
|
||||
self._kommune = kommune
|
||||
self._husnummer = husnummer
|
||||
self._api_url = (
|
||||
"https://"
|
||||
+ self._kommune.lower()
|
||||
+ ".netdialog.renosyd.dk/citizen/default.aspx"
|
||||
)
|
||||
def __init__(self, house_number: str | int):
|
||||
house_number = str(house_number).zfill(6)
|
||||
self._api_url = f"https://skoda-selvbetjeningsapi.renosyd.dk/api/v1/toemmekalender?nummer={house_number}"
|
||||
|
||||
def fetch(self) -> List[Collection]:
|
||||
session = requests.Session()
|
||||
|
||||
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",
|
||||
}
|
||||
|
||||
address_select = session.get(
|
||||
self._api_url,
|
||||
cookies={"StoredAddress": str(self._husnummer)},
|
||||
)
|
||||
address_select.raise_for_status()
|
||||
|
||||
address_select_soup = BeautifulSoup(address_select.text, "html.parser")
|
||||
data = {
|
||||
i["name"]: i.get("value", "")
|
||||
for i in address_select_soup.select("input[name]")
|
||||
}
|
||||
|
||||
binfo = session.post(self._api_url, data=data)
|
||||
binfo.raise_for_status()
|
||||
|
||||
binfo_soup = BeautifulSoup(binfo.text, "html.parser")
|
||||
|
||||
calendar = binfo_soup.find_all(attrs={"class": "tableContainersAtProperty"})
|
||||
|
||||
months = []
|
||||
this_year = time.localtime().tm_year
|
||||
|
||||
for month in calendar[1].find_all("th"):
|
||||
value = month.contents[0].strip()
|
||||
if value == "Beholder":
|
||||
continue
|
||||
|
||||
months.append(datetime.date(this_year, DANISH_MONTHS.index(value), 1))
|
||||
|
||||
if value == "dec":
|
||||
this_year += 1
|
||||
response = requests.get(self._api_url)
|
||||
response.raise_for_status()
|
||||
data = response.json()
|
||||
|
||||
entries = []
|
||||
|
||||
rows = calendar[1].find_all("tr")
|
||||
|
||||
for row in rows[1:]:
|
||||
elements = row.find_all("td")
|
||||
|
||||
result = re.search(
|
||||
r"^(\d{1,2}\s?x\s?)([A-Za-z\/]*)(\s*\d{1,4}\s?L)?$",
|
||||
elements[0].contents[0].strip(),
|
||||
)
|
||||
if result is None:
|
||||
continue
|
||||
|
||||
container_type = result.groups()[1]
|
||||
|
||||
for idx, element in enumerate(elements[1:]):
|
||||
for subelement in element.contents:
|
||||
if not isinstance(subelement, NavigableString):
|
||||
continue
|
||||
|
||||
if subelement.strip() == "":
|
||||
continue
|
||||
|
||||
for item in data:
|
||||
for toemning in item.get("planlagtetømninger", []):
|
||||
date = datetime.strptime(toemning["dato"], "%Y-%m-%dT%H:%M:%SZ").date()
|
||||
for fraktion in toemning["fraktioner"]:
|
||||
entries.append(
|
||||
Collection(
|
||||
date=months[idx]
|
||||
+ datetime.timedelta(days=int(subelement.strip()) - 1),
|
||||
t=container_type,
|
||||
icon=ICON_MAP.get(container_type.upper()),
|
||||
date=date,
|
||||
t=fraktion,
|
||||
icon=ICON_MAP.get(
|
||||
fraktion.upper(), "mdi:trash-can-outline"
|
||||
),
|
||||
)
|
||||
)
|
||||
return entries
|
||||
|
||||
@@ -9,19 +9,15 @@ waste_collection_schedule:
|
||||
sources:
|
||||
- name: renosyd_dk
|
||||
args:
|
||||
kommune: "odder" OR "skanderborg"
|
||||
husnummer: See description
|
||||
house_number: See description
|
||||
|
||||
```
|
||||
|
||||
### Configuration Variables
|
||||
|
||||
**kommune**
|
||||
**house_number**
|
||||
*(String) (required)*
|
||||
|
||||
**husnummer**
|
||||
*(Int) (required)*
|
||||
|
||||
## Example
|
||||
|
||||
```yaml
|
||||
@@ -29,16 +25,20 @@ waste_collection_schedule:
|
||||
sources:
|
||||
- name: renosyd_dk
|
||||
args:
|
||||
kommune: skanderborg
|
||||
husnummer: 123000
|
||||
house_number: "023000"
|
||||
|
||||
```
|
||||
|
||||
## How to get the house number / husnummer
|
||||
|
||||
Go to the page for either [Odder](https://odder.netdialog.renosyd.dk/citizen/) or [Skanderborg](https://skanderborg.netdialog.renosyd.dk/citizen/). Select your street and then house/apartment number. Select "husk min adresse", and then select "Næste...".
|
||||
Go to the [Mit renosyd](https://mit.renosyd.dk/toemmekalender) page, enter your address and click "Gem".
|
||||
|
||||
Now the house number is saved as a cookie. Open developer tools (right-click-> inspect in Firefox/Chrome), and look at the cookies (in Storage in Firefox, Application->Storage->Cookies in Chrome). There should be a single cookie storing a "StoredAddress" value - the house id number - and a session id which you can ignore.
|
||||
Your house number is saved in Local Storage. To get this, you can:
|
||||
1) Open Developer Console
|
||||
- Chrome / Microsoft Edge: `CTRL + SHIFT + J` or `Cmd + Option + J`
|
||||
- Firefox: `CTRL + SHIFT + K` or `Cmd + Option + K`
|
||||
- Safari: `CMD + OPTION + C`
|
||||
2) Paste the following and press `enter`, which will output the number you need: `JSON.parse(localStorage.getItem('bookmarkedCollectionSites'))[0].standpladsNummer`
|
||||
|
||||
### Filtering Example
|
||||
|
||||
@@ -49,8 +49,7 @@ waste_collection_schedule:
|
||||
sources:
|
||||
- name: renosyd_dk
|
||||
args:
|
||||
kommune: skanderborg
|
||||
husnummer: 123001
|
||||
house_number: 123001
|
||||
customize:
|
||||
- type: Storskrald
|
||||
show: false
|
||||
|
||||
Reference in New Issue
Block a user