Monitoring Solar Panels with NodeRed + InfluxDB + Grafana

This post will guide you through how to monitor your solar panels using some free open source tools running on your local network.

Required technical level: Moderate to Advanced experience with programming/networking/sql/docker. This certainly isn’t a point and click solution.

Here’s a summary of the setup:

  • Solar System:
    • 18 x REC 350W panels
    • 18 x Enphase IQ 7+ Micro-Inverters: Each panel gets an inverter, allows per-panel monitoring, no DC power loss over long runs as you get AC straight from the panels, and no central inverter.
    • 1 x Envoy S-Metered: This is the brains that communicates with all the panels and manages input/output. It’s connected to your wifi/ethernet. We will talk to local Envoy API endpoints to read realtime power usage, individual solar panel status and solar generation data.
  • Software:
    • NodeRED: This is a cool piece of software that lets you build a program by dragging blocks around and connecting them with lines. It’s in a nice web interface and doesn’t take long to get use to. I like NodeRED because you can always just drag a “function” block onto the screen and write whatever you like in JavaScript, so you’re not limited to the drag & drop blocks it provides.
    • InfluxDB: This is a special kind of database where we store all our solar data in a time based format. InfluxDB is really good at certain time based queries and makes graphing and computing things easy.
    • Grafana: This is the pretty graphing dashboard that we’ll run to highlight various parts of our solar usage. It will read the data straight from InfluxDB and we can configure graphs and values to display in each dashboard card.
    • Unraid (optional): This is a really cool operating system that runs off a USB drive. I’ve got it running on an old computer with 4 hard drives. Unraid has very nice harddrive / redundancy management, and an even nicer “docker” app repository. The above 3 pieces of software can all be installed within Unraid and be up and running in minutes. Setting up Unraid can be quite involved, so do some research before decided to go down that path. The software above can run fine elsewhere on your local network, even on a Raspberry Pi sitting on your shelf.

How does it work?

Basically Node-RED is configured to reads values directly from the Enphase solar system API every few seconds. This happens over the local network. No internet connection is required. Node-RED does some basic calculations on the data and then writes that data to InfluxDB.

What we end up with is a nice historical record of solar generation, house power usage, individual panel output, how much we’re exporting to the grid and how much we’re pulling from the grid.

Once all the data is in InfluxDB you can configure Grafana to display pretty graphs based on that data. You can also query InfluxDB directly to determine current power usage / daily usage in order to decide on some home automation tasks (e.g. is there enough Solar generation to turn the aircon on automatically?)

I’ll break all these steps down into sections below:

The Enphase Envoy API:

The Envoy S-Metered is connected to your local network (either via WiFi or an Ethernet cable). It has some handy “API” endpoints that you can query to get all sorts of interesting data.

How do you find these API endpoints? The easiest way is to login to the Envoy web dashboard and view the Chrome network inspector. You can see all the API requests that are used to generate the built in Envoy dashboard. But to save you from that hassle I’ve listed some of them below:

Assuming 10.30.0.14 is the IP address of your Envoy, try these endpoints:

