No description
  • Python 97.4%
  • Shell 2.6%
Find a file
Repository files (latest commit first)
Filename Latest commit message Latest commit date
HWE70 5f89347595 Stop the bridge automations from flooding the activity log
The publisher fired ~465 times per hour on a live host and wrote roughly
930 recorder rows per hour just for last_triggered, which buried every
other entry in the logbook.

The three voltage sensors alone accounted for ~345 runs/h: they jitter by
tenths of a volt around the clock, while evcc only displays them. Drop
them from the trigger list - they are still published on the 30 s cycle.

The remaining ~120 runs/h are the deliberate republish cycle and cannot be
optimised away, so document the logbook/recorder exclude filters instead.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
2026-09-06 09:00:02 +02:00
custom_components/anker_v1 Fix per-phase currents being a factor of ten too small 2026-09-02 22:34:27 +02:00
examples Stop the bridge automations from flooding the activity log 2026-09-06 09:00:02 +02:00
scripts Add Home Assistant integration for the Anker SOLIX V1 charger 2026-08-30 14:24:01 +02:00
.gitignore Add Home Assistant integration for the Anker SOLIX V1 charger 2026-08-30 14:24:01 +02:00
LICENSE Add Home Assistant integration for the Anker SOLIX V1 charger 2026-08-30 14:24:01 +02:00
README.md Confirm phase switching works mid-session 2026-09-03 00:36:47 +02:00

ha-anker-solix-v1

License: MIT AI-assisted

A Home Assistant custom integration that reads — and optionally controls — an Anker SOLIX V1 Smart EV Charger (A5191) over its local Modbus TCP interface. No cloud account, no Anker app in the loop, no polling of Anker's servers.

This project was developed with the assistance of Claude (Anthropic).

Mirror: https://opencommit.eu/HWE70/ha-anker-solix-v1 · Primary: https://git.highwire.de/HWE70/ha-anker-solix-v1

🤔 Why this exists

The V1 is normally driven either through the Anker app or through OCPP. Both hide what the charger is actually doing — in particular how many phases it is using, which the charger decides on its own and never reports over OCPP. When a charging session unexpectedly runs single-phase, OCPP can tell you the current per phase but not whether the charger switched to one phase or the vehicle simply stopped drawing on the other two.

Modbus exposes both: register 20087 is the charger's own phase mode, and 21005 is the configured phase setting. Recording them alongside the per-phase currents makes that question answerable from history instead of requiring someone to be watching at the right moment.

Features

  • 🔌 Local polling only — Modbus TCP straight to the charger, nothing leaves the LAN.
  • 📦 No external dependencies — the Modbus client is ~200 lines of standard library. Nothing to pin, nothing to collide with the pymodbus version Home Assistant's own modbus integration already loaded.
  • 🔍 Full state visibility — phase mode, charging status, control pilot state, charging mode, OCPP/cloud connectivity, load and solar balancing.
  • 📊 Per-phase measurements — current, power and voltage on each phase, plus line-to-line voltages and a derived Active phases sensor.
  • 🎛️ Optional control — charging release, current limit and phase setting, all opt-in (see below).
  • 🌍 English and German translations.

📋 Requirements

Modbus TCP must be enabled on the charger first. In the Anker app: device → Settings → Integrations → Modbus TCP. Until that switch is on, port 502 is closed and setup will fail with "no answer on this address".

The charger serves at most two Modbus clients at once. If an evcc instance or another tool already holds both slots, this integration cannot connect.

🚀 Installation

Copy custom_components/anker_v1/ into your Home Assistant config/custom_components/ directory and restart Core, then add the integration under Settings → Devices & Services → Add Integration → Anker SOLIX V1.

The repo ships a deploy script for hosts reachable over SSH:

./scripts/deploy-hassio.sh hassio-pb

