- Details link: /config/app/<slug>/documentation on HA 2026.2+ (the old /hassio/addon path is a 404 from 2026.5), /hassio/addon on 2026.1 and older. Slug from GET /addons/self/info, version from GET /info, hostname as fallback. - Shadow mode: the over-rating alarm and row say what would have been sent, the peak alarm no longer says the battery is giving all it can. - "controller" -> "the add-on" / "control". Settings named by their labels; four labels changed to match (Peak reserve, Battery level entity, Solar production ..., Reversed-sign solar entities). - Shadow banner and inverter link notes moved to messages.py and checked. - DOCS Notifications and Status page rewritten for home owners, with a "For installers" part each. Allowlist 168 -> 167. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01LyR88rXETvwhTgx6yHE39p
56 lines
5.0 KiB
Markdown
56 lines
5.0 KiB
Markdown
# STYLE.md - how user-facing text is written (UX-08)
|
|
|
|
This applies to everything a home owner or installer reads: notifications, phone pushes, the add-on page, refusals, add-on log lines at WARNING and above, and the names and descriptions of options. It is enforced by `goodwe_controller/test_messages.py`. Kinds that have not been rewritten yet are on its allowlist, and that allowlist only shrinks.
|
|
|
|
## 1. Shape
|
|
- **Title**: at most 5 everyday words. It says what is wrong ("Meter reading may be stuck"). No "GoodWe:" prefix, no full stop.
|
|
- **Body**: **one sentence** of at most 25 words, saying what happened and what to do. A **red alarm** may use up to **3 sentences** (70 words, each sentence at most 30 words), so that no action a person must take is lost.
|
|
- **Details**: the last line links to the add-on documentation and names the section with the rest: `Details: add-on documentation, section "<title>" under Notifications.` Background, figures, reason codes and history go there or into the log, never into the body.
|
|
- **Status row**: one sentence of at most 15 words. A **red** row may use up to 3 sentences (30 words), like a red alarm. It shows the live numbers the reader acts on and never an HA entity id. **Banner**: at most 12 words. **Refusal**: at most 30 words, naming the setting by its label. **Option name**: at most 6 words, not counting the group prefix. **Option description**: at most 30 words. Where a value comes from belongs in DOCS.md.
|
|
- **Log line** (WARNING/ERROR): one line, at most 25 words. The reasoning goes on a DEBUG line. Log lines stay in English and are not translated.
|
|
- **Sentences**: one idea each, active voice, present tense, with nothing nested in brackets and no semicolons (a semicolon is a second sentence in disguise). These translate well into Dutch and French.
|
|
|
|
## 2. Numbers
|
|
Use a number only if it helps the reader act, for example the peak limit, or what was asked and what was sent in a fault report. Write it the way `app/messages.py` does: `5 000 W`, `20 %`, `10 minutes`, `14:05`.
|
|
|
|
## 3. Severity
|
|
Severity is shown by the title and the colour, never by CAPITALS or by words like "BUG SIGNAL".
|
|
|
|
| Level | Colour | When |
|
|
|---|---|---|
|
|
| alarm | red | Control stopped, money or energy lost now, a fault, or a person must act now. Up to 3 sentences. |
|
|
| warning | orange | Control is still running, but something needs a look. 1 sentence. |
|
|
| info | grey | No action needed. 1 sentence. |
|
|
| resolved | green | An earlier alarm or warning has cleared. 1 sentence. |
|
|
|
|
A rewrite never changes an alarm's severity, `notification_id` or cadence.
|
|
|
|
## 4. Words - the same word for the same thing everywhere
|
|
A setting is named by its label in `translations/en.yaml`, in quotes when it sits mid-sentence (“Inverter rating”). The words below match those labels. If a label changes, change it here and in `app/messages.py` in the same change.
|
|
|
|
| Say | Not |
|
|
|---|---|
|
|
| the add-on (who decides), control (what it does: "start control", "Control: last ran …") | controller, loop, planner |
|
|
| battery | pack, BMS pack |
|
|
| inverter, or its name | unit, device, actuator |
|
|
| meter | P1 feed, telegram |
|
|
| peak limit / this month's peak | ceiling, capaciteitstarief, billed quarter |
|
|
| 15-minute period | quarter |
|
|
| battery level (setting: “Battery level entity”) | SoC, state of charge, charge level |
|
|
| battery cut-out level, or cut-out level next to "battery" (setting: “Battery cut-out level”) | BMS floor, `bms_soc_floor` |
|
|
| peak reserve (setting: “Peak reserve”) | `peak_soc_floor`, EMS floor, "peak guard will not discharge below" |
|
|
| “Inverter rating” (the setting) | `max_w`, rail, inverter rating as a fact about the hardware |
|
|
| solar production, solar entity (settings: “Solar production entity”, “Solar production entities, per inverter”, “Reversed-sign solar entities”) | PV, reversed-sign list, single sensor setting |
|
|
| “Where the meter reading comes from” | meter source |
|
|
| “Grid power entity”; entity for any Home Assistant sensor a setting points at | grid power sensor, sensor setting |
|
|
| draw the battery down, give power | discharge, discharging |
|
|
| control is stopped / every inverter is set to 0 W | failsafe, trip, latch, parked |
|
|
| safety stop (a stop that only starting control clears) | failsafe latch |
|
|
| software fault | BUG SIGNAL |
|
|
| control board | master, ESP32 |
|
|
| shadow mode | a mode that makes every decision but commands 0 W. The name is kept. In shadow mode a text says what the add-on **would** send, never that it sent it. |
|
|
|
|
**Banned in titles and bodies** (the test fails on them): SAFETY-/TARIFF-/TEL-/CFG-/FW-/HW-nn and other card ids, integrator, anti-windup, windup, clamp, clamped, saturated, BUG SIGNAL, latch, latched, arbiter, allocator, register, `0x…`, layer 1/2/3, heartbeat, watchdog, telegram, ACK, CRC, OTA, Modbus, planner, `§n`, file names, IP addresses, option keys in snake_case, **HA entity ids**, and runs of 2 or more CAPITALISED words.
|
|
|
|
HA entity ids are allowed only in refusals and validator messages, where the installer has to find that entity. They are never allowed in alarms or status rows.
|