http://10.30.0.14/production.json – current consumption and production data:
{
   "production": [
     {
       "type": "inverters",
       "activeCount": 18,
       "readingTime": 1580639250,
       "wNow": 0,
       "whLifetime": 7062574
     },
     {
       "type": "eim",
       "activeCount": 1,
       "measurementType": "production",
       "readingTime": 1580639747,
       "wNow": -0.846,
       "whLifetime": 7047408.938,
       "varhLeadLifetime": 311108.038,
       "varhLagLifetime": 828596.594,
       "vahLifetime": 7906976.196,
       "rmsCurrent": 1.228,
       "rmsVoltage": 246.489,
       "reactPwr": 299.641,
       "apprntPwr": 302.769,
       "pwrFactor": 0,
       "whToday": 42939.938,
       "whLastSevenDays": 245381.938,
       "vahToday": 46195.196,
       "varhLeadToday": 3546.038,
       "varhLagToday": 2608.594
     }
   ],
   "consumption": [
     {
       "type": "eim",
       "activeCount": 1,
       "measurementType": "total-consumption",
       "readingTime": 1580639747,
       "wNow": 3484.957,
       "whLifetime": 6812381.751,
       "varhLeadLifetime": 2232700.619,
       "varhLagLifetime": 1052652.057,
       "vahLifetime": 7903318.012,
       "rmsCurrent": 15.917,
       "rmsVoltage": 246.502,
       "reactPwr": -870.018,
       "apprntPwr": 3923.522,
       "pwrFactor": 0.89,
       "whToday": 67028.751,
       "whLastSevenDays": 412962.751,
       "vahToday": 35580.012,
       "varhLeadToday": 9815.619,
       "varhLagToday": 5360.057
     },
     {
       "type": "eim",
       "activeCount": 1,
       "measurementType": "net-consumption",
       "readingTime": 1580639747,
       "wNow": 3485.803,
       "whLifetime": 3241750.723,
       "varhLeadLifetime": 1921592.581,
       "varhLagLifetime": 224055.463,
       "vahLifetime": 7903318.012,
       "rmsCurrent": 14.689,
       "rmsVoltage": 246.516,
       "reactPwr": -570.377,
       "apprntPwr": 3620.717,
       "pwrFactor": 0.97,
       "whToday": 0
     }
   ],
   "storage": []
 }
http://10.30.0.14/api/v1/production/inverters – Current individual panel data
Note: this endpoint is protected with authenentication. Use the last 6 digits of the Envoy serial number as password, example:
curl -m 10 --digest -u "envoy:054786" http://10.30.0.14/api/v1/production/inverters
{
     "serialNumber": "121921415",
     "lastReportDate": 158062595,
     "devType": 1,
     "lastReportWatts": -1,
     "maxReportWatts": 286
   },
   {
     "serialNumber": "121923489",
     "lastReportDate": 1580632601,
     "devType": 1,
     "lastReportWatts": -1,
     "maxReportWatts": 286
   },
   {
     "serialNumber": "12191458",
     "lastReportDate": 158063252,
     "devType": 1,
     "lastReportWatts": -1,
     "maxReportWatts": 285
   },
   {
     "serialNumber": "121921029",
     "lastReportDate": 158063298,
     "devType": 1,
     "lastReportWatts": -1,
     "maxReportWatts": 285
   },
   {
     "serialNumber": "121921138",
     "lastReportDate": 158063204,
     "devType": 1,
     "lastReportWatts": -1,
     "maxReportWatts": 285
   },
   {
     "serialNumber": "121921119",
     "lastReportDate": 158063615,
     "devType": 1,
     "lastReportWatts": -1,
     "maxReportWatts": 285
   },
   {
     "serialNumber": "121921534",
     "lastReportDate": 158063212,
     "devType": 1,
     "lastReportWatts": -1,
     "maxReportWatts": 286
   },
   {
     "serialNumber": "121921155",
     "lastReportDate": 158062619,
     "devType": 1,
     "lastReportWatts": -1,
     "maxReportWatts": 286
   },
   {
     "serialNumber": "121911022",
     "lastReportDate": 15806257,
     "devType": 1,
     "lastReportWatts": 1,
     "maxReportWatts": 286
   },
   {
     "serialNumber": "121926272",
     "lastReportDate": 158063614,
     "devType": 1,
     "lastReportWatts": -1,
     "maxReportWatts": 286
   },
   {
     "serialNumber": "121917527",
     "lastReportDate": 158063607,
     "devType": 1,
     "lastReportWatts": -1,
     "maxReportWatts": 286
   },
   {
     "serialNumber": "121115993",
     "lastReportDate": 158062616,
     "devType": 1,
     "lastReportWatts": -1,
     "maxReportWatts": 286
   },
   {
     "serialNumber": "121116476",
     "lastReportDate": 158063610,
     "devType": 1,
     "lastReportWatts": -1,
     "maxReportWatts": 285
   },
   {
     "serialNumber": "121117665",
     "lastReportDate": 158063592,
     "devType": 1,
     "lastReportWatts": -1,
     "maxReportWatts": 286
   },
   {
     "serialNumber": "121913427",
     "lastReportDate": 158062600,
     "devType": 1,
     "lastReportWatts": -1,
     "maxReportWatts": 285
   },
   {
     "serialNumber": "121115085",
     "lastReportDate": 158063206,
     "devType": 1,
     "lastReportWatts": -1,
     "maxReportWatts": 286
   },
   {
     "serialNumber": "121916266",
     "lastReportDate": 158032602,
     "devType": 1,
     "lastReportWatts": -1,
     "maxReportWatts": 285
   },
   {
     "serialNumber": "121117194",
     "lastReportDate": 158062609,
     "devType": 1,
     "lastReportWatts": -1,
     "maxReportWatts": 286
   }
 ]
