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 rtltcp, rtltcp 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.