Protocols and data

OPC UA vs MQTT vs Modbus

OPC UA, MQTT and Modbus compared: data model, status and timestamps, security, ports, a worked example of one meter reading through all three, and the failures to test at commissioning.

An active power reading can cross all three protocols before it reaches an energy platform. It leaves the meter as two Modbus registers with no unit, time or status. A PLC can expose it as an OPC UA node with a data type, a StatusCode and two timestamps. It leaves the site as an MQTT message in a format that the sender and the receiver agreed in advance. Each hop can lose part of that meaning, and the commissioning faults listed below all occur at a hop.

Side by side

ModbusOPC UAMQTT
PatternRequest and reply. One master per RTU bus; TCP devices limit concurrent connectionsRequest and reply in a session; PubSub also defined (Part 14)Publish and subscribe through a broker
Data modelFour tables: coils, discrete inputs, input registers, holding registers (16-bit)Typed nodes in an address space, with references between themNone; the payload is any bytes
Meaning of a valueIn the device's register mapData type and name in the node; engineering units only where the server provides the optional propertyAgreed between publisher and subscriber, or defined by Sparkplug
Time and qualityNone in the protocolStatusCode, source timestamp and server timestamp on each valueNone in MQTT; put them in the payload
DiscoveryNoneBrowse the address spaceNone. Wildcard subscriptions show only topics being published or retained; Sparkplug birth messages declare metrics
SecurityNone; protect with network designApplication certificates, signing, encryption, user authenticationTLS to the broker, with the broker's access control
Default port502 (TCP)4840 (TCP)1883, or 8883 with TLS
Typical placeMeters, drives, inverters, small controllersPLCs, SCADA servers, plant controllersGateway to platform, between applications
StandardModbus OrganizationOPC Foundation OPC 10000, also IEC 62541OASIS; Sparkplug by the Eclipse Foundation, also ISO/IEC 20237

Modbus registers and register maps

Almost every electricity meter, inverter and drive has a Modbus interface. The protocol reads and writes four tables: coils and discrete inputs (1 bit), and input registers and holding registers (16 bits). Function 03 reads holding registers and function 04 reads input registers, up to 125 contiguous registers in one request. Nothing in a response says what the bits mean. Units, scale factor, data type and word order come from the manufacturer's register map, and the protocol has no timestamp or status. The Modbus register map guide explains what to record for each point.

On RS-485, Modbus RTU is slow enough that the poll list has to be sized. With 8 data bits, even parity and 1 stop bit, each character is 11 bits. A read of two registers is an 8-byte request and a 9-byte reply. At 9600 baud, those 17 characters take 19.5 ms on the wire. Add a silent interval of 3.5 characters (4.0 ms) after each frame, and the meter's own response delay from its datasheet. If each transaction takes 60 ms in total, 20 meters with 4 reads each take 4.8 s per scan. Only one master may poll an RTU bus.

Modbus TCP removes the baud-rate limit but adds a connection limit. Many meters accept only a few simultaneous TCP connections, and some accept one. When a BMS and a gateway both poll the same meter, one of them can lose its connection or time out without a clear error.

OPC UA address space, status and security

OPC UA, defined in the OPC 10000 series (IEC 62541), models a system as an address space of nodes. A client can browse from a pump to its speed, its running hours and its alarms. Each read of a variable returns a DataValue: the value, its data type, a StatusCode, a source timestamp from the device or PLC, and a server timestamp from the OPC UA server.

The top two bits of the StatusCode give its severity (Part 4, 7.38.1). Good is 00, Uncertain is 01 and Bad is 10. For example, UncertainLastUsableValue (0x40900000) means that whatever updated the value has stopped. BadCommunicationError (0x80050000) means that the server lost its source. A client that keeps the value and discards the StatusCode turns these into ordinary readings.

Engineering units are not part of every node. Part 8 defines EngineeringUnits as an optional property of analog variables. Many servers expose plain variables with no unit, so the unit must come from the point list.

