mirror of
https://github.com/sascha-hemi/hacs_waste_collection_schedule.git
synced 2026-03-21 02:04:22 +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,15 +1,18 @@
|
|||||||
// See https://aka.ms/vscode-remote/devcontainer.json for format details.
|
// See https://aka.ms/vscode-remote/devcontainer.json for format details.
|
||||||
{
|
{
|
||||||
"name": "Waste Collection Schedule development",
|
"name": "Waste Collection Schedule development",
|
||||||
"image": "ghcr.io/ludeeus/devcontainer/integration:stable",
|
"image": "mcr.microsoft.com/devcontainers/base:ubuntu",
|
||||||
"context": "..",
|
|
||||||
"appPort": [
|
"appPort": [
|
||||||
"9123:8123"
|
"9123:8123"
|
||||||
],
|
],
|
||||||
"containerEnv": {
|
"containerEnv": {
|
||||||
"TZ": "Europe/Berlin" // Set your local timezone here
|
"TZ": "Europe/Berlin" // Set your local timezone here
|
||||||
},
|
},
|
||||||
"postCreateCommand": "container install",
|
"features": {
|
||||||
|
"ghcr.io/devcontainers/features/python:1": {}
|
||||||
|
},
|
||||||
|
"customizations": {
|
||||||
|
"vscode": {
|
||||||
"extensions": [
|
"extensions": [
|
||||||
"ms-python.python",
|
"ms-python.python",
|
||||||
"github.vscode-pull-request-github",
|
"github.vscode-pull-request-github",
|
||||||
@@ -31,3 +34,5 @@
|
|||||||
"files.trimTrailingWhitespace": true
|
"files.trimTrailingWhitespace": true
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -1,134 +1,59 @@
|
|||||||
import requests, re, time, datetime
|
from datetime import datetime
|
||||||
from bs4 import BeautifulSoup, NavigableString
|
|
||||||
from dateutil import parser
|
|
||||||
from waste_collection_schedule import Collection # type: ignore[attr-defined]
|
|
||||||
from typing import List
|
from typing import List
|
||||||
|
|
||||||
|
import requests
|
||||||
|
from waste_collection_schedule import Collection # type: ignore[attr-defined]
|
||||||
|
|
||||||
TITLE = "Renosyd"
|
TITLE = "Renosyd"
|
||||||
DESCRIPTION = "Renosyd collections for Skanderborg and Odder kommunes"
|
DESCRIPTION = "Renosyd collections for Skanderborg and Odder kommunes"
|
||||||
URL = "https://renosyd.dk"
|
URL = "https://renosyd.dk"
|
||||||
TEST_CASES = {
|
TEST_CASES = {
|
||||||
"TestCase1": {
|
"TestCase1": {
|
||||||
"kommune": "skanderborg",
|
"house_number": "013000",
|
||||||
"husnummer": 123000,
|
|
||||||
},
|
},
|
||||||
"TestCase2": {
|
"TestCase2": {
|
||||||
"kommune": "skanderborg",
|
"house_number": "012000",
|
||||||
"husnummer": 186305,
|
|
||||||
},
|
},
|
||||||
"TestCase3": {
|
"TestCase3": {
|
||||||
"kommune": "odder",
|
"house_number": 11000,
|
||||||
"husnummer": 89042,
|
|
||||||
},
|
},
|
||||||
}
|
}
|
||||||
|
|
||||||
ICON_MAP = {
|
ICON_MAP = {
|
||||||
"RESTAFFALD": "mdi:trash-can",
|
"RESTAFFALD": "mdi:trash-can",
|
||||||
"PAPIR/PAP": "mdi:note-multiple",
|
"PAPIR": "mdi:newspaper",
|
||||||
|
"PAP": "mdi:archive",
|
||||||
"EMBALLAGE": "mdi:recycle",
|
"EMBALLAGE": "mdi:recycle",
|
||||||
"STORSKRALD": "mdi:dump-truck",
|
|
||||||
"HAVEAFFALD": "mdi:leaf", # Uncertain about this name, can't find an example
|
"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:
|
class Source:
|
||||||
def __init__(self, kommune: str, husnummer: int):
|
def __init__(self, house_number: str | int):
|
||||||
self._kommune = kommune
|
house_number = str(house_number).zfill(6)
|
||||||
self._husnummer = husnummer
|
self._api_url = f"https://skoda-selvbetjeningsapi.renosyd.dk/api/v1/toemmekalender?nummer={house_number}"
|
||||||
self._api_url = (
|
|
||||||
"https://"
|
|
||||||
+ self._kommune.lower()
|
|
||||||
+ ".netdialog.renosyd.dk/citizen/default.aspx"
|
|
||||||
)
|
|
||||||
|
|
||||||
def fetch(self) -> List[Collection]:
|
def fetch(self) -> List[Collection]:
|
||||||
session = requests.Session()
|
response = requests.get(self._api_url)
|
||||||
|
response.raise_for_status()
|
||||||
session.headers = {
|
data = response.json()
|
||||||
"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
|
|
||||||
|
|
||||||
entries = []
|
entries = []
|
||||||
|
|
||||||
rows = calendar[1].find_all("tr")
|
for item in data:
|
||||||
|
for toemning in item.get("planlagtetømninger", []):
|
||||||
for row in rows[1:]:
|
date = datetime.strptime(toemning["dato"], "%Y-%m-%dT%H:%M:%SZ").date()
|
||||||
elements = row.find_all("td")
|
for fraktion in toemning["fraktioner"]:
|
||||||
|
|
||||||
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
|
|
||||||
|
|
||||||
entries.append(
|
entries.append(
|
||||||
Collection(
|
Collection(
|
||||||
date=months[idx]
|
date=date,
|
||||||
+ datetime.timedelta(days=int(subelement.strip()) - 1),
|
t=fraktion,
|
||||||
t=container_type,
|
icon=ICON_MAP.get(
|
||||||
icon=ICON_MAP.get(container_type.upper()),
|
fraktion.upper(), "mdi:trash-can-outline"
|
||||||
|
),
|
||||||
)
|
)
|
||||||
)
|
)
|
||||||
return entries
|
return entries
|
||||||
|
|||||||
@@ -9,19 +9,15 @@ waste_collection_schedule:
|
|||||||
sources:
|
sources:
|
||||||
- name: renosyd_dk
|
- name: renosyd_dk
|
||||||
args:
|
args:
|
||||||
kommune: "odder" OR "skanderborg"
|
house_number: See description
|
||||||
husnummer: See description
|
|
||||||
|
|
||||||
```
|
```
|
||||||
|
|
||||||
### Configuration Variables
|
### Configuration Variables
|
||||||
|
|
||||||
**kommune**
|
**house_number**
|
||||||
*(String) (required)*
|
*(String) (required)*
|
||||||
|
|
||||||
**husnummer**
|
|
||||||
*(Int) (required)*
|
|
||||||
|
|
||||||
## Example
|
## Example
|
||||||
|
|
||||||
```yaml
|
```yaml
|
||||||
@@ -29,16 +25,20 @@ waste_collection_schedule:
|
|||||||
sources:
|
sources:
|
||||||
- name: renosyd_dk
|
- name: renosyd_dk
|
||||||
args:
|
args:
|
||||||
kommune: skanderborg
|
house_number: "023000"
|
||||||
husnummer: 123000
|
|
||||||
|
|
||||||
```
|
```
|
||||||
|
|
||||||
## How to get the house number / husnummer
|
## 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
|
### Filtering Example
|
||||||
|
|
||||||
@@ -49,8 +49,7 @@ waste_collection_schedule:
|
|||||||
sources:
|
sources:
|
||||||
- name: renosyd_dk
|
- name: renosyd_dk
|
||||||
args:
|
args:
|
||||||
kommune: skanderborg
|
house_number: 123001
|
||||||
husnummer: 123001
|
|
||||||
customize:
|
customize:
|
||||||
- type: Storskrald
|
- type: Storskrald
|
||||||
show: false
|
show: false
|
||||||
|
|||||||
Reference in New Issue
Block a user