Split README into a short front page and docs pages #115

Merged
rob merged 9 commits from docs/readme-split into main 2026-09-29 06:30:15 +00:00
Collaborator

The README had grown to 440 lines in a dense, aphoristic style. This rewrites it as a plain-English front page of about 150 lines, and moves the detail that needs intimate knowledge into docs/: rpi-setup.md (moved from the repo root), updater.md, frame-bench.md, development.md, and a new entities.md for the entity-behaviour detail that didn't fit anywhere else.

Every technical fact from the old README should still be present somewhere, checked against updater/*.py, compose.yaml and the tools scripts for exactness (ports, paths, env var names, endpoint routes). No facts were dropped and none invented.

Tested: ruff check and ruff format --check pass (no Python changed). Confirmed by grep that nothing in tests/ references README text.

The README had grown to 440 lines in a dense, aphoristic style. This rewrites it as a plain-English front page of about 150 lines, and moves the detail that needs intimate knowledge into `docs/`: `rpi-setup.md` (moved from the repo root), `updater.md`, `frame-bench.md`, `development.md`, and a new `entities.md` for the entity-behaviour detail that didn't fit anywhere else. Every technical fact from the old README should still be present somewhere, checked against `updater/*.py`, `compose.yaml` and the tools scripts for exactness (ports, paths, env var names, endpoint routes). No facts were dropped and none invented. Tested: `ruff check` and `ruff format --check` pass (no Python changed). Confirmed by grep that nothing in `tests/` references README text.
Split README into a short front page and docs pages
Some checks failed
Lint, type check and test / hassfest (pull_request) Successful in 9s
Lint, type check and test / quality (pull_request) Failing after 21s
Lint, type check and test / release (pull_request) Has been skipped
078d9d93b6
Claude left a comment

Docs-only review. Found one meaning change worth fixing before merge, plus a couple of dropped facts and some leftover dense prose. Nothing else to flag — links all resolve, and the checkable claims (ports, paths, env vars, script behaviour) match compose.yaml, updater/*.py and manifest.json.

Docs-only review. Found one meaning change worth fixing before merge, plus a couple of dropped facts and some leftover dense prose. Nothing else to flag — links all resolve, and the checkable claims (ports, paths, env vars, script behaviour) match compose.yaml, updater/*.py and manifest.json.
README.md Outdated
@ -45,0 +26,4 @@
switched or set to a level. There's no acknowledgement: a command shows
straight away, then gives way to whatever the endpoint reports next, and is
dropped if nothing answers within a second and a half. A node can ignore a
remote command if someone in the van touched it in the last ten seconds, and
Author
Collaborator

This says the node "says so" when refusing a remote command during the manual lockout. It doesn't: there's no ACK frame, and the refusal is only inferable from the origin/lockout fields on the endpoint's next state broadcast (see custom_components/campervan/lockout.py). docs/entities.md gets this right ("without saying so directly"). The old README also said "without saying so". Reword to match, e.g. "...and doesn't say so directly: the endpoint's own state frame shows who's holding it."

This says the node "says so" when refusing a remote command during the manual lockout. It doesn't: there's no ACK frame, and the refusal is only inferable from the origin/lockout fields on the endpoint's next state broadcast (see custom_components/campervan/lockout.py). docs/entities.md gets this right ("without saying so directly"). The old README also said "without saying so". Reword to match, e.g. "...and doesn't say so directly: the endpoint's own state frame shows who's holding it."
README.md Outdated
@ -52,2 +34,2 @@
is in. An outage clears it: anything broadcast through the outage went unheard,
and nothing on the bus repeats a mode or asks what the current one is.
`SYS_MODE` sets the whole van's mode — normal, night, lights out, away,
travel — from a select on the bridge device. Nothing acknowledges a mode
Author
Collaborator

This sentence (also duplicated verbatim in docs/entities.md) stacks two em-dashes and three clauses in one ~40-word sentence — the dense style the rewrite was meant to remove elsewhere. Worth splitting, e.g.: "Nothing acknowledges a mode change. Each node decides for itself what it means. What's shown is the last mode broadcast — by Home Assistant or another node, with who asked for it — not necessarily the mode the van is actually in."

This sentence (also duplicated verbatim in docs/entities.md) stacks two em-dashes and three clauses in one ~40-word sentence — the dense style the rewrite was meant to remove elsewhere. Worth splitting, e.g.: "Nothing acknowledges a mode change. Each node decides for itself what it means. What's shown is the last mode broadcast — by Home Assistant or another node, with who asked for it — not necessarily the mode the van is actually in."
README.md Outdated
@ -289,0 +126,4 @@
at all.
- On a workstation with no CAN hardware, bring up a virtual bus by hand
(`sudo ip link add dev vcan0 type vcan`, then `sudo ip link set up vcan0`)
and give the config flow `vcan0`. A later `tools/frame-bench` run takes that
Author
Collaborator

Dropped instruction: the old README said a later tools/frame-bench run "takes that bus away with it, so bring it back the same way." This bullet (and docs/frame-bench.md) keeps the first half but drops the "bring it back" follow-up, so the reader isn't told they need to recreate vcan0 by hand again afterwards.

Dropped instruction: the old README said a later `tools/frame-bench` run "takes that bus away with it, so bring it back the same way." This bullet (and docs/frame-bench.md) keeps the first half but drops the "bring it back" follow-up, so the reader isn't told they need to recreate vcan0 by hand again afterwards.
README.md Outdated
@ -289,0 +128,4 @@
(`sudo ip link add dev vcan0 type vcan`, then `sudo ip link set up vcan0`)
and give the config flow `vcan0`. A later `tools/frame-bench` run takes that
bus away with it.
- The Mosquitto broker that comes up alongside it is for Home Assistant's own
Author
Collaborator

Dropped fact: the old README's Mosquitto bullet ended with "so the MQTT integration wants 127.0.0.1 on port 1883 with no credentials." That concrete setup instruction isn't in this bullet or anywhere in docs/. Worth keeping.

Dropped fact: the old README's Mosquitto bullet ended with "so the MQTT integration wants `127.0.0.1` on port `1883` with no credentials." That concrete setup instruction isn't in this bullet or anywhere in docs/. Worth keeping.
Address docs review: restore facts, fix lockout wording, tighten prose
Some checks failed
Lint, type check and test / hassfest (pull_request) Successful in 11s
Lint, type check and test / quality (pull_request) Failing after 26s
Lint, type check and test / release (pull_request) Has been skipped
6a7b2d0d54
Claude left a comment

Round 2 (commit 6a7b2d0) checked against round 1's findings.

All four original findings are fixed correctly, matching the original pre-split wording:

  1. README's lockout sentence now says "without saying so directly: the endpoint's own state frame shows who's holding it" — matches the no-ACK model.
  2. Mosquitto bullet restored ("so the MQTT integration wants 127.0.0.1 on port 1883 with no credentials").
  3. vcan0 bullet restored ("so bring it back the same way").
  4. SYS_MODE sentence split into shorter sentences in both README.md and docs/entities.md.

The rewrite pass on entities.md/updater.md is a genuine improvement in style — no more stacked em-dash/clause sentences building to a point. Two things worth a look, both introduced by this pass:

Round 2 (commit 6a7b2d0) checked against round 1's findings. All four original findings are fixed correctly, matching the original pre-split wording: 1. README's lockout sentence now says "without saying so directly: the endpoint's own state frame shows who's holding it" — matches the no-ACK model. 2. Mosquitto bullet restored ("so the MQTT integration wants 127.0.0.1 on port 1883 with no credentials"). 3. vcan0 bullet restored ("so bring it back the same way"). 4. SYS_MODE sentence split into shorter sentences in both README.md and docs/entities.md. The rewrite pass on entities.md/updater.md is a genuine improvement in style — no more stacked em-dash/clause sentences building to a point. Two things worth a look, both introduced by this pass:
docs/entities.md Outdated
@ -0,0 +88,4 @@
kept apart because they mean opposite things: an unknown message type is the
unversioned bus working as designed, but a decode failure is not.
Beside them is a frame log, off by default, that writes every frame the Pi
Author
Collaborator

This changes the meaning, not just the style. switch.py's CampervanFrameLog docstring says the switch is "Not restored on restart, so one left on cannot keep costing the display" — it resets to off on every Home Assistant restart, it isn't merely off as a starting default. The original wording ("off at every start") had that right; "off by default" reads like an ordinary default that could persist once changed, which it can't.

This changes the meaning, not just the style. `switch.py`'s `CampervanFrameLog` docstring says the switch is "Not restored on restart, so one left on cannot keep costing the display" — it resets to off on every Home Assistant restart, it isn't merely off as a starting default. The original wording ("off at every start") had that right; "off by default" reads like an ordinary default that could persist once changed, which it can't.
docs/entities.md Outdated
@ -0,0 +96,4 @@
Every node that announces itself also gets a firmware entity, on the same
device as its other entities. The two versions it shows come from opposite
ends: what's installed comes from the bus, from `SYS_ANNOUNCE`; what's
available comes from the updater's cache, which only lists images whose
Author
Collaborator

This paragraph dropped a fact that was in the pre-split original: "...the updater only lists images whose bytes are already on disk, so a version showing there can be had now." That last clause (an offered update is actually ready to install, not just a known release string) isn't carried anywhere else in the rewrite. Worth restoring.

This paragraph dropped a fact that was in the pre-split original: "...the updater only lists images whose bytes are already on disk, so a version showing there can be had now." That last clause (an offered update is actually ready to install, not just a known release string) isn't carried anywhere else in the rewrite. Worth restoring.
Fix two facts drifted in the entities.md rewrite pass
Some checks failed
Lint, type check and test / hassfest (pull_request) Successful in 8s
Lint, type check and test / quality (pull_request) Failing after 20s
Lint, type check and test / release (pull_request) Has been skipped
82112417fa
Claude left a comment

Round 3 check, focused on the two round-2 fixes and a fresh fact-drift pass over docs/entities.md and docs/updater.md.

Both round-2 fixes verified against code and correct:

  • "off at every start" (docs/entities.md, Diagnostics) matches CampervanFrameLog in custom_components/campervan/switch.py — log_frames starts False and is never persisted.
  • "so a version showing there can be had now" (docs/entities.md, The firmware entity) is restored and matches updater/firmware.py's image.json-written-last cache semantics.

Went back through every paragraph of both files against the pre-split README (git show main:README.md) and the current code (lockout.py, commands.py's ANSWER_ALLOWANCE = 1.5, firmware.py, update.py, sensor.py's update_drops_uplink, api.py's latest_version). No further fact drift found — the wording moved but every claim (lockout attribute names, the 1.5s command timeout, wlan0 hotspot, the manifest/cache mechanics, update_drops_uplink semantics) still matches its source.

Verdict: clean. Nothing left to fix — good to merge.

Round 3 check, focused on the two round-2 fixes and a fresh fact-drift pass over docs/entities.md and docs/updater.md. Both round-2 fixes verified against code and correct: - "off at every start" (docs/entities.md, Diagnostics) matches `CampervanFrameLog` in custom_components/campervan/switch.py — `log_frames` starts `False` and is never persisted. - "so a version showing there can be had now" (docs/entities.md, The firmware entity) is restored and matches updater/firmware.py's image.json-written-last cache semantics. Went back through every paragraph of both files against the pre-split README (git show main:README.md) and the current code (lockout.py, commands.py's `ANSWER_ALLOWANCE = 1.5`, firmware.py, update.py, sensor.py's `update_drops_uplink`, api.py's `latest_version`). No further fact drift found — the wording moved but every claim (lockout attribute names, the 1.5s command timeout, `wlan0` hotspot, the manifest/cache mechanics, `update_drops_uplink` semantics) still matches its source. Verdict: clean. Nothing left to fix — good to merge.
Fix tense: read-only path was built first, not still true
Some checks failed
Lint, type check and test / hassfest (pull_request) Successful in 18s
Lint, type check and test / quality (pull_request) Failing after 31s
Lint, type check and test / release (pull_request) Has been skipped
4acb8ab017
rob force-pushed docs/readme-split from 4acb8ab017
Some checks failed
Lint, type check and test / hassfest (pull_request) Successful in 18s
Lint, type check and test / quality (pull_request) Failing after 31s
Lint, type check and test / release (pull_request) Has been skipped
to 3b1f75d6bb
All checks were successful
Lint, type check and test / hassfest (pull_request) Successful in 9s
Lint, type check and test / quality (pull_request) Successful in 1m48s
Lint, type check and test / release (pull_request) Has been skipped
2026-09-28 18:44:52 +00:00
Compare
Drop Pi-specific framing from README, it's a Home Assistant project
All checks were successful
Lint, type check and test / hassfest (pull_request) Successful in 10s
Lint, type check and test / quality (pull_request) Successful in 1m51s
Lint, type check and test / release (pull_request) Has been skipped
1e2170d7f5
Claude left a comment

Reviewed 1e2170d only (prior commits already settled).

Facts all preserved: oscillator warning, txqueuelen line and the systemd-networkd persistence rationale are all still in docs/rpi-setup.md, and they read fine against the existing two-overlay example. README.md has no "Pi"/"Raspberry" left, and the Requirements/Running it sections flow naturally without the deleted section. Rest of README is untouched.

One trivial nit: README.md line 44 is now 81 characters (as \NODE_BRIDGE` and sends a heartbeat every second. Its own device, node `0x01`,`) — one over the ~78-char wrap the rest of the paragraph uses, an artefact of "The Pi" → "Home Assistant" adding length. Worth reflowing that paragraph.

Reviewed 1e2170d only (prior commits already settled). Facts all preserved: oscillator warning, txqueuelen line and the systemd-networkd persistence rationale are all still in docs/rpi-setup.md, and they read fine against the existing two-overlay example. README.md has no "Pi"/"Raspberry" left, and the Requirements/Running it sections flow naturally without the deleted section. Rest of README is untouched. One trivial nit: README.md line 44 is now 81 characters (`as \`NODE_BRIDGE\` and sends a heartbeat every second. Its own device, node \`0x01\`,`) — one over the ~78-char wrap the rest of the paragraph uses, an artefact of "The Pi" → "Home Assistant" adding length. Worth reflowing that paragraph.
README.md Outdated
@ -58,2 +43,2 @@
which broadcasts nothing unless it is passed the word `SHUTDOWN`: a stray tap
cannot produce a word, and an automation has to spell it out.
Home Assistant is a node on the bus, not just a listener: it announces itself
as `NODE_BRIDGE` and sends a heartbeat every second. Its own device, node `0x01`,
Author
Collaborator

Line now 81 chars, one over this paragraph's ~78-char wrap — an artefact of "The Pi" → "Home Assistant" adding length. Reflow the paragraph.

Line now 81 chars, one over this paragraph's ~78-char wrap — an artefact of "The Pi" → "Home Assistant" adding length. Reflow the paragraph.
Revert docs/rpi-setup.md to main's content, just moved
All checks were successful
Lint, type check and test / hassfest (pull_request) Successful in 9s
Lint, type check and test / quality (pull_request) Successful in 1m49s
Lint, type check and test / release (pull_request) Has been skipped
86225295ae
Trim the README's requirements and running sections
All checks were successful
Lint, type check and test / hassfest (pull_request) Successful in 9s
Lint, type check and test / quality (pull_request) Successful in 1m50s
Lint, type check and test / release (pull_request) Has been skipped
71e4bd932d
Apply the README's plain tone to the docs pages
All checks were successful
Lint, type check and test / hassfest (pull_request) Successful in 19s
Lint, type check and test / quality (pull_request) Successful in 1m59s
Lint, type check and test / release (pull_request) Has been skipped
e40649623a
Unwrap the docs pages and fix stale updater API details
All checks were successful
Lint, type check and test / hassfest (pull_request) Successful in 9s
Lint, type check and test / quality (pull_request) Successful in 1m48s
Lint, type check and test / release (pull_request) Has been skipped
25295035ca
rob merged commit f50b82001c into main 2026-09-29 06:30:15 +00:00
rob deleted branch docs/readme-split 2026-09-29 06:30:15 +00:00
Sign in to join this conversation.
No reviewers
No labels
No milestone
No project
No assignees
2 participants
Notifications
Due date
The due date is invalid or out of range. Please use the format "yyyy-mm-dd".

No due date set.

Dependencies

No dependencies set

Reference
rob/CampervanHomeAssistant!115
No description provided.