OPC UA secures each connection with application certificates. The server offers endpoints, each with a security policy and a mode: None, Sign or SignAndEncrypt. Users connect anonymously, with a user name and password, or with a certificate. Disable the None endpoint on the server. If it stays enabled, a client set to accept any endpoint can connect without signing or encryption.

The OPC UA node identity guide explains node identifiers and namespaces, and the OPC DA migration guide covers moving from OPC Classic.

MQTT brokers, topics and payload contracts

MQTT is a transport. A publisher sends a message to a topic on a broker, and the broker delivers it to every client subscribed to that topic. The publisher and the subscribers do not connect to each other. The broker becomes the one component that every party must reach, and it must be secured. A publisher cannot tell whether a subscriber received a message. It needs an application acknowledgement or a state message for that.

MQTT adds delivery options (QoS 0, 1 and 2), retained messages and a last will. The broker publishes a client's will message if the client stops sending for 1.5 times its keep-alive interval, which is a simple way to detect a lost gateway. The MQTT QoS guide explains the delivery options, and the MQTTS guide covers TLS and topic permissions.

MQTT does not define what is in a message. MQTT 5 adds a payload format indicator, a content type and user properties, but not field names or units. Every integration needs a payload contract: the topic structure, the field names, the units, the timestamp format and how bad data is marked. If the receiving platform defines its own format, get its topic and payload specification before you commission the site.

Two standards define a contract on top of MQTT. Sparkplug B (Eclipse Foundation, ISO/IEC 20237:2023) uses topics of the form spBv1.0/group/message_type/edge_node/device and a Protocol Buffers payload. NBIRTH and DBIRTH messages declare every metric with its data type. NDEATH is registered as the node's will. Data messages (NDATA, DDATA) are published at QoS 0, and a sequence number from 0 to 255 lets the host application detect a lost message and request a rebirth. OPC UA PubSub (Part 14) can also use an MQTT broker as its transport, with UADP or JSON encoding. With MQTT 3.1.1, subscribers must be configured in advance for the encoding.

One reading through all three

A meter measures 200.5 kW of active power. Its register map puts the value at holding registers 0 and 1, as a 32-bit IEEE 754 float with the high word first.

On Modbus, the gateway reads the two registers and gets 0x4348 and 0x8000. Put together high word first, they give 0x43488000, which is 200.5. If the gateway puts the low word first, it gets 0x80004348, which is about -2.4 × 10⁻⁴¹. A dashboard shows that as zero, so the fault looks like an idle load. The Modbus register decoder shows all four word orders for a pair of registers.

On OPC UA, a PLC that reads the same meter can expose it as node ns=2;s=Meter1.ActivePower. A read returns 200.5 as a Float, with StatusCode Good (0x00000000), the time the PLC sampled it and the time the server answered. If the PLC loses the meter, the server may keep returning 200.5 with UncertainLastUsableValue. The value is valid only while the status is Good.

On MQTT, a JSON contract can carry the point as {"point":"meter1/active_power","value":200.5,"unit":"kW","ts":"2026-09-24T10:15:00Z","quality":"good"}. Under Sparkplug B, the same value is a Float metric in a DDATA message on spBv1.0/site-a/DDATA/gateway-1/meter-1, with a timestamp in milliseconds since the Unix epoch. Sparkplug has no standard field for the OPC UA StatusCode. Agree how an Uncertain or Bad value is sent, for example as a null metric, before the site goes live.

Failures to test at commissioning

SymptomLikely causeHow to check
Values near zero, or very large, from a correct meterWrong word order, data type or scale factorCompare one reading with the meter's display under load
Intermittent Modbus TCP timeoutsTwo clients polling a meter that accepts one connectionRead the connection limit in the datasheet. Let one client poll and serve the others
CRC errors and lost replies on RS-485Two masters on one RTU bus, or a poll list faster than the busCalculate the scan time. Confirm one master
OPC UA connection refused on first attemptClient certificate not trusted (BadCertificateUntrusted, 0x801A0000)Trust the client certificate on the server, and the server certificate on the client
OPC UA security fails after a restartGateway or server clock wrong, so a certificate is outside its validity periodCheck both clocks against a time server
A frozen value published as currentOPC UA StatusCode dropped at the gatewayDisconnect the source and watch what the gateway publishes
Gaps after a broker or network outageQoS 0 messages, or no store and forward at the publisherBlock the broker for ten minutes, then compare received and expected counts

