×Solar inverter dashboard

Projects

Solar inverter dashboard

Live telemetry from a hybrid solar inverter whose Wi-Fi logger allows no local access, read off its own cloud uplink on the LAN.

Python collector, Next.js, Neon Postgres, VercelSource on GitHub

The solar dashboard with solar, battery, home load and grid tiles, a live power-flow diagram, a 24-hour power chart and the battery's state of charge.

The dashboard above shows a day of the repo’s demo data, the same generator its demo seed uses. The real dashboard sits behind a login.

The problem

The inverter talks to a Wi-Fi logger stick over RS485, and the stick is locked down. Its only local web page is for firmware upload. There’s no Modbus over TCP and no AT interface. The one thing it does is open a TCP connection to the Solarman cloud on port 10000 and send what it polls from the inverter, wrapped in Solarman’s V5 framing around raw Modbus RTU responses.

So the collector reads that uplink instead of polling the inverter.

 inverter ──RS485──► logger stick
                         │  Solarman V5 frames (Modbus RTU inside)
                         ▼  TCP :10000
                 collector on the LAN
                 ├─ relays to the real Solarman server, so the vendor app keeps working
                 ├─ decodes V5 → Modbus registers → metrics
                 └─ spools locally, pushes to Postgres
                         │
                         ▼
                 Next.js dashboard, reads Postgres server-side

Getting the stick to talk to the collector

The stick has no server setting; it looks up a Solarman hostname. The collector answers that lookup with its own address, one of two ways:

  1. Stick only (preferred). The collector tells the stick, and only the stick, that it’s the gateway, by ARP, and answers its DNS. Nothing else on the network changes.
  2. Whole network. Point the router’s DHCP DNS at the collector. Simpler, but every device’s lookups now go through it, so reserve the collector’s address on the router.

Running it safely

The collector binds one address on the LAN, never all of them, and talks only to the stick: the relay drops any other source, and DNS answers only the stick, so it can’t be used as an open resolver. It needs root only to bind port 53 and set up the ARP redirect, and drops to your user before it reads a byte from the network. Frames over 2 KB are rejected, and connections, frame rate and the local spool are all capped.

The stick itself needs hardening too: change its web password, turn off its setup hotspot, and keep it on an isolated IoT network.

All projects