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 — push-driven, with first-class Sparkplug B support
OPC UASubscribe to an OPC UA server — per-tag node binding, with quality (good / uncertain / bad) preserved end to end
AVEVA PIRead live values + federated history from a PI Web API server
IgnitionStream tag values + federated history from an Ignition gateway via the Control Seat Ignition module
TableRun a SQL, Flux, or PromQL query against a connected datasource and surface the result as a table — for data table components and multi-row bindings
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.

History reads are federated — Control Seat never copies PI history into its own historian. Chart queries against PI-bound tags pull recorded values on demand from the configured PI Web API server. Your PI install stays the source of truth; Control Seat is the live + analysis lens.

Ignition

Control Seat ships an Ignition module (ControlSeat-Connector.modl, downloadable from the download page) plus a cloud-side / gateway-side connector that talks to it.

  • 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.
  • Federated history — like PI, history reads for Ignition-bound tags hit the Ignition gateway live instead of duplicating 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 ClickHouse. 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