Tags & Data Sources

Dashboards don't connect directly to databases or APIs. Instead, they bind to tags. Tags are the universal data layer that sits between your data sources and your dashboards.

What Are Tags?

A tag is a named value that updates in real time. Examples:

default/temperature        → 72.5
default/pump/speed         → 1450
default/alarms/high_temp   → true

Tag paths use / as the separator between folders and the tag name. Tag names themselves can contain any characters except /.

Every chart, gauge, text block, or color binding in your dashboard reads from tags. When a tag value changes, every dashboard bound to it updates instantly.

Connecting Data Sources

Tags can pull data from multiple source types:

SourceDescription
ManualSet values directly — good for setpoints, constants, and testing
SQLPoll a PostgreSQL, MySQL, or other SQL database on an interval
HTTPPoll a REST API endpoint and extract values from the JSON response
InfluxDBQuery InfluxDB v2 with Flux
PrometheusQuery Prometheus with PromQL
MQTTSubscribe to an MQTT broker for real-time updates, with native Sparkplug B support
OPC UASubscribe to an OPC UA server, with per-tag node binding and source quality preserved
AVEVA PIRead live values and on-demand history from a PI Web API server
IgnitionStream tag values and on-demand history from an Ignition gateway via the Control Seat Ignition module
TableRun a SQL, Flux, or PromQL query against a connected data source and use the result as a table
SimulationGenerate synthetic data for demos and testing
ComputedCalculate values from other tags using JavaScript

No matter what the source is, your dashboard binds to the tag the same way. If you swap a simulated source for a real database later, the dashboard doesn't need to change.

Table Tags

A Table tag is backed by a live query against one of your connected datasources and produces a table of rows as its value. Pick the datasource, write the query in the built-in editor, preview the result, and save — the tag's value updates as the query returns new results.

Table tags are useful when you need:

  • A tag whose value is a table of rows (for data table components)
  • A derived result that requires a real query (joins, filters, aggregations) rather than a simple point read
  • A tag backed by a SQL datasource, InfluxDB Flux expression, or PromQL expression with minimal setup

The query editor

The tag form has a built-in query editor with:

  • Syntax highlighting for SQL, Flux, and PromQL
  • Schema-aware autocomplete — for SQL datasources, the editor completes table and column names discovered from the connected database
  • Theme-aware — matches the app's light/dark theme
  • Result preview — run your query inside the modal and see the result (including multi-row tables) before saving

The same editor is used wherever you write datasource queries in Control Seat — tag sources, chart data queries, and data table bindings — so the experience is consistent everywhere.

Binding to data tables

Data table components on your dashboard can bind directly to a table tag. Drop a data table, pick a table tag, and the table renders the live query result with sorting and pagination. Only table tags are selectable for data-table bindings — scalar tags won't appear in the dropdown, so you can't accidentally wire a table to a single value.

MQTT and Sparkplug B

