Kommunens tømmekalender inn i Home Assistant

Kommunens tømmekalender skulle vise neste dato per fraksjon (rest, papir, plast, mat) på veggpanelet i Home Assistant. Det gikk fint lenge, kjørt fra et skyhostet script, helt til det sluttet å levere datoer uten en eneste feilmelding.
Symptomet så ut som kodefeil
Scriptet var en Google Apps Script som hentet data fra kommunens renovasjons-API og dyttet det videre til Home Assistant. Loggen viste timeout mot kommunens server. Den første, naturlige antagelsen var at API-et var endret eller nede. Men det stemte ikke: det nøyaktig samme kallet fra et norsk hjemmenett svarte med en gang.
Forskjellen lå altså i hvor kallet kom fra. Kommunens server lyttet på en port som ikke er standard, og de utgående IP-ene til skyleverandøren nådde rett og slett aldri frem. Trafikken ble stoppet et sted mellom skyen og kommunen. Fra et norsk nett gikk den rett igjennom, uten kluss.
Diagnose: et nettverksproblem

En rask test for å skille kode fra nett: kjør nøyaktig samme forespørsel fra to steder, og se hva som skjer.
# Fra hjemmenett: svarerNår koden er identisk og det eneste som skiller er hvilket nett kallet kommer fra, da er det ikke koden som er problemet. En del offentlige API-er er geo- eller nettgjerdet. De slipper inn norske aksessnett, men stenger ute utenlandske skyranger, gjerne ekstra hardt på uvanlige porter.
curl -m 10 -v https://api.kommune.example:8443/renovasjon/neste
# Fra skyhost: henger og timer ut
curl -m 10 -v https://api.kommune.example:8443/renovasjon/neste
Løsning: flytt henteren hjem

Henteren ble flyttet til en liten lokal container på samme nett som Home Assistant. Den poller én gang i døgnet med litt tilfeldig jitter, så kommunens server slipper å få et treff på nøyaktig samme sekund hver eneste dag. Resultatet skrives inn i input_datetime-hjelpere, én per fraksjon.
# Home Assistant hjelpere (configuration.yaml)Selve container-scriptet henter dataene og skriver dem via REST-API-et til Home Assistant.
input_datetime:
neste_restavfall:
name: Neste restavfall
has_date: true
has_time: false
neste_papir:
name: Neste papir
has_date: true
has_time: false
import random, time, requestsDet hele kjøres som en cron-jobb inne i containeren, én gang i døgnet.
time.sleep(random.randint(0, 3600)) # jitter, skånsom mot kommunen
data = requests.get("https://api.kommune.example:8443/renovasjon/neste",
timeout=15).json()
for fraksjon, dato in data.items():
requests.post(
f"http://192.168.x.x:8123/api/services/input_datetime/set_datetime",
headers={"Authorization": "Bearer "},
json={"entity_id": f"input_datetime.neste_{fraksjon}", "date": dato},
timeout=15)
# crontab: kl 06 hver dag, container legger på jitter selvSer noe ut som en kodefeil, kjør samme kall fra et annet nett før du graver i koden. Skiller bare opprinnelsen, ligger problemet i nettet og ikke i logikken. For geo- eller nettgjerdede offentlige API-er er svaret å kjøre hentingen fra riktig nett; en liten lokal container koster nesten ingenting og rydder unna hele klassen med skyrelaterte tilgangsfeil på én gang.
0 6 * * * python3 /app/hent_tommekalender.py


