Skip to content

fix: Make the docs and the code say the same thing - #19

Merged
sdebasek merged 1 commit into
mainfrom
fix/review-docs-and-cleanup
Aug 21, 2026
Merged

sdebasek merged 1 commit into
mainfrom
fix/review-docs-and-cleanup

Conversation

@sdebasek

@sdebasek sdebasek commented Aug 21, 2026

Copy link
Copy Markdown
Owner

1. The config flow contradicted the integration

config.step.user still said relays, power and energy stay with the official BleBox integration. That stopped being true when this became a full replacement: it creates the relay switch and the power and energy sensors itself. It was the first and only text shown when adding a device by IP, it shipped in both languages, and it steered users into keeping the official entry running, which the README says produces two of every entity and two device rows.

Rewritten in all three language files, along with the discovery screen, which carried the same events-only framing and is the more common entry point.

Further drift found while checking: config.step.inputs.description said the input count could be changed later by re-adding the device. Re-adding hits _abort_if_unique_id_configured and aborts as already_configured; there is no reconfigure step. Corrected.

2. The backlight offered a brightness slider that did nothing

Reported from the field during this work: colour works, brightness does not.

ColorMode.RGB is Home Assistant's contract for "supports brightness", but async_turn_on read only rgb_color, so a brightness argument passed schema validation and was silently discarded, and the entity published brightness: None while on.

Confirmed against live hardware that the device stores no brightness field at all:

"buttonsBacklight": {"enabled": 1, "color": "ff890e"}

Implemented rather than withdrawn, because withdrawing was not available: every colour mode is in COLOR_MODES_BRIGHTNESS, so the only way to stop advertising brightness is ColorMode.ONOFF, which drops the colour control the device really does have.

Brightness lives where the hardware already keeps it, in the colour: 804000 is ff8000 at half power. brightness is the largest component, rgb_color is the stored colour normalised back to full, and turn_on folds them together, taking the missing half from what the device holds. Verified against the real stored value:

stored ff890e -> (255, 137, 14), brightness 255 (100%)
set brightness 128 -> writes 804507   (same hue, half power)
set brightness  64 -> writes 402204

Plain turn_on() with no arguments still writes only {"enabled": 1}, so it does not rewrite the colour on every call.

One inherent caveat: scaling is lossy in one direction, so a deliberately dark colour reads back as a brighter one at low brightness. The device cannot distinguish dim orange from dark brown. That is how every RGB-only light in Home Assistant behaves.

3. The device API register was incomplete

Missing four endpoints the code calls: /info, GET /api/device/network, POST /api/device/set and GET /api/ota/check. The full list was re-derived from blebox_actions.py rather than taken from the review; those four were the only gaps. POST /api/device/set matters most, an undocumented write that reconfigures the device's network and whose response the code trusts. The "both set endpoints answer with the resulting state" section named two of the three writes that do.

4. Setup guide inaccuracies

  • power_w was promised unconditionally, but the placeholder is only appended to URLs the integration provisions. A manually pasted URL has no query string and yields nothing.
  • The slot shortage message was described as reporting needed versus free. It reports neither. The doc now says so and points at where the numbers do appear.
  • Automatic mode restoring a callback deleted in the wBox app was undocumented. It is deliberate and would be baffling otherwise, so it is now written down with the two ways to stop it.
  • The troubleshooting slot-count figure was removed as unverifiable, then restored after checking the live device, which reports itemsLimit: 30. Every test fixture uses 6 for convenience, which is what made it look unsupported. Now qualified with the firmware it was measured on.

5. Four module docstrings described the pre-replacement architecture

__init__.py said the official integration keeps ownership of relay, power and energy while PLATFORMS below lists six platforms. sensor.py stated a design rule that two classes in the same file break. switch.py said "neither of these is exposed by the official integration" in a module with three kinds of switch. coordinator.py omitted the fast poll that is now its primary job.

This matters more here than in most projects: the commenting style is deliberately verbose about device quirks, so readers learn to trust the prose and have no way to spot the stale paragraphs. A grep sweep found three more drifting mentions, now fixed; the rest were verified still true and left.

6. Dead code and duplication

Deleted after confirming each unreachable: a firmware check nothing called (kept green by its own tests, which is exactly the false confidence the audit named), a trigger parameter no production caller ever set, an unused constraint accessor, a brute-forced inverse of an existing function, and two unread config-flow fields.

Kept deliberately, with the reason now written down: TRIGGER_ANY_EDGE and TRIGGER_PERIODIC are a decoding table for slots read back off a device, not a menu of what gets written. Someone reading a diagnostics dump needs to know triggerType: 19 is a timer and not a broken binding.

The relay placeholder constants were deleted, but what they recorded, that the device substitutes a constant rather than the relay state, is kept in prose. A constant nobody reads implies it is used; a sentence explaining why it is not cannot.

Per-relay construction appeared three times and the field walk four. Factoring those out caught a live hazard: one copy of the countdown predicate had drifted from the one capability_signature uses, so a device restarted while unreachable would have got the wrong countdown sensors. The capability checks in each async_setup_entry are deliberately left alone.

Testing

226 passing, coverage 98% to 99%, ruff clean, all three language files key-for-key in sync.

Behaviour changes (backlight brightness) have new tests. Everything else is either comment-only or a behaviour-preserving refactor where the existing tests are the evidence, and the report says plainly which is which.

Backlight brightness is verified against the real device's stored colour but not yet exercised on hardware end to end.

The config flow's first screen still told users that relays, power and
energy stay with the official BleBox integration. That stopped being
true when this became a full replacement: it creates those entities
itself. It was the only text shown when adding a device by IP, it
shipped in both languages, and it steered people into keeping the
official entry, which produces two of every entity and two device rows.
The discovery screen carried the same events-only framing, and so did
four module docstrings, one of which stated a design rule that its own
file breaks, so a contributor checking the UI text against the code
found it corroborated rather than contradicted.

The backlight offered a brightness slider that did nothing. Colour mode
RGB is Home Assistant's way of saying an entity supports brightness, but
turn_on read only the colour and discarded the rest. The device stores
no brightness field, only an rrggbb value, so brightness now lives where
the hardware already keeps it: in the colour itself, since 804000 is
ff8000 at half power. Withdrawing the claim instead was not available.
Every colour mode implies brightness, so the only way to stop
advertising it would have been to drop to on and off and lose the colour
control the device really does have.

The device API register was missing four endpoints, one of them an
undocumented write that reconfigures the device's network and whose
answer the code trusts. The setup guide promised an event attribute that
only provisioned URLs carry, described a slot shortage message as
reporting numbers it does not report, and never mentioned that automatic
mode puts back a callback deleted in the wBox app, which is deliberate
and would be baffling undocumented. The input count was documented as
changeable by re-adding the device, which aborts.

Dead code removed: a firmware check nothing called, kept green by its
own tests, a trigger parameter no caller ever set, an unused constraint
accessor and a brute-forced inverse of a function that already exists.
The protocol constants that decode what a device reports are kept, since
those are knowledge rather than dead weight, and the reason is now
written down. The relay placeholder constants are deleted, but what they
recorded, that the device substitutes a constant rather than the relay
state, is kept in prose where it cannot look accidental.

Per-relay entity construction and the relay field walk were written out
three and four times. One copy of the countdown predicate had already
drifted from the one the capability cache uses, which would have given a
device restarted while offline the wrong sensors.
@sdebasek
sdebasek merged commit 2c6775e into main Aug 21, 2026
6 checks passed
@sdebasek
sdebasek deleted the fix/review-docs-and-cleanup branch August 21, 2026 12:14
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant