`_raw_read_blocking` decoded the CBOR body and kept it only when it was a
Property map, so a Collection -- which answers the `[devcol rep, {href,
rep}, ...]` batch `parse_device0_batch` reads -- came back as `2.05` with
`rep: {}`. That renders as "the resource exists and has nothing in it",
which is the opposite of what a populated batch means, and `/device/0`
itself would have read the same way.
It cost a real result: issue #335's board answers `/sec/devices` (the
`x.com.samsung.devcol` sibling of `/device/0`, and the one remaining place
a composite appliance could be enumerating its indoor units) with exactly
that empty-looking 2.05, and it was nearly written off as a dead end.
The read path now returns the decoded body alongside `rep`, and the service
response carries it as `body` whenever it isn't the map `rep` already has --
omitted for the ordinary case rather than duplicating every rep in every
response. Records the probe round this came out of: indexed leaves 4.04 on
that board, and the UUID prefix confirmed routable by a positive control, so
Patterns A/B/C are ruled out there on evidence rather than on absence.
185 lines
8.9 KiB
Markdown
185 lines
8.9 KiB
Markdown
# Composite AC subdevices: where else a sibling's hrefs could live
|
|
|
|
Open question behind issue #335 (`ARTIK051_FAC_BORA_19K`, a 2-in-1 floor +
|
|
wall AC): the board reports a sibling in `/subdevices/vs/0`'s
|
|
`subdeviceIdList`, but every seed `registry/subdevices.enumerate_subdevices`
|
|
tries comes back 4.04, so `subdevices` and `subdevices_skipped` are both
|
|
empty and the wall unit never becomes an entity.
|
|
|
|
This file records what that actually rules out (less than it looks like),
|
|
why, and which hrefs are worth reading next.
|
|
|
|
## `/oic/res` does not enumerate the resource tree on modern firmware
|
|
|
|
This is the finding that reopens the question. Across every fixture that
|
|
carries a captured `/oic/res`:
|
|
|
|
| board | links | `sec:true` | lists `/device/0`? |
|
|
| --- | --- | --- | --- |
|
|
| `ARTIK051_DONGLE_FAC_18K` | 91 | 78 | yes |
|
|
| `TP2X_FAC_BORA_21K` (2-in-1) | 17 | 6 | no |
|
|
| `TP2X_FAC_BORA_21K` (#205 flat) | 17 | 6 | no |
|
|
| `TP1X_DA_KS_RANGE_0101X` | 10 | 6 | no |
|
|
| `AWM-WW-AID-26-ONEBODY` | 15 | 9 | no |
|
|
| `ARTIK051_FAC_BORA_19K` (#335) | 18 | 6 | no |
|
|
|
|
The `ARTIK051_DONGLE_FAC_18K` board — the one Pattern A was built against —
|
|
is the outlier, not the model. Everywhere else `/oic/res` lists the
|
|
onboarding surface and nothing else: `/oic/d`, `/oic/p`, the security and
|
|
EasySetup/WiFiConf/CoapCloudConf/DevConf resources, file transfer, and the
|
|
`sec/*` pair. On issue #335's board the six `sec:true` links are exactly
|
|
doxm, pstat and the four setup URIs; every other listed link is `sec:false`.
|
|
The entire secure operational tree — `/device/0` included, which
|
|
demonstrably answers, since the dump comes from it — is absent.
|
|
|
|
Two consequences, both load-bearing:
|
|
|
|
1. **Nothing is learned from an href's absence in `/oic/res`.** On the range
|
|
board (issue #324) `/oic/res` lists ten onboarding links and no
|
|
`/device/0`, yet `/device/1` answers a full indexed dual-cavity sibling.
|
|
It was found only by `_SPECULATIVE_DEVICE_INDICES`, never by enumeration
|
|
of the links.
|
|
2. **Pattern A's `/oic/res` index scan is dead weight on these boards.** It
|
|
contributes nothing anywhere except the dongle board, so in practice
|
|
indexed siblings are found by the speculative `/device/1`, `/device/2`
|
|
probe alone.
|
|
|
|
## What issue #335 has actually ruled out
|
|
|
|
All 26 probes in the report returned false. Twenty-three of them are the
|
|
issue #205 flat fallback walking the master's own href list under the
|
|
sibling's UUID prefix, plus `/<uuid>/device/0`, `/device/1`, `/device/2`
|
|
and `/multidevice/vs/0`. Four more were read by hand from the issue thread
|
|
(`/<uuid>/information/vs/{1,2}`, `/<uuid>/device/{1,2}`), all 4.04.
|
|
|
|
So what is ruled out is: the UUID-prefixed namespace (Pattern B/C), and the
|
|
indexed **Collection** (`/device/<n>`). What has never been read on this
|
|
board — or on any `FAC_BORA` board — is **a bare indexed leaf**:
|
|
`/mode/vs/1`, `/temperatures/vs/1`, and friends. Every indexed href ever
|
|
probed by this project arrived via a `/device/<n>` batch; none was ever
|
|
GETed directly.
|
|
|
|
That gap matters because the "leaves exist, their Collection does not" shape
|
|
is already confirmed on this exact product family, just in the other
|
|
namespace: issue #205's `TP2X_FAC_BORA_21K` answers
|
|
`/<uuid>/information/vs/0` while `/<uuid>/device/0` comes back empty. A
|
|
board that mounts sibling leaves without mounting a sibling Collection is
|
|
the documented BORA behavior, so `/device/1`'s 4.04 is evidence about the
|
|
Collection and not about `/mode/vs/1`.
|
|
|
|
## What the OCF spec says about composite devices
|
|
|
|
The Core/Device specifications model this as a *Composite Device*: one
|
|
Platform representing the whole appliance, `/oic/d` carrying the Device
|
|
Types of every constituent Device, and — the relevant part — a **Collection
|
|
per distinct Device in the composition**, each Collection's `rt` including
|
|
the Device Type it represents.
|
|
|
|
Issue #335's `/oic/d` reports `["oic.wk.d", "oic.d.airconditioner"]`, which
|
|
is consistent with a two-indoor-unit composite (both constituents are air
|
|
conditioners, so the type appears once) and equally consistent with a single
|
|
unit. It does not discriminate.
|
|
|
|
The Collection half does suggest something untried. `x.com.samsung.devcol`
|
|
is Samsung's Collection type, carried by `/device/0` — and on the dongle
|
|
board `/oic/res` advertises a second resource with the same
|
|
`["x.com.samsung.devcol", "oic.wk.col"]` pair: **`/sec/devices`**. A
|
|
collection of devices, sitting alongside `/device/0`, never read by this
|
|
project or by any issue thread. If the composite enumeration is exposed
|
|
anywhere as a first-class resource, that is the shape it would take.
|
|
|
|
## Results of the second probe round
|
|
|
|
The reporter ran these live. Three answers, all informative.
|
|
|
|
**Indexed leaves do not exist.** `/information/vs/1`, `/power/vs/1`,
|
|
`/mode/vs/1` → 4.04. Pattern A is ruled out on this board properly now:
|
|
not just the `/device/1` Collection, but the leaf namespace it would have
|
|
carried.
|
|
|
|
**The UUID prefix routes, and is empty of operational resources.** The
|
|
control pair settles it:
|
|
|
|
/c24e25e9-.../file/list/vs/0 → 2.05, two items
|
|
/file/list/vs/0 → 2.05, the same two items
|
|
(/opt/data/energy.db, /opt/data/hass.db)
|
|
|
|
So the sibling's prefix is a live, routed namespace — the 23 flat-fallback
|
|
4.04s under it are the firmware answering "no such resource", not a dead
|
|
prefix swallowing everything. Pattern B/C is ruled out on this board on
|
|
positive evidence rather than on absence. That the two listings are
|
|
identical is expected either way: one board, one flash, one filesystem.
|
|
|
|
**`/sec/devices` exists — and this project could not see what's in it.**
|
|
It answered `2.05` with `rep: {}`, which reads as "the resource is there and
|
|
has nothing in it". It is not. `coordinator._raw_read_blocking` decoded the
|
|
CBOR body and then kept it *only if it was a Property map*:
|
|
|
|
```python
|
|
if isinstance(body, dict):
|
|
rep = body
|
|
```
|
|
|
|
A Collection answers a **list** — the `[devcol rep, {href, rep}, ...]` batch
|
|
`parse_device0_batch` reads. `/device/0` itself would have rendered exactly
|
|
the same accepted-but-empty `2.05 {}` through `read_resource`. Fixed: the
|
|
read path now returns the decoded body alongside `rep`, and the service
|
|
response carries it as `body` whenever it isn't the map already in `rep`.
|
|
|
|
`/sec/devices` therefore remains the one open lead, and needs one re-read on
|
|
a build carrying that fix.
|
|
|
|
## Still worth reading
|
|
|
|
**1 — `/sec/devices`, again.** Same `x.com.samsung.devcol` + `oic.wk.col`
|
|
pair as `/device/0`, so its body should be a batch naming its members. If a
|
|
composite enumeration is exposed anywhere, it is here.
|
|
|
|
**2 — the file-transfer pair.** `/oic/res` advertises
|
|
`/c24e25e9-.../file/transfer/vs/0` alongside the master's, and the prefix is
|
|
now known to route. Issue #301 documents the shape: a baseline GET returns
|
|
one item, `x.com.samsung.name` plus `x.com.samsung.blob`, no write needed to
|
|
see whatever it currently serves. If the prefixed endpoint serves *different
|
|
bytes* than the master's, that is the first hard local evidence the wall
|
|
unit exists as a data producer, and `/opt/data/energy.db` would be where its
|
|
runtime history lives.
|
|
|
|
/file/transfer/vs/0
|
|
/c24e25e9-55dd-ba18-d567-000000000001/file/transfer/vs/0
|
|
|
|
Mind the blob: #301 measured 2172 B on a `KRAC_18K`, and a raw `bytes` value
|
|
in a service response is not guaranteed to survive rendering in Developer
|
|
Tools. Ask for `x.com.samsung.name` and whether a blob field appears, not
|
|
for the blob pasted into a comment.
|
|
|
|
## Dead ends, so they aren't re-tried
|
|
|
|
- `/hass/state/vs/0`, `/hass/command/vs/0` — advertised in `/oic/res` on
|
|
every board here, and indexed per subdevice on the dongle board
|
|
(`/hass/state/vs/{0,1,2}`), which makes them look like a subdevice-aware
|
|
state channel. They are not: 4.04 on every interface on
|
|
`ARTIK051_KRAC_18K` (see `ac-filter-reset.md`). Cheap enough to retry once
|
|
on #335's newer build, but expect nothing.
|
|
- `/multidevice/vs/0` — probed, 4.04. Absent on this board; only the dongle
|
|
family exposes it.
|
|
- `/actions/vs/0` — GET returns `{}` on baseline and `oic.if.a`; publishes
|
|
no schema (`ac-filter-reset.md`).
|
|
|
|
## Where this lands if `/sec/devices` is empty too
|
|
|
|
Then the sibling is named in `subdeviceIdList` for the cloud's benefit and
|
|
has no local operational surface at all on this firmware — every namespace
|
|
it could occupy has now been read directly, and the UUID one was confirmed
|
|
routable first, so the negatives mean what they say. That closes issue #335
|
|
as a firmware limitation rather than leaving it open against a probe
|
|
strategy that was never actually exercised.
|
|
|
|
Worth keeping in view for the enumeration code either way: both remaining
|
|
patterns hinge on a Collection, and this board answers neither `/device/1`
|
|
nor a prefixed `/device/0`. An indexed flat-probe fallback — the mirror of
|
|
issue #205's prefixed one, gated on a board that claims a sibling but
|
|
materialized nothing — would have cost 8 round trips here and returned the
|
|
same 4.04s the reporter got by hand. It is worth building only if some
|
|
other board turns out to serve indexed leaves without their Collection;
|
|
this one does not.
|