RTL_SDR & Ubuntu with RLTAMR – Reading power meter output

iTron power meters (and others) emit an RF signal a few times every couple minutes with the reading that shows on the LCD screen on the meter itself. This information can then be read with a software defined radio along with rtlamr. The readings can then be pushed into something such as graphite or in this case, influxdb. I won’t go over setting up influxdb, graphite or grafana – you can follow their docs for that.

The USB SDR dongle that will be used can be found here on Amazon

RTLAMR (https://github.com/bemasher/rtlamr) will be used to interpret the signal that the SRD dongle reads. We’ll then use RTLAMR-COLLECT (https://github.com/bemasher/rtlamr-collect) to push the data to influxdb so that we can graph/chart & manipulate the data  in Grafana (https://grafana.com/). Since I’m in a rental property, I cannot (would rather not) install clip-on meters inside the breaker box on the mains.

The install (along with the others for graphite, grafana, sensu etc) will be on Ubuntu 14.04 as Ubuntu seems to play nicer with these applications as opposed to CentOS/RHEL.

 

Install GoLang (assumes apt-get update already run)

apt-get install -y golang

 

Check the current environment

#go env
GOARCH="amd64"
GOBIN=""
GOCHAR="6"
GOEXE=""
GOHOSTARCH="amd64"
GOHOSTOS="linux"
GOOS="linux"
GOPATH=""
GORACE=""
GOROOT="/usr/lib/go"
GOTOOLDIR="/usr/lib/go/pkg/tool/linux_amd64"
TERM="dumb"
CC="gcc"
GOGCCFLAGS="-g -O2 -fPIC -m64 -pthread"
CXX="g++"
CGO_ENABLED="1"

 

Next set the gopath & goroot – for these, I just set gopath to /root/go

export GOPATH=/root/go

export PATH=$PATH:$GOROOT/bin:$GOPATH/bin

 

After, check the environment again and those should be present:

#go env
GOARCH="amd64"
GOBIN=""
GOCHAR="6"
GOEXE=""
GOHOSTARCH="amd64"
GOHOSTOS="linux"
GOOS="linux"
GOPATH="/root/go"
GORACE=""
GOROOT="/usr/lib/go"
GOTOOLDIR="/usr/lib/go/pkg/tool/linux_amd64"
TERM="dumb"
CC="gcc"
GOGCCFLAGS="-g -O2 -fPIC -m64 -pthread"
CXX="g++"
CGO_ENABLED="1"

 

GIT will need to be installed, this could have been installed in-line earlier on. This is on a fresh system that GIT was not previously installed on.

apt-get install -y git

 

Install RTLAMR

go get github.com/bemasher/rtlamr

 

Then also install RTL-COLLECT

go get github.com/bemasher/rtlamr-collect

 

Create the blacklist to stop the conflicting dvd drivers from loading

nano -w /etc/modprobe.d/Blacklist-rtl.conf

 

Put this into the Blacklist-rtl.conf file & reboot after saving

blacklist dvb_usb_rtl28xxu

 

Next install rtl-sdr

apt-get install -y rtl-sdr

 

Installing rtl-sdr will have the following options now

#rtl_
rtl_adsb rtl_eeprom rtl_fm rtl_power rtl_sdr rtl_tcp rtl_test

 

After rebooting to sort out the drivers noted above, we can run the rtl_test command

#rtl_test
Found 1 device(s):
 0: Generic RTL2832U OEM

Using device 0: Generic RTL2832U OEM
Found Rafael Micro R820T tuner
Supported gain values (29): 0.0 0.........

 

Next we’ll want to set this up to run as a service – create the /etc/systemd/system/rtl_tcp.service file & input the info below – note, in my case it’s installed in /usr/bin – yours may be different depending on your OS distro

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

[Service]
ExecStart=/usr/bin/rtl_tcp
Restart=always

[Install]
WantedBy=multi-user.target

 

After, enable it to start at boot

systemctl enable rtl_tcp.service

*note – if you get command not found, install systemd (apt-get install -y systemd)

 

From the steps above we set the gopath to /root/go – so in /root/go/bin we should see the rtlamr & rtlamr-collect

# ls /root/go/bin/
rtlamr rtlamr-collect

 

So now, for a quick test we can check rtlamr by going to the /root/go/bin directory and running it

cd /root/go/bin

./rtlamr

00:52:38.339470 decode.go:43: CenterFreq: 912600155
00:52:38.339715 decode.go:44: SampleRate: 2359296
00:52:38.339747 decode.go:45: DataRate: 32768
00:52:38.339774 decode.go:46: ChipLength: 72
00:52:38.339802 decode.go:47: PreambleSymbols: 21
00:52:38.339829 decode.go:48: PreambleLength: 3024
00:52:38.339857 decode.go:49: PacketSymbols: 96
00:52:38.339885 decode.go:50: PacketLength: 13824
00:52:38.339912 decode.go:51: Preamble: 111110010101001100000
00:52:38.339939 main.go:94: GainCount: 29
{Time:2018-03-11T00:52:46.254 SCM:{ID:XXXXXXXX Type: 5 Tamper:{Phy:00 Enc:02} Consumption: 7718065 CRC:0x9740}}
{Time:2018-03-11T00:52:51.975 SCM:{ID:XXXXXXXX Type: 7 Tamper:{Phy:02 Enc:01} Consumption: 7760622 CRC:0x0636}}
{Time:2018-03-11T00:52:53.200 SCM:{ID:XXXXXXXX Type: 7 Tamper:{Phy:02 Enc:01} Consumption: 2969197 CRC:0x71C7}}
{Time:2018-03-11T00:52:53.477 SCM:{ID:XXXXXXXX Type: 7 Tamper:{Phy:02 Enc:01} Consumption: 3760933 CRC:0x3F17}}
{Time:2018-03-11T00:52:54.308 SCM:{ID:XXXXXXXX Type: 7 Tamper:{Phy:02 Enc:00} Consumption: 9402018 CRC:0x1546}}

 

The XXXXXXXX listed in the above output are meter ID’s that the SDR dongle is picking up. These are replaced with XXXXXXXX for privacy. I know that my meter ID is 6378XXXX (again XXXX for privacy) so we’ll filter that below using the -filterid= parameter

./rtlamr -filterid=6378XXXX

00:56:01.388407 decode.go:43: CenterFreq: 912600155
00:56:01.388759 decode.go:44: SampleRate: 2359296
.........removed output data not needed...............
00:56:01.389300 main.go:94: GainCount: 29
{Time:2018-03-11T00:56:57.339 SCM:{ID:6378XXXX Type: 7 Tamper:{Phy:00 Enc:03} Consumption: 1505477 CRC:0x5BA7}}
{Time:2018-03-11T00:58:00.057 SCM:{ID:6378XXXX Type: 7 Tamper:{Phy:00 Enc:03} Consumption: 1505480 CRC:0xF732}}

 

Showing above, we can see the output was read twice in the few minutes I ran it and the outputs for Consumption are the current output listed on the meter. Important note is that the meter LCD outputs 5 digits whereas the RF signal outputs 7 – the last 2 digits are 2 decimal points and show a more granular output reading. So in the last reading above, the current khw consumption from the first time the meter was programmed would be 15,054.80 kwh.

 

Previously a few steps back we already set up the rtl_tcp.service and configured systemd to enable it at boot. Now, we must add the rtlamr-collect.env & rtlamr-collect.service files. The rtlamr-collect.env is the configuration for sending the collected data from the rtl_tcp service into influxdb.

Create /etc/systemd/system/rtlamr-collect.env and place the following into it

GOPATH=/root/go

RTLAMR_FORMAT=json
RTLAMR_MSGTYPE=idm
RTLAMR_FILTERID=00000000

COLLECT_INFLUXDB_HOSTNAME=influxdbhost #(your host)
COLLECT_INFLUXDB_USER=username #(if applicable)
COLLECT_INFLUXDB_PASS=password #(if applicable)

 

Create the /etc/systemd/system/rtlarm-collect.service and place the following into it

[Unit]
Description=RTLAMR Collector
BindsTo=rtl_tcp.service
After=rtl_tcp.service

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

[Install]
WantedBy=multi-user.target

 

Now we should be able to start the services & enable them – note that we already enabled rtl_tcp.service a few steps back.

systemctl enable rtlamr-collect
systemctl start rtl_tcp rtlamr-collect

 

If everything was correct, systemctl status servicename should be running

# systemctl status rtl_tcp
rtl_tcp.service - Software Defined Radio TCP Server
 Loaded: loaded (/etc/systemd/system/rtl_tcp.service; enabled)
 Active: active (running) since Sun 2018-03-11 01:56:37 EST; 44min ago
 Main PID: 466 (rtl_tcp)
 CGroup: name=dsystemd:/system/rtl_tcp.service
 └─466 /usr/bin/rtl_tcp

Mar 11 01:56:38 thin02 rtl_tcp[466]: Found Rafael Micro R820T tuner
Mar 11 01:56:38 thin02 rtl_tcp[466]: Tuned to 100000000 Hz.
Warning: Journal has been rotated since unit was started. Log output is incomplete or unavailable.

# systemctl status rtlamr-collect
rtlamr-collect.service - RTLAMR Collector
 Loaded: loaded (/etc/systemd/system/rtlamr-collect.service; enabled)
 Active: active (running) since Sun 2018-03-11 01:57:08 EST; 45min ago
 Main PID: 1104 (sh)
 CGroup: name=dsystemd:/system/rtlamr-collect.service
 ├─1104 /bin/sh -c /root/go/bin/rtlamr | /root/go/bin/rtlamr-collect
 ├─1105 /root/go/bin/rtlamr
 └─1106 /root/go/bin/rtlamr-collect

Mar 11 01:57:08 thin02 sh[1104]: 01:57:08.096701 main.go:163: connecting to ""@"http://XXX.XXX.XXX.XXX:8086"
Mar 11 01:57:08 thin02 sh[1104]: 01:57:08.097656 decode.go:45: DataRate: 32768
Mar 11 01:57:08 thin02 sh[1104]: 01:57:08.097738 decode.go:46: ChipLength: 72
Mar 11 01:57:08 thin02 sh[1104]: 01:57:08.097754 decode.go:47: PreambleSymbols: 32
Mar 11 01:57:08 thin02 sh[1104]: 01:57:08.097810 decode.go:48: PreambleLength: 4608
Mar 11 01:57:08 thin02 sh[1104]: 01:57:08.097826 decode.go:49: PacketSymbols: 736
Mar 11 01:57:08 thin02 sh[1104]: 01:57:08.097842 decode.go:50: PacketLength: 105984
Mar 11 01:57:08 thin02 sh[1104]: 01:57:08.097903 decode.go:51: Preamble: 01010101010101010001011010100011
Mar 11 01:57:08 thin02 sh[1104]: 01:57:08.097924 main.go:94: GainCount: 29
Mar 11 01:57:08 thin02 sh[1104]: 01:57:08.101861 main.go:127: Preloaded: 0

 

Now that the services are running, we should be able to head over to the influxdb service and tail the log to see if we’re getting data – of course, ensure you’re allowing the ports through the firewalls if you’re using firewalls for both servers. If you’re using local host for influxdb on the same server as rtlamr & rtlamr-collect, it wouldn’t be needed.

# tail -f /var/log/influxdb/influxd.log

[httpd] XXX.XXX.XXX.XXX - - [11/Mar/2018:03:44:27 -0400] "POST /write?consistency=&db=rtlamr&precision=s&rp= HTTP/1.1" 204 0 "-" "InfluxDBClient" 06adb0fd-2500-11e8-89db-000000000000 247

 

We can see the data is being written to influxdb as expected. Right now, authentication is not being used for testing purposes, it’s simply pushing data from the server running rtl_tcp & rtlamr/rtlamr-collect directly to my server running influxdb, graphite, sensu & grafana

 

Now that there’s data being pushed into influxdb, we can add it in grafana. You’ll need to add your datasource first, it’s assumed you’re already familiar with how to do that, so that will not be discussed here. Simply select from the influxdb data source to display the results pushed from rtlamr-collect

 

After, graphs can be created based on time frames or however else you want to manipulate the data.

 

Currently, the data is being pushed into influxdb at values that I’m not sure of the measurement. After recording data for a few hours and comparing the outputs to the output on the actual meter, some adjustments may need to be made; scaling, decimal points etc.