Panels become devices: per-device documents in the flow repo, a Devices tab
- flow/devices.py: DeviceDef in FLOWS_DIR/_devices/<id>.json, committed under
the flow store's write lock, 409 on a stale version; nonces in DEVICES_FILE
outside git; in-memory presence announced as device_status
- api/routes/devices.py: CRUD, pairing with an optional {name, board,
firmware}, a pending list adopted without a code from the LAN only, unpair;
/panels/pair, /panels/pair/{code} and GET /panels/{id} kept as aliases,
PUT /panels/ gone
- _device_may replaces _panel_may, JWT claims unchanged
- panels.json moves into devices once at startup, then .migrated
- MCP list_devices, get_device; search category device
- Devices tab (list, detail with presence, pairing, ordered dashboards,
touch, I/O), PanelsDialog removed, serialised optimistic saves
This commit is contained in:
@@ -39,6 +39,7 @@ instance from the portal first if this browser has not recently.
|
||||
| Inspect flows | `list_flows`, `get_flow`, `get_node_source`, `list_node_types`, `get_graph`, `list_shared_nodes` |
|
||||
| Inspect values | `get_flow_state`, `get_message_history` |
|
||||
| Inspect the instance | `list_secrets` (names only), `get_modules`, `get_health`, `get_metrics`, `list_failures`, `list_runs` (live cascades) |
|
||||
| Inspect devices | `list_devices`, `get_device` |
|
||||
| Edit flows | `save_flow`, `save_node_source`, `validate_flow`, `publish_flow`, `discard_draft`, `delete_flow` |
|
||||
| Operate flows | `run_flow`, `trigger_node`, `start_flow`, `stop_flow`, `pause_flow`, `resume_flow`, `cancel_node` |
|
||||
| Install node packages | `apply_modules` |
|
||||
|
||||
+11
-6
@@ -179,7 +179,7 @@ a run, a current message or a flow input's initial value still references the
|
||||
digest, the call returns `409`. The hourly sweep removes unreferenced bytes
|
||||
on its own, so this is for reclaiming space sooner.
|
||||
|
||||
## Dashboards and panels
|
||||
## Dashboards and devices
|
||||
|
||||
| Method | Path | Action |
|
||||
|---|---|---|
|
||||
@@ -190,11 +190,16 @@ on its own, so this is for reclaiming space sooner.
|
||||
| `PUT` | `/dashboards/{name}` | save a draft |
|
||||
| `POST` | `/dashboards/{name}/publish`, `/dashboards/{name}/discard`, `/dashboards/{name}/rename` | publish, discard, or rename |
|
||||
| `POST` | `/dashboards/{name}/duplicate` | copy into an unpublished `{name}_copy` |
|
||||
| `GET`, `PUT` | `/panels/` | read or replace panel assignments; send the current `version` |
|
||||
| `POST` | `/panels/pair` | start device pairing |
|
||||
| `GET` | `/panels/pair/{code}` | poll pairing with its `secret` |
|
||||
| `POST` | `/panels/{id}/pair` | approve the pairing |
|
||||
| `POST` | `/panels/{id}/unpair` | revoke the panel credential |
|
||||
| `GET` | `/devices/` | list devices, with `online` and `last_seen` |
|
||||
| `POST`, `GET`, `PUT`, `DELETE` | `/devices/{id}` | create, read, save or delete one; a save sends the `version` it read and gets 409 when someone saved first |
|
||||
| `POST` | `/devices/pair` | start device pairing, optionally with `{name, board, firmware}`; unauthenticated |
|
||||
| `GET` | `/devices/pair/{code}` | poll pairing with its `secret`; answers `device` (and `panel` for older firmware); unauthenticated |
|
||||
| `GET` | `/devices/pending` | devices waiting for a code, as they describe themselves |
|
||||
| `POST` | `/devices/{id}/pair` | adopt by `{code}`, or by `{request}` from the pending list for a request from your network |
|
||||
| `POST` | `/devices/{id}/unpair` | revoke the device credential |
|
||||
|
||||
`/panels/pair`, `/panels/pair/{code}` and `GET /panels/{id}` answer as their
|
||||
`/devices/` counterparts, for firmware that has not updated yet.
|
||||
|
||||
## Secrets, modules, and alerts
|
||||
|
||||
|
||||
+1
-1
@@ -366,7 +366,7 @@ directory. Common choices:
|
||||
| `FLUKSIO_HOME` | Select the CLI's data directory |
|
||||
| `NODE_VENV` | `auto` adopts an existing venv; `managed` requests a separate one; a path selects an interpreter |
|
||||
| `REDIS_HOST` | Use Redis for flow state and queues |
|
||||
| `FRONTEND_HOST` | Browser address used in mail, OAuth metadata and panel links |
|
||||
| `FRONTEND_HOST` | Browser address used in mail, OAuth metadata and device links |
|
||||
| `ENVIRONMENT` | `production` disables interactive API documentation |
|
||||
| `MCP_ENABLED` | Enable the [agent endpoint](agents.md) |
|
||||
|
||||
|
||||
@@ -111,7 +111,7 @@ Create a dashboard and add a gauge bound to `house.living_temperature`.
|
||||
Publish the dashboard to see the current reading. Dashboard controls can also
|
||||
publish messages, so choose their bindings with care.
|
||||
|
||||
See [Dashboards and panels](../interface/dashboards.md) for widgets and pairing
|
||||
See [Dashboards and devices](../interface/dashboards.md) for widgets and pairing
|
||||
a wall tablet.
|
||||
|
||||
For longer-term history, add an **InfluxDB** node that consumes
|
||||
|
||||
@@ -1,8 +1,8 @@
|
||||
# Dashboards and panels
|
||||
# Dashboards and devices
|
||||
|
||||
A **dashboard** is a grid of widgets bound to message names. It can show values
|
||||
and send controls across several flows. A **panel** assigns published dashboards
|
||||
to a paired screen, such as a wall tablet.
|
||||
and send controls across several flows. A **device** is a paired screen, such
|
||||
as a wall tablet or a knob, and shows an ordered set of published dashboards.
|
||||
|
||||
## Building one
|
||||
|
||||
@@ -441,46 +441,61 @@ under the finger, as a tile view moves.
|
||||
## Showing one
|
||||
|
||||
Open `/view/{name}` for a dashboard-only view with your normal session.
|
||||
For a dedicated screen, pair a panel.
|
||||
For a dedicated screen, pair a device.
|
||||
|
||||
## Panels: hanging a screen on a wall
|
||||
## Devices: hanging a screen on a wall
|
||||
|
||||
As a superuser:
|
||||
|
||||
1. Open **Dashboards → Panels**, add a panel and select its dashboards. The
|
||||
name you add it under sets its address, `/panel/{id}`, and a later change of
|
||||
title keeps it.
|
||||
2. Enable **Touch friendly** for larger controls.
|
||||
3. Open the displayed pairing link on the device. It shows a six-character code.
|
||||
4. Enter that code for the panel, check the device description, then press
|
||||
**Pair device**.
|
||||
1. Open **Devices → Add device** and name it after where it hangs. The name
|
||||
sets its address, `/panel/{id}`, and a later change of title keeps it.
|
||||
2. Under **Dashboards**, add the ones it shows. The first is what it opens
|
||||
with, and the arrows set the order of its rail.
|
||||
3. Enable **Touch friendly** for larger controls.
|
||||
4. Open the pairing link on the device. It shows a six-character code.
|
||||
5. Enter that code under **Pairing**, check the device description, then press
|
||||
**Pair**. A device asking from your own network also appears in the list
|
||||
below, with what it says about itself, and **Pair this one** adopts it
|
||||
without the code.
|
||||
|
||||
The screen collects its credential and shows the assigned published dashboards.
|
||||
Several dashboards get a navigation rail.
|
||||
Several dashboards get a navigation rail. The page says whether the device is
|
||||
online, which it is while its live socket is open, and when it was last seen
|
||||
since the instance started.
|
||||
|
||||
A panel credential reads its assigned dashboards, their bound messages and the
|
||||
Each save carries the version it was read at. When someone else saved the
|
||||
device first, the save is refused and the page shows their version.
|
||||
|
||||
A device credential reads its assigned dashboards, their bound messages and the
|
||||
artifacts they show. It writes only the targets of their controls and query
|
||||
charts, and the `in` ports of its own [I/O](#the-devices-own-io). A message its
|
||||
tiles only draw, or a dashboard setting is bound to, stays read only. On a
|
||||
locked dashboard only the query charts may still publish.
|
||||
|
||||
**Unpair screen** revokes a locally paired credential and keeps the panel's
|
||||
dashboard assignments. Deleting the panel removes the assignment and its
|
||||
access.
|
||||
**Unpair screen** revokes a locally paired credential and keeps the device and
|
||||
its dashboards. Deleting the device removes the assignment and its access, and
|
||||
a device added again under the same name does not bring the old credential
|
||||
back.
|
||||
|
||||
The device definitions are stored in the flow repository (`_devices/<id>.json`),
|
||||
so their history is in git with the flows. The credential generation lives in
|
||||
`DEVICES_FILE` outside it, so reverting the repository never undoes an unpair.
|
||||
An instance from before devices moves its `panels.json` there on its first
|
||||
start and renames the file `panels.json.migrated`.
|
||||
|
||||
### A screen without a browser
|
||||
|
||||
The openpanel firmware, kept in its own repository, draws dashboards as native
|
||||
widgets on an ESP32-P4 wall panel (Waveshare ESP32-P4-WIFI6-Touch-LCD-7B,
|
||||
1024×600). Once its config page points it at this instance (the dialog's link
|
||||
works too, the device keeps only its address), it shows the pairing code itself; enter it as in step 4. It reads the same published
|
||||
1024×600). Once its config page points it at this instance (the device's link
|
||||
works too, the device keeps only its address), it shows the pairing code itself; enter it as in step 5. It reads the same published
|
||||
dashboards and live values and draws every widget type with two exceptions,
|
||||
both shown as a placeholder: a website tile that embeds a page (image tiles
|
||||
work), and a chart of runs, which a panel credential may not read. Media tiles
|
||||
work), and a chart of runs, which a device credential may not read. Media tiles
|
||||
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 the panel's [I/O](#the-devices-own-io) port names
|
||||
The device decides what its [I/O](#the-devices-own-io) port 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)
|
||||
@@ -488,9 +503,8 @@ turns `mic` into text and text into `speaker`.
|
||||
|
||||
### The device's own I/O
|
||||
|
||||
A panel can also act as a node. Under **I/O**, wire a port on the device to a
|
||||
message. A new port saves once it has a port name and a message, at the latest
|
||||
when the dialog closes:
|
||||
A device can also act as a node. Under **I/O**, wire a port on the device to a
|
||||
message. A new port saves once it has a port name and a message:
|
||||
|
||||
| Field | Meaning |
|
||||
|---|---|
|
||||
@@ -515,12 +529,14 @@ by the nodes that produce it.
|
||||
### A screen somewhere you cannot reach
|
||||
|
||||
An [enrolled instance](portal.md) also shows a portal pairing link. Use that
|
||||
link on the remote screen, then approve its code in the same dialog. The
|
||||
device description says *via portal*.
|
||||
link on the remote screen, then approve its code on the device's page. The
|
||||
device description says *via portal*. Anyone can ask the portal for a code, so
|
||||
a request that came through it, or from outside your network, is adopted by
|
||||
its code only and never from the list.
|
||||
|
||||
The instance enforces the same dashboard and message limits. Remote
|
||||
credentials are issued by the portal, so **Unpair screen** does not revoke
|
||||
them; revoke them at the portal. Deleting the panel removes access on the
|
||||
them; revoke them at the portal. Deleting the device removes access on the
|
||||
instance.
|
||||
|
||||
## See also
|
||||
|
||||
@@ -13,13 +13,13 @@ below, so a large flow grows downwards in one column.
|
||||
- **Edges** are routed around the nodes, a loop back to an earlier node
|
||||
included, and pulse when values pass through. Click one to inspect its
|
||||
payload.
|
||||
- **Endpoints** show flow inputs, dashboard widgets, panel I/O ports and nodes
|
||||
- **Endpoints** show flow inputs, dashboard widgets, device I/O ports and nodes
|
||||
in other flows that exchange messages with this flow. A value passing lights
|
||||
one up in a sweep: left to right when it sends into the flow, right to left
|
||||
when it reads out of it.
|
||||
- **Clicking an endpoint** shows a flow input's type, starting value and
|
||||
current value, with a pencil that opens the flow settings to edit it. A panel
|
||||
port opens its panel in the Panels dialog. A node in another flow opens that
|
||||
current value, with a pencil that opens the flow settings to edit it. A device
|
||||
port opens the device in the Devices tab. A node in another flow opens that
|
||||
flow on the label leading back here, with its edges highlighted.
|
||||
|
||||
Values update over a websocket. A connection banner tells you when the editor
|
||||
|
||||
@@ -13,7 +13,8 @@ The sidebar opens as a sheet on phones.
|
||||
|---|---|
|
||||
| **Home** | see the brain graph, health and recent activity |
|
||||
| **Flows** | create flows and open their editors |
|
||||
| **Dashboards** | build widget dashboards and pair wall panels |
|
||||
| **Dashboards** | build widget dashboards |
|
||||
| **Devices** | pair wall screens and choose the dashboards each shows |
|
||||
| **Runs** | start batch runs and review their results |
|
||||
| **Workers** | manage machines that execute nodes |
|
||||
| **Secrets** | store credentials; superusers only |
|
||||
@@ -29,7 +30,7 @@ the docs in another tab.
|
||||
### Search
|
||||
|
||||
Use **Search**, or ⌘K / Ctrl-K, to find flows, nodes, flow inputs and outputs,
|
||||
dashboards, widgets, panels, secrets, modules, workers and alert channels.
|
||||
dashboards, widgets, devices, secrets, modules, workers and alert channels.
|
||||
Selecting a result opens its editor or settings.
|
||||
|
||||
Search covers the current instance. When connected through a portal,
|
||||
@@ -91,6 +92,6 @@ Light and dark follow your system by default. Change this under
|
||||
## Next stops
|
||||
|
||||
- [The flow editor](flow-editor.md)
|
||||
- [Dashboards and panels](dashboards.md)
|
||||
- [Dashboards and devices](dashboards.md)
|
||||
- [Secrets, modules and alerts](operations.md)
|
||||
- [Accounts and the portal](portal.md)
|
||||
|
||||
@@ -115,5 +115,5 @@ service is not included, so the Docker stack does not start one.
|
||||
## See also
|
||||
|
||||
- [The fluksio command](../code/cli.md): data directories and enrollment options.
|
||||
- [Dashboards and panels](dashboards.md): pair a wall screen through the portal.
|
||||
- [Dashboards and devices](dashboards.md): pair a wall screen through the portal.
|
||||
- [Getting started](../getting-started/index.md): install and open your first instance.
|
||||
|
||||
+1
-1
@@ -22,7 +22,7 @@
|
||||
|
||||
- [The dashboard app](/interface/): the shell, Home, health and activity
|
||||
- [The flow editor](/interface/flow-editor/): canvas, node panel, dock, shortcuts, drafts
|
||||
- [Dashboards and panels](/interface/dashboards/): widgets, typed bindings, wall screens
|
||||
- [Dashboards and devices](/interface/dashboards/): widgets, typed bindings, wall screens
|
||||
- [Secrets, modules and alerts](/interface/operations/): credentials, packages, failure routing
|
||||
- [Accounts and the portal](/interface/portal/): enrolment, remote users, revoking
|
||||
|
||||
|
||||
@@ -23,7 +23,8 @@ For CLI installations, select storage with `--data-dir`, `FLUKSIO_HOME` or
|
||||
| `ALERTS_FILE` | `$DATA_DIR/alerts.json` | alert channels and rules |
|
||||
| `WEBPUSH_FILE` | `$DATA_DIR/webpush.json` | push keys and browser subscriptions |
|
||||
| `PROVISIONERS_FILE` | `$DATA_DIR/provisioners.json` | optional worker provisioning configuration |
|
||||
| `PANELS_FILE` | `$DATA_DIR/panels.json` | wall-panel pairings |
|
||||
| `DEVICES_FILE` | `$DATA_DIR/devices.json` | device credential nonces, outside the flow repository |
|
||||
| `PANELS_FILE` | `$DATA_DIR/panels.json` | panels of an instance from before devices, moved into devices on first start and renamed `.migrated` |
|
||||
| `OAUTH_PRIVATE_KEY_FILE` | `$DATA_DIR/oauth-key.pem` | agent and worker signing key |
|
||||
| `CLOUD_CONFIG_FILE` | `$DATA_DIR/cloud.json` | optional portal enrollment |
|
||||
| `AI_CONFIG_FILE` | `$DATA_DIR/ai.json` | optional assistant provider configuration |
|
||||
|
||||
@@ -170,4 +170,4 @@ port and received value. It is not published downstream.
|
||||
|
||||
- [Flows, nodes and messages](../concepts/flows.md)
|
||||
- [Node types](node-types.md)
|
||||
- [Dashboards and panels](../interface/dashboards.md)
|
||||
- [Dashboards and devices](../interface/dashboards.md)
|
||||
|
||||
Reference in New Issue
Block a user