Skip to content

OPC UA PubSub Connector

The OPC UA PubSub connector implements the publish/subscribe pattern defined by the OPC UA PubSub specification (Part 14). It enables high-throughput, decoupled communication between OPC UA producers and consumers using one of two transport mappings:

  • MQTT - JSON-encoded messages over MQTT/UDP for broker-based fan-out
  • UADP - Binary UADP (UA Datagram Protocol) over UDP multicast for low-latency LAN distribution

Connector Types:

  • OpcuaPubSubReader - Listens for inbound PubSub messages and emits them as Meddle payloads
  • OpcuaPubSubWriter - Publishes Meddle payloads as PubSub messages
  • ✅ Two transports: MQTT (JSON) and UADP (binary multicast)
  • ✅ Automatic decoding of both JSON and UADP wire formats
  • ✅ UDP multicast group management with interface selection
  • ✅ Optional publisher ID and dataset name filtering
  • ✅ Decoupled producer/consumer (no point-to-point session needed)
  • ✅ Built for high-frequency telemetry distribution
{
"type": "OpcuaPubSubReader",
"config": {
"transport": "uadp",
"multicastAddr": "opc.udp://224.0.5.1:4840/eth0",
"publisherId": "Publisher_1",
"dataSetName": "TankFarmDataSet"
}
}
{
"type": "OpcuaPubSubWriter",
"config": {
"transport": "uadp",
"multicastAddr": "opc.udp://224.0.5.1:4840/eth0",
"publisherId": "Publisher_1",
"dataSetName": "TankFarmDataSet"
}
}

The wire transport used for PubSub messages. Must be one of:

  • mqtt - JSON messages over UDP (broker-bridged in production)
  • uadp - Binary UADP frames over UDP multicast
{
"transport": "uadp"
}

Required when transport: mqtt. The address Meddle binds (reader) or sends to (writer).

{
"brokerUrl": "192.168.1.20:1883"
}

Format: host:port.

Notes:

  • The reader binds a UDP listener on this address
  • For the writer, this is the destination address that PubSub messages are sent to

Optional logical topic identifier. Informational metadata included alongside dataset filtering.

{
"topic": "factory/line1"
}

Required when transport: uadp. The IPv4 multicast group plus optional interface.

{
"multicastAddr": "opc.udp://224.0.5.1:4840/eth0"
}

Format: opc.udp://<host>:<port>/<interface>.

  • host:port - The multicast group and port (typically 224.0.5.1:4840 for OPC UA PubSub default)
  • interface - Required network interface name (eth0, en0, lo0)

Why is interface required? UDP multicast joins are interface-scoped. Without a specified interface, the OS cannot reliably bind the multicast group, especially on macOS (lo0) and cloud VMs with multiple NICs.

Plain host:port (no scheme) is also accepted for backward compatibility but interface selection is highly recommended.

Identifies the source of PubSub messages.

{
"publisherId": "Publisher_1"
}

Notes:

  • Required on the writer (every published message is tagged with it)
  • Optional on the reader (when set, only messages from this publisher are kept; when empty, all publishers are accepted)

Identifies the logical dataset within a publisher.

{
"dataSetName": "TankFarmDataSet"
}

Notes:

  • Optional on both reader and writer
  • On the reader, acts as a filter when set

The MQTT transport emits messages in a standard JSON envelope:

{
"PublisherId": "Publisher_1",
"Messages": [
{
"DataSetName": "TankFarmDataSet",
"Payload": {
"tank_1_level": 78.4,
"tank_2_level": 62.1,
"pump_running": true
}
}
]
}

The UADP transport emits binary frames following OPC UA Part 14 framing. The reader automatically detects UADP vs JSON content and decodes both. Each decoded UADP DataSet emits one Meddle payload.

Multicast / UDP → OpcuaPubSubReader → (decode JSON or UADP) → Meddle Payload(s)

Multiple datasets in a single network message produce multiple Meddle payloads (one per dataset).

Meddle Payload → OpcuaPubSubWriter → (encode JSON envelope) → UDP send → Subscribers

The writer always emits JSON for both transports. Each Write invocation produces exactly one network message.

1. Decoupled Plant-Floor Telemetry Distribution

Section titled “1. Decoupled Plant-Floor Telemetry Distribution”

