Tags
A tag is a named value with engineering metadata. This page is the complete property reference.
Tags hold configuration only. The live value lives in the runtime store; history lives in the historian.
General properties
| Property | Type | Description |
|---|---|---|
| Name | string | The leaf name. Combined with its ancestors it forms the tag path. |
| Enabled | bool | A disabled tag is not polled, not evaluated for alarms and not historised. Its configuration is kept. |
| Data type | enum | See data types. |
| Unit | string | Engineering unit — °C, bar, %, RPM. Used as a label by widgets, trends and exports. |
| Description | text | What this value means. Shown in pickers, tooltips and the AI assistant's context. Write it. |
| Writable | bool | Whether the tag accepts writes at all. Off by default. |
| Write level | 0–3 | Required operator write-security level. 0 = any writer, 3 = admin. Meaningful only when writable; enforced server-side. |
| Source | device | internal | expression | Device-backed (has a binding), a QUBIQ-owned memory tag, or computed from other tags. |
| Format string | string | Display format, e.g. #,##0.00. Applied consistently wherever the tag is shown. |
Data types
| Type | Range / notes |
|---|---|
boolean | true / false |
sbyte, byte | 8-bit signed / unsigned |
int16, uint16 | 16-bit |
int32, uint32 | 32-bit |
int64, uint64 | 64-bit |
float | 32-bit IEEE-754 |
double | 64-bit IEEE-754 |
string | Text |
datetime | Timestamp |
json | Structured payload |
array | Array, with dimensions carried from the source |
Match the tag's data type to the source. A mismatch surfaces as a conversion failure with Bad
quality — which is correct behaviour, and much better than a silently truncated number.
Scaling
Scaling converts the device's raw range into engineering units. It is applied after the protocol read and before history, alarms and screens — so everything downstream sees the same engineering value.
| Property | Description |
|---|---|
| Raw low / Raw high | The device's range, e.g. 0 – 27648, or 4 – 20 for a current loop. |
| Eng low / Eng high | The engineering range, e.g. 0 – 100 °C. |
| Invert scaling | Reverses the curve, for sources where raw-high means engineering-low. |
| Clamp scaled | Bound the result to the engineering range. On by default. |
All four range values must be set for scaling to apply.
Raw 4 – 20 (mA) → Eng 0 – 100 (°C)
raw 12 mA → 50 °C
Scaling in each widget means the historian stores raw counts, alarms compare against raw counts, and every new screen has to repeat the arithmetic. Do it here.
Quality and validation
| Property | Description |
|---|---|
| Quality default | Quality assumed before the first read: Good, Bad, Uncertain, Unknown. |
| Deadband | Change threshold. A change smaller than this is not propagated or stored. |
| Stale after (ms) | Mark the value stale if no update arrives within this window. |
| Validation rule | Optional constraint applied to incoming values. |
Quality
Quality travels with every value, through bindings, expressions, alarms and charts.
| Quality | Meaning |
|---|---|
Good | The value is trustworthy. |
Uncertain | Readable but suspect — a stale value, a degraded source. |
Bad | Not trustworthy — connection down, read error, conversion failure. |
NotFound | The address does not exist on the source. |
Widgets show bad quality rather than rendering a stale number as if it were current. Expressions propagate the worst quality of their inputs, so a computed value cannot look better than the data behind it.
Deadband
The single most effective control on both network traffic and history volume.
| Deadband | Effect |
|---|---|
0 | Every change propagates. Correct for discrete states and counters. |
| Small (0.1–0.5% of span) | Removes sensor noise; charts are visually unchanged. |
| Larger (1–2% of span) | Substantial storage saving; adequate for slow analogue values. |
Set it once here, and every consumer benefits.
Stale after
Push protocols (MQTT, OPC-UA subscribe, TCP) only send on change. A value that never changes is indistinguishable from a dead link — unless you set stale after. When the window expires without an update, quality degrades and the screen shows it.
Set it to a few times the expected update interval. It is the cheapest possible dead-link detection.
History
| Property | Description |
|---|---|
| Enable history | Stream this tag's values to the historian. |
| Store interval (ms) | Force a stored point at this interval even if nothing changed — proves the signal was alive. |
| Storage connection | Which store receives it. Normally the designated system historian. |
History respects the tag's deadband, so noise is filtered before it reaches storage.
Alarming
| Property | Description |
|---|---|
| Alarm enabled | Per-tag master switch. Alarm definitions are only evaluated when this is on. |
Individual alarms — mode, setpoints, priority, delays, deadband, latching — are configured per alarm
on the tag. One tag can carry many alarms (Hi, HiHi, Lo, LoLo, Fault).
Write security
Two independent gates protect device writes:
- Writable — off by default. A non-writable tag rejects every write.
- Write level (0–3) — the minimum runtime operator level required. Enforced server-side in the write gate, so a modified client cannot bypass it.
| Level | Typical use |
|---|---|
| 0 | Unrestricted for anyone with write capability — HMI setpoints of no consequence |
| 1 | Routine operator actions |
| 2 | Supervisor actions — recipe changes, mode switches |
| 3 | Administrator only — calibration, safety-adjacent parameters |
Internal (memory) tags
Set source to internal for a value QUBIQ owns:
- Operator setpoints and targets
- Counters and accumulators
- Computed KPIs written by a script or pipeline
- Mode and state flags
Internal tags have no binding, are persisted without expiry, and are written from scripts
(system.tag.write), pipelines or screens. An initial value can be supplied at creation to seed
them.
Expression tags
Set source to expression for a value computed from other tags. The expression engine
recalculates it whenever an input changes, and the result behaves like any other tag: it can be
bound to a widget, trended, alarmed and read from a script.
Line1/Filler/Motor1/Power = Speed * Torque * 0.105
Line1/OEE = Availability * Performance * Quality
Line1/Filler/Motor1/Overspeed = Speed > 2800
An expression tag is a read-only projection. It has no protocol binding and rejects external writes — there is nowhere for a written value to go, because the next input change would overwrite it.
Settings
| Setting | Values | Purpose |
|---|---|---|
| Expression | text | The formula. Reads other tags by absolute path. |
| Evaluation mode | on_change (default) · interval | Recompute when an input changes, or on a fixed period. |
| Evaluation interval | ms | Required for interval mode. Also the tick period when the expression reads the clock. |
| Minimum interval | ms, 0 = unlimited | Rate-limits the output. A fast input does not have to mean a fast output. |
| Quality policy | worst_of_inputs (default) · always_good · explicit | How the result's quality is derived. |
Dependencies are worked out for you
You never list the inputs. They are extracted from the expression when you save it, and the engine indexes by them, so a tag recomputes only when something it actually reads changes.
That index answers the other direction too: what breaks if I delete this tag? is a question the system can answer before you delete it, rather than after.
Quality is not an afterthought
The default worst_of_inputs means an expression reading one Bad input produces a Bad result.
That is almost always what you want — a computed KPI built on a dead sensor should not look healthy.
Reach for always_good only when the expression genuinely does not depend on input quality (a
constant, or a pure clock reading), and explicit when the expression decides quality itself.
→ Expression functions for the built-in function reference.
Using the clock
An expression that reads the current time is recognised as such and subscribed to a periodic tick, so it keeps recomputing even when no input tag changes. Set the evaluation interval to control how often — a "minutes since last batch" tag does not need to tick every second.
When not to use one
| Arithmetic, unit conversion, bit unpacking, thresholds | An expression tag |
| Anything with a database round trip, an API call, or a loop | A pipeline |
| A value a human or a screen sets | An internal tag |
An expression that needs a comment to explain it has usually outgrown being an expression.
Reading and writing tags in scripts
result = system.tag.read("Line1/Filler/Motor1/Speed")
if result["quality"] == "Good" and result["value"] > 2800:
system.tag.write("Line1/Filler/Motor1/SpeedSetpoint", 2500)
const r = await system.tag.read("Line1/Filler/Motor1/Speed");
if (r.quality === "Good" && r.value > 2800) {
await system.tag.write("Line1/Filler/Motor1/SpeedSetpoint", 2500);
}
Always check quality before acting on a value. A Bad-quality read still returns a value — the
last known one — and acting on it is how a dead sensor drives a live process.
Batch where you can: system.tag.readAll([...]) is one round trip, a loop of read is N.
Permissions
Reading tags and their bindings needs View the namespace. Creating, editing, deleting and bulk-deleting tags all need Manage tags; changing a binding needs Bind a tag to a protocol.
Checklist for a well-formed tag
- Data type matches the source
- Unit set
- Description written in plain language
- Scaling configured if the device sends raw counts
- Deadband set for analogue values
- Stale-after set for push sources
- History enabled only where someone will look at it
- Writable off unless it needs to be on — and a write level if it is