Unlike SQL or HTTP sources (which Control Seat polls on an interval), MQTT is push-driven: the broker delivers messages as they happen and tag values update in real time. Configure brokers in Gateway → Connectors → MQTT — broker URL (mqtt://, mqtts://, ssl://, ws://, wss://), credentials, optional TLS client cert, keep-alive interval.

Cloud vs self-hosted networking. The gateway opens an outbound TCP connection to your broker, so MQTT works on cloud SaaS as long as the broker is reachable from the public internet (or via a VPC peering / VPN coordinated with us). On self-hosted deployments this is usually a non-issue — the gateway and broker often sit on the same plant network.

Once a broker is configured, the tag form has three subscription modes:

  • Topic per tag — explicit topic, value type (auto-infer / string / number / boolean / JSON), QoS 0 or 1, optional JSONPath for picking values out of larger JSON payloads.
  • Wildcard auto-create — point a wildcard subscription at a topic tree (factory/floor1/#) and tags auto-materialize as messages arrive. Good for "I just want everything under here".
  • Sparkplug B — full Sparkplug B support, with the protocol's hierarchy modeled directly in your tag tree.

Sparkplug B specifics

Sparkplug B is a layer on top of MQTT that's common in industrial deployments. Control Seat handles it natively:

  • Node and device hierarchy — messages on spBv1.0/<group>/NBIRTH/<edge> auto-create the metric tree under tag folders matching <group>/<edge>/<metric>. Device-level messages use the four-segment form <group>/<edge>/<device>/<metric>. The folder layout in the tag tree mirrors your physical edge / device topology one-to-one.
  • Aliases and rebirth — Sparkplug B optimizes bandwidth by sending integer aliases instead of metric names after the initial NBIRTH. We track aliases per session; if the gateway restarts and we lose the alias table, we send a Rebirth command (Node Control) to the edge node to recover.
  • Death cascade — when an edge node sends NDEATH (or just goes offline), every metric under it is marked bad quality with the disconnect reason — never silently overwritten with stale values. DDEATH only marks the specific device that died.
  • PropertySet metadata — Sparkplug payloads can carry per-metric metadata (engineering unit, low/high range). We capture and persist it on the tag (unit, eng_low, eng_high) and expose it via the tag API for use in gauges and chart axes.

Tag quality and disconnects

When any source goes offline (broker drop, network partition, server stopped), Control Seat marks every tag bound to that source with a bad quality flag plus the disconnect reason — instead of leaving tag values frozen at their last good value. This applies across all push sources, not just MQTT.

For dashboards, that means a chart looking at "pump RPM" can tell the difference between "the pump is genuinely at 1450 RPM" and "the broker died ten minutes ago, so we don't actually know what RPM is right now." Quality propagates through bindings and is queryable from scripts.

OPC UA

Configure servers in Gateway → Connectors → OPC UA (endpoint URL, security mode, authentication), then point any tag at a server + node from the tag form. Values stream into Control Seat the moment the OPC UA server publishes them; type conversion handles Int16 / Float / Boolean / String / DateTime automatically.

  • Quality preserved end-to-end. OPC UA's good / uncertain / bad status follows the value through Control Seat — charts, bindings, and scripts all see it.
  • Watchdog. Every connection is monitored against its configured publishing interval. If a server goes quiet, all tags bound to it are marked bad quality with a "no recent publish" reason and the gateway tries a fresh connect.
  • Practical deployment note. OPC UA servers are typically firewalled off from the public internet, which makes self-hosted the realistic deployment for this protocol — the gateway sits on the same plant network as the OPC UA server. Cloud SaaS supports it but requires you to expose the OPC UA endpoint to controlseat.com via a network you control (VPC peering / VPN / static-IP allowlist).

AVEVA PI

Configure a PI Web API server in Gateway → Connectors → PI (endpoint, auth, optional Kerberos), then point any tag at a PI point and live values stream in at the configured poll interval.

Control Seat reads PI history directly from the configured PI Web API server when you need it, so your PI system remains the system of record.

Ignition

Control Seat ships an Ignition module for supported Ignition versions, available from the download page, plus the matching connector inside Control Seat.

  • Install the module on an Ignition gateway, paste the API key from Control Seat's connector page, and the module dials Control Seat over a persistent WebSocket.
  • Browse the Ignition tag tree from Control Seat's tag browser and bulk-import the subtrees you care about. Imported tags bind to their Ignition source.
  • Direct history access — like PI, history for Ignition-bound tags is read from Ignition when needed instead of copied into Control Seat's historian.
  • Scope control — only the tags you've imported are streamed back to Control Seat. Re-import to expand or contract the scope on the fly without restarting Ignition.

Live Data Flow

Data source (database, API, device, etc.)
  → Tag system
  → WebSocket stream
  → Your dashboard updates in real time

The editor preview and the published dashboard both use the same live data stream, so what you see while building is what your users see in production.

Historian

Control Seat automatically records tag history to its built-in historian. You can query historical data for:

  • Raw points — every recorded value in a time range
  • Last values — the most recent value for a set of tags
  • Aggregates — averages, min, max, and count over time buckets

Historian data powers time-series charts and historical replay features.

Example Tag

{
  "path": "process/pump/speed",
  "type": "float64",
  "writable": true,
  "source_kind": "sql"
}

Why Tags?

  • One naming model — dashboards use tag paths regardless of the underlying source
  • Portable bindings — swap data sources without changing dashboards
  • Controlled writes — write operations go through a managed path, not raw device APIs
  • Shared address space — live values, historian, simulation, and computed values all use the same tag paths