# Simulated

> Synthetic in-app signals for testing, training and dashboard building without hardware.

The Simulated driver produces synthetic signals inside the app, with no equipment
and no network involved. It is a first-class driver, not a shortcut: its devices
are onboarded, polled and cached through exactly the same runtime path as real
hardware, so plots, data types, quality indicators and write behavior all work as
they would in the field. Use it to try the [Connector](connector) model, build
dashboards before equipment arrives, or stage a demonstration.

## Device {#device}

A simulated device has no connection fields — only its name and the default
**Poll interval (ms)** (1000 by default). Its Base URI is
`simulated://<device>`; the device segment is informative only, because every
behavior lives on the tags.

## Discovery {#discovery}

**Discover** needs no target and lists the built-in catalog: one ready-to-add
instance of each archetype, tags included. Untick the channels you do not want
before adding.

| Model | Instance | Channels |
| --- | --- | --- |
| Universal Controller | UC-01 | ProcessValue (sine), SetPoint (writable setpoint, default 50), Output (ramp), RunStatus (Run/Stop/Pause/Fault) |
| Electrical Power Meter | PM-01 | Voltage, Current, ActivePower and Frequency (random walks around 230, 10, 2300 and 60, polled at 250 ms), PowerFactor (sine) |
| Production Counter | CNT-01 | Count (Int32 counter), Rate (random walk around 100), Running (toggling Boolean) |
| Status Panel | STS-01 | State (Run/Stop/Pause/Fault), Alarm (toggling Boolean), Uptime (Int64 counter) |
| Type Showcase | SHOW-01 | One channel per OPC UA built-in type, fifteen in all — useful for exercising every value display |

## Tags {#tags}

A simulated tag has no address to type: the tag name is the point. Every OPC UA
built-in data type is available, and all three access modes. What the tag produces
is chosen with **Signal kind** on the Source card; the picker offers only the
shapes compatible with the tag's data type, and changing the data type snaps an
incompatible shape to a sensible default. A tag whose access allows writing is
offered only the shapes that take a write, Setpoint hold and Pulse, and changing
the access snaps the shape the same way.

| Signal kind | Produces | Compatible types | Writable |
| --- | --- | --- | --- |
| **Sine** | A smooth wave with a light ripple, seeded from the tag name, so differently named tags move differently and a restart reproduces the same curve | numeric | no |
| **Ramp** | A triangle wave (up, then down), period 10 to 59 s seeded from the tag name | numeric | no |
| **Random walk** | Realistic meter noise: steps from the last value with mean reversion toward the default value (50 when unset), step size 1% of the center (at least 0.5) | numeric | no |
| **Counter** | A monotonically increasing integer: starts at the default value (0 when unset) and adds 1 per read, so the rate follows the poll interval | numeric | no |
| **Toggling boolean** | A Boolean that alternates every second | Boolean | no |
| **Enumerated text** | A string cycling through a fixed list of states, one step every 3 s | String | no |
| **Clock** | The current time, sampled at each read | DateTime | no |
| **Random GUID** | A new random Guid per read | Guid | no |
| **Random bytes** | An 8-byte random payload per read | ByteString | no |
| **Setpoint hold** | Holds a default value until written; a write replaces what every following read answers | any | yes |
| **Pulse** | A momentary point: rests at a baseline, and a write holds the written value for a stated number of seconds before falling back on its own | any | yes |

A tag created without an explicit kind gets a lively default: writable tags become
**Setpoint hold** (so writes stick), and read-only tags get a type-appropriate
generator (numeric → Sine, Boolean → Toggling boolean, String → Enumerated text,
DateTime → Clock, Guid → Random GUID, ByteString → Random bytes). **Pulse** is never a default —
a point that hands a written value back and then abandons it is a deliberate
choice.

### Parameters in the panel {#parameters-in-the-panel}

Two parameters are edited directly on the Source card:

| Field | Shown for | Meaning |
| --- | --- | --- |
| **Default value** | Random walk, Counter, Setpoint hold | The walk's center, the counter's starting value, or the setpoint's answer until something is written. The input matches the tag type (checkbox for Boolean, date picker for DateTime, text otherwise). |
| **States** | Enumerated text | Semicolon-separated list to cycle through, e.g. `Run;Stop;Pause`. A blank or memberless list falls back to `Run;Stop;Pause`. |

### Advanced signal parameters {#advanced-signal-parameters}

The remaining shape parameters travel as query arguments on the tag's stored
address (for example `ProcessValue?min=20&max=80&period=30`). The panel does not
edit them but preserves them across every edit; seeded examples use them, and an
agent can set them through the tag tools on the [agent](agent) surface.

| Argument | Applies to | Meaning | When absent |
| --- | --- | --- | --- |
| `min`, `max` | Sine | The band the wave runs in; the output is clamped to it | A band seeded from the tag name (amplitude 10 to 49 around an offset of 20 to 49), unclamped |
| `period` | Sine | Wave period in seconds | A frequency seeded from the tag name (0.05 to 0.24 Hz) |
| `phase` | Sine | Phase offset in degrees | Seeded from the tag name |
| `default` | Random walk, Counter, Setpoint hold | Same value the panel's Default field edits | 50 / 0 / type default |
| `values` | Enumerated text | Same list the panel's States field edits | `Run;Stop;Pause` |
| `baseline` | Pulse | The value the point rests at between episodes, parsed as the tag's type | The type's zero value (the current time for DateTime, empty for String) |
| `hold` | Pulse | How many seconds one written episode lasts | 10 s |
| `warmup` | any | Seconds after connect before the first read answers, like an instrument that needs to stabilize; the poll loop absorbs the wait | none |

## Writes {#writes}

- **Setpoint hold** accepts writes and answers with the written value from then on.
  The held value lives in memory for as long as the device stays connected; it is
  not stored in configuration, so disabling the device or restarting the app
  returns the point to its default.
- **Pulse** takes a write as an episode: it answers with the written value until
  the hold runs out, then falls back to its baseline. A second write during an
  episode replaces it whole, so holding a button down restarts the hold instead of
  stacking two.
- Every other kind refuses writes; an attempted write is journaled once per tag
  rather than flooding the log on every poll.

As with any driver, the write field takes the engineering value and the
[value pipeline](connector-value-pipeline) is reversed before the raw value reaches the signal.

## Limits worth knowing {#limits-worth-knowing}

- Values are synthesized per run. Deterministic shapes (Sine, Ramp, Clock)
  reproduce the same curve after a restart; stateful ones (Counter, Random walk,
  Setpoint hold, Pulse) start over.
- Pairing a signal kind with an incompatible data type (possible only through
  programmatic configuration; the panel constrains the picker) makes the tag fail
  every read, with a warning journaled once.
