Voltrus Gateway Documentation

Overview

Voltrus Gateway is a single Rust binary that unifies six industrial protocols — Modbus TCP, OPC UA, EtherNet/IP (CIP), Siemens S7, DNP3, and BACnet/IP — behind one typed gRPC API. Instead of writing and maintaining a different client for every protocol, your application talks to the gateway once and reads, writes, and subscribes to tags on any PLC.

The gateway runs the same mt-* engines that power the Voltrus explorer apps, making it the single canonical implementation of each protocol. SCADA shrinks to SCADA concerns; protocol bugs get fixed once, everywhere.

One license = one host. Voltrus Gateway is a commercial, one-time-purchase product — not open source, not a subscription. Each license covers a single machine that runs the binary. Buy a license per host you deploy on.

Installation

Voltrus Gateway ships as a single static binary per platform — Linux, macOS, and Windows. No installer, no runtime, no package manager required. Download it, make it executable, run it.

Download

System Requirements

RequirementMinimum
OSLinux (x86_64 / aarch64), macOS (Apple Silicon & Intel), or Windows x64
NetworkReachability to the device on its protocol port (Modbus 502, S7 102, OPC UA 4840, …)
LicenseOne VOLTRUS-GATEWAY-* key per host

First Run

Make the binary executable (Linux/macOS) and activate the license by exporting it as an environment variable:

chmod +x voltrus-gateway
export VOLTRUS_GATEWAY_LICENSE=VOLTRUS-GATEWAY-XXXX-XXXX-XXXX
./voltrus-gateway
On Linux/macOS you may also drop a license file beside the binary instead of using the environment variable.

Quick Start

The gateway exposes five RPCs. The flow is the same for every protocol: open a session, read or write tags, then subscribe for live updates.

  1. Open a session. Call OpenSession with a ConnectRequest describing the protocol and target — e.g. a Modbus TCP device at 192.168.10.5:502, unit ID 1. The gateway holds the connection and speaks the native wire protocol.
  2. Read tags. Call ReadTags with the tag paths or addresses you want. Values come back typed — bool, int, float, double, string, bytes — never flattened.
  3. Write a tag. Call WriteTag with a typed value. The gateway encodes it correctly for the target protocol.
  4. Subscribe. Call SubscribeTags and consume the server-streamed TagUpdateBatch as devices change — no client-side polling loop.
  5. Discover. Don't know the tag list? Call Discover to browse the device's tag namespace over the same surface.

The gRPC API

The full surface is five RPCs. One client talks to every protocol through them.

rpc OpenSession(ConnectRequest)     -> ConnectResponse
rpc ReadTags(ReadTagsRequest)       -> ReadTagsResponse
rpc WriteTag(WriteTagRequest)       -> WriteResult
rpc SubscribeTags(SubscribeRequest) -> stream TagUpdateBatch
rpc Discover(DiscoverRequest)       -> DiscoverResponse

Typed tag values

Every tag value is carried as a rich oneof so a CIP DINT or an OPC UA string round-trips without being flattened to a number:

message TagValue {
  oneof value {
    bool   v_bool   = 1;
    int32  v_int32  = 2;
    int64  v_int64  = 3;
    uint32 v_uint32 = 4;
    float  v_float  = 5;
    double v_double = 6;
    string v_string = 7;
    bytes  v_bytes  = 8;
  }
  string source_type = 9;   // e.g. "CIP.DINT", "OPCUA.String"
}

Supported Protocols

All six protocols ship with full read, write, and subscribe support today. An MQTT broker joins the same gRPC surface on the roadmap.

ProtocolReadWriteSubscribe
Modbus TCP
OPC UA
EtherNet/IP (CIP)
Siemens S7
BACnet/IP
DNP3
MQTT brokerRoadmap — same gRPC surface

Configuration

Listen address

By default the gateway listens for gRPC on 127.0.0.1:50051. Override with --listen (or VOLTRUS_GATEWAY_LISTEN) to bind another address/port — e.g. 0.0.0.0:50051 to expose it on the LAN, behind your firewall.

Per-protocol connection options

Each ConnectRequest carries protocol-specific options (timeout, unit ID / node ID, OPC UA security mode, S7 rack/slot). Sensible defaults are applied; override only what differs from the device's documented configuration.

Licensing

Provide the key via VOLTRUS_GATEWAY_LICENSE or a license file beside the binary. The gateway validates the key on startup and refuses to serve if it is missing or bound to another host.

Type Preservation

Industrial protocols carry rich data types that get destroyed when flattened to a JSON number: a CIP DINT, an OPC UA String, a signed vs unsigned 32-bit register. Voltrus Gateway preserves them via the TagValue oneof and a source_type string, so your client code branches on type rather than guessing byte order.

The same value read over Modbus, OPC UA, or EtherNet/IP arrives at the client in the same shape — the gateway absorbs each protocol's encoding quirks.

Troubleshooting

License rejected on startup

Symptom: The gateway exits with a license error.
Fix: Confirm VOLTRUS_GATEWAY_LICENSE is set in the environment the binary actually runs in (not just your interactive shell — check systemd unit, container env, or launch agent). One license binds to one host; a key activated elsewhere will be rejected.

OpenSession fails (connection refused)

Symptom: OpenSession returns an unreachable / refused error.
Fix: Confirm network reachability to the device on its protocol port from the gateway host — nc -zv 192.168.10.5 502. Check the protocol-specific addressing: Modbus unit ID, S7 rack/slot, OPC UA endpoint URL and security mode.

Tag values come back flattened

Symptom: A 32-bit register reads as a raw integer instead of a typed value.
Fix: The gateway preserves types only when the request names the tag with its native type/path. For raw Modbus addresses, specify the intended decoding in the read request; for CIP/OPC UA, use the symbolic tag path so the device reports its type.

Subscription gaps / missed updates

Symptom: SubscribeTags stream opens but updates seem delayed or batched irregularly.
Fix: The gateway pushes server-streamed deltas. Slow devices throttle internally; raise the device's scan rate, or for Modbus increase the poll cadence. Confirm the client is draining the stream — a blocked consumer stalls backpressure.

Roadmap

  • Now: read, write, subscribe, and discover over Modbus TCP, OPC UA, EtherNet/IP (CIP), Siemens S7, DNP3, and BACnet/IP.
  • Next: MQTT broker on the same gRPC surface — publish/subscribe bridged into the unified tag model.
  • Then: richer discovery, batch write APIs, and per-session diagnostics.

Support

When reporting a connection issue, include the protocol, the ConnectRequest parameters (redact IPs), and the gateway's startup log lines.