One gRPC API for
every industrial protocol.
A single Rust binary that speaks Modbus, OPC UA, EtherNet/IP, Siemens S7, DNP3, BACnet/IP, and MQTT, and exposes them all behind one typed gRPC surface. Read, write, and subscribe to tags on any PLC with one client.
The problem
Stop writing a different client for every PLC.
Every industrial protocol has its own wire format, addressing scheme, and quirks. The gateway absorbs all of that: your application talks one gRPC API and the gateway drives the device.
The same protocol logic gets re-implemented in every SCADA, HMI, and edge collector. Voltrus Gateway makes the mt-* crates (the engines powering the Voltrus explorer apps) the single canonical implementation. SCADA shrinks to SCADA concerns; protocol bugs get fixed once.
How it works
One client. Any device. Any protocol.
Point the gateway at a device and talk to it over gRPC. Connect, read or write typed tag values, then subscribe for live updates. The same three calls regardless of protocol.
Open a session
Point the gateway at a device: Modbus TCP, OPC UA endpoint, EtherNet/IP PLC, S7 CPU, DNP3 outstation, or BACnet controller. The gateway holds the connection and speaks the native wire protocol.
Typed tag values
Call ReadTags or WriteTag over gRPC. Values carry bool, int, float, double, string, and bytes plus a source type. A CIP DINT or an OPC UA string round-trips intact, never flattened to a number.
Live updates
Subscribe to tags and receive live server-streamed batches. No polling loop to maintain on the client. The gateway pushes deltas as devices change.
Features
A single binary that replaces a stack of clients.
One canonical, cross-platform implementation of every protocol your plant uses, self-hosted, type-preserving, with native streaming subscriptions.
One binary, seven protocols
Modbus TCP, OPC UA, EtherNet/IP (CIP), Siemens S7, DNP3, BACnet/IP, and MQTT, all over the same API.
Type-preserving values
Tag values carry bool, int, float, double, string, and bytes plus a source type. A CIP DINT or an OPC UA string round-trips intact, not flattened to a number.
Streaming subscriptions
Subscribe to tags and receive live server-streamed batches, no polling loop to maintain on the client.
Self-hosted & cross-platform
A single static binary for Linux, macOS, and Windows. Run it at the edge, in a container, or beside your SCADA. No per-tag licensing.
One canonical implementation
The same mt-* engines that power the Voltrus explorer apps. Protocol bugs get fixed once, everywhere.
Discover & browse
Browse tags and discover devices over the same gRPC surface. No separate tooling to map out a PLC's tag namespace.
Supported protocols
Read, write, and subscribe on every protocol below.
Full read, write, and subscribe on seven industrial protocols, all over the same gRPC surface.
# one client, any device — the full gRPC surface rpc OpenSession(ConnectRequest) -> ConnectResponse rpc ReadTags(ReadTagsRequest) -> ReadTagsResponse rpc WriteTag(WriteTagRequest) -> WriteResult rpc SubscribeTags(SubscribeRequest) -> stream TagUpdateBatch rpc Discover(DiscoverRequest) -> DiscoverResponse
SDKs
Talk to the gateway from your own code.
Official Python and TypeScript gRPC clients live in the source repository under gateway/sdks/, not on PyPI or npm yet. They wrap the typed API the gateway exposes: server-side sessions, reads and writes of type-preserving tag values, tag browsing, and streaming subscriptions. Where the SCADA SDKs speak REST to the SCADA server, these speak gRPC to the lightweight 24/7 protocol layer.
Subscribe once and the gateway pushes an initial batch, then sends a new one only when a value or its quality changes. Polls that fail while a device is down arrive as per-tag errors and quality stamps instead of killing the stream, and values return when the device recovers. Both SDKs ship a subscribe_24x7 example with reconnect and backoff for unattended use.
Python SDK
A thin wrapper over the generated gRPC stubs, committed so no protoc is needed. Dicts in, proto values out; only grpcio and protobuf as dependencies.
git clone https://github.com/dzulfikar08/MacTools.git cd MacTools/gateway/sdks/python && pip install -e .
from voltrus_gateway import VoltrusGateway
with VoltrusGateway("http://127.0.0.1:50061") as gw:
session = gw.connect("modbus", ip="192.168.1.10", unit_id=1, endianness="big")
tags = [{"name": "temperature", "address": 0, "reg_type": "float32",
"register_area": "holding"}]
for tv in gw.read_tags(session, tags):
print(tv.tag.modbus.name, tv.value.double_val, tv.quality)
gw.write_tag(session, tags[0], 72.5) # -> WriteResult(success, error, latency_ms)
gw.disconnect(session)
Source: gateway/sdks/python in github.com/dzulfikar08/MacTools
TypeScript SDK
The same gRPC surface with plain objects in and typed messages out. Only @grpc/grpc-js and @bufbuild/protobuf as runtime dependencies, and connect configs are compile-time checked per protocol.
git clone https://github.com/dzulfikar08/MacTools.git cd MacTools/gateway/sdks/typescript && npm install
import { VoltrusGateway, valueOf } from "voltrus-gateway";
const gw = new VoltrusGateway("http://127.0.0.1:50061");
const session = await gw.connect("modbus", { ip: "192.168.1.10", unitId: 1, endianness: "big" });
const tags = [{ name: "temperature", address: 0, regType: "float32", registerArea: "holding" }];
for (const tv of await gw.readTags(session, tags)) {
console.log(tv.tag.modbus?.name, valueOf(tv.value), tv.quality);
}
await gw.writeTag(session, tags[0], 72.5); // -> WriteResult { success, error, latencyMs }
await gw.disconnect(session);
gw.close();
Source: gateway/sdks/typescript in github.com/dzulfikar08/MacTools
Driving the SCADA server instead? See its SDKs.
Perpetual license
Stop writing a client
for every protocol.
A commercial product: not open source, not a subscription. Buy it once and run it forever. Each license covers a single host: a workstation, a server, an edge box, or a VM.
FAQ
Questions engineers ask.
Stay Updated
Get notified about gateway updates & new protocols
MQTT broker support, new protocols, and API updates land regularly. No spam, only product news.
Also from Voltrus