See what your Voltronic / Axpert solar inverter is doing — locally, no cloud, no vendor app.
A plain-English dashboard, a full history, and readings that are checked rather than trusted. Read the inverter straight from its USB port on a Linux machine, or put a ~$10 ESP32-S3 next to it as a WiFi bridge.
| Tested on | Axpert VM III 6000 (sold as Exideve), firmware 60.14, with a Felicity 48 V LiFePO4 battery on a BMS link |
| Should work | Anything speaking Voltronic PI30: Axpert, MPP Solar PIP, EASun, Mecer, Kodak, PowMr and many other rebrands. The USB port shows up as 0665:5161 |
| Won't work | PI17/PI18 models (InfiniSolar) and Modbus inverters (Deye, Sunsynk, Growatt…) |
Quick check once installed: ./venv/bin/python axpert.py --raw QPI should print PI30.
Only one unit has been tested. If yours differs, axpert.py --scan shows what it answers, and issues or PRs are welcome.
| USB → Linux machine | ESP32-S3 WiFi bridge | |
|---|---|---|
| Hardware | The inverter's own USB cable | ESP32-S3 board with two USB-C ports, a USB-C OTG adapter, a phone charger |
| Good for | Trying it today | A permanent install; the laptop is free to leave |
| Keeps recording when your computer is off | No | Yes — about 45 days on the ESP32, filled in when you reconnect |
| Setup | 5 minutes | ~30 minutes, see docs/esp32-bridge.md |
Two things flow through this setup: data from the inverter to the dashboard, and power to keep the bridge board running.
DATA: inverter ──USB cable──▶ OTG adapter ──▶ ESP32-S3 (USB port) ──WiFi──▶ router ──▶ dashboard
POWER: inverter's AC socket ──▶ phone charger ──A-to-C cable──▶ ESP32-S3 (COM port)
With the USB route you only need the inverter's own USB cable and a Linux machine; everything below the first table is for the ESP32 bridge.
| Part | What it is | Why it matters here |
|---|---|---|
| Inverter — Axpert VM III 6000 (Voltronic; sold as Exideve) | 6 kVA off-grid hybrid, one solar input (MPPT), 48 V battery, 230 V output | Its control chip (an STM32) speaks PI30 on its USB port (used here), RS232/RJ45, and a BMS port |
| Battery — Felicity Solar 48 V 100 Ah | LiFePO4, 16 cells, 5.12 kWh | Its BMS talks to the inverter, so it sets charge voltages and a charge limit that changes as it fills |
| Solar panels | Feed the inverter's MPPT | Solar powers the house directly; the battery only takes or gives the difference |
| Part | What it is | Its job |
|---|---|---|
| ESP32-S3 board, 16 MB flash (e.g. "N16R8", two USB-C ports labelled COM and USB) | WiFi chip: 2 cores at 240 MHz, 2.4 GHz WiFi | USB host for the inverter, serves readings over WiFi, keeps ~45 days of history in flash |
| ↳ COM port | Goes through a USB-to-serial chip (e.g. CH343) | Power in, plus flashing and logs |
| ↳ USB port | The S3's own USB, wired straight to the chip | Switched to host mode by the firmware: powers and talks to the inverter's USB port |
| USB-C OTG adapter | USB-C plug → USB-A socket | Lets the inverter's normal USB cable plug into the board |
| Inverter's USB cable | USB-A ↔ USB-B (printer style), usually in the box | The same cable you'd use with a laptop |
| 5 V phone charger + USB-A → USB-C cable | Plain power supply | Powers the board through COM. Use A-to-C: many of these boards lack the resistors a USB-C charger needs before it sends power, so a C-to-C cable leaves them dark |
Why an S3: the inverter's port is a USB device, so something has to be the host — the role a laptop normally plays. The classic ESP32 has no USB host hardware; the S3 does.
Safety: everything here is low voltage (USB, 5 V) and nothing goes inside the inverter. The board shares a ground with the inverter through the USB cable — one reason a cheap, replaceable board sits there instead of a laptop. Plug the charger into a socket the inverter powers so the bridge keeps reporting during blackouts.
git clone https://github.com/OmarMujahid/axpert-local.git
cd axpert-local
./linux/install.shPlug in the inverter's USB cable, then open http://localhost:8770.
The installer sets up a Python environment, adds one udev rule so the USB port works without sudo, and can start the dashboard on login. Each step asks first.
Command-line tool:
./venv/bin/python axpert.py # full report
./venv/bin/python axpert.py --watch 5 # live table
./venv/bin/python axpert.py --scan # which commands your unit answers
./venv/bin/python axpert.py --json # machine readableOnly one program can hold the USB port at a time, so stop the dashboard before running the CLI against USB.
- One sentence on top saying what's happening: "Running on solar and battery — the grid is ready as backup."
- Live tiles and a flow diagram: solar, house, battery, grid; moving dashes show where power actually flows.
- Battery: charge, kWh stored, and about how long until the grid takes over.
- Health checks in plain words, not fault codes.
- History: every reading to
history.csv, every change (grid in/out, charging started…) toevents.csv, and the inverter's own 14-day energy record. - Every field explained and labelled confirmed, spec or unverified.
validate.py proves the field meanings against independent evidence: two commands reporting the same value must agree, and physics must hold (apparent ≥ real power, the battery never charges and discharges at once, solar + battery = load + losses).
./venv/bin/python validate.pyRun it on your unit — it's the quickest way to find out whether your firmware lays fields out differently.
- Read-only by default. Changing settings goes through one endpoint that needs a token and accepts only output priority, charger priority and the clock. Everything else is refused before it reaches the inverter.
- The token travels in plain HTTP. It protects against accidents on your home network, not a determined attacker on it. Don't expose the dashboard or the ESP32 to the internet.
- Only touch the inverter's communication ports. Never open the case.
- Changing priorities and battery thresholds is covered step by step in docs/settings-guide.md. Wrong battery settings can damage a battery — check your battery's datasheet.
| docs/esp32-bridge.md | Parts, flashing, wireless updates, the bridge's API |
| docs/settings-guide.md | Run on solar and battery with automatic grid backup (SBU), screen program by program |
| docs/protocol.md | How the USB/HID transport and PI30 framing work, and what each field was proved to mean |
| docs/troubleshooting.md | No /dev/ttyUSB0, permission errors, board not detected, can't reach the ESP32 |
axpert.py protocol driver + command-line tool (USB or bridge)
dashboard.py collector and web server for the dashboard
dashboard.html the dashboard page (no external dependencies)
validate.py proves field meanings against the live inverter
esp32/ ESP32-S3 bridge firmware (C, ESP-IDF via PlatformIO)
linux/ installer, udev rule, systemd unit
tests/ offline protocol tests: python -m unittest discover tests
docs/ guides
- jblance/mpp-solar — Python library covering many protocols
- syssi/esphome-pipsolar — ESPHome component over RS232
- ned-kelly/docker-voltronic-homeassistant — Home Assistant via MQTT
This project's angle: no RS232 wiring (it uses the USB port, even from an ESP32), readings validated field by field, and a dashboard a non-technical household can read.
MIT. Not affiliated with Voltronic Power or any inverter brand. Use at your own risk.
