Cut verbosity across the firmware for less code, same behaviour #63

Merged
rob merged 17 commits from chore/cut-verbosity into main 2026-09-20 15:48:12 +00:00
Collaborator

A whole-codebase quality pass aimed only at less code for the same behaviour.
Wire format, hardware behaviour and the public shape the tests use are
unchanged; pio test -e native passes at every commit, and pio run for
both node envs and host_sim still build.

Structural changes, one per commit:

  • Collapse sim::Dimmer into LevelEndpoint: the ramp/lockout/command logic
    now lives once in level_endpoint.cpp, unguarded, with only the LEDC
    output and pin setup behind #if defined(ARDUINO). sim::Dimmer is now a
    thin ctrl::LevelEndpoint subclass. This forced a small follow-up fix to
    host_sim's circuit table, since sim::Dimmer and sim::Switch no longer
    share a base beyond ctrl::Endpoint.
  • Endpoint::onCommand defaults to return false; delete the read-only
    overrides it made redundant.
  • One ctrl::UpdateStack for the WiFi/update/boot object graph both nodes
    built by hand, one ctrl::printBusEvent, and the CTRL_BUILD_ID fallback
    centralised in firmware_version.h.
  • Switch-on-integer name tables replaced with bounds-checked array lookups.
  • WifiManager::onFrame's validate-then-dispatch switches merged into one.
  • A detail::frame helper for the codec encode boilerplate in
    lib/can-protocol/src/codecs.h (header-only, no behaviour change; the
    shared test vectors confirm the bytes are unchanged).
  • memmove for the two backends' pending TX queues; Node::notePeer walks
    the peer table once instead of three times.
  • Deleted dead accessors (Endpoint::failsafe(), TouchSensor::baseline(),
    TouchSensor::stdDev()) with no caller.

Then a comment sweep, keeping only bare spec pointers, genuine hardware/protocol
traps and non-obvious constant reasons; narration, rationale essays and
restatements of CLAUDE.md or the spec are gone.

lib/: 237 insertions, 431 deletions across 40 files. src/: 68 insertions,
370 deletions across 5 files.

Tested: pio test -e native (436 cases) and pio run for node_lighting,
node_bathroom and host_sim after every commit.

A whole-codebase quality pass aimed only at less code for the same behaviour. Wire format, hardware behaviour and the public shape the tests use are unchanged; `pio test -e native` passes at every commit, and `pio run` for both node envs and `host_sim` still build. Structural changes, one per commit: - Collapse `sim::Dimmer` into `LevelEndpoint`: the ramp/lockout/command logic now lives once in `level_endpoint.cpp`, unguarded, with only the LEDC output and pin setup behind `#if defined(ARDUINO)`. `sim::Dimmer` is now a thin `ctrl::LevelEndpoint` subclass. This forced a small follow-up fix to `host_sim`'s circuit table, since `sim::Dimmer` and `sim::Switch` no longer share a base beyond `ctrl::Endpoint`. - `Endpoint::onCommand` defaults to `return false`; delete the read-only overrides it made redundant. - One `ctrl::UpdateStack` for the WiFi/update/boot object graph both nodes built by hand, one `ctrl::printBusEvent`, and the `CTRL_BUILD_ID` fallback centralised in `firmware_version.h`. - Switch-on-integer name tables replaced with bounds-checked array lookups. - `WifiManager::onFrame`'s validate-then-dispatch switches merged into one. - A `detail::frame` helper for the codec encode boilerplate in `lib/can-protocol/src/codecs.h` (header-only, no behaviour change; the shared test vectors confirm the bytes are unchanged). - `memmove` for the two backends' pending TX queues; `Node::notePeer` walks the peer table once instead of three times. - Deleted dead accessors (`Endpoint::failsafe()`, `TouchSensor::baseline()`, `TouchSensor::stdDev()`) with no caller. Then a comment sweep, keeping only bare spec pointers, genuine hardware/protocol traps and non-obvious constant reasons; narration, rationale essays and restatements of CLAUDE.md or the spec are gone. `lib/`: 237 insertions, 431 deletions across 40 files. `src/`: 68 insertions, 370 deletions across 5 files. Tested: `pio test -e native` (436 cases) and `pio run` for `node_lighting`, `node_bathroom` and `host_sim` after every commit.
Claude left a comment

