feat(diagnostics): capture /oic/res discovery links
/oic/res is OCF's baseline resource-discovery endpoint: a unicast RETRIEVE returns every href/Collection the connection hosts, not just the one /device/0 seed path the coordinator polls. Relevant to the OCF "Composite Device" model (issue #177) -- a single physical unit sharing one IP/session across more than one logical Device, each exposed as its own Collection resource (same rt shape as our own /device/0). Nothing routes on this yet; captured alongside the existing /oic/p and /oic/d reads so a report from a multi-unit device shows us whether its firmware actually implements that model before any code assumes it does.
This commit is contained in:
@@ -31,9 +31,13 @@ async def async_get_config_entry_diagnostics(
|
||||
# detector when called inline here. Offload it to the executor.
|
||||
stl_version = await hass.async_add_executor_job(pkg_version, "smartthings-local")
|
||||
|
||||
# /oic/p and /oic/d sit outside the /device/0 batch captured below, so
|
||||
# they'd otherwise never reach an issue report. /oic/d's `rt` is OCF's
|
||||
# standard device-type declaration -- see registry/identity.py.
|
||||
# /oic/p, /oic/d, and /oic/res sit outside the /device/0 batch captured
|
||||
# below, so they'd otherwise never reach an issue report. /oic/d's `rt`
|
||||
# is OCF's standard device-type declaration; /oic/res is OCF's
|
||||
# discovery endpoint, listing every href/Collection the connection
|
||||
# hosts -- relevant to the "Composite Device" model (issue #177) where
|
||||
# a single physical unit exposes more than one logical Device. See
|
||||
# registry/identity.py.
|
||||
identity = coordinator._identity
|
||||
return {
|
||||
"device_type": coordinator.device_type_name or "unknown",
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
"""Read device identity from standard OCF resources (/oic/p, /oic/d)."""
|
||||
"""Read device identity from standard OCF resources (/oic/p, /oic/d, /oic/res)."""
|
||||
from __future__ import annotations
|
||||
|
||||
from dataclasses import dataclass, field
|
||||
@@ -28,6 +28,20 @@ def _get(sess, path) -> dict:
|
||||
return {}
|
||||
|
||||
|
||||
def _get_links(sess, path) -> list:
|
||||
"""Like _get, but for /oic/res: a baseline-Interface RETRIEVE on it
|
||||
returns a CBOR array of Link objects (href/rt/if/di/...), not a single
|
||||
Property map."""
|
||||
try:
|
||||
code, pl = sess.get(path, timeout=10.0)
|
||||
if code == 0x45 and pl:
|
||||
body = cbor2.loads(pl)
|
||||
return body if isinstance(body, list) else []
|
||||
except Exception:
|
||||
pass
|
||||
return []
|
||||
|
||||
|
||||
def _device_types(d: dict) -> tuple[str, ...]:
|
||||
"""/oic/d's `rt` -- the device's own OCF device-type declaration.
|
||||
|
||||
@@ -52,6 +66,16 @@ def _device_types(d: dict) -> tuple[str, ...]:
|
||||
def read_identity(sess, serial: Optional[str]) -> DeviceIdentity:
|
||||
p = _get(sess, ['oic', 'p'])
|
||||
d = _get(sess, ['oic', 'd'])
|
||||
# /oic/res is OCF's baseline resource-discovery endpoint: a unicast
|
||||
# RETRIEVE on it returns every Resource/Collection href this endpoint
|
||||
# hosts, not just the one /device/0 seed path the coordinator polls.
|
||||
# Relevant for the OCF "Composite Device" model (issue #177: a single
|
||||
# physical unit -- one IP, one /oic/p -- exposing more than one logical
|
||||
# Device, each as its own Collection resource, same rt shape as our own
|
||||
# /device/0). Nothing consumes this yet; captured so a report from a
|
||||
# multi-unit device shows us whether its firmware actually implements
|
||||
# that model before any code assumes it does.
|
||||
res = _get_links(sess, ['oic', 'res'])
|
||||
return DeviceIdentity(
|
||||
manufacturer=p.get('mnmn') or 'Samsung',
|
||||
model=p.get('mnmo') or '',
|
||||
@@ -61,5 +85,5 @@ def read_identity(sess, serial: Optional[str]) -> DeviceIdentity:
|
||||
# Kept whole rather than field-by-field: these resources are outside
|
||||
# the /device/0 dump diagnostics already captures, and we don't yet
|
||||
# know which of their fields will turn out to identify a device type.
|
||||
raw={'/oic/p': p, '/oic/d': d},
|
||||
raw={'/oic/p': p, '/oic/d': d, '/oic/res': res},
|
||||
)
|
||||
|
||||
Reference in New Issue
Block a user