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.