Skip to content
Martin Pospisil edited this page Sep 23, 2026 · 13 revisions

SolaX Local Controller

A standalone background service that manages a SolaX X3-HYB-G4 PRO hybrid inverter and an X1/X3-HAC EV charger entirely over your local network — no cloud account, no vendor API, no telemetry leaving the LAN.

Runtime .NET 10 Worker Service
Protocol Modbus TCP, local only
Platforms linux/amd64, linux/arm64, Windows Nano Server ltsc2022
Images ghcr.io/mpospisil/solax-controller

What it is

The controller polls your inverter and charger directly over Modbus TCP on the local network, then applies decision logic to route surplus household energy into the car and the home battery. Because nothing round-trips through a vendor cloud, control keeps working during an internet outage and the decision cycle runs at LAN speed rather than cloud latency.

The simplest way to run it is to clone the repository, set your two device addresses and dotnet run — that alone gives you live telemetry and the controller's own web UI, with no broker, no Home Assistant and no Docker involved. See Get started.

For unattended operation it runs as a long-lived process; the reference installation is Docker containers on a Raspberry Pi — the controller (with its own web UI) alone on a 1 GB board, or alongside Home Assistant and an MQTT broker where there is 2 GB or more. Both control surfaces are first-class; run either, both, or neither. See Deployment for the two workflows and which your hardware fits.

Capabilities

  • Real-time polling of PV generation, battery state of charge, grid import/export and charger status.
  • Surplus-aware EV charging — ramps charge current up and down to track available household surplus.
  • Battery discharge hold — stops the home battery serving house load, so the car charges from PV and grid while the battery still absorbs surplus.
  • Fast charge without the battery — a "I leave in an hour" mode that pulls maximum current from PV and grid, holds the battery out of it, and returns to Off by itself when the car is full. You can also say how much — an amount in kWh, or a battery target like 80% — and it stops there instead. And when you leave: given a departure it waits, starting as late as it can and still finish, so a car charged above 80% sits at that state of charge for minutes rather than all night. It still charges flat out; only the start moves.
  • Targeted charging — "15 kWh in the car by 17:00, and use as little grid as you can". The car is paced across the whole window at the rate the deadline needs, taking every watt of sun above that rate for free, because the charger can only use the sun that shines while it runs. On a forecast the sun can cover, a target set at 02:00 buys nothing overnight and starts when the surplus first clears the charger's minimum. It returns itself to Off once the energy is delivered.
  • Solar forecasting via a cached Solcast forecast, logged against actual generation.
  • The weather each session ran in — optional, via OpenWeatherMap: the conditions at each end of a session and the day's daylight window, so a finished session can be read against the day it happened on rather than only against the forecast.
  • Self-hosted web UI — a dashboard served by the controller itself on :8090, on by default and needing no configuration: live telemetry, every control, charging-session history, the energy history, the solar forecast for today and tomorrow, and the forecast plan, no Home Assistant or broker required. A password is an optional extra, not a prerequisite. See Deployment.
  • Home Assistant integration over MQTT discovery, with runtime mode control and full telemetry.
  • Charging session history — every controlled session recorded to local SQLite: when it ran, which strategy drove it, and how much energy came from solar, grid and battery.
  • A graceful stop from either surface — stopping the service from the web UI or Home Assistant releases the charger, closes the open session and flushes the store, none of which happens if the process is killed. It then stays stopped until you start it again, while a reboot or power cut still brings it straight back. See Deployment.

Hardware targets

Device Model Interface
Hybrid inverter SolaX X3-HYB-G4 PRO Modbus TCP
EV charger SolaX X1/X3-HAC Modbus TCP
Home battery SolaX T-BAT H 2.5 + BMS via the inverter — no direct connection

Safety posture

Warning

Read before enabling anything. Two features write to your hardware: ChargeControl (the charger) and BatteryHold (the inverter). Both ship disabled, and BatteryHold additionally defaults to dry-run. Register addresses vary between SolaX generations and firmware revisions — verify them against your own device before turning either on. A wrong address writes to a real inverter.

Note

A first run is safe by default. Starting the controller writes nothing to your hardware. Charge control always boots in mode Off — whatever the config says — and takes control only when you pick a mode, in the web UI or in Home Assistant. No mode persists across a restart, so after a crash, power cut or redeploy the charger is left exactly as its owner set it.

Where to next

Start here — clone, configure, build, run. That is the whole first pass; nothing in the Advanced table below is needed for it.

Page What's on it
Get started Clone the repository, point it at your devices, build and run it
Configuration Every setting, in both its file and environment form
Solcast Optional solar forecasting — when to bother, and how to get a key
Weather Optional weather on each recorded session — what it answers, and how to get a key
Troubleshooting Symptom → cause → fix

Advanced — for unattended operation, or a second control surface.

Page What's on it
Docker Image tags, and running the controller as a container
Platforms Linux x64, Raspberry Pi and Windows Nano Server — and what differs
Deployment Controller, Home Assistant and MQTT broker via Compose
MQTT How the controller and Home Assistant actually talk

SolaX Local Controller

Advanced


Images: ghcr.io/mpospisil/solax-controller

Clone this wiki locally