I've had solar power for a couple of years now. The package included a Fronius inverter and a stack of panels; and while I made sure the the Fronius came with the WiFi adapter and at least some monitoring, it's ... well lacklustre.
Recently I've been building myself Grafana dashboards (because all the cool kids are doing it). And since the inverter has its own little webserver onboard, I dug into it - and what do you know, it's relatively "current" tech wise, using JSON to update the data on the client.
Well I can parse that! Here's how it all fits together.
InfluxDB for Data Storage
I happen to use InfluxDB for my data storage. Why? Well because ... I just do. It was the one that everyone seemed to be using.
I won't run through the whole setup guide for InfluxDB - suffice it to say mine lives on a Linux VM and its datastores are on a separate (growable) virtual disk. No special data grooming, I'll deal with that if I ever have to.
The "schema" for the data is very simple:
Measurement | ||
---|---|---|
Column Name | Data "Type" | Description |
time | nanoseconds | Timestamp for Data Point |
Instant | Watts | Actual generation at time of retrieval |
Lifetime | Watt-Hours | Total lifetime power generation |
Today | Watt-Hours | Total generation "today" |
Year | Watt-Hours | Total generation this calendar year |
Status | Integer | Inverter status - I don't use this yet |
Message | String | Reason for status code - I don't use this yet |
BASH Script for Data Gathering
All the data is gathered using a script started at boot. You'll need to have the wget and jq tools installed (or adjust the script appropriately). Don't forget to set the variables at the top to suit your environment:
#!/bin/bash
# This script pulls JSON data from a Fronius solar inverter
# The time we are going to sleep between readings
sleeptime=10
# Dependencies:
# jq (JSON command line parser)
endpoint=IPADDRESS_OR_HOSTNAME_OF_INVERTER
ephost=FRIENDLY_NAME_FOR_INVERTER
database=INFLUXDB_NAME
series=MEASUREMENT_NAME
get_json_data () {
#Get JSON data
tempdatafile=/tmp/JSONdata-$endpoint
wget http://$endpoint/solar_api/v1/GetPowerFlowRealtimeData.fcgi -qO $tempdatafile
Status=`cat $tempdatafile | jq '.Head.Status.Code'`
Reason=`cat $tempdatafile | jq '.Head.Status.Reason'`
Message=`cat $tempdatafile | jq '.Head.Status.UserMessage'`
PVOutput=`cat $tempdatafile | jq '.Body.Data.Site.P_PV'`
PVDaily=`cat $tempdatafile | jq '.Body.Data.Site.E_Day'`
PVAnnual=`cat $tempdatafile | jq '.Body.Data.Site.E_Year'`
PVTotal=`cat $tempdatafile | jq '.Body.Data.Site.E_Total'`
if [ -z $Status ]; then Status="0"; fi
if [[ -z $Reason || $Reason == "null" || $Reason = "\"\"" ]]; then Reason=; fi
if [[ -z $Message || $Message == "null" || $Message = "\"\"" ]]; then Message=; fi
if [[ -z $PVOutput || $PVOutput == "null" ]]; then PVOutput="0"; fi
if [ -z $PVDaily ]; then PVDaily="0"; fi
if [ -z $PVAnnual ]; then PVAnnual="0"; fi
if [ -z $PVTotal ]; then PVTotal="0"; fi
rm $tempdatafile
}
print_data () {
echo "System Status: $Status"
echo "Reason: $Reason"
echo "Message: $Message"
echo "Instantaneous Output: $PVOutput W"
echo "Output Today: $PVDaily Wh"
echo "Output This Year: $PVAnnual Wh"
echo "Output Lifetime: $PVTotal Wh"
}
write_data () {
#Write the data to the database
data=$''$series',host='$ephost' Status='$Status
data=$data$'\n'$series',host='$ephost' Reason="'$Reason'"'
data=$data$'\n'$series',host='$ephost' Message="'$Message'"'
data=$data$'\n'$series',host='$ephost' Instant='$PVOutput
data=$data$'\n'$series',host='$ephost' Today='$PVDaily
data=$data$'\n'$series',host='$ephost' Year='$PVAnnual
data=$data$'\n'$series',host='$ephost' Lifetime='$PVTotal
echo "Write data:\n"$data
curl -i -XPOST 'http://localhost:8086/write?db='$database --data-binary "$data"
}
#Prepare to start the loop and warn the user
echo "Press [CTRL+C] to stop..."
while :
do
# Retrieve the data
get_json_data
#Output console data for future reference
print_data
# Store the data in Influx
write_data
if [[ $1 == "once" ]];
then
exit 0
fi
#Sleep between readings
sleep "$sleeptime"
done
You can test by running it with the "once" parameter before you set it up in your init/systemctl database:
grafana:~$ sudo /var/lib/influxscripts/http-solar.sh once
Press [CTRL+C] to stop...
System Status: 0
Reason:
Message:
Instantaneous Output: 3277 W
Output Today: 21338 Wh
Output This Year: 2555065 Wh
Output Lifetime: 31261123 Wh
Write data:\nSolar,host=solar Status=0 Solar,host=solar Reason="" Solar,host=solar Message="" Solar,host=solar Instant=3277 Solar,host=solar Today=21338 Solar,host=solar Year=2555065 Solar,host=solar Lifetime=31261123
HTTP/1.1 204 No Content
Content-Type: application/json
Request-Id: 4173314c-02e5-11e7-a694-000000000000
X-Influxdb-Version: 1.2.0
Date: Tue, 07 Mar 2017 03:22:12 GMT
Grafana for Display
Here's a snapshot of the dashboard for my system.
Logically there are only 2 data rows (the numbers and the graphs) but that's not too critical - it's just the way I did it to simplify setting row heights. The first row is the quick data view with some colour coding of the "today" output to highlight how effective it is:
Next, the graph of "today's" production. Obviously if you tweak the display dates, this will change, but the default setup is "today". Today is a mixed bag of sun and rain.
Then some historical data. First the last month (well, 30 days is close):
Then the last year. Shows the seasonal change, and the density highlights good and bad periods:
Then the last 5 years. This is where I'm hoping I can spot some longer term trends (such as "overall production is down because the panels are degrading with age"). Unfortunately a lot of the older data includes only the daily totals as I had to export it from the manufacturer portal.
The JSON for the dashboard itself is 21kB. If you want to use it for your own Grafana instance you're more than welcome.