Repository navigation
Get Started
The default way in: clone the repository, point it at your two devices, build it, run it. No Docker, no MQTT broker, no Home Assistant, no Solcast account — every one of those is a separate opt-in, and none is needed to get live data out of your own hardware.
What these four steps give you is a process that polls the inverter and the EV charger over Modbus
TCP, logs what it sees, and serves its own web UI on http://localhost:8090 — dashboard, controls,
charging-session history and the forecast plan.
Note
A first run writes nothing to your hardware. The service always boots with the charge mode
Off and the battery hold off, and BatteryHold:Enabled ships false. It only reads until you
deliberately change that.
-
.NET 10 SDK —
dotnet --versionshould print10.* - Git
- Network reachability from this machine to both devices, with Modbus TCP enabled on them
Check the last one first. The controller cannot poll what it cannot reach, and an unreachable device looks identical to a wrong register map — you will waste an afternoon on the wrong problem.
nc -vz 192.168.2.10 502 # inverter
nc -vz 192.168.2.6 502 # EV charger
Both devices answer on port 502, so this check passes even if the two addresses are the wrong way
round -- and that mistake is unpleasant to diagnose: SOC freezes at some constant, solar and grid sit
at 0, and the charger reads permanently "Unknown". Confirm which is which before trusting either
value. The charger serves its own web page, which identifies it:
```bash
curl -s http://<address>/ | head -20 # the EV charger's page mentions "chargeweb"
Substitute your own addresses. If these fail, fix that before going further: Modbus TCP is off by
default on some SolaX firmware and has to be enabled on the device itself.
## 2. Clone and build
```bash
git clone https://github.com/mpospisil/solax-controller.git
cd solax-controller
dotnet build SolaxLocalController.slnx
dotnet test SolaxLocalController.slnx # optional — exercises the control logic without hardware
The tests mock the hardware boundary, so they pass whether or not your devices are reachable. A green run means the decision logic is sound on your machine; it says nothing about your register map.
The one genuinely site-specific thing. Open src/Solax.Worker/appsettings.json and replace the two
IP addresses in the Solax section with your own — the shipped values are the reference install's:
Everything else in that file has a working default. If you would rather not edit a tracked file, the
same two settings can come from the environment instead — : becomes __:
export Solax__Inverter__Host=192.168.2.10
export Solax__EvCharger__Host=192.168.2.6On Windows also set Controller__TimeZone to a Windows zone id (Central Europe Standard Time),
because .NET there ignores TZ. On Linux and macOS leave it empty and the OS zone is used. See
Platforms.
dotnet run --project src/Solax.WorkerThe first log line names the running build — 0.0.0-dev with no commit hash is expected for a local
build; only CI-published images carry a real version. Within one poll interval the log should show
live figures: PV generation, battery SOC, grid power, charger status.
Then open http://localhost:8090. No broker and no Home Assistant involved — the controller serves this itself.
Nothing switched it on: the UI is enabled by default and asks for no password, here and in every
container, because it needs no broker, credentials or onboarding to be useful. Setting a password is
an advanced option, and Web__Enabled=false is what turns the UI off. See
Configuration.
To stop it, Ctrl+C is fine — or use Stop service on the UI's Health page, which runs the same
graceful shutdown and is the only way to stop it once it is running unattended. Either way the last
line of the log says the run ended on purpose; see Deployment
for what that buys you and why killing the process instead is worth avoiding.
Leave the charge mode on Off until the numbers match what your inverter's own display and the SolaX
app say. Register addresses vary between SolaX generations and firmware revisions, and this is the
step that catches a wrong map while nothing can act on it. Only then turn on the features that write:
ChargeControl (the charger) and BatteryHold (the inverter, dry-run by default).
Each of these is independent, and none is required for the above.
| Next step | What it adds | Where |
|---|---|---|
| Solcast API key | The forecast-driven Forecasted charge mode |
Solcast |
| OpenWeatherMap key | The weather recorded with each charging session | Weather |
| Run it in Docker | Unattended operation with no SDK on the target machine | Docker |
| Raspberry Pi or Windows host | The per-platform things that actually break setups | Platforms |
| MQTT broker + Home Assistant | A second control surface beside the web UI | Deployment · MQTT |
Next: Configuration
Runs entirely on your LAN · Full configuration reference in README.md · Pi preparation and backup in deploy/README.md
- Home
- Get started — build & run
- Configuration
- Solcast
- Weather
- Troubleshooting
Advanced
- Docker
- Platforms
- Deployment — Pi, two workflows
- MQTT
Images: ghcr.io/mpospisil/solax-controller