Slimme meterstanden opslaan in Prometheus
Een van de redenen dat ik een Raspberry Pi in m’n meterkast heb hangen is omdat ik de slimme meter wil kunnen uitlezen, zodat het duidelijk is welk deel van de opbrengst van de zonnepanelen terug het net op gaat en welk deel we zelf gebruiken. Zeker nu het salderen er in 2027 uit gaat is dat interessante informatie om te bepalen wat een thuisbatterij zou opleveren.
Om de meter uit te lezen en de tellerstanden op te slaan heb ik een tooltje geschreven in Rust, een programmeertaal die de laatste jaren heel populair is geworden onder systeemprogrammeurs. Eén van de killer features van Rust is memory-safeness, wat het makkelijker maakt om veilige code te schrijven… of althans, makkelijker dan C en C++ dat doen in ieder geval.
C makes it easy to shoot yourself in the foot; C++ makes it harder, but when you do it blows your whole leg off
– Bjarne Stroustrup (uitvinder van C++)
In ieder geval, hier wilde ik graag eens mee spelen en dan is een concreet project wel handig. Omdat ik werkelijk geen idee had van hoe Rust werkt en dat de verder uitstekende tutorials natuurlijk niet vertellen hoe je een slimme meter uitleest of hoe je een Prometheus exporter schrijft, heb ik ChatGPT gevraagd een voorzetje te geven. Dit leverde in eerste instantie een hoop niet werkende rommel op, maar wel een paar waardevolle regels code die ik vervolgens kon aanpassen en gebruiken.
Uiteindelijk heb ik alles verwerkt in een tool met de prachtige naam kamstrup-162jxc-p1-prometheus-exporter-rs.
Meterstanden uitlezen
Slimme meters in Nederland zijn gespecificeerd in het document “Dutch Smart Meter Requirements” dat wordt onderhouden door Netbeheer Nederland. Er zijn inmiddels meer dan tien versies van de standaard in omloop en je meter, afhankelijk van wanneer die is geïnstalleerd, moet voldoen aan een van die versies.
Bij ons in de meterkast hangt een “oudje”, een Kamstrup 162JXC, die voldoet aan DSMR 3.0 uit 2010. Volgens DSMR zit er een seriële poort op die het eindgebruikers mogelijk maakt om de meter lokaal uit te lezen. Deze poort wordt P1 genoemd en is een aansluiting met RJ-11 plug; een telefoonstekker.
Voor het uitlezen van de meter heb je een kabel nodig vanuit de RJ11 poort naar je
computer; ik heb deze besteld. Met het UNIX “call up”
command cu
praat je vervolgens over de seriële poort:
cu -l /dev/ttyUSB0 -E% --parity=even
Elke 10 seconden verschijnt een rapport van de actuele meterstanden in beeld:
/KMP5 KA6UXXXXXXXXXXXX
0-0:96.1.1(XXXXXX)
1-0:1.8.1(20203.975*kWh)
1-0:1.8.2(18247.900*kWh)
1-0:2.8.1(00238.368*kWh)
1-0:2.8.2(00532.631*kWh)
0-0:96.14.0(0001)
1-0:1.7.0(0000.29*kW)
1-0:2.7.0(0000.00*kW)
0-0:96.13.1()
0-0:96.13.0()
0-1:24.1.0(3)
0-1:96.1.0(XXXXXX)
0-1:24.3.0(240914210000)(08)(60)(1)(0-1:24.2.1)(m3)
(14094.865)
!
Steeds wanneer er zo’n blok langskomt lees ik de standen uit, reken het om naar de juiste eenheden (kWh naar Wh, kW naar W) en houdt het bij voor de volgende stap, het opslaan van de tellerstanden.
Exporteren naar Prometheus
Om meterstanden langdurig op te slaan gebruik ik de “timeseries” database Prometheus. Een timeseries database is een database geoptimaliseerd voor het opslaan van gegevensreeksen afgezet tegen de tijd. Voorbeelden zijn aandelenkoersen, waterstanden en dus ook de meterstanden van je stroomteller. Prometheus verzamelt de informatie actief door elke geconfigureerde service periodiek te bevragen. Daarbij doet een simpele HTTP (web)server die slechts een enkele “pagina” bevat in een specifiek formaat dienst als bron.
# HELP kamstrup_162jxc_p1_actual_power_delivered_watts Actual electricity power delivered (+P) in 1 Watt resolution (1-0:1.7.0)
# TYPE kamstrup_162jxc_p1_actual_power_delivered_watts gauge
kamstrup_162jxc_p1_actual_power_delivered_watts 290
# HELP kamstrup_162jxc_p1_actual_power_received_watts Actual electricity power received (-P) in 1 Watt resolution (1-0:2.7.0)
# TYPE kamstrup_162jxc_p1_actual_power_received_watts gauge
kamstrup_162jxc_p1_actual_power_received_watts 0
# HELP kamstrup_162jxc_p1_total_energy_delivered_watthours Total electricity energy delivered (+P) in 1 Watthour resolution (1-0:1.8.1 / 1-0:1.8.2)
# TYPE kamstrup_162jxc_p1_total_energy_delivered_watthours counter
kamstrup_162jxc_p1_total_energy_delivered_watthours{meter="1"} 20203975
kamstrup_162jxc_p1_total_energy_delivered_watthours{meter="2"} 18247900
# HELP kamstrup_162jxc_p1_total_energy_received_watthours Total electricity energy received (-P) in 1 Watthour resolution (1-0:2.8.1 / 1-0:2.8.2)
# TYPE kamstrup_162jxc_p1_total_energy_received_watthours counter
kamstrup_162jxc_p1_total_energy_received_watthours{meter="1"} 238368
kamstrup_162jxc_p1_total_energy_received_watthours{meter="2"} 532631
# HELP kamstrup_162jxc_p1_total_gas_delivered_m3 Total gas delivered in m3 (0-1:24.3.0)
# TYPE kamstrup_162jxc_p1_total_gas_delivered_m3 counter
kamstrup_162jxc_p1_total_gas_delivered_m3 14094.865
Automatisch opstarten met de Raspberry Pi
Het is natuurlijk het handigst als zo’n exporter altijd opstart samen met de rest van het systeem. Raspberry Pi OS is
Debian based and as such uses systemd
for managing persistent services. On my Pi, I just created a file
/etc/systemd/system/kamstrup-162jxc-p1-prometheus-exporter.service
with the contents below:
[Unit]
Description=Kamstrup 162JXC P1 Prometheus exporter
After=time-sync.target
[Service]
ExecStart=/usr/bin/kamstrup-162jxc-p1-prometheus-exporter-rs --port 9292 --serial-port /dev/ttyUSB0
Type=simple
[Install]
WantedBy=multi-user.target
Nu nog een systemctl enable kamstrup-162jxc-p1-prometheus-exporter-rs
, de service wordt ingeladen en start voortaan
bij elke boot. Het verbindt automatisch met de seriële poort en start de Prometheus exporter webserver.
Conclusie
Het is vrij eenvoudig om een slimme meter uit te lezen en de resultaten bij te houden in een database. De componenten zijn klein en overzichtelijk. Het ging zelfs zó eenvoudig dat ik meteen ook ben begonnen aan een tool om de zonnepanelen uit te lezen!
Links
Webmentions
Heb je een reactie op dit artikel geschreven? Stuur me een webmention! Het kan een paar dagen duren voordat je reactie hier verschijnt.