rtlamr Power Meter Data in OpenHAB

Wouldn’t it be cool if you could monitor your electricity usage with OpenHAB for less than 20 bucks with the same accuracy your power company uses for billing?

Using an inexpensive rtl-sdr dongle, it’s possible to listen for signals from ERT compatible smart meters using rtlamr. This script runs as a daemon, launches rtl_tcp and rtlamr, and parses the output from rtlamr. If this matches your meter, it will push the data into OpenHAB using the REST API.

Turns out these ERT meters (at least in Omaha) are broadcasting 4 hours of usage data with 5 minute resolution. It broadcasts this data every minute, repeating the previous broadcast until the next 5 minute interval has completed. This data is flying around unprotected. Using free software and an inexpensive SDR dongle it’s possible to pull this data into OpenHAB.

rtlamr does all the heavy lifting here. It listens for the data, decodes, and passes along the meter readings.

On my meter, the interesting information is just above the readout. That’s my meter’s type and endpoint ID or serial number. I’ve blurred my details for privacy.

meter2

You can check your meter’s compatibility on the meters list on the rtlamr project page

The hardware required isn’t very bulky, I’ve got it attached to an old computer that also runs my OpenHAB server. I got mine on amazon, there are a lot of them available. Just search for RTL2832U

server

I’m looking at IDM Interval Data Message because my usage over the previous 5 minute interval is one of the most important datapoints for changing my usage. The first differential consumption is my most recent 5 minute period, and the last consumption field is my current meter reading. Interestingly, my meter shows 5 digits on the front, but the rtlamr data has 7 digits. This gives me hundredths of a kilowatt hour.

Keeping this front and center on the home automation dashboard on the wall mounted android tablets makes me more mindful of our power usage.

tablet-power

Checking on OPPD rates, in the summer, it’s 11.24 cents per kilowatt hour

Looking more closely at usage, the air conditioning is my biggest use by far.

Quick overview of how this actually works

  • Meter broadcasts usage with 5 minute interval data
  • rtl sdr dongle recieves it
  • rtlamr detects decodes and parses it
  • data is then passed to my script which only sends part of the data to OpenHAB through the REST API
  • This updates the first 4 items in the power items group
  • The rules then calculate my usage from data in OpenHAB’s mysql persistence
  • And update the rest of the items
  • Then I see the numbers and dial back the AC

Requirements

rtl-sdr installed
http://sdr.osmocom.org/trac/wiki/rtl-sdr

Set dongle serial number with rtl-eeprom
http://manpages.ubuntu.com/manpages/trusty/man1/rtl_eeprom.1.html

install Go programming language & set gopath
[shell]sudo apt-get install golang[/shell]
https://golang.org/doc/code.html#GOPATH

install rtlamr
[shell]go get github.com/bemasher/rtlamr[/shell]
https://github.com/bemasher/rtlamr

install perl packages
[shell]sudo apt-get install libwww-mechanize-perl libfile-pid-perl[/shell]

Install

Start by downloading as a zip and extracting, or git clone https://github.com/ragingcomputer/amridm2openhab

The script needs some configuration, see the configuration section starting around line 60
[perl]
## Configuration
my $port = 1234; # port for rtl_tcp to listen on
my $address = "192.168.1.100"; # bind address for rtl_tcp.
# Can be 127.0.0.1 or actual address of your server
my $dongleSerial = "00000011"; # serialnumber set by rtl_eeprom
my $rtltcp = "/usr/local/bin/rtl_tcp"; # path to rtl_tcp
my $rtlamr = "/opt/gopath/bin/rtlamr"; # path to rtlamr
my $rtleeprom = "/usr/local/bin/rtl_eeprom" # path to rtl_eeprom
my $meterSerial = "5XXXXXX3"; # meter serial number, likely on the front of your meter
# used to filter results to just your meter
my $openhabServer = "http://username:password@127.0.0.1:8080"; # URL of OpenHAB server.
# Be mindful of the escaping the @ sign for basic auth.
# If you aren’t using auth, just enter the URL similar to http://127.0.0.1:8080
[/perl]

create log file and set permissions
[shell]sudo touch /var/log/amridm2openhab.log
sudo chmod 644 /var/log/amridm2openhab.log
sudo chown root:adm /var/log/amridm2openhab.log[/shell]

copy perl script into /usr/sbin and set executable
[shell]sudo cp amridm2openhab /usr/sbin/amridm2openhab
sudo chmod +x /usr/sbin/amridm2openhab[/shell]

copy initscript into init.d and set executable
[shell]sudo cp initscript-amridm2openhab /etc/init.d/amridm2openhab
sudo chmod +x /etc/init.d/amridm2openhab[/shell]

set initscript to start and start
[shell]update-rc.d amridm2openhab defaults 99
sudo service amridm2openhab start[/shell]

