I haven’t blogged in nearly a week due to a lot of time spent developing an interface for the SolarEdge API. The idea is to display results in the PHP environment I have inside WordPress.

DISCLAIMER: this post will be mostly about nerdy developer things, with some added data analysis and chart talk. Apologies if your eyes glaze over; normal service will resume soon.

SolarEdge API

Back to the (PHP) Future …

The last time I touched PHP was for my rugby club a few years back, with only incremental maintenance on that site since. I also had no experience driving API calls with PHP, or handling the resulting JSON, so there was quite a bit of a learning curve. Foolishly, I didn’t bother setting up a local environment to test, thinking I’d just pulverise it with my mad skillz.

Shyeah.

The last 12 months at work was mostly concerned with learning NodeJS, which made my PHP a little hazy. They share some commonalities, so I’d keep using the wrong function calls. Throw in the minor differences between MySQL and my work DBs of PostGreSQL and SQL Server, and I had trouble getting things straight some nights.

Bad words were muttered. Repeatedly.

The results so far are a few charts that I’ll describe a bit later in the post, with more to come as I start to slice and dice the data I’m getting out of SolarEdge. Mostly, I laid down a foundation for data ETL (Extract Transform Load) that will allow future developments to be faster.

SolarEdge API Details

You can see the tech specs of the SolarEdge API in this PDF, but of course to use this you first need:

  • a SolarEdge supported system with appropriate firmware
  • an API Key from SolarEdge (generated by your installer in most cases)
  • your Site Id
  • a working knowledge of JSON (or the willingness to research it)
  • a plan of what to do with the output

SolarEdge users will know there is already a web portal they can log into to check their summaries and current power flows. It produces things like the charts I’ve used previously via screenshot:

However, for some of us, logging into the portal can be a little tedious, and sometimes the data may not be as granular as we like. Perhaps we also want to compare it in different ways.

I’ve already logged a few suggestions through to the SolarEdge API development team, particularly in regard to battery-related data. It will help me develop new tools for Powerwall reporting in future.

Another thing to be aware of is regional differences. I was having a twitter DM brainstorm with a top bloke in Buffalo (hey Eric!) about the differences in data he was seeing. It appears that certain things we get in the SolarEdge Monitoring Portal in Australia are different to the USA.

I also know from personal experience that a previous firmware version on my SE5000 didn’t support monitoring of particular power flows.

Eric and a mate of his put up a GitHub Repo with some Google Sheets on it to pull data back. Recommend you have a look as they have good instructions and have cracked most of the eggs for that omelette.

SolarEdge API for UTP

My approach is a little more bespoke, because I’m of the opinion that my way is the best way, or at least the most interesting (*ahem*).

The SolarEdge API lists a limit of 300 calls per diem, which is fair enough, and I had PHP to get it, and MySQL to store it. After a bit of testing in Postman (REST Client) I settled on an initial strategy, to schedule calls every 15 minutes for two primary data flows in the SolarEdge API document.

Power Flow

/currentPowerFlow – a fairly simple summary of what power flows in the system, with source and destination mapped.

It seems to be used for this readout in the SolarEdge Monitoring Portal.

Source Graphic Destination(s) Notes
GRID Power lines LOAD Export is +ve, Import is -ve
LOAD House GRID Current consumption
PV Solar Panels STORAGE, LOAD Can feed both
STORAGE Battery LOAD Charging / Discharging

This data is it is not provided with a time stamp, which gives me a bit of pause; the accuracy of what this API call is doing against others with time stamps creates doubt. So I am making a few assumptions for now.

At present I’m using the retrieved data to track battery charge through both the fuel gauge on the side panel (to your right), and a battery charge line graph, which is not published on any other pages.

The latter operates on a rolling 24 hour basis, and was mainly done as a simple test of the WP Business Intelligence Lite plugin.

That said, its still pretty cool to know when the Powerwall got back up to full during the day. And its important to note that the SolarEdge API always reports “Full” as 98% and never above. I can live with that.

Power Details

/powerDetails is an API that gives power movement over a submitted time interval, broken down in 15 minute reads. This is a little different from the above, in that it doesn’t reference devices specifically, just the Watts that are flowing in the major categories of the system.

Term Meaning Notes
Consumption House usage Sourced from grid, battery, or panels
SelfConsumption Self use Usage covered by Production
Production System output Total of Solar PV + Powerwall output
FeedIn Export Power fed to grid
Purchased Import Power purchased from grid

The aim of the chart is to give at-a-glance notice of what is happening in the system, also on a rolling 24-hour basis. I have joined this data with some of the battery stats from currentPowerFlow.

And yes, I realise this is a mess, and will make it nicer in the coming weeks.

Joining data like that presents an issue, as they’re sourced from different API calls. As a result, there is no guarantee of accuracy because time-based joining of two datasets might represent different system states.

The fact that they run within milliseconds of each other is not quite good enough. You’ll see that inaccuracy borne out by “Powerwall Discharging” line spikes occasionally lagging behind the Consumption/Self Consumption spikes.

Overall, I’m happy if the “Importing” line stays near zero, and the “Consuming” line never goes above the “Consuming Own Power”. That means I’m catering for all my own needs with the system I have.

Tying it Together

There is little point to any of this unless you can automate it. I’m big on automation, and after building my own scheduler for PHP, I still didn’t have access to a cron-like tool with my current host.

Nor was I going to pay monthly fees to kick things off via Pingdom or other services – lack of capital, you understand.

Someone at work suggested using a Google Sheet script, with a per-minute trigger, to consume a page that simply called the scheduler function. Bam! Automation! Works pretty well, particularly for that kind of money i.e. zero dollars.

Total code base for doing this is about 480 lines of PHP total, excluding plugins for chart. I’m big on whitespace and comments, so its more like 200 functional lines.

Next Steps

There are some other APIs I’m looking into, and of course I’ll be thinking about new chart types in order to give some interesting insights.

I was also presented with a request, this very day, to make data downloadable in CSV or JSON format. That might have to wait until I’ve got a bigger dataset to report on, or more ETL running, or get a few feature requests done by the good people at SolarEdge.

Conclusions

Seeing these things in my own charts has led me to ask a few questions of the system itself. If I’ve got a near-full battery, and panels running hot, why am I ever importing power? My personal theory comes down to one of two things:

(A) Its a false read created by internal calculation errors, or inverter feedback of some kind; or

(B) The inverter, for whatever reason, isn’t responding to surges quickly enough to cover use from the solar panels or Powerwall.

I’m going to start keeping an eye on the smart meter I have installed to see which is more likely, based on the import/export it is reporting.

We shall see.


 

As I got halfway into typing this, I realised I hadn’t observed Earth Hour (19th March 2030-2130 hours) in any way. For the record, I only used 0.41kWh today, only a tiny bit of which was during Earth Hour.

Though maybe that was a false reading based on (A) above…