Capability report: PUT /devices/{id}/report, a Capabilities section, offline devices degraded

A device reports its board, screen, camera and ports from its own
credential (16 KB, schema 1, replacing the last report), and the flows
are validated against it again. The node panel turns a reported port's
config schema into a form, a reported screen is a canvas preset and a
touch screen's first report turns Touch friendly on. An offline device
node is degraded: amber on the canvas, a warning on Home, never a fault.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_0138N7k5PT4dcR1iEqXaaQ9k
This commit is contained in:
Melvin Strobl
2026-10-16 17:37:49 +02:00
co-authored by Claude Opus 5.5
parent a9d453c9d9
commit ad76200d3d
28 changed files with 820 additions and 129 deletions
+46 -8
View File
@@ -496,9 +496,9 @@ play MJPEG streams, pushed frames, images, and H.264 Baseline or MJPEG clips up
to 640×360. Re-encode other clips with the [clip recipe](../code/nodes.md#making-clips-playable-on-an-lvgl-panel).
The device decides what its [port](#the-devices-own-ports) names
mean. openpanel serves `gpio.<n>`, `backlight`, `touch`, `mic` and `speaker`,
lists each one's `config` in its README and ignores any other name. A browser
screen serves none of them. The [speech recipe](../code/nodes.md#speech-to-and-from-a-panel)
mean. openpanel [reports](#what-a-device-reports) the ones it serves, such as
`gpio.<n>`, `backlight`, `touch`, `mic` and `speaker`, with the settings each
one reads, and ignores any other name. A browser screen serves none of them. The [speech recipe](../code/nodes.md#speech-to-and-from-a-panel)
turns `mic` into text and text into `speaker`.
### The device's own ports
@@ -507,8 +507,8 @@ A device can also act as a node, with a button on its GPIO, its backlight or
its microphone. Its ports are wired in a flow with a **Device** node: pick the
device, then add each port under **Publishes** (`in`, the device sends to the
message) or **Follows** (`out`, the device reads it). **Use in flow** on the
device's page puts its node in a flow you pick, and **Ports** lists what the
published flows wire, each linked to its node.
device's page puts its node in a flow you pick, and **Capabilities** lists the
ports it reports and what the published flows wire, each linked to its node.
| Field | Meaning |
|---|---|
@@ -520,7 +520,8 @@ published flows wire, each linked to its node.
Only published flows count. A port wired in two of them, or a device node
naming a device that does not exist, is an error on the canvas. Until a device
reports what it has, a port name is free text; once it has, a port it does not
list is a warning and one wired the wrong way round an error.
list is a warning and one wired the wrong way round, or to another type, an
error. `int` and `float` pass for each other.
The device reads its ports as `io` on `GET /devices/{id}`, in a fixed order,
and is told to read them again when publishing or deleting a flow changes them.
@@ -528,8 +529,45 @@ The credential may publish to its `in` messages even when a dashboard is
locked, and may upload an artifact named after one
(`PUT /artifacts?name=<message>`), which is how a microphone sends a recording.
A value it publishes there is credited to its device node, so the node's edge
lights up on the canvas. `out` messages are read only. The node is shown down,
*Offline*, while the device is not connected.
lights up on the canvas. `out` messages are read only. The node is shown
degraded, *Offline*, in amber while the device is not connected: a warning on
Home, not a fault, since a panel switched off or asleep breaks nothing.
### What a device reports
A paired device says what it has with `PUT /devices/{id}/report`, from its own
credential only. openpanel sends it after pairing and once per boot. The report
replaces the one before, is at most 16 KB and keys this version does not know
are dropped:
```json
{
"schema": 1,
"platform": "esp32p4",
"board": "p4",
"firmware": "0.1.2",
"display": {"w": 1024, "h": 600, "shape": "rect", "touch": true},
"ports": [
{"port": "backlight", "direction": "out", "dtype": "int",
"config": {"type": "object", "properties": {"wake_s": {"type": "integer", "default": 30}}}},
{"port": "gpio.4", "direction": "in", "modes": ["in", "out"], "dtype": "bool"}
],
"camera": {"sensor": "IMX415", "w": 1920, "h": 1080, "fps": 15},
"features": {"display": true}
}
```
`config` is a JSON schema of the settings the device reads for that port, which
the Device node turns into a form. `modes` lists the directions a port may be
wired in when it may be either, as a GPIO pin. `on_demand` marks a port that
sends only while somebody wants it.
The device's page shows the report under **Capabilities**, with each port's
binding or **Use in flow** for it. A reported screen becomes a canvas preset in
the dashboard settings, named after the device, and the first report of a
touch screen turns **Touch friendly** on.
### Before device nodes
Before device nodes a device carried its ports itself. On its first start an
instance moves each one into the flow that declares its message, one device
+5 -3
View File
@@ -40,8 +40,9 @@ streaming toggle.
A **Device** node stands for a paired device instead: pick the device, then
its ports under **Publishes** and **Follows** (see
[the device's own ports](dashboards.md#the-devices-own-ports)). A device that
reports its ports offers them in a list with their type filled in, and the
command palette offers each one as a shortcut, such as *Hallway camera*.
reports its ports offers them in a list with their type filled in and a form
for the settings each one reads, and the command palette offers each one as a
shortcut, such as *Hallway camera*.
Message fields suggest existing names. Matching an output's message is how
you connect an input.
@@ -156,7 +157,8 @@ conflict. Reload and review their changes before retrying.
The canvas reports unconnected inputs, missing starting values, cycles and
code-load errors. These prevent the affected flow from running. Unauthenticated
webhooks are advisory; runtime node-health problems clear when the node
recovers. See [Flow issues](../concepts/flows.md#when-a-flow-needs-attention).
recovers. A degraded node, such as a device node whose device is offline, is
marked amber: it is a warning, and the flow keeps running. See [Flow issues](../concepts/flows.md#when-a-flow-needs-attention).
## See also
+2 -1
View File
@@ -57,7 +57,8 @@ a small sketch of each layout; open one for its live readings.
Health shows flow status, node load errors, queue depth and event-loop lag.
After you have used batch runs, it also shows running and queued runs.
A degraded instance lists the problems that need attention.
A degraded instance lists the problems that need attention. Warnings, such as
a device that is offline, are listed in amber and leave the status as it is.
### Execution time per node type