Optional, watch log file to verify it has started
[shell]tail -f /var/log/amridm2openhab.log[/shell]

It doesn’t do any good if you haven’t configured the items and the rules in OpenHAB.

power.items
[text]
/* Power Data from RTL-AMR */
Group gPowerMeterData
Number PowerMeterIntervalNum "Interval [%s]" (gPowerMeterData)
Number PowerMeterLastInterval "Last Interval Consumption [%s]" (gPowerMeterData)
Number PowerMeterLastIntervalAverage "Last Interval Average Consumption [%s]" (gPowerMeterData)
Number PowerMeterConsumption "Consumption [%s]" (gPowerMeterData)
Number Power2DaysAgoUsage "2 Days Ago [%.2f KWH]" (gPowerMeterData)
Number Power2DaysAgoCost "2 Days Ago [$%.2f]" (gPowerMeterData)
Number PowerYesterdayUsage "Yesterday [%.2f KWH]" (gPowerMeterData)
Number PowerYesterdayCost "Yesterday [$%.2f]" (gPowerMeterData)
Number PowerTodayUsage "Today [%.2f KWH]" (gPowerMeterData)
Number PowerTodayCost "Today [$%.2f]" (gPowerMeterData)
[/text]

power.rules
[text]
rule "Update Power Costs"
when
Item PowerMeterConsumption received update
then
// http://www.oppd.com/residential/residential-rates/
// Summer (June 1 – Sept. 30) – 11.42 cents/kWh for all kWh
var Number midnightReading
var Number yesterdayMidnightReading
var Number days2agoMidnightReading
var Number currentReading
var Number days2agoUsageKWH
var Number yesterdayUsageKWH
var Number todayUsageKWH
var Number yesterdayCost
var Number days2agoCost
var Number todayCost
var Number KWHCost = 0.1142

if (PowerMeterConsumption.state instanceof DecimalType) {

days2agoMidnightReading = (PowerMeterConsumption.historicState(now.toDateMidnight.minusDays(2), "mysql").state as DecimalType)
yesterdayMidnightReading = (PowerMeterConsumption.historicState(now.toDateMidnight.minusDays(1), "mysql").state as DecimalType)
midnightReading = (PowerMeterConsumption.historicState(now.toDateMidnight, "mysql").state as DecimalType)
currentReading = PowerMeterConsumption.state as DecimalType

days2agoUsageKWH = ((yesterdayMidnightReading – days2agoMidnightReading)/100)
yesterdayUsageKWH = ((midnightReading – yesterdayMidnightReading)/100)
todayUsageKWH = ((currentReading – midnightReading)/100)
days2agoCost = days2agoUsageKWH*KWHCost
yesterdayCost = yesterdayUsageKWH*KWHCost
todayCost = todayUsageKWH*KWHCost

postUpdate(PowerTodayUsage, todayUsageKWH)
postUpdate(PowerTodayCost, todayCost)

postUpdate(PowerYesterdayUsage, yesterdayUsageKWH)
postUpdate(PowerYesterdayCost, yesterdayCost)

postUpdate(Power2DaysAgoUsage, days2agoUsageKWH)
postUpdate(Power2DaysAgoCost, days2agoCost)

}
end
[/text]

power portion of sitemap
[text]
Text label="AMR Power Meter" {
Text item=PowerMeterIntervalNum
Text item=PowerMeterLastInterval
Text item=PowerMeterLastIntervalAverage
Text item=PowerMeterConsumption
Text item=PowerTodayCost
Text item=PowerTodayUsage
Text item=PowerYesterdayCost
Text item=PowerYesterdayUsage
Text item=Power2DaysAgoCost
Text item=Power2DaysAgoUsage
Chart item=PowerMeterLastInterval period=4h refresh=10000
Chart item=PowerMeterLastInterval period=D refresh=10000
Chart item=PowerMeterLastInterval period=W refresh=10000
}
[/text]

5 thoughts on “rtlamr Power Meter Data in OpenHAB

  1. Hello. I am attempting to implement rtlamr as you did and it seems to connect to rtl_tcp ok but, I cannot see data coming in. Any tricks to picking up the meter signal? Thanks, rtlamr output:

    02:33:36.711598 decode.go:79: CenterFreq: 912600155
    02:33:36.711867 decode.go:79: SampleRate: 2392064
    02:33:36.711923 decode.go:79: DataRate: 32768
    02:33:36.711972 decode.go:79: ChipLength: 73
    02:33:36.712020 decode.go:79: PreambleSymbols: 21
    02:33:36.712070 decode.go:79: PreambleLength: 3066
    02:33:36.712117 decode.go:79: PacketSymbols: 96
    02:33:36.712165 decode.go:79: PacketLength: 14016
    02:33:36.712211 decode.go:79: Preamble: 111110010101001100000
    02:33:36.712260 main.go:93: GainCount: 29

    Like

Leave a comment