Reviewed against the task list and CLAUDE.md invariants. All 436 native tests pass, node_lighting, node_bathroom and host_sim all build. test/, vectors/, tools/vector_cases.h, docs/, README.md, CONTRIBUTING.md and CI are untouched. Traced the wire-affecting bits by hand (LevelEndpoint/Dimmer collapse, codecs.h detail::frame, the name-table array lookups against their enum declaration orders, the memmove queue shifts, notePeer's single-pass rework, host_sim's Circuit function-pointer table) and none change behaviour. No ponytail: comments, no scope creep, commit messages are subject-only with British spelling.

One minor finding, not a correctness bug:

Centralising the two nodes' onBusEvent into ctrl::printBusEvent dropped a genuine hardware-trap comment that was specific to node_lighting: "A bus-off here means nothing this node sent reached the wire, so suspect the run from twaiTxPin to the transceiver, or the transceiver itself." That's exactly the kind of one-line hardware-trap comment the sweep says to keep, and it doesn't survive anywhere else (checked can_bus_twai.h/.cpp and the new node.h/update_stack.h). The equivalent MCP2515 fact ("this backend reports no bus-off yet") did survive, in can_bus.h and can_bus_mcp2515.cpp, so only the TWAI side lost its diagnostic note. Worth a one-liner back near twaiTxPin/busConfig in src/node_lighting/main.cpp, since ctrl::printBusEvent is necessarily generic and can't carry it.

Reviewed against the task list and CLAUDE.md invariants. All 436 native tests pass, `node_lighting`, `node_bathroom` and `host_sim` all build. `test/`, `vectors/`, `tools/vector_cases.h`, `docs/`, `README.md`, `CONTRIBUTING.md` and CI are untouched. Traced the wire-affecting bits by hand (LevelEndpoint/Dimmer collapse, codecs.h `detail::frame`, the name-table array lookups against their enum declaration orders, the `memmove` queue shifts, `notePeer`'s single-pass rework, `host_sim`'s `Circuit` function-pointer table) and none change behaviour. No `ponytail:` comments, no scope creep, commit messages are subject-only with British spelling. One minor finding, not a correctness bug: Centralising the two nodes' `onBusEvent` into `ctrl::printBusEvent` dropped a genuine hardware-trap comment that was specific to `node_lighting`: "A bus-off here means nothing this node sent reached the wire, so suspect the run from twaiTxPin to the transceiver, or the transceiver itself." That's exactly the kind of one-line hardware-trap comment the sweep says to keep, and it doesn't survive anywhere else (checked `can_bus_twai.h/.cpp` and the new `node.h`/`update_stack.h`). The equivalent MCP2515 fact ("this backend reports no bus-off yet") did survive, in `can_bus.h` and `can_bus_mcp2515.cpp`, so only the TWAI side lost its diagnostic note. Worth a one-liner back near `twaiTxPin`/`busConfig` in `src/node_lighting/main.cpp`, since `ctrl::printBusEvent` is necessarily generic and can't carry it.
@ -40,3 +19,4 @@
// (WCMCU-230): no SPI bus and no MCP2515 here.
constexpr uint8_t twaiTxPin = 25;
constexpr uint8_t twaiRxPin = 26;
constexpr ctrl::CanBusConfig busConfig = {0, twaiTxPin, twaiRxPin};
Author
Collaborator

The old onBusEvent here carried a TWAI-specific diagnostic hint on bus-off ("suspect the run from twaiTxPin to the transceiver, or the transceiver itself") that's now gone along with the function, since ctrl::printBusEvent is shared and generic. That was a genuine hardware-trap comment (category b of the sweep), not narration, and it isn't preserved anywhere else. Worth putting back as a one-liner near busConfig/twaiTxPin.

The old `onBusEvent` here carried a TWAI-specific diagnostic hint on bus-off ("suspect the run from twaiTxPin to the transceiver, or the transceiver itself") that's now gone along with the function, since `ctrl::printBusEvent` is shared and generic. That was a genuine hardware-trap comment (category b of the sweep), not narration, and it isn't preserved anywhere else. Worth putting back as a one-liner near `busConfig`/`twaiTxPin`.
Restore the TWAI bus-off diagnostic note lost in the printer merge
All checks were successful
Build and test / build (pull_request) Successful in 51s
Build and test / release (pull_request) Has been skipped
70c25b6cb9
Claude left a comment

Re-reviewed at 70c25b6. The restored bus-off note in src/node_lighting/main.cpp checks out — correct content, sits next to twaiTxPin/busConfig as described. No other regressions found against the rest of the diff. pio test -e native (436 cases), pio run -e node_lighting -e node_bathroom, and pio run -e host_sim all pass. Clean to merge.

