Skip to content
View as Markdown

Virtual ​

An in-memory connector with no hardware behind it. A Virtual connector holds values, computed properties and methods that dashboards and scripts read and write exactly like a device — but nothing is connected. Use it as a shared scratchpad: setpoints a dashboard slider adjusts and a script reads, status text a script writes and a dashboard shows, counters, flags, derived values.

The driver itself declares no properties and no actions. Everything the connector exposes comes from the connector file's own properties: and methods: blocks. State lives in the file's module-scope variables.

Safety gate

This driver ships with requiresSafetyGates: false — there is no hardware to protect, so writes and calls bypass the safety gate entirely and no audit rows are written. See Per-driver opt-out.

Declaring one ​

The driver: keyword is optional. A connector file with no driver: / protocol: / engine: key resolves to Virtual automatically, as long as every top-level key is a standard connector key:

config, properties, methods, poll, ai, hide, expose, safety, allowedConnectors, allowedHosts

javascript
// workspace/connectors/store.js
let setpoint = 20;
let running = false;
let status = "Idle";

export default {
  ai: { instructions: "In-memory store with no hardware attached. Safe to read and write freely." },

  properties: {
    setpoint: { get: () => setpoint, set: (v) => { setpoint = Number(v); },  description: "Target setpoint", poll: true },
    running:  { get: () => running,  set: (v) => { running = Boolean(v); },  description: "Run flag",        poll: true },
    status:   { get: () => status,   set: (v) => { status = String(v); },    description: "Status line",     poll: true },
    summary:  { get: () => `${status} — setpoint ${setpoint}${running ? " (running)" : ""}`, poll: true },
  },

  methods: {
    reset: [() => { setpoint = 20; running = false; status = "Idle"; }, "Restore defaults"],
  },
};

driver: "Virtual" (or engine: "Virtual") is accepted too if you prefer the keyword spelled out — that's what the Add Connector template uses.

Unknown keys still fail ​

Only files whose top-level keys are all standard resolve to Virtual. A misspelt keyword is an unknown key, so it keeps the usual load error and the connector shows as disabled in the Hardware panel with the offending key named:

Connector config missing 'driver' / 'protocol' / 'engine': …/psu.js (unrecognised top-level key: drivr)

This is deliberate: drivr: "Webcam" must not quietly turn into an empty store.

.json connector files are unaffected — they still require an explicit "driver" field.

Properties ​

None from the driver. A property with a set is writable (R/W); one with only a get is read-only (R). The type shown in the Hardware panel is inferred from the last value read.

Actions ​

None from the driver. Declare them under methods: in any of the three usual forms (bare function, [fn, "description"], { fn, description }).

Config Options ​

None. A config: block is allowed but ignored by the driver — use it for your own constants if you like.

Using it ​

From a script:

javascript
const s = connector("store");
s.setpoint = 42;          // write — dashboards update immediately
if (s.running) { … }      // read
s.reset();                // method

From a dashboard: bind any widget to store.setpoint, store.running, store.status, … A slider bound to store.setpoint writes it; a gauge bound to the same property follows.

From another connector: list it in that connector's allowedConnectors and call connector("store") from its methods.

Polling and updates ​

  • A direct property write (script, dashboard, AI) updates the value and broadcasts a state: event immediately. No polling is involved.
  • A value changed inside a method (reset() above) is only noticed by the poller, so mark such properties poll: true (or list them in a top-level poll: [...] array) to keep dashboards in sync.
  • Computed read-only properties (summary) are re-read on each poll, so they follow the values they derive from.

Persistence ​

In memory only. Values reset to the file's initial let values whenever the server restarts or the connector reloads. If a value must survive, write it out with FileAccess and read it back in a getter or a startup script.

Limits ​

Virtual connectors count against your tier's connector limit like any other connector.

Muxit — Hardware Orchestration Platform