Monitoring Utility Meters
There are quite a few options for monitoring your whole house water or power usage, but i’m not thrilled about adding a bunch of extra hardware to my breaker panel.
I’ve known for a while that the city reads my utility meters by driving by, but had assumed this radio technology was some kind of encrypted proprietary data that I couldn’t access. However it turns out most utility meters in the US broadcast their readings in a completely unencrypted format every 15-60 seconds and with the recent advances in Software Defined Radio’s it doesn’t require anything particularly complex to pick it up.
I bought a Nooelec NESDR Smart v4 for $40 and then plugged it straight into the USB port on my Synology NAS. It does get quite hot in regular operation, but that doesn’t seem to affect its performance.
I was then able to make a meters bucket on my InfluxDB database
curl 'http://nas-server:8086/query?pretty=true' --data-urlencode "q=CREATE database meters"
Software-Defined Radio Stack
The tools I’ll need to capture the readings are as follows:
- rtltcp – This is a library that allows a software defined USB radio to be accessed by TCP over the network
- rtlamr – This tool connects to a radio being exposed by rtltcp and decodes and exports meter readings
- rtlamr-connect – This takes the readings from rtlamr and writes them into InfluxDB
Fortunately, I found a handy docker image that rolls all that together into one:
docker \ run \ -d \ --privileged \ # Normally docker container can't access USB -v /dev/bus/usb:/dev/bus/usb \ # This maps the whole USB bus to this docker container, probably overkill --name rtlamr \ # Here's a name -e COLLECT_INFLUXDB_USER=user \ # Add your InfluxDB credentials here -e COLLECT_INFLUXDB_PASS=pass \ -e COLLECT_INFLUXDB_HOSTNAME=http://nas-server:8086 \ -e COLLECT_INFLUXDB_DATABASE=meters \ # Here's the bucket we're writing to, don't forget to create it first -e RTLAMR_FORMAT=json \ # This is very important -e RTLAMR_MSGTYPE=scm,r900 \ # These two message types grab my meters, you can use "all" if unsure shoginn/rtlamr-collect:latest # The image to run
Let’s let it run for a while and look at the data in influx:
from(bucket: "meters") |> range(start: dashboardTime) |> filter(fn: (r) => r._measurement == "rtlamr" and (r._field == "consumption"))
Well that seems to work, all in all I can see pretty reliable transmissions from about 50 utility meters. Figuring out which
endpoint_id belongs to my meters required a bit of detective work but I found something that mostly corresponded to my endpoint on both my electricity and water meters.
The next challenge will be to use InfluxDB to get those numbers into a usable format for monitoring.