Skip to content

Everything is a tag

A tag is a named value at a path. It is the only data structure in JasperNode you really need to learn, because everything is one: sensor readings, setpoints, computed values, connector configuration, operating mode, system metrics, even log buffers. They all live in a single in-memory tag tree.

A tag’s address — its Tag ID — is its path plus its name, joined with /:

factory/line1/temperature
└──── path ────┘ └─ name ─┘

Each tag carries three things: a value, live stats, and durable properties.

A value is one of:

TypeUse
numberanalog readings, setpoints, counts (64-bit float)
booleanon/off, run/stop, alarms
stringstates, labels, short text
bytesbinary payloads (frames, blobs) — fetched on demand
null”no value” / not yet written

A numeric tag can declare a decimals precision. Rounding is applied before the engine decides whether the value changed, so a write that rounds to the same number produces no event and no subscriber churn.

Every tag tracks, automatically:

  • previous value, and timestamps for the current and previous change (ts, prevTs) and the last write (setTs);
  • sourcewho set it: ui, script, system, an MQTT connector, a Modbus instance, and so on. Every write is attributed.

There is also a derived quality: good (a connected writer connector is producing it), stale (its writer disconnected but it has prior data), uncertain (linked but never written), or unknown (no connector linked — e.g. a script or UI value).

Properties change rarely and are saved with the tag:

  • description — human text;
  • valueType and decimals;
  • script — the optional attached logic (see Logic & the Logic Cycle);
  • connector linkage — which connectors touch the tag and in what role.

Every tag also has an rid — a durable 64-bit identity assigned when it is created. The rid is the tag’s real identity:

  • rids are never reused. Delete a tag and its rid is gone forever; a new tag at the same path gets a fresh rid.
  • path and name are just metadata — you can rename or move a tag and its rid (and everything subscribed to it) follows.

You rarely type an rid, but it is why renaming a tag never silently re-points a subscription at the wrong data, and why persisted references survive reorganisation.

Paths form a folder hierarchy you organise freely: factory/line1/, hvac/building_a/, modbus_data/vsd_ethernet/. Folders are just shared path prefixes — there is nothing to “create” beyond giving a tag a path.

Subscriptions use MQTT-style wildcards, which makes it easy to watch a whole area at once:

PatternMatches
factory/line1/temperatureexactly that tag
factory/+/temperaturetemperature under any single sub-path (line1, line2, …)
factory/#every tag anywhere under factory/

+ matches exactly one path segment; # matches the rest of the path and must be last. (Subscribing to the bare root # is not allowed — it would wake on every change in the system.) The IDE, the AI agent, connectors and scripts all use this same matching.

The tree is split into user space and the system space (__sys/). The split is about who may write where:

SpaceYou can edit?Holds
User spaceYes — fullyYour application: I/O, setpoints, computed values, logic. Any path not under __sys.
__sys/host/No (regenerated each boot)Host machine facts: a 1 Hz clock, OS, network, CPU/memory/disk
__sys/node/about/NoEngine identity: version, uuid, load state
__sys/node/user/Yes — the only editable __sys subtreeApp config, connector configs and enable switches, tool parameters
__sys/node/service/No (system writes only)Connector status & diagnostics, manifests, the operating mode
__sys/node/stats/NoEngine internals: ring health, counts, subscriber pressure
__sys/node/logger/NoLog ring buffers (debug / info / warning / error)

Two consequences worth internalising:

  • You configure connectors by writing tags. Saving a Modbus instance in the IDE writes __sys/node/user/connectors/modbus/<id>/config; flipping its switch writes the sibling enabled tag. The AI agent does the exact same thing.
  • __sys/node/user/** is the project boundary. Only that subtree is captured by backup/restore and carried between nodes; everything else is regenerated. See System tags for the full map.
  • Every tag keeps its previous value for free. A tag can opt in to deeper history — up to 1000 recent entries — for trends and troubleshooting; scripts can read that history of tags they depend on.
  • A tag marked memory-only is never written to disk — the equivalent of non-retentive PLC memory, for transient counters, timers and scratch values.

Everything else about how tags reach disk is in Architecture → Persistence.

Open Node Views → Tag Tree. Expand __sys/host/clock to watch the live 1 Hz clock; expand a connector’s base path (e.g. modbus_data/…) to see field values update each cycle. Select any tag to edit its value, description and properties, or to attach logic.

The Tag Tree: folders on the left, the selected tag's properties on the right