It stages the files through /tmp, moves them into place with sudo (the SSH add-on's user does not own custom_components/ on every host) and restarts Core through the ha CLI rather than docker restart, so it also works where the SSH add-on runs in protection mode.

HACS is not an option here: HACS only supports GitHub repositories.

⚙️ Configuration

Option Default Notes
IP address Give the charger a DHCP reservation; the config entry is pinned to the address.
Port 502
Modbus unit ID 1 Verified value for the A5191.
Polling interval 10 s Minimum 5 s. Keep in mind the two-client limit.
Enable control off Adds the switch, current limit and phase setting entities.

Polling interval and control access can be changed later via the integration's options without re-adding the device.

⚠️ Writing while OCPP is connected

Control is off by default, deliberately.

The charger accepts Modbus commands while an OCPP backend (evcc, for instance) is also controlling it — the Modbus server and the OCPP client run in parallel, and the register map even reports OCPP connection state. But Anker does not document which side wins when the two disagree. A current limit written over Modbus and a charging profile pushed over OCPP are two controllers steering the same device.

Recommended sequence, mirroring the staged approach in the sibling ha-automations repo:

  1. Run read-only across several charging sessions. Watch the OCPP connected binary sensor — if parallel Modbus polling ever destabilised the OCPP link, it shows up there.
  2. Only then enable control, and start with a single current-limit write below what the OCPP backend is asking for. Observe which value the charger actually applies.

The watchdog

Register 21003 is a watchdog timeout (120 s from the factory). If no Modbus write arrives within that window, the charger falls back to its own control. That is a safety feature — it stops a crashed automation from leaving the wallbox pinned at a limit forever — but it also means a value written once does not stay applied indefinitely. Anything that needs to hold a limit must keep writing it.

📟 Register map status

Register numbers come from Anker SOLIX V1 Smart EV Charger Modbus Protocol V1.0.0 (30-11-2025). Three things in that document do not match the hardware, both established by reading back from a live A5191 on 2026-08-30:

Vendor document says Actually
Register numbers, function code unspecified 20xxx are input registers (FC4), 21xxx are holding registers (FC3). Using the wrong function code returns exception code 2 for every address in the range.
21001 in a column reading "W", gain 10 Amps, gain 10 — the charger returned 160 while the OCPP backend was offering exactly 16.0 A.
Per-phase currents 2005920061 at gain 100 Gain 10. Verified under load against power and voltage: raw 145 with P = 3413 W at U = 235.4 V is 14.5 A, not 1.45 A. Reading them at gain 100 makes every current a factor of ten too small.

Also worth knowing:

  • The holding range ends at 21005. Reading 21006, or any block that extends past it, returns exception code 2 — so read the control registers as a 6-register block, not 10.
  • 2005620058 are line-to-line voltages (~414 V), not documented in the register list this integration was built from.
  • The charger's voltage measurement sits upstream of the contactor: it reports ~240 V on all three phases even with no vehicle plugged in. Voltage therefore tells you nothing about which phases are switched through to the car — use the per-phase currents and the Active phases sensor for that.
  • 21000 (start/stop) reads back 0 regardless of what was last written, so the charging switch derives its state from the status and control pilot registers instead.
  • 20087 (phase mode) reads a constant 3 while no vehicle is connected, which makes it look like a static capability field. It is not — during a session it tracks the actual mode and follows 21005 within 19100 s. Registers carrying an operating state cannot be assessed while idle.

All register gains are now verified against live measurements; nothing in the map is taken on faith from the vendor table alone.

Device identity

Undocumented ASCII fields, found by dumping the full readable range. Two characters per register, NUL-padded. They feed the device registry entry (model, serial number, firmware) and are read once at setup:

Registers Content Example
2000120003 Model A5191
2001120019 Serial number AT2D... (masked)
2002320026 Firmware version 1.0.6.1
2002920032 Hardware version 1.0.0.0

The serial number is the same string the charger uses as its OCPP station id.

RFID

The charger exposes no RFID data over Modbus. The readable range was dumped register by register and contains no tag identifier; there is no second register bank either (probing 1900024000 in 50-step increments finds nothing outside 2000020100 and 2100021005).

RFID arrives over OCPP instead: the charger sends the card UID as the idTag in StartTransaction. In evcc it shows up as the session identifier (/api/sessions) and on the loadpoint as vehicleIdentity — a real card reads as a UID like 22848AB3, while a session started without a card gets the charger's own pseudo tag, J_ followed by the serial number.

🧩 Entities

Sensors — Phase mode · Charging status · Control pilot · Charging mode · Phase setting · OCPP status · Active phases · Charging power · Power L1/L2/L3 · Current L1/L2/L3 · Offered current · Voltage L1/L2/L3 · Voltage L1-L2/L2-L3/L3-L1 · Session energy · Session duration · Rated power

Binary sensors — Vehicle connected · Charging · Load balancing · Solar balancing · OCPP connected · Cloud (MQTT) connected

Controls (only when enabled) — Charging (switch) · Current limit (number) · Modbus watchdog (number) · Phase setting (select)

🔌 Using it from evcc instead of OCPP

examples/evcc/ contains a complete setup that lets evcc drive the charger through this integration rather than over OCPP — a Home Assistant package (MQTT bridge in both directions, plus the watchdog keepalive) and the matching evcc charger definition.

The point is phase control: the V1 has no OCPP-controlled phase switching and decides the count by an undocumented automatic. Over Modbus, register 21005 turns that into an input, so evcc decides and applies its own hysteresis. The trade-off is RFID — see the example's README.

🎛️ Dashboard cards

The device page's controls cannot be placed on a dashboard — Home Assistant has no device card. examples/lovelace/ rebuilds that group as a section for a sections view, or as a plain entities card.

📄 License

MIT — see LICENSE.