Modbus, OPC UA & EtherNet/IP in One Binary: One Protocol Layer for the Edge

August 9, 2026 · Category: Guide · Tags: Modbus, OPC UA, EtherNet/IP, S7, DNP3, BACnet

A modern plant doesn't run one protocol. It runs Modbus on the power meters, OPC UA on the newer PLCs, EtherNet/IP on the Allen-Bradley gear, S7 on the Siemens line, DNP3 on the SCADA outstations, BACnet on the building automation, and MQTT toward the cloud. Reaching all of them used to mean seven clients, seven mental models, and seven sets of edge-case bugs.

Voltrus Gateway puts all seven behind a single gRPC API, driven by one Rust binary. This piece walks through what "unified" means in practice, and where the gateway stops and the rest of an edge stack begins.

The Seven Protocols, One Mental Model

Every protocol in the gateway answers the same questions the same way: how do I connect, how do I read, how do I write, how do I subscribe, how do I discover tags. The docs describe the five RPCs in full, but the shape is uniform:

ProtocolReadWriteSubscribeTypical Port
Modbus TCP✓✓✓ (gateway-polled)502
OPC UA✓✓✓ (native)4840
EtherNet/IP (CIP)✓✓✓44818
Siemens S7✓✓✓102
BACnet/IP✓✓✓47808
DNP3✓✓✓20000

For protocols with native subscriptions (OPC UA most prominently), the gateway bridges them straight through. For protocols without (Modbus, BACnet), the gateway runs the poll internally and streams only changes, so your client code looks identical either way.

The mt-* Engines

Each protocol is implemented in its own mt-* Rust crate: mt-modbus, mt-opcua, mt-enip, mt-s7, mt-dnp3, mt-bacnet. These are the same engines that power the Voltrus explorer apps. The gateway isn't a second implementation: it's the canonical one, exposed over gRPC.

Why that matters: a bug fixed in mt-enip is fixed for the EtherNet/IP Explorer desktop app, for the gateway, and for anything else built on the engine. Protocol complexity lives in one place per protocol, audited and battle-tested by both surfaces.

Read / Write / Subscribe Parity

"Unified" only means something if the parity is real. Voltrus Gateway ships full read, write, and subscribe on the six device protocols (MQTT adds publish, read and subscribe), not "read on most, write on a few." A holding-register write on Modbus, a tag write on OPC UA, and a coil write on a CIP controller all go through the same WriteTag RPC with a typed value. The gateway encodes the value correctly for the target protocol; your client doesn't know or care which one.

Discover, Don't Guess

Half the work in talking to a new device is figuring out what tags it actually exposes. Discover browses the device's tag namespace over the same gRPC surface (OPC UA's address space, a CIP controller's symbol table, an S7 CPU's data blocks), so you don't need a separate browsing tool to map out a PLC before you can read it.

What a Protocol Layer Should Handle

Translating between OT and IT protocols is more than reformatting bytes. Four jobs belong in the layer that holds the device connection, so that every consumer does not redo them:

What to Keep Out of It

The gateway's job is the device connection and the typed API. Store-and-forward buffering, history, dashboards and a message broker are better handled by whatever consumes the data, and the arithmetic shows why you want to be deliberate about where they live. A remote site with 100 tags read once a second produces 8.64 million data points a day. If the uplink drops for a weekend, whichever component buffers that has to survive it without filling the disk, and it has to send alarms ahead of bulk history when the link returns. Deadband filtering (do not send a value that has not changed) cuts that volume a lot, and it is best done before data leaves the site.

A Minimal Edge Stack

For plain protocol translation, a minimal stack covers most sites with three parts on one small machine:

  1. Protocol layer. Voltrus Gateway holds the connections to the PLCs, meters and controllers.
  2. A consumer with a local store. A small collector or SCADA that subscribes over gRPC and writes to an embedded database such as SQLite, so an outage costs you nothing but delay.
  3. Northbound transport. MQTT or HTTP out to the cloud or the central SCADA.

The alternative stack that vendors like to sell adds a local MQTT broker, a flow engine, a time-series database and a dashboard server, each its own service. Each one is another thing to patch, monitor and restart on a box that may be hours away, and when the site stops reporting you have four suspects instead of one. That stack earns its keep when you need a local HMI that works without the uplink, several independent consumers of the same data, months of local history, or non-programmers building logic. If none of those apply, start minimal. For reaching a remote box when something does go wrong, see Voltrus Remote.

MQTT on the Same Surface

MQTT ships in the same binary and joins the same gRPC surface: publish, read and subscribe bridged into the unified tag model. Adding a protocol doesn't add a client; it adds a connect option.

Seven Protocols, One Binary

Voltrus Gateway drives Modbus, OPC UA, EtherNet/IP, S7, DNP3, BACnet, and MQTT behind one typed gRPC API. Linux and Windows, self-hosted, one-time per host.

Explore Voltrus Gateway →