Harrison Was Here

No Cloud Required: Talking Directly to My SunPower Hardware

TL;DR: I discovered an official API for my SunPower hardware. I can use Python (or whatever) to talk to my system.

Sunnyvale, California

BACKGROUND

I bought a Sunpower solar/battery system in January 2023. After securing permits, installation began later that year. Despite some hiccups, such as having to reboot and reset everything when the battery is exhausted, the system works well enough. We survive power outages by flipping breakers to run the refrigerator and nothing else. When the house is quiet and only the refrigerator is drawing power, the site load drops to around 0.1 kW.

⚑Record: 80 hours without power on February 2024

SunPower filed for Chapter 11 bankruptcy on August 6, 2024. SunStrong Management, which bought out SunPower's share in SunStrong Capital, took over the monitoring app. They wanted $200/year for the app! Excessive but not too surprising: Supporting their goofy, bespoke app for a tiny customer base can't be cheap. I wasn't completely surprised when the latest release, 1.1.8 (10981), broke chart rendering. No idea how this version made it out of QA.

IMG_9819

Update: They fixed the chart rendering bug a few weeks later.

THE SUNFLOWER CLUE

While researching a replacement, I came across a third party app called Sunflower.

Screenshot 2026-04-03 at 13

To my complete surprise, Sunflower could connect directly to the monitoring gateway. All I had to do was:

But how the heck was Sunflower talking to it when my own attempts failed?

% curl '10.10.10.134/cgi-bin/dl_cgi?Command=DeviceList'
{ "status":403, "error" : "Unauthorized", "path":"" }

AN EXCITING DISCOVERY

After Kagi-ing around, I was floored to discover that SunStrong has published official documentation for the local API including how authentication works. The username is always ssm_owner and the password is the last five characters of the serial number.

WHAT I BUILT

I've been having a lot of fun coding with Claude over the last year. Together we wrote a Python script to explore PVS6 data: pvs6_query.py

It expects two environment variables:

Output:

PVS6 Local Monitor
Device : 10.10.10.134
Auth   : ssm_owner:*****  (19-char serial)

────────────────────────────────────────────────────────────
  Gateway / Firmware
────────────────────────────────────────────────────────────
  Model                              PVS6
  Serial                             <redacted>
  SW version                         2025.10, Build 61846
  FW version                         1.0.0
  Build                              61846

  βœ“ Authenticated  (session: REDACTED)

────────────────────────────────────────────────────────────
  Live Power  (updates every ~15 s)
────────────────────────────────────────────────────────────
  Timestamp                          2026-04-01 11:19:32 PDT

  Solar PV output                    +6,688 W
  Site load                          -5,801 W  (negative = consuming)
  Grid                               -5,794 W  (negative = exporting βœ“)
  Battery                            -7 W  (βˆ’ charging  + discharging)

  Lifetime solar generated           37,650.1 kWh
  Lifetime net grid                  3,978.7 kWh
  Lifetime site load                 2,480.6 kWh
  Lifetime battery net               -1,498.2 kWh

────────────────────────────────────────────────────────────
  Battery (ESS / SunVault)
────────────────────────────────────────────────────────────
  Operating mode                     TARIFF_OPTIMIZER
  Measurement time                   2026-04-01 11:10:00 PDT

  State of charge (SOC)              100.0%
  Customer SOC                       100.0%  (what the app shows)
  State of health (SOH)              100.0%
  Minimum customer SOC               50.0%  (reserve floor)

  Battery power now                  -7 W
  Charge limit                       +178 W
  Discharge limit                    +10,117 W

  Battery voltage                    54.23 V
  AC voltage L1                      120.05 V
  AC voltage L2                      120.05 V
  Inverter temp                      35.9 Β°C
  Cell temp (max)                    29.9 Β°C
  Cell temp (min)                    2.1 Β°C
  Cell voltage (max)                 3.41 V
  Cell voltage (min)                 3.38 V

  Lifetime charged                   2,246.5 kWh
  Lifetime discharged                3,744.6 kWh

  Product model                      SPWR-Equinox-model
  Serial(s)                          <redacted>

────────────────────────────────────────────────────────────
  System Info (varserver)
────────────────────────────────────────────────────────────
  hwrev                              6.02
  sw_rev                             2025.10.20.61846
  boardtype                          B0K LIB 1.0 PSoC5
  model                              PVS6
  serialnum                          <redacted>

────────────────────────────────────────────────────────────

The 37,650 kWh of lifetime solar generation represents about three years of production from our system in Monterey, California.

TARIFF_OPTIMIZER is a neat trick: Using the Sunstrong app I can feed power back to PG&E starting at 4PM M-F.

WEB UI

The newest design including a warning due to the battery not charging:

Recent Update

An earlier version on mobile:

Screenshot 2026-04-03 at 17

The daily summary screen:

Screenshot 2026-06-22 at 10

OUTAGE DETECTION & WARNINGS

A separate cron job determines whether grid power to the home is OFF and solar/battery is exclusively powering the house — i.e. the system has islanded due to an outage. A notification is sent when state changes: UP→DOWN or DOWN→UP

Screenshot 2026-06-19 at 08

Another cron job pulls weather data and warns me if tomorrow looks particularly windy and to reserve battery capacity.

wind advisory

This sort of thing happens from time to time:

doh

ADDITIONAL LEARNINGS

The SunPower brand now belongs to Complete Solaria with no legacy warranty liability.

EmPhase offers "legacy SunPower support" that restores monitoring but doesn't cover SunVault hardware.

SunVault's ESS inverter is a rebadged Schneider Conext XW Pro, so the F.xx codes on the battery LCD are Schneider fault codes.

REFERENCES