A central PLC publishes process variables to a UADP multicast group; multiple Meddle subscribers consume them independently.

{
"type": "OpcuaPubSubReader",
"config": {
"transport": "uadp",
"multicastAddr": "opc.udp://224.0.5.1:4840/eth0",
"publisherId": "PLC_Master"
}
}

Bridge OPC UA PubSub to a JSON-friendly MQTT topic for ingestion into cloud platforms:

{
"type": "OpcuaPubSubReader",
"config": {
"transport": "mqtt",
"brokerUrl": "0.0.0.0:1883",
"topic": "factory/sensors",
"dataSetName": "EnergyMeters"
}
}

3. Edge Gateway Publishing Aggregated KPIs

Section titled “3. Edge Gateway Publishing Aggregated KPIs”

After processing, publish aggregated KPIs as a single PubSub message:

{
"type": "OpcuaPubSubWriter",
"config": {
"transport": "uadp",
"multicastAddr": "opc.udp://224.0.5.1:4840/eth0",
"publisherId": "Edge_Gateway_1",
"dataSetName": "PlantKPIs"
}
}

Problem: Reader silently runs but never emits payloads

Solutions:

  1. Confirm the multicast group matches the publisher exactly (224.0.5.1:4840)
  2. Specify the interface in multicastAddr (e.g. /eth0) — auto-discovery is not reliable
  3. Use a network sniffer like tcpdump -i eth0 host 224.0.5.1 and port 4840 to confirm packets are arriving
  4. Verify multicast routing is enabled on switches/routers between publisher and subscriber

Problem: UADP configuration is rejected at startup

Solutions:

  1. Update multicastAddr to include the interface: opc.udp://224.0.5.1:4840/eth0
  2. On macOS the loopback interface is lo0; on Linux it’s lo. Check with ifconfig or ip addr

Problem: Reader sees messages on the wire but emits none

Solutions:

  1. Check the publisherId filter on the reader — when set, only messages from that publisher pass through. Clear it to accept all
  2. Same goes for dataSetName — when set, only matching datasets pass

Problem: bind: address already in use

Solutions:

  1. Multiple readers on the same host must use distinct ports
  2. For UADP multicast, multiple processes on the same host can join the same group only if SO_REUSEPORT is honored (Linux); on macOS only one binding per group+port is allowed per process

Problem: ErrOpcuaPubSubDecode is raised on every message

Solutions:

  1. Check whether the publisher uses JSON or UADP — the reader auto-detects but malformed data fails both paths
  2. Inspect the publisher’s PubSub configuration: dataset content type must be a supported scalar or structure
  3. Verify the publisher and subscriber agree on encoding (the OPC UA Server’s PubSub config defines this)

UADP is faster and has lower overhead than JSON-over-MQTT. Use it whenever you control the network.

JSON is portable and easy to debug. When messages must traverse the public internet or be consumed by non-OPC UA tools, MQTT-JSON is more pragmatic.

Never rely on the OS to “guess” the right NIC. Multi-homed hosts and containers fail silently otherwise.

publisherId and dataSetName filtering is server-side cheap and dramatically reduces downstream processing load.

  • Use the OPC UA Foundation’s reserved range (224.0.5.0/24)
  • Coordinate with your network team — uncontrolled multicast can flood the LAN
  • Test with tcpdump/Wireshark before going to production
PLC (Publisher) → UADP multicast 224.0.5.1:4840
┌────────┼────────┬──────────────┐
↓ ↓ ↓ ↓
OpcuaPubSubReader OpcuaPubSubReader OpcuaPubSubReader
(Storage) (Dashboard) (Alerting)
│ │ │
↓ ↓ ↓
InfluxDb2Writer Chart Isa182 → Alert
ModbusReader → Reshape → OpcuaPubSubWriter (MQTT) → External Broker → Cloud Subscribers

Bridges legacy Modbus devices into the modern OPC UA PubSub ecosystem.

  • OPC UA - Classic OPC UA client/server protocol (point-to-point)
  • MQTT v5 - Generic MQTT (non-OPC UA) PubSub
  • Modbus - Bridge legacy devices into the PubSub fabric
  • Reshape - Normalize field names before publishing
  • InfluxDB v2 - Persist subscribed telemetry