# SunPower PVS6 — Local Monitoring Handoff

**Last updated:** 2026-06-10
**Purpose:** Everything another Claude session needs to pick up local monitoring of the SunPower solar system and get it into Home Assistant.

---

## 1. The system

- **Gateway:** SunPower **PVS6** (PV Supervisor), hardware rev **6.02**
- **Firmware:** `2025.10.20.61846` (build **61846**) — recent, locked-down
- **Serial:** `ZT222985000549W3742`
- **Array:** **18 microinverters** (SunPower AC modules, "Type H") → 18-panel array
- **Metering:** production meter only (`PVS6M…p`); **no consumption CT pair** — house load is derived by subtraction
- **Battery:** **none** (`sys_type: PV-only`, ESS/SoC = `nan`) — no SunVault
- **Cloud:** the old mySunPower app is now **mySunStrong** (after SunPower's 2024 bankruptcy → SunStrong). Local API works regardless of cloud status.

### Live snapshot captured (afternoon, ~3:45pm local)
| Metric | Value |
|---|---|
| Solar production | ~3.87–4.22 kW |
| House load | ~0.32 kW |
| Grid | exporting ~3.54 kW |

### Lifetime counters (PVS keeps running totals, no time-series history)
| Counter | Lifetime total |
|---|---|
| Solar produced | 26,960 kWh |
| Exported to grid (`negLtea`) | 21,780 kWh |
| Imported from grid (`posLtea`) | 7,475 kWh |
| Net (import − export) | −14,305 kWh (net exporter) |
| House consumed (derived) | 12,655 kWh |

Sanity check: produced 26,960 − net-exported 14,305 = 12,655 consumed ✓

**Per-panel note:** inverters #0–9 vs #10–17 differed ~2× midday (#0–9 ≈ 0.15 kW, #10–17 ≈ 0.30–0.36 kW). Almost certainly **two roof planes at different sun angles**, not a fault — worth confirming over a full day vs. shading.

---

## 2. Network location

- **PVS6 IP on the home LAN: `192.168.1.136`** (subnet `192.168.1.0/24`)
- Router/gateway: `192.168.1.1` (**Ubiquiti / UniFi**)
- Main workstation `gideon`: `192.168.1.178` (Ubuntu 24.04)
- The PVS6 is **already bridged onto the home LAN** — no physical installer-port tap needed. This is the hard part that's normally required; here it's already done.
- The classic installer-port address `172.27.153.1` is **NOT routable** from the LAN (ignore it).
- Identified via MAC vendor as an **AMPAK** Wi-Fi module (AMPAK makes the PVS6's internal radio); server header is `lighttpd/1.4.67`.

### IMPORTANT — Claude's sandbox CAN reach the PVS
Claude Code's Bash tool runs in a microVM (`172.16.0.2/24`, gateway `172.16.0.1`), a different subnet from the home LAN. **But the VM host forwards outbound traffic onto `192.168.1.0/24`**, so Claude CAN reach `192.168.1.136` directly over TCP/HTTP — this was verified by pulling live data. Do **not** assume otherwise.

Caveats:
- **ICMP/ping is blocked** in the sandbox (every ping exits code 2). Use **TCP connect scans** (`/dev/tcp`) or `curl`, not ping.
- `ip neigh` / ARP only shows the VM's own gateway — the home LAN is reached via L3 routing, not the local L2 segment, so ARP-based discovery won't list home devices.
- The `!` prefix in the Claude Code session runs in this same VM (so it shares this routing).

---

## 3. Local API access (the key finding)

Firmware build **61839+** (this unit is 61846) **deliberately killed the old unauthenticated `dl_cgi` API**:
- `GET /cgi-bin/dl_cgi?Command=DeviceList` → **403 Unauthorized** (old query-style API, dead)
- `GET /cgi-bin/dl_cgi/<resource>` (devices, meters, power, production, …) → **403** (also dead)
- `GET /cgi-bin/dl_cgi/supervisor/info` → **200** (the one unauthenticated endpoint left — returns model/serial/firmware)

The successor is SunStrong's official, documented **LocalAPI / "varserver"**, which requires a login. (Tell: `GET /vars` returned **400** not 404 earlier — the endpoint is alive, just waiting for auth.)

### Credentials (now standardized by SunStrong)
- **Username:** `ssm_owner`
- **Password:** last 5 chars of the serial → serial `ZT222985000549W3742` → **`W3742`**
  - If rejected, try lowercase `w3742` (the official integration auto-detects).

### Working auth + live-data pull (verified)
Run from anything that can reach `192.168.1.136` (gideon, a Pi, HA, or the Claude sandbox VM):

```bash
ip=192.168.1.136
pwd=W3742
auth=$(echo -n "ssm_owner:$pwd" | base64)

# 1. Log in (https, self-signed cert → -k). Stores session cookie.
curl -sk -c /tmp/pvs.cookies -H "Authorization: basic $auth" "https://$ip/auth?login"; echo
#   → success prints {"session":"<token>"}

# 2. Pull live data
curl -sk -b /tmp/pvs.cookies "https://$ip/vars?match=livedata&fmt=obj" | head -c 2500; echo
```

Notes:
- If `https` gives a connection error, retry with plain `http://` (drop `-k`).
- The varserver exposes ~**295 variables**. There is **no** `history`/`log`/`archive`/`trend`/`daily` namespace (all 400) — only instantaneous values + lifetime counters.
- Some `match=` strings from the official docs are approximate and don't all work on this firmware; discover actual namespaces by dumping the var tree if a match fails.

---

## 4. Home Assistant integration path (NOT yet installed)

- **No native SunPower integration exists in `home-assistant/core`.** (`home-assistant/core` is cloned at `/home/user/home-assistant-core`, shallow, ~279 MB.)
- **Use the community integration `smcneece/ha-esunpower`** (Enhanced SunPower) — it's the actively maintained fork that handles this exact new-firmware varserver auth flow automatically. (Older `krbaker/hass-sunpower` predates the firmware lockdown.)

Steps:
1. HACS → add custom repo `https://github.com/smcneece/ha-esunpower` → Download → restart HA
2. Add integration → IP `192.168.1.136` (auto-detects firmware + `ssm_owner`/`W3742` login)
3. **DHCP-reserve `192.168.1.136`** in UniFi so it never moves
4. Add production/consumption/net entities to the HA **Energy Dashboard**

History: HA builds long-term statistics going forward (polls ~60s). No backfill — pre-existing history lives only in the **mySunStrong** cloud (separate exercise if wanted).

---

## 5. Remote monitoring (from an external server)

**Do NOT port-forward the PVS6 to the internet.** It's grid-tied energy hardware with weak security:
- Trivial auth (`ssm_owner` + last-5-of-serial; serial is printed on the unit and embedded in its SSID `SunPower29742`).
- **Write-capable** endpoints (`grid_profile`, network config) — not read-only telemetry.
- Unhardened embedded stack (lighttpd 1.4.67), HTTP Basic over self-signed cert, never patched.
- Internet-exposed devices get found by Shodan/scanners within hours.

Better options:
- **Option A (recommended):** poll locally, push out. Run the auth+poll loop on a LAN device and have *it* push readings to the external server (HTTPS POST or MQTT). **Zero inbound ports.**
- **Option B:** mesh VPN — Tailscale/WireGuard on a LAN device + the external server; advertise `192.168.1.0/24` as a subnet route. Server reaches `192.168.1.136` over the tailnet, no public exposure.

---

## 6. Possible local monitoring host

An **Intel NUC** was being set up last session. As of 2026-06-10 it appears to have finished installing and is online at **`192.168.1.77`** (SSH banner `OpenSSH_10.2p1 Ubuntu-2ubuntu3.2` → **Ubuntu 26.04**; distinct from gideon's 24.04 at `.178`). Not yet 100% confirmed via hostname/dmidecode. This NUC is the likely target to run a standalone polling/logging service or Home Assistant.

---

## 7. Open threads / next steps

- [ ] (Optional) Write a standalone polling+logging script using the verified auth in §3 — immediate local data, independent of HA.
- [ ] Install `smcneece/ha-esunpower` in Home Assistant (§4).
- [ ] DHCP-reserve `192.168.1.136` in UniFi.
- [ ] Confirm the NUC at `192.168.1.77` (hostname/product name) and decide if it hosts the monitor.
- [ ] Decide remote-access approach (§5) if monitoring from an external server.
- [ ] Watch panels #0–9 over a full day to confirm orientation (not shading).
