> ## Documentation Index
> Fetch the complete documentation index at: https://docs.hyperwisor.com/llms.txt
> Use this file to discover all available pages before exploring further.

# Real-time Widget Updates

> The message contract that lets a device drive any widget live — change values, text, visibility, position, size, and rotation from an incoming message.

Every widget on a dashboard is **remotely drivable**. When a message arrives at the
dashboard containing a **widget ID**, the dashboard applies it to that widget
immediately — no refresh, no polling. This page documents the exact payload keys
the dashboard listens for.

## Mental model

Think of each widget as having a **radio receiver tuned to its widget ID**. Any
message addressed to the dashboard whose payload names that ID is picked up by
that widget — and depending on which keys the payload carries, the widget changes
its **value**, its **visibility**, or even its **position, size, and rotation** on
the canvas, live.

The firmware helpers (`updateWidget`, `updateWidgetPosition`, …) are just
conveniences that build these payloads for you — a device can also send them raw.

## The envelope

A device sends the standard message envelope; the dashboard reads the payload:

```json theme={null}
{
  "targetId": "<dashboard / user id>",
  "payload": { "widgetId": "tempGauge", "value": 27.4 }
}
```

Everything below describes what goes inside `payload`.

## Payload reference

### Value update — `value`

```json theme={null}
{ "widgetId": "tempGauge", "value": 27.4 }
```

Sets the widget's value: a number for a Gauge/Slider, **text for a Label**, an
array for a Chart/Heatmap, text to speak for Text-to-Speech, a URL for an Image.

```json theme={null}
{ "widgetId": "statusLabel", "value": "Pump running" }
```

<Note>
  **No `value` key? The whole payload becomes the value.** If the payload has other
  keys (besides `widgetId` and the transform keys), they're passed to the widget as
  an object — this is how structured widgets receive rich data:

  ```json theme={null}
  { "widgetId": "adi", "roll": 12.5, "pitch": -3.2 }
  ```

  The Attitude Indicator receives `{ roll: 12.5, pitch: -3.2 }`. The 3D Viewer
  accepts `{ roll, pitch, yaw, modelUrl, modelColor, autoRotate, zoom, … }` the
  same way.
</Note>

### Visibility — `v`

```json theme={null}
{ "widgetId": "alertPanel", "v": 1 }
```

`1` shows the widget, `0` hides it — reveal an alert panel or hide controls from
the device side.

### Position, size, rotation — `x` `y` `w` `h` `r`

```json theme={null}
{ "widgetId": "marker", "x": 120, "y": 80 }          // move
{ "widgetId": "panel",  "w": 400, "h": 250 }          // resize
{ "widgetId": "needle", "r": 45 }                     // rotate (degrees)
{ "widgetId": "hud",    "x": 10, "y": 10, "w": 200, "h": 120, "r": 0 }
```

Any combination works, numbers or numeric strings. The widget moves/resizes/
rotates on the canvas in real time — a device can literally animate the layout.

### Countdown control — `hr` `min` `sec`

```json theme={null}
{ "widgetId": "runTimer", "hr": 0, "min": 5, "sec": 30 }
```

Starts the [Countdown Timer](/dashboard/widgets/countdown-timer) with that
duration (5m30s here).

### Toast notification — no widget ID

```json theme={null}
{ "type": "toast", "text": "Watering complete", "visibility_time": 4000 }
```

Shows a toast on the dashboard for `visibility_time` ms (min 2s, default 5s).
For richer dialogs, use the firmware
[dialog helpers](/firmware/arduino/api-reference#dialogs).

## How the firmware helpers map to these messages

| Firmware call (Arduino)                             | Payload it sends                                |
| --------------------------------------------------- | ----------------------------------------------- |
| `updateWidget(target, "id", 27.4)`                  | `{ "widgetId": "id", "value": 27.4 }`           |
| `updateWidget(target, "id", "text")`                | `{ "widgetId": "id", "value": "text" }`         |
| `updateWidgetPosition(target, "id", x, y, w, h, r)` | `{ "widgetId": "id", "x", "y", "w", "h", "r" }` |
| `updateCountdown(target, "id", "0", "5", "30")`     | `{ "widgetId": "id", "hr", "min", "sec" }`      |
| `updateFlightAttitude(target, "id", roll, pitch)`   | `{ "widgetId": "id", "roll", "pitch" }`         |
| `sendTo(target, builder)`                           | Any raw payload you build — full control        |

The ESP-IDF `hyperwisor_update_widget_*` functions produce the same shapes.

## Worked examples

### Change a label's text from the device

```cpp theme={null}
// Arduino — the label with ID "statusLabel" updates instantly
device.updateWidget(targetId, "statusLabel", String("Cycle complete"));
```

### Move and rotate a widget from the device

```cpp theme={null}
device.sendTo(targetId, [](JsonObject &p) {
  p["widgetId"] = "windArrow";
  p["r"] = heading;          // rotate to the live heading
});

device.updateWidgetPosition(targetId, "marker", 120, 80, 40, 40);
```

### Reveal an alert panel when something goes wrong

```cpp theme={null}
device.sendTo(targetId, [](JsonObject &p) {
  p["widgetId"] = "alertPanel";
  p["v"] = 1;                // show it
});
```

### Test it with no hardware

Open the [LiveLink Simulator](/studio/livelink-simulator), connect the Device
side, and send any of the JSON payloads above from the **Send from Device** panel
— watch the widget react on the dashboard.

## Typed message variants

Devices can also send typed messages (`"type"` + widget-specific key); the
dashboard processes these too:

| `type`                           | Key it reads                  |
| -------------------------------- | ----------------------------- |
| `widget_update`                  | `value` (any)                 |
| `widget_status`                  | `status` (string)             |
| `widget_gauge` / `widget_slider` | `value` (number)              |
| `widget_switch`                  | `checked` (boolean)           |
| `widget_button`                  | `action` (+ optional `value`) |
| `widget_heatmap`                 | `value` (array of points)     |
| `widget_text_to_speech`          | `value` (text to speak)       |

The direct payload format above is the recommended one — it's what the firmware
helpers emit.

<CardGroup cols={2}>
  <Card title="Binding data" icon="diagram-project" href="/dashboard/binding-data">
    The widget-ID contract these messages ride on.
  </Card>

  <Card title="LiveLink Simulator" icon="tv" href="/studio/livelink-simulator">
    Fire these payloads with no hardware.
  </Card>
</CardGroup>
