fix(subdevices): fall back to per-href probing when a prefixed subdevice has no /device/0 Collection
Issue #205 shows the UUID-prefixed pattern's own reference device (TP2X_FAC_BORA_21K) doesn't always answer /<uuid>/device/0, contrary to what the pattern was built against. When that Collection GET comes back empty, enumerate_subdevices now probes every href the master itself answered this cycle individually under the UUID prefix, keeping whichever ones respond. Subdevice gains a flat_hrefs field for this, and the coordinator re-polls those hrefs individually each cycle instead of re-fetching a Collection batch that doesn't exist. Built a fixture from the reporter's real #205 diagnostics dump: the fallback finds a candidate through the one href already confirmed live under this UUID (/information/vs/0, from the #177 thread), and discover_partitioned's liveness gate correctly holds it back since that href alone binds no entity -- honest current state, not a guessed resolution.
This commit is contained in:
@@ -218,10 +218,14 @@ This is a rule about **writes and entities**, not about reading. A speculative
|
||||
`GET` of an href a dump doesn't contain is fine and the codebase already relies
|
||||
on it: `read_identity` reads `/oic/p`, `/oic/d` and `/oic/res`, and
|
||||
`subdevices.enumerate_subdevices` probes `/device/<n>`, `/<uuid>/device/0` and
|
||||
`/multidevice/vs/0` on every device. A RETRIEVE is non-mutating and a 4.04 is
|
||||
tolerated everywhere in that path, so the cost of a wrong guess is one wasted
|
||||
round trip. Guessing a *write* against live hardware is the thing this rule
|
||||
forbids — as is materializing an entity from a field you can't explain.
|
||||
`/multidevice/vs/0` on every device — and, when a prefixed candidate's own
|
||||
`/<uuid>/device/0` doesn't answer (issue #205: not guaranteed even on the
|
||||
board this pattern was built against), every href the master itself
|
||||
answered this cycle, individually under that UUID's prefix (see §11). A
|
||||
RETRIEVE is non-mutating and a 4.04 is tolerated everywhere in that path, so
|
||||
the cost of a wrong guess is one wasted round trip. Guessing a *write*
|
||||
against live hardware is the thing this rule forbids — as is materializing
|
||||
an entity from a field you can't explain.
|
||||
|
||||
## 6. Select options: read them from the device, don't hardcode
|
||||
|
||||
@@ -372,22 +376,38 @@ the dump in this order; each step rules out a different cause.
|
||||
|
||||
1. **`subdevice_probes`** — did we even look? Every seed attempted appears
|
||||
here with what it returned. An absent seed means enumeration never tried
|
||||
that path; a `false` means it tried and got nothing.
|
||||
2. **`subdevices_skipped`** — did we find it and reject it? A candidate lands
|
||||
here when its seed answered but it produced no *primary* (non-diagnostic)
|
||||
entity with a populated value. Its `resources` block holds the exact reps
|
||||
the gate judged, so you can check the call yourself. If every
|
||||
power/mode/temperature rep is `{}`, the subdevice is an unused slot and the
|
||||
skip is correct. If they're populated, the gate is wrong — that's a bug
|
||||
worth a fixture.
|
||||
3. **`multidevice.numofsubdevice`** — the board's own count, where it
|
||||
reports one. Disagreement with `len(subdevices) + 1` is a strong hint,
|
||||
not proof; only one board family is known to expose it.
|
||||
4. **Which pattern is this board?** `identity.resources['/oic/res']` listing
|
||||
that path; a `false` means it tried and got nothing. On a UUID-prefixed
|
||||
board whose `/<uuid>/device/0` reads `false` (issue #205 — this isn't
|
||||
rare, not even on the board the pattern was built against), the report
|
||||
also carries one probe per href the master itself answered that cycle,
|
||||
individually under that prefix (`subdevices.enumerate_subdevices`'s flat
|
||||
fallback) — a `true` there is real, confirmed-live evidence for that one
|
||||
href, not a guess.
|
||||
2. **`subdevices`**/**`flat_hrefs`** — for a *materialized* subdevice found
|
||||
this way, `flat_hrefs` lists exactly which hrefs it's actually being
|
||||
polled on (individually, no Collection endpoint to batch through) —
|
||||
compare against the master's own hrefs to see what's still unconfirmed
|
||||
for that sibling.
|
||||
3. **`subdevices_skipped`** — did we find it and reject it? A candidate lands
|
||||
here when its seed(s) answered but it produced no *primary*
|
||||
(non-diagnostic) entity with a populated value. Its `resources` block
|
||||
holds the exact reps the gate judged, so you can check the call
|
||||
yourself. If every power/mode/temperature rep is `{}`, the subdevice is
|
||||
an unused slot and the skip is correct. If they're populated, the gate
|
||||
is wrong — that's a bug worth a fixture. A flat-fallback candidate whose
|
||||
only confirmed href is `/information/vs/0` (never bound to any entity —
|
||||
only ever read for device-type resolution) will *always* land here until
|
||||
more of its hrefs are confirmed live; that's the gate working as
|
||||
intended, not a bug to chase.
|
||||
4. **`multidevice.numofsubdevice`** — the board's own count, where it
|
||||
reports one. Disagreement with `len(subdevices) + len(subdevices_skipped)`
|
||||
is a strong hint, not proof; only one board family is known to expose it.
|
||||
5. **Which pattern is this board?** `identity.resources['/oic/res']` listing
|
||||
`/device/1`, `/device/2` means indexed siblings. `resources['/subdevices/
|
||||
vs/0']` carrying a `subdeviceIdList` means a UUID-prefixed tree, and that
|
||||
same UUID usually shows up as an href prefix in `/oic/res` too. Neither
|
||||
present, on a device the owner insists has two subdevices, is the
|
||||
same UUID usually shows up as an href prefix in `/oic/res` too — enumerate
|
||||
whether or not `/<uuid>/device/0` itself answers, per §5's fallback.
|
||||
Neither present, on a device the owner insists has two subdevices, is the
|
||||
interesting case — that's a third mechanism and needs a new dump, not a
|
||||
code guess.
|
||||
|
||||
|
||||
Reference in New Issue
Block a user