Re-reviewed at 70c25b6. The restored bus-off note in src/node_lighting/main.cpp checks out — correct content, sits next to twaiTxPin/busConfig as described. No other regressions found against the rest of the diff. pio test -e native (436 cases), pio run -e node_lighting -e node_bathroom, and pio run -e host_sim all pass. Clean to merge.
rob requested changes 2026-09-20 14:27:27 +00:00
Dismissed
@ -38,2 +22,2 @@
return "?";
}
static const char* const names[] = {"off", "connecting", "connected", "ap-active", "updating", "failed", "update-failed"};
return state < (sizeof(names) / sizeof(names[0])) ? names[state] : "?";
Owner

I'm seeing that pattern quite a lot over a few files. Could it be abstracted?

I'm seeing that pattern quite a lot over a few files. Could it be abstracted?
Extract a nameOf helper for the repeated name-table lookup
All checks were successful
Build and test / build (pull_request) Successful in 55s
Build and test / release (pull_request) Has been skipped
6a4a578032
Also replace remaining sizeof(x)/sizeof(x[0]) with std::size.
Author
Collaborator

Good catch — abstracted into one template <size_t N> const char* nameOf(const char* const (&names)[N], size_t i) in lib/node-runtime/src/update_log.h, used by wifiStateName/wifiActionName, busEventName (node.h), twaiStateName (can_bus_twai.cpp) and className (host_sim/main.cpp). Also swept the remaining sizeof(x)/sizeof(x[0]) in lib/ and src/ to std::size. Pushed at 6a4a578; tests and both node envs plus host_sim all still pass.

Good catch — abstracted into one `template <size_t N> const char* nameOf(const char* const (&names)[N], size_t i)` in `lib/node-runtime/src/update_log.h`, used by `wifiStateName`/`wifiActionName`, `busEventName` (node.h), `twaiStateName` (can_bus_twai.cpp) and `className` (host_sim/main.cpp). Also swept the remaining `sizeof(x)/sizeof(x[0])` in lib/ and src/ to `std::size`. Pushed at 6a4a578; tests and both node envs plus host_sim all still pass.
Claude requested review from rob 2026-09-20 14:31:57 +00:00
rob requested changes 2026-09-20 15:39:29 +00:00
Dismissed
@ -18,14 +19,20 @@
namespace ctrl {
// A name table indexed by an enum or a small integer; out of range reads "?".
Owner

Remove the comment

Remove the comment
@ -20,1 +21,4 @@
// A name table indexed by an enum or a small integer; out of range reads "?".
template <size_t N>
inline const char* nameOf(const char* const (&names)[N], size_t i) {
Owner

Pull this out in to its own file. We shouldn't be pulling in this file just for this method. Also, not a fan of single letter parameters

Pull this out in to its own file. We shouldn't be pulling in this file just for this method. Also, not a fan of single letter parameters
Move nameOf into its own header and rename its index parameter
All checks were successful
Build and test / build (pull_request) Successful in 55s
Build and test / release (pull_request) Has been skipped
c8d12d8108
Author
Collaborator

Re "Remove the comment" (#4045): done.

Re "Pull this out in to its own file... not a fan of single letter parameters" (#4046): moved nameOf into lib/node-runtime/src/name_table.h (just <stddef.h> and the template); update_log.h includes it for wifiStateName/wifiActionName, and node.h, can_bus_twai.cpp and host_sim/main.cpp now include name_table.h directly instead of update_log.h. Renamed the parameter to index. Pushed at c8d12d8.

Re "Remove the comment" (#4045): done. Re "Pull this out in to its own file... not a fan of single letter parameters" (#4046): moved `nameOf` into `lib/node-runtime/src/name_table.h` (just `<stddef.h>` and the template); `update_log.h` includes it for `wifiStateName`/`wifiActionName`, and `node.h`, `can_bus_twai.cpp` and `host_sim/main.cpp` now include `name_table.h` directly instead of `update_log.h`. Renamed the parameter to `index`. Pushed at c8d12d8.
Claude requested review from rob 2026-09-20 15:41:43 +00:00
rob approved these changes 2026-09-20 15:44:11 +00:00
rob merged commit 544f089426 into main 2026-09-20 15:48:12 +00:00
rob deleted branch chore/cut-verbosity 2026-09-20 15:48:12 +00:00
Sign in to join this conversation.
No reviewers
rob
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/CampervanControlSystems!63
No description provided.