435 lines
24 KiB
Markdown
435 lines
24 KiB
Markdown
# Dashboards and panels
|
||
|
||
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.
|
||
|
||
## Building one
|
||
|
||
1. Open **Dashboards → New dashboard**.
|
||
2. Enter edit mode, choose **Add widget** and select a type.
|
||
3. Bind the widget to a message in its settings. On desktop, drag and resize
|
||
tiles on the grid.
|
||
4. **Publish** when the dashboard is ready.
|
||
|
||
Edits stay in a draft; paired screens show the published version. On phones,
|
||
tiles stack in one column and dragging is disabled, but settings remain editable.
|
||
|
||
Controls can publish real values while you edit, so choose their targets with
|
||
care. Your new Switch may already be flipping something!
|
||
|
||
## The widgets
|
||
|
||
### Display
|
||
|
||
| Widget | Binds to | Shows |
|
||
|---|---|---|
|
||
| **Value** | anything | formatted reading, unit and precision |
|
||
| **Gauge** | `float`, `int` | reading within a min/max range |
|
||
| **Chart** | numeric messages, a query response or run metrics | up to five lines |
|
||
| **Bar** | `float`, `int` | up to eight readings with separate scales |
|
||
| **Icon** | numbers, booleans or strings | a glyph selected from the value |
|
||
| **Text** | — | Markdown |
|
||
| **Agenda** | `list` | upcoming items |
|
||
| **Forecast** | `list` | an outlook strip |
|
||
| **Notification** | `record` | title, body and severity |
|
||
| **Media** | `image`, `audio`, `video`, `artifact` | image, audio or video |
|
||
| **Player** | `record` | playback status and transport controls |
|
||
| **Clock** | — | current time |
|
||
| **Website** | — | embedded page or image |
|
||
|
||
Every widget has a title. **Show title** controls its visibility; the title
|
||
still names the widget for accessibility and published values.
|
||
|
||
### Input
|
||
|
||
| Widget | Publishes | Settings |
|
||
|---|---|---|
|
||
| **Button** | fixed value | one-shot action |
|
||
| **Buttons** | a value per button | grid of actions |
|
||
| **Switch** | `bool` | on/off |
|
||
| **Slider** | `float`, `int` | min, max, step; horizontal or vertical; a reading beside it |
|
||
| **Input** | text or number | free entry |
|
||
| **Selector** | selected value | menu or row of choices |
|
||
| **Colour** | list or string | HSV, RGB or hex |
|
||
|
||
Colour defaults to `[h, s, v]`: hue 0–360°, saturation and brightness 0–100%.
|
||
**Sends** can select RGB (`[r, g, b]`, 0–255) or hex (`"#rrggbb"`).
|
||
HSV and RGB bind to `list`; hex binds to `str`.
|
||
|
||
Controls publish to their bound messages. The flow canvas shows them as
|
||
endpoints feeding the nodes that consume those messages.
|
||
|
||
Bindings are checked in the editor and on the server. See
|
||
[Payload types](../reference/payload-types.md).
|
||
|
||
### A slider's reading
|
||
|
||
A Slider can also show what it sets against, such as the room's temperature
|
||
beside a setpoint: **Beside it** binds `reading: {message, dtype, label}` to a
|
||
`float` or `int`. The reading is only shown, never published. It is written in
|
||
the slider's unit and to its step's decimals (a step of 0.5 writes 21 as
|
||
`21.0`), as the slider writes its own value, so the two always match; `—`
|
||
stands in for the value until one arrives. On a round face it takes the middle
|
||
(see [Round dashboards](#round-dashboards)); in a tile it is a line under the
|
||
slider's value.
|
||
|
||
It is also marked where it sits on the slider's scale, as a thermostat marks
|
||
the room's temperature: the handle is what is set, the dot what is. The dot is
|
||
at the reading's fraction of the scale, (reading − min) / (max − min) held to
|
||
0–1, so a reading outside the range sits at that end. It takes no pointer, and
|
||
there is none until a value arrives. See [Dots on the track](#dots-on-the-track).
|
||
|
||
Sizes are CSS pixels of the canvas, as in the round geometry below. The
|
||
slider's own value is at the tile's text size (14; 16 on a touch-friendly
|
||
panel), centred on a line as tall as the control (32; 48 touch-friendly).
|
||
|
||
| Part | Value |
|
||
|---|---|
|
||
| Line | 16 high, text 12: the label (muted, at most 96 wide, cut with an ellipsis), 6, the value (text colour), 6, the unit (muted). Without a label, the value and unit alone |
|
||
| Row | directly under the slider's value, right-aligned with it, in the column right of the track (12 apart). With ticks the line shares the ticks' row, so the tile grows no taller; without them it adds 16 |
|
||
| Row width | the value column is as wide as its wider line, but at most half the row; the track takes the rest. What does not fit is cut from the label; the value and unit never are |
|
||
| Fader | directly under the slider's value, both centred under the track, 8 below it; the line no wider than the tile inside its padding, cut from the label first |
|
||
|
||
### Dots on the track
|
||
|
||
A slider's ticks, a selector's options on a round face and a slider's reading
|
||
are dots inside the track, on its midline — on a round face the ring's centre
|
||
line, radius c − 20. Each is drawn in the colour that reads on what covers it:
|
||
the track, the value's fill, or the handle.
|
||
|
||
| Dot | Size, tile / ring | On the track | On the fill | On the handle |
|
||
|---|---|---|---|---|
|
||
| Stop: a tick, an option | half the track's thickness (4 on the 8 track) / 6 | `--muted-foreground` | `--primary-foreground` at 70 % | hidden under it |
|
||
| Reading | three quarters of the track's thickness (6) / 10 | `--foreground` | `--primary-foreground` | Fluksio `--foreground`, Material `--primary-foreground`, Glass black at 75 % |
|
||
|
||
The reading is the larger dot in the stronger colour, and it is the one dot
|
||
that shows on the handle, so a reading at the setpoint is still visible.
|
||
|
||
| Part | Value |
|
||
|---|---|
|
||
| Place (tile) | the dot's centre on the handle's travel: handle ÷ 2 + fraction × (track length − handle) from the track's left end (from its bottom end on a fader), so a dot and the handle line up at the same value |
|
||
| Place (ring) | the dot's centre at the fraction of the sweep, as the handle |
|
||
| Ticks | with `ticks` on (the default), n intervals of the scale — the steps when there are 5 or fewer, else the first of 4, 3 or 2 that divides the steps evenly, else 4 — and a dot at each i/n, both ends included. A row keeps its labels under the track; a fader has none |
|
||
| Options | a dot per option at i/(n − 1) of the sweep (one option: the middle). The selector's ring has a value arc from the start to the selected option, so the options up to it are on the fill |
|
||
| Colour change | where the fill or the handle covers a dot, that part of it takes the colour for the fill or the handle, so a dot changes colour as the fill's end or the handle passes over it, and follows them while they move. A device may instead switch a whole dot when the fill's end or the handle's centre passes the dot's centre |
|
||
| Order | track, dots, fill, the dots again over the fill, handle, the reading again over the handle |
|
||
| Locked | in a tile, the dots at 0.45 opacity, as the handle; on the ring, the whole ring at 0.45 |
|
||
|
||
## Charts
|
||
|
||
Choose the chart's data source:
|
||
|
||
- **Live:** recent numeric message history, updated as values arrive.
|
||
- **Query:** publishes a `record` request containing `range_s` and
|
||
`interval_s`, then draws a flow's `series` response. Include those fields in
|
||
the answer so the chart can reject responses for a different window.
|
||
- **Runs:** compares a numeric metric from named runs, a sweep or the latest
|
||
runs of a flow. See [Runs](../concepts/runs.md).
|
||
|
||
Multi-line charts show a legend as well as different colours.
|
||
|
||
!!! tip "Skip the unfinished bucket"
|
||
|
||
If your query aggregates into time buckets, leave out the bucket still
|
||
filling. Otherwise an incomplete total can look like a sudden drop.
|
||
|
||
## Media tiles
|
||
|
||
Media messages contain artifact references; the widget loads the bytes they
|
||
name. **Crop or fit** controls image sizing. **Play as it arrives** enables
|
||
autoplay, subject to the browser's rules for sound.
|
||
|
||
For local streams, `volatile=True` artifacts can be pushed over the websocket
|
||
with their message. Stored artifacts are fetched individually, as are frames
|
||
viewed through a portal. Use occasional snapshots for remote screens.
|
||
|
||
For continuous video, set **Live stream** to a browser-compatible camera URL.
|
||
The browser must be able to reach that URL; enrollment does not expose the
|
||
camera itself. See [Media payloads](../reference/payload-types.md#image-audio-video).
|
||
|
||
## Player tiles
|
||
|
||
A Player reads a status `record` and publishes commands to a separate `str`
|
||
message.
|
||
|
||
| Status field | Meaning |
|
||
|---|---|
|
||
| `title`, `artist`, `album` | track details |
|
||
| `status` | `play`, `pause`, `stop`, `load` or `off` |
|
||
| `position`, `duration` | seconds |
|
||
|
||
Controls send `toggle`, `next`, `prev` and `seek:<seconds>`. Your receiving
|
||
node translates those into device actions. The position advances in the
|
||
browser between readings and resets to each fresh reading.
|
||
|
||
## Website tiles
|
||
|
||
Set **Address** to a page to embed, or choose **Image** for a snapshot or MJPEG
|
||
URL. A website may refuse embedding.
|
||
|
||
Embedded pages run in a sandbox without cookies or storage by default.
|
||
**Trusted site** permits the site's own origin, cookies and storage.
|
||
Use it only for a trusted destination. The app blocks trusted embeds of its
|
||
own origin, including the portal origin, to protect your session.
|
||
|
||
## Dashboard settings
|
||
|
||
Open **Dashboard settings** from the dock. Each setting can hold a fixed value
|
||
or follow a message chosen in **Driven by**. The fixed value is the fallback
|
||
when no usable message value is available.
|
||
|
||
| Setting | Choices | Message type |
|
||
|---|---|---|
|
||
| **Look** | `fluksio`, `material`, `glass` | `str` |
|
||
| **Theme** | `system`, `light`, `dark` | `str` |
|
||
| **Palette** | ordered hex colours | `list` |
|
||
| **Background** | image URL | `str` |
|
||
| **Lock** | read-only on/off | `bool` |
|
||
|
||
To change one on a schedule, have a scheduled node publish its bound message.
|
||
|
||
### Look and theme
|
||
|
||
**Fluksio** is the default look. **Material** uses flat tonal cards; **Glass**
|
||
uses translucent tiles. Widgets work the same in all three.
|
||
|
||
Theme follows the chosen preference unless a palette sets the background
|
||
colour.
|
||
|
||
### Palette
|
||
|
||
Paste a colour list or a [Coolors](https://coolors.co) palette link. Colours
|
||
have roles by position:
|
||
|
||
| Position | Role |
|
||
|---|---|
|
||
| 1 | background |
|
||
| 2 | widget surface |
|
||
| 3 | primary controls and first chart line |
|
||
| 4 | accent |
|
||
| 5 | text |
|
||
| 6+ | additional chart lines |
|
||
|
||
Missing roles are derived, so three colours are enough to get started.
|
||
**Rotate** shifts their order. Text contrast is corrected automatically;
|
||
failure and success indicators keep their status colours.
|
||
|
||
### Background and lock
|
||
|
||
Background draws an image beneath the widgets. Lock disables publishing from
|
||
controls and shows **Read-only** when viewing the dashboard. It does not
|
||
restrict API permissions and does not disable controls in edit mode.
|
||
|
||
## Round dashboards
|
||
|
||
For a round screen such as a rotary knob, set the canvas to **Round** in the
|
||
dashboard settings, or pick the **Knob** preset (360×360). A round canvas is
|
||
square (`shape: "round"` forces `canvas_height` to `canvas_width`), and nothing
|
||
outside its circle is drawn.
|
||
|
||
A round dashboard has no grid. It shows one widget at a time, each drawn as the
|
||
whole face, in the order of `widgets`; `layout` is not read. In the editor, the
|
||
faces are a row above the dock: press one to show it and open its settings,
|
||
drag it along the row (or Alt+←/→) to move it, and add more with **Add widget**.
|
||
|
||
A Slider, Selector, Colour or Gauge draws on the **ring** along the edge, which
|
||
a knob's own ring turns. In a browser, drag along the ring or use the mouse
|
||
wheel (or the arrow keys once it has focus): one notch is one step, one option
|
||
(no wrap) or one hue step (`hue_step`, default 5°, wrapping). The value moves
|
||
at once and is published once, 300 ms after the last notch or when the pointer
|
||
is released. A Gauge only shows. On any other face, turning a knob only wakes
|
||
the screen.
|
||
|
||
A Slider's reading (**Beside it**) is written large in the middle, under its
|
||
label; the slider's own title and value move to the line in the ring's gap.
|
||
|
||
Value, Switch, Button, Clock, Icon, Notification and Text have faces of their
|
||
own. Every other type is drawn as its rectangular body in the middle of the
|
||
face, and the editor marks it **Poor fit for round**.
|
||
|
||
### Moving between faces
|
||
|
||
| Gesture | Effect |
|
||
|---|---|
|
||
| Swipe left / right | next / previous face of this dashboard; stops at either end |
|
||
| Swipe up / down | next / previous dashboard of the panel (`/panel/{id}` only); stops at either end |
|
||
| Page dot | that face |
|
||
| PageDown / PageUp | next / previous face |
|
||
| Shift+PageDown / Shift+PageUp | next / previous dashboard of the panel |
|
||
| Arrow keys | turn the ring, not the page |
|
||
|
||
A swipe is a drag of at least 40 canvas pixels, decided by its longer axis; a
|
||
drag that starts on the ring turns the ring instead. A dashboard reopens on the
|
||
face it was last left on in this session, otherwise on its first. Landing on
|
||
another dashboard shows its title and icon in the middle of the face for one
|
||
second; a round panel has no rail.
|
||
|
||
### Geometry
|
||
|
||
Devices that draw dashboards natively use these numbers. They are canvas
|
||
pixels, scaled with the canvas; S is the canvas width and c = S/2. Angles are
|
||
degrees clockwise from three o'clock. Text sizes are font sizes; muted is the
|
||
look's muted text colour.
|
||
|
||
| Part | Value |
|
||
|---|---|
|
||
| Face | circle of diameter S at (c, c) |
|
||
| Title | one line centred at y = c − 80, 15, muted, at most 200 wide; the widget's title, or the label of a slider's reading |
|
||
| Middle | a 240 × 128 box centred at (c, c); what a face draws in its middle is centred in it and clipped to it |
|
||
| Centre reading | centred at (c, c), line height 1, its unit after it at 0.4 em, muted. Size: 72, or 240 ÷ (0.6 × the characters written) rounded down where that is smaller, never below 24 |
|
||
| Ring band | 40 along the edge |
|
||
| Ring arc | start 120°, sweep 300° (ends at 60°), centre-line radius c − 20, stroke 16 with round caps |
|
||
| Slider | track over the sweep, value arc from the start to the value (none at the minimum), handle 28 across, its ticks as [dots](#dots-on-the-track); the value as the centre reading |
|
||
| Slider with a reading | the reading as the centre reading; the gap line holds the title (muted) and the slider's value. The reading as a dot 10 across on the centre line at its fraction of the sweep ([Dots on the track](#dots-on-the-track)) |
|
||
| Selector | a value arc from the start to the selected option (none at the first), a dot 6 across per option at i/(n−1) of the sweep (one option: the middle), the selected one under the handle; its label as the centre reading, at most 36 |
|
||
| Colour | hue h at h/360 of the sweep in 150 strokes of 2°, red at both ends; the handle filled with the colour; a swatch 96 across in the middle, with a hairline border |
|
||
| Gauge | track and value arc, no handle; the value as the centre reading |
|
||
| Gap line | centred at y = S − 28, 13, at most 160 wide |
|
||
| Value | the reading as the centre reading, to its precision; a word shrinks like any other |
|
||
| Switch | a disc 128 across centred at (c, c): the look's button, filled when on and tonal when off, with a power glyph 40 over the word On or Off at 15; a press toggles |
|
||
| Button | a disc 128 across centred at (c, c), tonal, its label at 15 over at most three lines; a press sends its value |
|
||
| Clock | the time (hours and minutes, the device's locale) sized as a centre reading, over the date (weekday, day, month) at 15, muted, 4 apart; the pair centred at (c, c) |
|
||
| Icon | the glyph 96 across over its label at 15, muted, 4 apart; the pair centred at (c, c). Nothing matched: a dash at 72, muted |
|
||
| Notification | the title at 15, medium (an error in the destructive colour, led by ⚠), over the body at 15, muted; centred lines in the middle |
|
||
| Text | centred lines at 15: `#` at 1.35 em and `##` medium, `###` muted, list items led by a bullet; in the middle |
|
||
| Not wired | the problem, at 15, muted, in the middle; a ring type draws no ring |
|
||
| Any other type | its rectangular body, without a card, from y = c − 64 to c + S/(2√2), x = c ± S/(2√2) (Knob: 53–307 × 116–307) |
|
||
| Page dots | one per face, from two faces: dots 6 across on targets 16 apart (closer when more than 128 wide would be needed), centred at y = S − 12; the current one in the text colour, the others muted at half opacity |
|
||
| Dashboard name | a pill centred at (c, c), 36 high: the icon 16 and the title at 15, medium, at most 220 wide, on the frosted surface; for 1000 ms |
|
||
| Paging | faces slide sideways, dashboards up and down; see [Motion](#motion) |
|
||
| Locked | controls do nothing and read as disabled; the ring at 0.45 opacity |
|
||
|
||
Paint follows the look: Fluksio draws a muted track, a primary value and a
|
||
handle of the ground colour ringed in primary; Material a tonal track and a
|
||
primary handle; Glass a translucent track, a glowing value and a white handle.
|
||
A Switch or Button face wears the look's own button.
|
||
|
||
## Motion
|
||
|
||
How a dashboard moves, for devices that draw it natively. Distances are canvas
|
||
pixels. Each look moves at its own spring; a device without springs runs the
|
||
spring's closed form for the duration given and then sets the end value, or
|
||
uses the cubic-bezier that stands in for it.
|
||
|
||
| Look | Spring (stiffness, damping, mass) | ζ, ω₀ | Duration (within 1 %) | Overshoot | Cubic-bezier stand-in |
|
||
|---|---|---|---|---|---|
|
||
| Fluksio | 420, 34, 1 | 0.830, 20.49 s⁻¹ | 210 ms | 0.9 % | (0.26, 0.12, 0.25, 1.01) over 250 ms, at most 1.5 % off |
|
||
| Material | 550, 38, 1 | 0.810, 23.45 s⁻¹ | 270 ms | 1.3 % | (0.20, 0.11, 0.27, 1.19) over 260 ms, at most 1.7 % off |
|
||
| Glass | 320, 22, 0.8 | 0.688, 20.00 s⁻¹ | 330 ms | 5.1 % | (0.26, 0.20, 0.20, 1.33) over 320 ms, at most 1.7 % off |
|
||
|
||
From rest, a spring's progress is p(t) = 1 − e^(−ζω₀t)·(cos ω_d t +
|
||
(ζω₀/ω_d)·sin ω_d t), with ω_d = ω₀·√(1 − ζ²). "Spring" below is the
|
||
dashboard's look's.
|
||
|
||
| What | Moves | From → to | Timing | Input during it |
|
||
|---|---|---|---|---|
|
||
| Face paging (round) | the new face and the old | new: x +48 (next) or −48 (previous), opacity 0 → x 0, opacity 1; old: x 0, opacity 1 → x −48 (next) or +48, opacity 0. Both at once | spring | another page retargets: each face heads for its new end from where it is |
|
||
| Dashboard paging (round panel) | the new dashboard's face and the old | the same on y: the next rises from +48, the previous comes down from −48. One opened by its address only fades | spring | as faces |
|
||
| Page dot | the current dot and the last | muted at 0.5 opacity ↔ text colour at 1 | 200 ms, cubic-bezier(0.4, 0, 0.2, 1) | retargets |
|
||
| Dashboard name | the pill | opacity 0 → 1, held 1000 ms, 1 → 0 | in 200 ms, out 150 ms, cubic-bezier(0.4, 0, 0.2, 1) | — |
|
||
| Ring value set by a notch, a key or the engine | the value arc's end, the handle (slider, selector, colour) | from where it is drawn to the new fraction of the sweep | spring | each notch retargets from where it is, at the speed it has |
|
||
| Ring value set by a drag | the same | follows the pointer exactly | none | — |
|
||
| Hue across red | the colour handle | a change of more than half the sweep jumps to the other end | none | — |
|
||
| Slider's reading on the ring, gauge on the ring | the reading's dot; the value arc | from where it is drawn to the new fraction; a dot's colour follows the fill and the handle as they pass | spring | retargets |
|
||
| Numbers on the ring | centre reading, gap line | switch at once, with the notch | none | — |
|
||
| Value face, Value and Gauge tiles | the number | counts to the new value, written to its precision | spring | retargets |
|
||
| Slider tile set elsewhere | the fill's end, the handle, the reading's dot | from where it is drawn to the new fraction | spring | a drag or a key moves it at once |
|
||
| Gauge and Bar tiles | the value arc, each bar's fill | from where it is drawn to the new fraction | spring | retargets |
|
||
| Dashboard change (rectangular panel) | every tile | the old dashboard goes at once; each new tile opacity 0 → 1, y +8 → 0 | spring | — |
|
||
| Rail | the current entry's marker | slides to the new entry | spring | retargets |
|
||
|
||
With reduced motion asked for, nothing travels: pages and dashboards only
|
||
cross-fade (opacity at the spring), and every value is drawn at its new place
|
||
at once. The dot and the name pill, which only change colour or opacity, keep
|
||
their timing.
|
||
|
||
A device may simplify where its hardware is slow, keeping the direction and
|
||
the end state: a page may slide without the fade, fade without the slide, or
|
||
cut; a retarget may restart the curve from where it is without carrying the
|
||
speed; a counting number may switch; and the value arc may be redrawn each
|
||
frame as an arc to the eased angle, which is what the browser's reveal
|
||
amounts to.
|
||
|
||
## Showing one
|
||
|
||
Open `/view/{name}` for a dashboard-only view with your normal session.
|
||
For a dedicated screen, pair a panel.
|
||
|
||
## Panels: hanging a screen on a wall
|
||
|
||
As a superuser:
|
||
|
||
1. Open **Dashboards → Panels**, add a panel and select its dashboards.
|
||
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**.
|
||
|
||
The screen collects its credential and shows the assigned published dashboards.
|
||
Several dashboards get a navigation rail.
|
||
|
||
A panel credential permits its assigned dashboards, their bound messages and
|
||
the artifacts they show. It also permits publishing from its controls and query
|
||
charts. 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.
|
||
|
||
### 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, it shows the
|
||
pairing code itself; enter it as in step 4. 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
|
||
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
|
||
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 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:
|
||
|
||
| Field | Meaning |
|
||
|---|---|
|
||
| `port` | The device's name for it, such as `gpio.4`, `backlight`, `touch`, `mic` or `speaker`. Lowercase letters, digits, `_` and `.` |
|
||
| `direction` | `in`: the device publishes to the message. `out`: the device follows it |
|
||
| `message` | A qualified `flow.name`. A flow must declare it, as for a control |
|
||
| `config` | A JSON object passed to the device unread, such as `{"pull": "up", "debounce_ms": 50}` |
|
||
|
||
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.
|
||
`out` messages are read only.
|
||
|
||
!!! note "If the local link is wrong"
|
||
|
||
Pairing links use `FRONTEND_HOST`. Set it to the app address reachable
|
||
from the screen's network.
|
||
|
||
### 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*.
|
||
|
||
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
|
||
instance.
|
||
|
||
## See also
|
||
|
||
- [Payload types](../reference/payload-types.md)
|
||
- [Flows, nodes and messages](../concepts/flows.md)
|
||
- [Accounts and the portal](portal.md)
|