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 microinverter1. 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 phone2 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
3 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 supported4.
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 edges5.
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 appliances6 at night.
So far, we have only drawn a negligible amount of power from the grid this week7.
This is to be contrasted with the more-traditional "string inverter" deployment, where the solar panels are all connected in series and send DC off the roof to a single large inverter at ground-level
an iPhone 16 Pro with the fastest single-core processor performance in the world, connected to WiFi 6 and a 10Gbps Internet connection
It really should be! There's a protocol called the Open Charge Point Protocol that should standardize these interconnects, but none of my devices support it. I guess I should've gotten a Wallbox...
I'm sure the distinction between watts and volt-amps in a mixed DC/AC system is not important, right?
A single dryer load consumes something like 4kWh of energy --- gotta get myself one of those fancy heat-pump combo units that only consumes 1.4 kWh for a wash and a dry cycle
~300Wh day, more than offset by the several kWh we've sold back. I wish I knew why the system ends up drawing ~14W from the grid, all the time...
Want to comment on this? How about we talk on Mastodon instead?
Share on Mastodon