Last week, I wrote bout my experience getting a solar power system installed; since then,
I've been spending some weekend and evening time working on improving the little corner of technical nonsense that
I have any control over!
Background
First, let's do a quick recap of how my system works:
I have 20 panels, each of which generates up to 460W of DC power and immediately converts it from DC to AC using an Enphase IQ8X microinverter. This gives us a peak of 9.2kW possible power split across two phases.
This power comes off the roof to an Enphase IQ Combiner 5 PV combiner. I'm not really sure what the combiner does! I assume it somehow aligns and balances the different AC signals coming off the roof into two 60Hz AC phases, but I have no idea how! Maybe it's just an expensive subpanel with a busbar and some breakers, who knows.
Anyhow, on the other part of the wall we have three Enphase 5P Batteries, storing 5 kWh each
(as DC, obviously, since you can't store AC). Each of them has six built-in IQ8D microinverters capable of putting out about 600W, so each battery can provide about 3.6 kW of instantaneous power.
The solar and the batteries both land on an Enphase IQ System Controller 3M, which merges all that power together and directs charge/discharge of the batteries. Unlike older Enphase systems, all of the communication is over powerline Ethernet instead of Zigbee.
The System Controller connects to the main panel in two ways: first, there's a 100A backfeed circuit to power the house with up to 19.2 kW of power; second, the System Controller is connected to the meter with an IQ Meter Collar , which allows the system to operate safely during an outage to provide whole-home backup without energizing PG&E's grid.
Management, Officially
So, how do you see what the system is doing and control it? It's all done through an Enphase app called Enlighten,
available both as a webapp and a mobile app. The mobile app is mostly just a wrapper around the webapp; there's almost no native functionality. Both of these tools
are incredibly slow. I just benchmarked launching the iOS app on my phone and it takes 13-21 seconds to start up. Once it
starts up, it's not responsive to taps at all and many features take forever to load. It also doesn't support widgets or App Intents
or anything else someone might want on a modern Apple platform. The webapp usually loads faster, but has a "do not sell my
personal information" banner that can't be dismissed and the layout is broken at lots of screen sizes (including the one in this screenshot).
I don't really need my data hosted in some cloud service anyway. Isn't there a way to get this information directly off the Enphase
system gateway (which is known as Envoy)?
Yes, Duh
This would be a short story if there weren't.
It turns out that Enphase provides a documented open API to get data off of the Envoy! The documentation is pretty hard to find,
but it's still around at https://enphase.com/download/iq-gateway-access-using-local-apis-or-local-ui-token-based-authentication-tech-brief.
You need to obtain a JWT from some dinky web service
(which expires after a year and can't be renewed without an interactive
session, alas), but then you can get all kinds of nice JSON data. Sometimes it's oddly slow (like, 15-20 seconds), and there's
no authz, so that same token that can read the data can also reconfigure the system, so you definitely don't want to expose
the Envoy directly to the Internet.
So, I wrote a small Rust application named envoyproxy
that polls the Envoy API every
minute and serves the most recent result and some other metrics as JSON and Prometheus. I'm running mine in my little k8s cluster here,
using the excellent Tailscale Kubernetes operator to expose it to my Tailnet
so I can reach it from anywhere.
But why?
The immediate goal here was to have a pleasant iOS experience for seeing system status, so I've also built a SwiftUI app, tentatively codenamed
Sunny Days
:
It's pretty ugly, but it takes 14MiB of RAM and launches in approximately 300ms. Not too bad for something cracked up on a weekend by
someone with absolutely no Swift experience.
I'm not sure what to do with it. It'd never make it onto the App Store — a third-party unsupported client for a proprietary
solar system which requires running an open-source server somewhere? Maybe it'll just live on my and my wife's devices through TestFlight
forever...
I also, of course, have a Prometheus instance ingesting these metrics, connected to Grafana.
Anything else?
Yeah, the other thing is my car. It's connected to an
Emporia EVSE on a fat 60A circuit. However, most of the time
I'd prefer to charge it slowly with excess solar. This is... not supported.
There are really two options:
- Pull out the Emporia EVSE and put in Enphase's, which can talk to the CTs in the Enphase boxes and natively do excess-solar charging. This would require permit and an electrician and a new EVSE and would probably come to around $1000
- Add the Emporia Vue CTs to the solar subpanel and main panel. This would require two sets (around $300) and should be done by a licensed electrician, so still pretty steep
I didn't want to do that, so instead I wrote a small Python program that reads the Envoy data every few minutes and uses it to
adjust the Emporia charge rate up-or-down. It's not as nice, because it's not instantaneous so sometimes it'll draw amps from the batteries
or the grid for minute, but that's not a big deal to me, and the cost was $0. It's called
emporia-enphase-control and is... pretty rough around the edges.
It does work, though! It's running in Kubernetes, right alongside envoyproxy
.
That's it, right?
For now. We're still adapting to life with solar; it's a surprising number of changes. For example, we usually ran
the dishwasher and the dryer at night (when the grid is the cheapest), but now that power is totally free while the sun's up
(the batteries are quite finite, especially when the A/C is running overnight on hot weeks like this one) it makes no
sense to run these expensive appliances at night.
So far, we have only drawn a negligible amount of power from the grid this week.