The 0x8081 PerKeyLighting v2 protocol has no GetIndividualRgbZones
function — there's no way to ask the device what colors are currently
on the per-key buffer over HID++. PerKeyLighting.read() papered over
this gap by fabricating an all-"No change" sentinel map whenever the
caller asked for a live (uncached) read, which produced misleading
solaar show output like:
Per-key Lighting (saved): {1:0xc01c28, 2:0xc52d26, ...}
Per-key Lighting : {1:No change, 2:No change, ...}
— even with the keyboard clearly running the saved colors.
Two-part fix:
1. PerKeyLighting.read() now returns self._value if populated (from
prior write or persister) regardless of `cached`. Only fabricates
the all-"No change" map when there's truly no state — fresh device,
no prior write, nothing persisted. This is the right starting state
in that case because per-key writes are additive over a buffer of
unknown content.
Other callers benefit too: solaar config calls read(cached=False) on
per-key settings to display current values, and prior to this
change it would get fabricated sentinels back instead of the
in-memory map.
2. Add a `live_readable = True` class attribute to Setting (default
preserves existing behavior). Override to False on PerKeyLighting.
solaar show gates its live-read print on this flag, so non-readable
settings show only the (saved) line — which is the authoritative
record of what was last written to a setting whose live state can't
be read back.
After both fixes solaar show prints just:
Per-key Lighting (saved): {1:0xc01c28, 2:0xc52d26, ...}
— honest about what we know.
690 tests pass; pre-commit clean.