Rebuilt the guide as something usable on site rather than a document to read at a desk: strict order of operations, DO / VERIFY / IF NOT blocks per step, pass-fail gates in a table, a printable sign-off sheet, and troubleshooting keyed by symptom rather than by subsystem. Includes real screenshots of the add-on's own Web UI - captured by running it against stub data - showing the healthy state and the misconfigured one side by side, because telling those apart at a glance is the single most useful skill on site. Plus the ESPHome step from a live builder. The text lives only in docs/build_guide.py, which renders the HTML and drives headless Chrome to produce the PDF. One source: a Markdown copy would inevitably drift from the PDF someone is holding in a cellar. Pagination is enforced, not hoped for. Each section must render under the A4 printable height (1039 px at 96 dpi) or Chrome silently spills it onto a second page and the page numbers stop matching the step numbers. Measured every section rather than eyeballing it: the Web UI reference page was 1170 px and is now 1017 px, and the PDF comes out at exactly one page per section. Co-Authored-By: Claude Opus 5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_016NckgXecasQb2eSsPYNSW6
76 lines
3.1 KiB
Markdown
76 lines
3.1 KiB
Markdown
# GoodWe RS485 Controller — Home Assistant add-on repository
|
|
|
|
Replaces a GoodWe battery inverter's vendor controller with a local one: holds
|
|
net grid exchange at zero by emulating the inverter's smart meter over RS485,
|
|
and runs the monthly battery maintenance cycle the vendor box was doing.
|
|
|
|
```
|
|
repository.yaml add-on repository metadata
|
|
goodwe_controller/ the add-on
|
|
config.yaml manifest + options schema (the per-site config form)
|
|
app/ the controller
|
|
control.py the control law — pure functions, no I/O
|
|
maintenance.py the monthly cycle state machine
|
|
hass.py Supervisor/Core API access
|
|
store.py persistent state in /data
|
|
mqtt.py optional status entities
|
|
web.py ingress UI
|
|
main.py orchestration, heartbeat, failsafe behaviour
|
|
test_control.py runnable checks — no framework needed
|
|
test_maintenance.py runnable checks — walks a full cycle in fake time
|
|
DOCS.md the add-on's documentation tab
|
|
firmware/goodwe-master.yaml ESPHome config for the T-CAN485
|
|
estop/rs485_log.py optional RS485 e-stop / bus witness
|
|
docs/GoodWe-RS485-Field-Guide.pdf the guide techs carry (10pp, A4)
|
|
docs/build_guide.py its single source - rebuilds the HTML and PDF
|
|
FIELD-GUIDE.md how to edit and rebuild the guide
|
|
```
|
|
|
|
## Install
|
|
|
|
Settings → Add-ons → Add-on store → ⋮ → **Repositories** → add this repository's
|
|
URL, then install **GoodWe RS485 Controller**.
|
|
|
|
Requires **Home Assistant OS or Supervised**. Add-ons cannot be installed on HA
|
|
Container or Core.
|
|
|
|
## Read this first
|
|
|
|
**The inverter holds its last command forever.** It has no meter-timeout of its
|
|
own — a controller that dies mid-command leaves the battery running until a
|
|
human intervenes. Measured on real hardware: 5 kW of discharge held for 113
|
|
seconds after a controller went silent.
|
|
|
|
Three layers exist because of that, and only the third covers the Home Assistant
|
|
machine itself dying:
|
|
|
|
1. **ESP32 watchdog** — no fresh setpoint for ~30 s → command 0 W, and keep
|
|
commanding it.
|
|
2. **Wind-down before firmware updates** — 0 W written before the update starts.
|
|
3. **RS485 e-stop (optional)** — writes 0 W after 30 s of total bus silence.
|
|
|
|
Sites sold without the e-stop must have the acknowledgement in `FIELD-GUIDE.md`
|
|
§10 signed.
|
|
|
|
## Development
|
|
|
|
The control law and the maintenance machine are pure Python with no Home
|
|
Assistant imports, so they run anywhere:
|
|
|
|
```bash
|
|
cd goodwe_controller
|
|
python3 test_control.py
|
|
python3 test_maintenance.py
|
|
```
|
|
|
|
Both must pass before shipping any change. They are not unit-test theatre —
|
|
each assertion corresponds to a rule whose absence produced an observed failure
|
|
on real hardware, and the comments in `control.py` say which.
|
|
|
|
## Compatibility
|
|
|
|
- GoodWe **ES / BP family** inverters (AA55 / RS485 meter-bus generation)
|
|
- The protocol is **reverse-engineered**. There is no vendor contract, and a
|
|
firmware change on GoodWe's side could break every installation at once. Say
|
|
so when you sell it.
|