Home Energy Display

2015-09-06 16.18.24 (Small) - Copy

I recently installed a PV (Solar) system on my home using enphase micro-inverters and wanted a way to see the power and energy generated without having to open an app or go to a website – basically an in-home display. The enphase envoy device displays this data on the front of it, but mine had to be located in my garage so it could pick up the signal for the micro-inverters which use power line communication. In addition to that, it isn’t something you would mount on the wall in your living room anyways (at least if you’re married and want to stay that way). I also wanted to see what the utility meter was reading and eventually trend this data.

Another requirement I had was to use devices that have a local API rather than only a cloud API.  Since this is all local data that is used locally, I felt there was no reason for it to have to be accessed over the internet. Also, what happens if the cloud company goes out of business, the API is changed, the servers go down, etc?

For full disclosure, some of the links below are affiliate links, allowing me to earn a commission at no cost to you if you decide to purchase any of the products.

The Thermostat

I’ve been looking into WiFi connected thermostats and found that the Radio Thermostat CT80 has a local API and a two line configurable display – perfect for what I wanted! The API for the Radio Thermostat is located here. There are a few different versions of this thermostat, so if you want one you can communicate with, make sure it is one with the WiFi module. The thermostat is a pretty basic programmable thermostat.  It’s cloud capabilities seem to be complete and it has a decent android app.

The Enphase Envoy

As mentioned previously, the enphase envoy is a device which communicates with all the micro-inverters and it is installed with most enphase systems.  This device has a single JSON response web page that will give you the approximate current power production along with the energy produced that day and for the life of the system.  If you have one of these, the API page is located at http:// <envoys_ip> /api/v1/production.  The power it reports is not exact, as the micro-inverters only check in about every 10 minutes or so.

The Rainforest EAGLE

The device that I use to get the meter data is a Rainforest EAGLE Ethernet ZigBee Gateway which uses the ZigBee protocol to read the utilities smart meter.  I had to have this registered with the utility for it to work, which took about a day for them to setup.  You will need to check with your utility for which devices they support.  It has a local API documented here.  Unfortunately, it does not have WiFi, so you will need to have it near you router/switch or you will need to run ethernet to it.  It also has to be near your utility meter for the ZigBee signal to reach.  My router is about 30 feet from the meter with a couple walls to get through and the ZigBee signal reaches without issue.  This device gives an updated reading every few seconds and is as accurate as your electric meter – so pretty good.

The Router

A while back I replaced my home router with one that was supported by OpenWrt, which allows me to have a low power device that is already running 24/7 to glue everything together. This essentially runs Linux, and has a Lua interpreter built into the OpenWrt build.  I have never used Lua before, but it was pretty straight forward to hack a functional, but not pretty script together.  Lots of copy and paste coding here.

Here is the not-so-pretty script that runs on the router.  Every network and device will be a little different so think of this as an example to get started with and modify to suit your needs.

--This script gets the current power from the rainforest and envoy and displays it on the thermostat
--Lua libraries
local json = require("luci.json")
local http = require("socket.http")
local mime = require("mime")
local ltn12 = require("ltn12")

--This function takes the line # and the message and sends it to the thermostat
function TstatDisplayMessage(line, message)

  local tstat_message = { message=message, line=line }

  local tstat_url="http://192.168.20.77/tstat/uma"
  local tstat_request=json.encode(tstat_message)
  local tstat_method="POST"
  local tstat_response={}
  rc = http.request{
    url = tstat_url,
    method = tstat_method,
    headers = {
      ["Content-Length"] = string.len(tstat_request)
    },
    source = ltn12.source.string(tstat_request),
    sink = ltn12.sink.table(tstat_response)
  }
end

--Local variables for the rainforest
local pwr_url="http://192.168.20.43/cgi-bin/cgi_manager"
local pwr_request="get_usage_data0x1234567890abcdef"
local pwr_method="POST"
local pwr_usrpwd="00000:9999999999999"

local pwr_response = {}
local rc = http.request{
  url = pwr_url,
  method = pwr_method,
  headers = {
    Authorization = "Basic " .. (mime.b64(pwr_usrpwd)),
    ["Content-Length"] = string.len(pwr_request)
   },
  source = ltn12.source.string(pwr_request),
  sink = ltn12.sink.table(pwr_response)
}

local power = json.decode(table.concat(pwr_response))

local today = os.date("%d")
local day = ""
local meter_now = power.summation_delivered - power.summation_received
local meter_start = ""
--Open a local temp file to store the daily power
local fMeter = io.open("/tmp/meter")
if fMeter then
  day = fMeter:read("*line")
  meter_start = fMeter:read("*line")
  fMeter:close()
  if day ~= today then
    fMeter = io.open("/tmp/meter", "w")
    fMeter:write(today, "\n")
    fMeter:write(meter_now, "\n")
    fMeter:close()
    --print(day .. " not equal to " .. today)
  end
else
  fMeter = io.open("/tmp/meter", "w")
  fMeter:write(today, "\n")
  fMeter:write(meter_now, "\n")
  fMeter:close()
  meter_start = meter_now
end

local power_used = meter_now - meter_start

local msg = "Meter: " .. power.demand * 1000 .. " W  " .. string.format("%.2f", power_used) .. " kWh"
TstatDisplayMessage(0, msg)

local envoy_url="http://192.168.20.78/api/v1/production"
local envoy_method="GET"
local envoy_response={}
rc = http.request{
  url = envoy_url,
  method = envoy_method,
  sink = ltn12.sink.table(envoy_response)
}

local envoy = json.decode(table.concat(envoy_response))

msg = "PV: " .. envoy.wattsNow .. " W  " .. envoy.wattHoursToday / 1000 .. " kWh"
TstatDisplayMessage(1, msg)

I then setup a shell script to call the lua script every 10 seconds:

#!/bin/sh
while 1
do
  lua getpower.lua
  sleep 10
done

I set this script to run on startup in /etc/init.d with the following init script:

#!/bin/sh /etc/rc.common

START=98

start(){
  getpower.sh &
}

stop(){
  killall -9 getpower.sh
}

You can see in the image of the thermostat the result of this script. I show the utility meter reading on the 1st line. It shows the power coming from or going out to the utility. Negative numbers are power flowing out to the utility (meter running backwards). On the right side of the line is the net energy we used so far that day. The script resets the daily energy at midnight. When it is negative we have produced more energy than we have received from the utility. The 2nd line shows the PV system production. Power is shown on the left, and the days total energy production on the right.  And yes, it is warm in my house right now.

Since I created this, I also added a data logging server which I can go back and see how much energy was used over night or last week verses this week, etc. Hopefully I’ll have the opportunity to write about that in the near future.

I am a participant in the Amazon Services LLC Associates Program, an affiliate advertising program designed to provide a means for sites to earn advertising fees by advertising and linking to amazon.com.

Leave a comment