Read your water, power, and gas meters using linux!

I've started a new hobby recently, I purchased a software defined radio dongle to explore the airwaves. With my setup, and a little investigation of my meter I can accurately read my water, gas, and electric meter readings.

amazon link to SDR I purchased

I've also written/tweaked Metermaid, utilizing rtl_tcp, rtlamr, mysql, and grafana.

It stores all reading, plus weather coming soon, and graphs with grafana. Check up the repository for more info. a graph created with grafana is in the title of this page. I think they look great, and data at 5 minute intervals for 300+meters is around 11 compressed MB a day. I also have a weather script I will be uploading soon.

https://github.com/jreiners/MeterMaid

Read the meters, the old way.

Install the prerequisites:

sudo yum install -y rtl_sdr go grafana influxdb

Now it's time to plug in your new SDR you purchased.

and install rtlamr using the instructions on the github repo.

[12:34 justin ~]$ go get github.com/bemasher/rtlamr
[12:34 justin ~]$ go get github.com/bemasher/rtlamr-collect

If you run into issues adding the go repo.

now, try and start rtl_tcp, rtl_tcp just lets your software defined radio to be controlled by the computer. It opens the port (:1234) for rtlamr to read data.

[12:30 justin ~/go]$ rtl_tcp 
Found 1 device(s):
  0:  Realtek, RTL2838UHIDIR, SN: 00000001

Using device 0: Generic RTL2832U OEM
Detached kernel driver
Found Rafael Micro R820T tuner
Tuned to 100000000 Hz.
listening...
Use the device argument 'rtl_tcp=127.0.0.1:1234' in OsmoSDR (gr-osmosdr) source
to receive samples in GRC and control rtl_tcp parameters (frequency, gain, 
...).

In another terminal, we will run rtlamr to read the meters. In my below example I am telling rtlamr to run for a -duration=1h and only give me -unique=true readings, in the --format=json.

[12:32 justin ~/go/bin]$ ./rtlamr -duration=1h -unique=true -format json | tee tuesday_meters.json
12:36:58.123668 decode.go:43: CenterFreq: 912600155
12:36:58.124372 decode.go:44: SampleRate: 2359296
12:36:58.124381 decode.go:45: DataRate: 32768
12:36:58.124388 decode.go:46: ChipLength: 72
12:36:58.124395 decode.go:47: PreambleSymbols: 21
12:36:58.124401 decode.go:48: PreambleLength: 3024
12:36:58.124408 decode.go:49: PacketSymbols: 96
12:36:58.124414 decode.go:50: PacketLength: 13824
12:36:58.124421 decode.go:51: Preamble: 111110010101001100000
12:36:58.124428 main.go:94: GainCount: 29
{"Time":"2018-01-23T12:37:00.13764021-06:00","Offset":0,"Length":0,"Message":{"ID":55736331,"Type":7,"TamperPhy":2,"TamperEnc":1,"Consumption":5050585,"ChecksumVal":18526}}

Running as a service

grafana-server.service - graphing server, reads and graphs saved data from within influxdb

[Unit]
Description=Starts and stops a single grafana instance on this system
Documentation=http://docs.grafana.org
Wants=network-online.target
After=network-online.target

[Service]
EnvironmentFile=/etc/default/grafana
Environment=CONF_FILE=/etc/grafana/grafana.ini
Environment=DATA_DIR=/var/lib/grafana
Environment=LOG_DIR=/var/log/grafana
User=grafana
Group=grafana
Type=simple
Restart=always
WorkingDirectory=/usr/share/grafana
ExecStart=/usr/sbin/grafana             \
    --config=${CONF_FILE}                \
    cfg:default.paths.logs=${LOG_DIR}     \
    cfg:default.paths.data=${DATA_DIR}
LimitNOFILE=10000
TimeoutStopSec=20
UMask=0027

[Install]
WantedBy=multi-user.target
Alias=grafana-server.service

influxd.service - time series databases, stores readings from rtlamr-collect service.


[Unit]
Description=InfluxDB is an open-source, distributed, time series database
After=network.target
Documentation=man:influxd(1)

[Service]
User=influxdb
Group=influxdb
LimitNOFILE=65536
EnvironmentFile=-/etc/default/influxdb
ExecStart=/usr/bin/influxd -config /etc/influxdb/influxdb.conf $INFLUXD_OPTS
KillMode=control-group
Restart=on-failure

[Install]
WantedBy=multi-user.target
Alias=influxd.service

rtlamr-collect.service - collection service, stores meter readings within influxdb

Description=RTLAMR Collector
BindsTo=rtl_tcp.service
After=rtl_tcp.service

[Service]
EnvironmentFile=/etc/systemd/system/rtlamr-collect.env
ExecStart=/bin/sh -c '${GOPATH}/bin/rtlamr | ${GOPATH}/bin/rtlamr-collect'
Restart=always
RestartSec=30

[Install]
WantedBy=multi-user.target

rtl_tcp.service - software defined radio endpoint service, read sdr data over network.

[Unit]
Description=Software Defined Radio TCP Server
Requires=network.target
After=network.target

[Service]
ExecStart=/usr/bin/rtl_tcp
Restart=on-failure
KillMode=control-group

[Install]
WantedBy=multi-user.target

rtlamr-collect.env - environment file to pass variables

GOPATH=/home/pi/go

RTLAMR_FORMAT=json
RTLAMR_MSGTYPE=idm

COLLECT_INFLUXDB_HOSTNAME=localhost
COLLECT_INFLUXDB_USER=influxusername
COLLECT_INFLUXDB_PASS=influxpassword

Keep an eye out here, because I will keep updating this post as I make progress. At this time it reads the electric meter using idm for history, this service can be stopped and started once an hour for a bit to obtain all the data it needs to graph.

to read my gas and water meter I will need to use SCM or SCM+. To make this work, I just need to stop obtaining data on rtlamr-collect, and start rtlamr in scm mode to log. This will take some modifications but should be easy enough to accomplish.

comments powered by Disqus