http://10.30.0.14/stream/meter – HTTP stream of instant usage / generation data
This is a fun one! It's a stream of instant values coming straight out of the Envoy. Turn on a light or the oven? You'll see values change in this stream instantly! Get some clouds go over the solar panels? Production numbers drop off instantly. It's really cool.
You'll need the installer password for the Envoy. You could ask your installer or google around for the way to find this out yourself. 
Getting access to this HTTP stream in Node-RED is a little tricky, and I certainly wouldn't recommend storing EVERY single value received in InfluxDB. But I've found this endpoint has been good to get instant values out of the Inverter when I want to do some home automation such as dialing back the aircon or pool pump if it gets cloudy.
Here's the output from this HTTP stream:
{
   "production": {
     "ph-a": {
       "p": 0,
       "q": 302.684,
       "s": 305.658,
       "v": 248.005,
       "i": 1.233,
       "pf": 0,
       "f": 50
     },
     "ph-b": {
       "p": 0,
       "q": 0,
       "s": 0,
       "v": 0,
       "i": 0,
       "pf": 0,
       "f": 0
     },
     "ph-c": {
       "p": 0,
       "q": 0,
       "s": 0,
       "v": 0,
       "i": 0,
       "pf": 0,
       "f": 0
     }
   },
   "net-consumption": {
     "ph-a": {
       "p": 1838.766,
       "q": -608.615,
       "s": 2144.261,
       "v": 248.097,
       "i": 8.647,
       "pf": 0.85,
       "f": 50
     },
     "ph-b": {
       "p": 0,
       "q": 0,
       "s": 0,
       "v": 0,
       "i": 0,
       "pf": 0,
       "f": 0
     },
     "ph-c": {
       "p": 0,
       "q": 0,
       "s": 0,
       "v": 0,
       "i": 0,
       "pf": 0,
       "f": 0
     }
   },
   "total-consumption": {
     "ph-a": {
       "p": 1838.766,
       "q": -911.299,
       "s": 2450.762,
       "v": 248.051,
       "i": 9.88,
       "pf": 0.75,
       "f": 50
     },
     "ph-b": {
       "p": 0,
       "q": 0,
       "s": 0,
       "v": 0,
       "i": 0,
       "pf": 0,
       "f": 0
     },
     "ph-c": {
       "p": 0,
       "q": 0,
       "s": 0,
       "v": 0,
       "i": 0,
       "pf": 0,
       "f": 0
     }
   }
 }

Node-RED setup:

This is the fun part! I’m going to assume some familiarity with Node-RED here. But if you’ve never used it just jump in and you’ll find it surprising intuitive.

Screenshot of Node-RED connected to Solar system

The above screenshot has 3 main flows going on:

  1. Processing the Envoy HTTP stream every few seconds.
  2. Processing the full details/overall production data every minute.
  3. Processing the individual panel data every 5 minutes.

todo..

Leave a Reply

Your email address will not be published. Required fields are marked *