The protocol gateway guide explains what to specify for each translated point. The source time and arrival time guide covers which timestamp to keep.

Choosing

QuestionGuidance
What does the equipment offer?Use its native interface. Do not replace a working Modbus meter to get OPC UA
Who receives the data?Platforms usually take MQTT or HTTPS. A SCADA system or BMS often takes OPC UA, Modbus or BACnet; some BMS accept only Modbus TCP
Must status and time travel with the value?OPC UA carries both. For MQTT, put them in the payload contract. For Modbus, the reading client adds its own read time
Is the network shared or untrusted?Use OPC UA with SignAndEncrypt, or MQTT over TLS. Keep Modbus on a protected network
Must many consumers receive the same data?MQTT through a broker, or OPC UA PubSub

The BACnet vs Modbus guide covers the building side.

OPC UA, MQTT and Modbus with Edge

Edge on the ZGW-20 Gateway takes the gateway role. It reads Modbus TCP and RTU equipment. It is also an OPC UA client that reads variable nodes at a set interval, from 1 s to 86,400 s. It supports security modes None, Sign and SignAndEncrypt, with anonymous, user name or certificate sign-in. Keep the Gateway clock correct, because certificate validation depends on it. EpiSensor wireless devices, LoRaWAN sensors and BACnet/IP controllers join the same data model.

Edge reads OPC UA by polling. It does not use OPC UA subscriptions or PubSub, so it does not use server-side deadbands, and a change shorter than the poll interval can be missed. Each point is timestamped with the scheduled read time, not the OPC UA source timestamp. The stored point does not carry the OPC UA StatusCode. Edge's quality figure is the share of expected reads that arrived in a rolling 15-minute window, which is a different measure. Test how the server's Uncertain and Bad values appear in Edge before you depend on them.

Edge sends data upstream over MQTTS or HTTPS. It can also serve mapped points to a BMS as Modbus TCP registers, on its own listener at port 10502, not 502.

Common questions

What is the difference between OPC UA and MQTT?

OPC UA is a client-server protocol with an information model: each value is a typed node with a StatusCode and timestamps, and the client can browse the server. MQTT is a publish-subscribe transport through a broker. It carries any payload and defines no data model. The two also combine: OPC UA PubSub (OPC 10000-14) can use an MQTT broker as its transport, with UADP or JSON message encoding.

When should I use OPC UA instead of Modbus?

Use OPC UA when the source is a PLC or SCADA server that already exposes one, when the receiving system needs status and source timestamps with each value, or when the data crosses a network that you do not control. For electricity meters, Modbus is usually the only interface available, so read it with Modbus.

What ports do OPC UA, MQTT and Modbus use?

OPC UA binary over TCP uses port 4840 by default. MQTT uses 1883, and 8883 over TLS. Modbus TCP uses 502. Vendors and sites often change these, so confirm the port on each device.

What is Sparkplug B?

A specification from the Eclipse Foundation, also published as ISO/IEC 20237:2023, that defines topic names, a Protocol Buffers payload and state messages on top of MQTT. Topics start with spBv1.0. NBIRTH and DBIRTH messages declare every metric, NDEATH tells subscribers that a node has gone, and data messages carry a sequence number so that a host can detect a lost message and ask for a rebirth.

Can OPC UA run over MQTT?

Yes. OPC 10000-14 defines an MQTT transport for OPC UA PubSub. The body is UADP (binary) or JSON. MQTT 3.1.1 has no field for the encoding, so subscribers must be configured in advance; MQTT 5 can carry it in the message properties.