Skip to content

Output Datasources

An output datasource writes data out to an external system — a PLC, broker, or control application. Use Output Mapping to map prediction channels to a destination tag or column; you can also send a payload directly with an on-demand test write.

ProtocolCapability
OPC-UAWrite to a node (synchronous)
MQTTPublish to a topic at QoS 1, retain off by default
CSVAppend rows to a rotating file — one column per mapped tag, plus timestamp_utc
  1. Go to Datasources → Output, click + Create, and pick the protocol.

  2. Each protocol has its own fields. Secret fields are masked as *** after saving.

    {
    "endpoint": "opc.tcp://your-plc-host:4840",
    "securityPolicy": "None",
    "authentication": "Anonymous"
    }
  3. Open Output Mapping on the row and map at least one prediction channel to a destination tag — an MQTT topic, a CSV column, or an OPC-UA node address. The mapped tag is the sink-native address verbatim: an MQTT tag of test publishes to the topic test, with no prefix added.

  4. Save the output, then enable it. An output must be enabled before it will deliver predictions or accept a test write.

The MQTT sink publishes at QoS 1, not QoS 0. At QoS 0 the broker acknowledges nothing, so a dropped message — most often a topic an ACL denies — still returns a successful write with no notification; QoS 1 gets a real acknowledgment (or a reason code) back from the broker.

retain stays false: a retained message replays to every future subscriber, so a dashboard opened hours later would read a stale value as current — a deliberate, per-deployment choice rather than a guessable default.

MQTT: reconnect, client ids, and Test Connection diagnostics

Section titled “MQTT: reconnect, client ids, and Test Connection diagnostics”

The MQTT sink reconnects with backoff after the broker drops the connection — a publish- only connection has nothing to re-subscribe, so recovery is just the reconnect itself. Without it, a transient outage used to be permanent.

An explicit Client ID is now role-suffixed (<id>-in for an input, <id>-out for an output) at connect time. This applies to every saved config, including one still storing the old shared aiboard default — so an input and output built from the same config no longer evict each other off the broker, and no edit is needed for that pairing. A blank id still auto-generates a unique id.

Eviction (SessionTakenOver) still happens if you explicitly reuse one Client ID across two datasources of the same role (two inputs, or two outputs), or if an external MQTT client connects with the same id as one of your datasources — give each a distinct value, or clear the field, in that case.

Test Connection classifies socket-level failures instead of showing a raw exception name: unreachable/refused/DNS failures map to connect_failed, and a cancelled connect maps to timeout. In Docker, localhost is the backend container, not your machine — the most common cause of a broker that’s reachable from your desktop client but not from AIBOARD. Use the broker’s service name instead (e.g. mqtt://mosquitto:1883 in the lab).

Output connections use the same security fields and ladder as inputs — Insecure for the bench, TLS with credentials for staging, mutual certificate authentication for production. Certificates are read from the /certs mount. See Security modes: Insecure, TLS, and Secure for the per-protocol field tables; they apply verbatim to outputs.

Two output-specific notes:

  • MQTT publishes at QoS 1 on the production path so a broker that drops a message (an ACL-denied topic is the classic case) surfaces as a failure instead of a silent success. Give the sink’s account publish rights on exactly the mapped topics.
  • CSV outputs write inside the jailed output directory only; rotation caps disk use. Secure the volume, not the protocol.

Test writes are sent through the API — POST /api/datasources/output/{id}/test-write, admin only. There is no Test Write button in the UI. Each sink validates its own payload shape: MQTT wants a topic, CSV wants columns/values, and OPC-UA wants a writes array. Use the matching example below.

{
"writes": [
{ "nodeId": "ns=2;s=Temperature", "value": 42.5 }
]
}

A successful write returns a success result; a protocol error returns a message such as OPC UA: node not found or MQTT: publish refused.

SymptomLikely cause
connect_failed on Test ConnectionBroker/endpoint unreachable, refused, or DNS failure — check network path, host, and port (MQTT 1883, OPC-UA 4840). In Docker, localhost means the backend container, not your machine.
timeout on Test ConnectionThe connect attempt was cancelled before finishing — check network path and port.
Enable fails with no_output_tags_mappedMap at least one output channel to a tag first via Output Mapping.
Datasource disabled errorEnable the output before sending a test write.
Node not found (OPC-UA)Check the NodeId format and that the node exists on the server.
Admin only (403)Test writes require an admin account.
Two MQTT inputs (or two outputs) keep disconnecting each otherBoth share the same explicit Client ID — clear one or give each a distinct value. An MQTT input and output on the same config are unaffected: each is auto-suffixed (-in/-out) at connect time, including on an older aiboard default.

See the Troubleshooting runbook for more.