How-to guide · for Developers, Engineers
MQTT and the UNS topics
Subscribe to live tag values on the MQTT broker built into every edge gateway, with the Unified Namespace topic layout, the JSON payloads and Sparkplug B.
At the end of this guide, an MQTT client of yours receives every tag value of a gateway's devices as it is read, on topics that follow the plant's Unified Namespace.
Before you start
You need:
- The address of the edge gateway whose devices you want. Each gateway runs its own broker and publishes only its own devices. The hub's gateway, SYSTEM, publishes the devices assigned to it.
- The gateway's MasterToken, from the
[MQTTBroker]section of that gateway's configuration file. If it is empty when the gateway starts, the gateway creates one and writes it into the file. - Network access to the broker port:
8883for TLS, or1883without TLS (MQTTBrokerPort). - For TLS: the platform CA, from Security > Certificate Store with Download CA.
- Any MQTT 3.1.1 or 5 client: MQTT Explorer,
mosquitto_sub, or a library such as Pythonpaho-mqtt.
Step 1: Connect
| Setting | Value |
|---|---|
| Host | the gateway's address |
| Port | 8883 with TLS, or 1883 (or MQTTBrokerPort) without TLS |
| User name | the gateway's MasterToken |
| Password | empty |
| TLS | on port 8883: verify the broker against the platform CA. See Connect with TLS. |
The broker accepts a connection when the user name is the MasterToken, when it is the Token of a device on that gateway (shown on the device page), or when AllowAnonymous = true. Any other connection is refused with Not authorized.
Connect with TLS
The broker accepts TLS on port 8883 with the gateway's own certificate, which the hub issues from the Certificate Store. The port opens once the hub has issued the certificate.
- In Security > Certificate Store, select Download CA. The file holds the CA certificates (PEM), no private key.
- In your client, set port
8883and use that file as the trusted CA. Connect to a host name or address that the gateway's certificate covers, because the name must match.
mosquitto_sub -h <gateway-host> -p 8883 --cafile proxus-ca.pem -u "<MasterToken>" -t 'v1/#' -vIn the Python example below, call client.tls_set(ca_certs="proxus-ca.pem") and use port 8883.
Port 1883 stays open for devices without TLS. To accept TLS only, set [MQTTBroker] PlainEnabled = false. When the gateway's certificate is renewed, the broker restarts for a few seconds and clients connect again.
Step 2: Subscribe
Subscribe to v1/# for everything, or to a part of the tree. For example:
| Subscription | Receives |
|---|---|
v1/# | every topic of the gateway |
v1/Meridian/Lyon_Foods_Plant/# | everything of one site |
v1/+/+/+/+/+/LYS_PACKER_04/telemetry/+ | each tag of one device, when its place has all five levels |
import os
import paho.mqtt.client as mqtt
BROKER = "localhost"
PORT = 1883
TOKEN = os.environ["PROXUS_MQTT_TOKEN"] # the gateway's MasterToken
def on_connect(client, userdata, flags, reason_code, properties):
print("connected:", reason_code)
client.subscribe("v1/#")
def on_message(client, userdata, msg):
print(msg.topic, msg.retain, msg.payload.decode())
client = mqtt.Client(mqtt.CallbackAPIVersion.VERSION2, client_id="uns-reader")
client.username_pw_set(TOKEN)
client.on_connect = on_connect
client.on_message = on_message
client.connect(BROKER, PORT)
client.loop_forever()Run it with PROXUS_MQTT_TOKEN=<token> python3 uns_reader.py.
The topic layout
v1/<Enterprise>/<Site>/<Area>/<Line or cell>/<Equipment>/<Device>/<category>/<name>v1is the namespace version.- The place levels come from the device. A level that is empty is left out, so the topic is shorter. A device with only a site and an area publishes under
v1/Lyon_Foods_Plant/Packaging/LYS_PACKER_04/...; a device with no place at all publishes underv1/<Device>/.... - Every character that is not a letter, a digit,
_or-becomes_.Lyon Foods PlantbecomesLyon_Foods_Plant,Line 1becomesLine_1. <category>istelemetryfor values andstatefor the device's state.
| Topic | Retained | Sent |
|---|---|---|
.../telemetry/<tag> | no | every time the tag is read |
.../telemetry/_summary | no | all tags of the device in one message, at most every SummaryIntervalMs (5 s) |
.../state/_lastSeen | yes | the time of the latest reading, at most every LastSeenIntervalMs (5 s) |
.../state/_status | yes | Online when values arrive, Offline when the device is disabled or deleted. For a device that publishes its own values (see below), also Offline when its client disconnects and Timeout after five minutes without values. |
Retained messages are kept by the broker and sent to a new subscriber at once, so a client that connects later still learns the status of every device. Set UNSRetainMessages = false to turn retaining off.
The payloads
One tag value, on v1/Lyon_Foods_Plant/Packaging/LYS_PACKER_04/telemetry/Temperature:
{"ts":"2026-10-15T19:01:43.450Z","value":25.4,"dataType":"Double","unit":"°C","quality":"Good","source":"Proxus"}| Field | Meaning |
|---|---|
ts | When the value was read, UTC, ISO 8601 with milliseconds. |
value | The value as a JSON number, true/false or string. |
dataType | Bool, Int, Long, Float, Double, DateTime or String. It is worked out from the value itself, so a UShort tag arrives as Int. |
unit | The tag's unit. Left out when the tag has none. |
quality | Always Good on this topic. Values that could not be read are not published here; see the device page for read errors. |
source | Always Proxus. |
With TelemetryThinPayload = false, each tag message also carries a context object with enterprise, site, area, processCell, equipmentModule, deviceId, deviceName and metric.
The summary, on .../telemetry/_summary:
{
"ts": "2026-10-15T19:01:46.955Z",
"deviceId": "48",
"deviceName": "MFB_LYS_MIXER_3",
"metrics": {
"Speed": {"value": 386, "dataType": "Int", "unit": "rpm", "quality": "Good"},
"Running": {"value": true, "dataType": "Bool", "quality": "Good"}
},
"context": {"enterprise": "Meridian", "site": "Lyon Foods Plant", "area": "Processing",
"processCell": "Dough", "equipmentModule": "_none"},
"source": "Proxus"
}context is left out when SummaryIncludeContext = false. _none means the device has no equipment level.
The state topics:
{"ts":"2026-10-15T19:01:39.551Z"}
{"status":"Online","ts":"2026-10-15T18:14:07.999Z"}
{"status":"Timeout","ts":"2026-10-15T19:20:00.000Z","reason":"Device timeout"}Publish values from a device
A device or program can send its own values to the broker. It connects with the device's Token as user name and publishes JSON to the topic telemetry (or any topic under telemetry/). Each field becomes a tag of that device:
{"Temperature": 21.7, "DoorOpen": false, "Pressure": {"value": 2.4, "unit": "bar"}}Nested objects become dotted names (Line.Speed), and arrays get an index (Axis[0]). The values then go through the same path as values the gateway reads itself: storage, pipelines, outbound targets and the UNS topics.
Writing to a device through MQTT, by publishing to a command topic, is not supported with the JSON format. Use a rule action or a pipeline to write values.
Sparkplug B
Set UNSPayloadFormat = "SparkplugB" in the [UNS] section of the gateway's configuration and restart the gateway. The gateway then publishes Sparkplug B 3.0 messages on its own broker instead of the JSON topics above:
- Topic namespace
spBv1.0/<UNSGroupId>/..., with the gateway as edge node<UNSEdgeNodeId>. - Each device is a Sparkplug device: a
DBIRTHwith its name, status, last-seen time and place, thenDDATAwith its tag values. Each metric carriesSource,QualityandUnitproperties. - The node answers the node commands
Node Control/Rebirth(sends the births again),discoveryandrefresh_metadata.
Sparkplug host applications connect with the MasterToken as user name, the same as JSON clients.
Broker and UNS settings
These keys are in the gateway's configuration file. See Configuration keys for the environment-variable form.
| Key | Default | Meaning |
|---|---|---|
[MQTTBroker] Enabled | true | Runs the broker on this gateway. With false there is no broker and no UNS publishing. |
[MQTTBroker] MQTTBrokerPort | 1883 | The broker port. If it is taken, the gateway picks a free port and logs a warning, unless AllowPortFallback = false. |
[MQTTBroker] TlsPort | 8883 | The TLS port, with the gateway's certificate. 0 turns TLS off. |
[MQTTBroker] PlainEnabled | true | Accept connections without TLS on MQTTBrokerPort. false accepts TLS only. |
[MQTTBroker] AllowAnonymous | false | Accept clients without a user name. |
[MQTTBroker] MasterToken | created at first start | The user name for UNS and Sparkplug clients. |
[MQTTBroker] EnableMQTTHooks | true | Publishes the values the gateway reads to the UNS topics. With false, only values that devices publish themselves appear. |
[UNS] UNSPayloadFormat | "JSON" | JSON or SparkplugB. |
[UNS] UNSRetainMessages | true | Retain the state topics. |
[UNS] UNSGroupId, UNSEdgeNodeId | "ProxusGroup", "ProxusEdge" | Sparkplug group and edge node. |
[UNS.Optimizations] TelemetryThinPayload | true | Leave context out of each tag message. |
[UNS.Optimizations] SummaryIntervalMs | 5000 | Least time between two summaries of a device. 0 sends one with every reading. |
[UNS.Optimizations] SummaryIncludeContext | true | Put context in the summary. |
[UNS.Optimizations] SummaryOnlyOnChange | false | Send a summary only when a value changed. |
[UNS.Optimizations] LastSeenIntervalMs | 5000 | Least time between two _lastSeen messages. |
[UNS.Optimizations] StatusOnChangeOnly | true | Send _status only when it changes. |
The QoS levels are 0 for telemetry and 1 for state messages.
What's next
- Unified Namespace: how the plant hierarchy is built.
- UNS Explorer: browse the same tree in the hub.
- Outbound targets: send values to your own MQTT broker instead.
Was this page helpful?
Evaluating Proxus? See it on your own machines in a 30-minute technical session.