One toolkit for Modbus, OPC UA and MQTT.

Read a register, browse a server and watch a broker in one window, with one project of tags across all three. When a gateway carries a value from one protocol to the next, IIoT Studio checks it end to end and names what went wrong. Fast, local, and the same on macOS, Windows and Linux.

  • MB Modbus RTU · TCP · RTU over TCP
  • UA OPC UA opc.tcp · security · history
  • MQ MQTT 3.1.1 · 5 · TLS · Sparkplug B
  • Coming soon
  • macOS, Windows, Linux
  • No account, no telemetry
IIoT Studio's gateway check on the sample project plant-floor.iiot.yaml: the explorer groups connections by site, Modbus, OPC UA and MQTT mixed, and a banner says 1 of 5 pairs disagree. Five source-to-published pairs: cold rooms 1 and 3 match, cold room 2's energy reads 4,153.3 kWh at the Modbus source but −3,772,768.25 on the MQTT broker and is a mismatch, the antechamber is stale because its edge node sent DDEATH, and pump P-101's speed matches. The inspector shows the source (unit 2, registers 12–13, raw 4581 CA66), the published Sparkplug metric (float_value 81 45 66 CA), and the source decoded in four word orders, where CDAB equals the published value: the gateway's word order is wrong, the device answers correctly.

Three protocols, one window

Each protocol at full depth.

Not a generic tag browser. Each protocol gets the depth of a dedicated tool, in the same window as the other two: the bus, the session and the broker traffic stay in reach.

  1. MB

    Modbus

    Serial lines and Ethernet devices

    Serial RTU · Modbus TCP · RTU over TCP · SSH bastion

    • Function codes 01, 02, 03, 04, 05, 06, 15 and 16, in the spec's own words: unit ID, coil, exception code, t3.5.
    • Register maps with types, scales, byte orders and validity rules, so a sentinel is not read as a temperature.
    • The RS-485 bus as it runs: transmit, wait and receive per unit, timeouts, backoff and the adapter's latency.
    • Serial ports that keep their names, and TCP devices that only a bastion host can reach, with pinned host keys.
  2. UA

    OPC UA

    Servers, security and history

    opc.tcp · None, Sign, SignAndEncrypt · Anonymous, UserName, X.509

    • Browse the address space; read, write and call methods with their arguments typed.
    • Subscriptions and MonitoredItems with the revised parameters the server actually granted.
    • History reads, and alarms and conditions you can acknowledge and confirm.
    • Certificates in the open: trust or reject a server, inspect the chain, manage the app's own PKI.
  3. MQ

    MQTT

    Brokers and Sparkplug B

    3.1.1 and 5.0 · TCP and TLS, mutual TLS optional · Sparkplug B

    • QoS 0, 1 and 2, retained messages and the last will, with v5 properties and reason codes shown as sent.
    • A live topic tree with message rates, and topic maps that turn JSON payloads into named values.
    • Sparkplug B: spBv1.0 topics, NBIRTH and DBIRTH, deaths, sequence numbers, aliases and commands.
    • The session and every packet on it: CONNECT to DISCONNECT, with the broker's answers.

plant-floor.iiot.yamlOne project: sites, connections and named tags across all three protocols, in a file you keep in git.

The gateway check

Follow one value across three protocols.

Plants rarely speak one protocol. A meter talks Modbus, a gateway republishes it on MQTT, SCADA reads it over OPC UA. IIoT Studio reads both ends of every hop and says which one is wrong, and why.

  1. 01

    Read it at the source.

    Cold room 2's meter answers on Modbus, RTU over TCP: unit 2, registers 12 and 13, the words 4581 CA66. In the map's ABCD order that is 4,153.3 kWh.

  2. 02

    Follow it through the gateway.

    The line-A edge gateway polls the meter and publishes energy_total as a Sparkplug B metric on the plant broker.

  3. 03

    Read it where it lands.

    On MQTT the metric arrives as −3,772,768.25 kWh. Both reads are project tags, paired in plant-floor.iiot.yaml with a tolerance of 0.5.

  4. 04

    Get the culprit by name.

    The gateway check tries the source in every word order. CDAB gives exactly what was published, so the fault is the gateway's configuration, not the device.

MB Cold rooms, line A Modbus RTU over TCP

unit 2 · 12–13 energy_total

4581 CA66

4,153.3 kWh

Line-A edge gateway Modbus → Sparkplug B
MQ Plant broker MQTT · Sparkplug B

spBv1.0/ColdStorage/DDATA/gw-line-a/cold-room-2 · energy_total

float_value 81 45 66 CA

−3,772,768.25 kWh

mismatchΔ −3,776,921.6 kWh · tolerance 0.5
The source's words in every order
ABCD4,153.3the map
CDAB−3,772,768.3= published
BADC−3.6257e-38
DCBA4.7815e23

The published value is the source decoded as CDAB: the gateway's word order is wrong. Fix it in the gateway's tag configuration, not here: the device answers correctly.

The project's tags: 12 tags across 3 protocols, each with its connection, protocol, address (a Modbus unit and register, an OPC UA NodeId, an MQTT Sparkplug topic or JSON path), live value, unit and status.

The tags behind the check, live from their connections: Modbus registers, OPC UA nodes and MQTT metrics side by side. On the sample plant two pairs match, cold room 2's energy is the CDAB mismatch, the antechamber is stale after its edge node sent DDEATH, and pump P-101's speed matches across an OPC UA to MQTT bridge.

  • Tags cross protocols

    A Modbus register, the OPC UA node that mirrors it and the MQTT metric a gateway publishes from it sit in one watch list, by name.

  • Sites mix protocols

    A site holds its serial lines, servers and brokers together, each connection with its own identity color.

  • One Decoder for three

    Paste a Modbus frame, an OPC UA chunk, an MQTT packet or a Sparkplug payload: the Decoder detects which it is and reads it field by field.

The wire is visible

From the value that looks wrong to the bytes that explain it.

The bus, the session and the broker traffic are one click away, for every protocol. Every screen here is the app itself, running on its fictional sample plant.

Every serial line has a scheduler, and the bus view shows it: transmit, wait and receive per unit on a timeline, bus occupancy, the t3.5 gap, timeouts, and the backoff of a unit that stopped answering.

The Modbus bus view of Bench RS-485 on ttyUSB0 at 57600 8N1: cycle time, bus occupancy, the t3.5 gap of 1.75 ms, an adapter latency of 16 ms and 2,400 ms lost to timeouts; a banner saying unit 41, an EEV controller, does not answer and is backing off, a tip with the command that lowers the adapter's latency timer to 1 ms, a timeline of transmit, wait and receive per unit with unit 41's timeouts hatched in red, and that unit's scheduler settings.

Healthy fear

Writes and publishes that name their target.

A write moves equipment, and so does a publish. Mark a connection as a live plant and its color tints the toolbar and the status bar, and every write, call and publish asks first, shows the raw value and reads back.

On a live plant a write asks for the register's name before the button works, previews the raw value (in two's complement for a negative number) and the frame it will send, and reads the register back after writing.

A write on Cold rooms, line A, a live plant reached over RTU over TCP: the dialog to write setpoint on unit 1 shows the register as protocol address 3 and 40004, the change from −18.6 to −20.0 °C, the raw value −200 as 0xFF38 in two's complement, the FC06 frame it will send and the read-back with FC03 that follows, and waits for the register's name, setpoint, to be typed before the Write setpoint button works.

Sites mix protocols

Every line, server and broker, by site.

A serial line on the bench, an OPC UA server at the water plant and the broker a gateway publishes to sit in one explorer, grouped by the site they belong to, each with an identity color.

Live plant, read-only or bench
Mark a connection as a live plant and its identity color tints the toolbar, the tab and the status bar, so it never looks like the bench, and every write, call, acknowledge and publish asks first. A read-only connection hides them all.
Every way in
Serial RTU, Modbus TCP and RTU over TCP for the serial-to-Ethernet converters in front of an RS-485 line, an SSH bastion for devices only a jump host can see, opc.tcp, and MQTT over TCP or TLS, with mutual TLS when the broker asks for it.
Security you can read
OPC UA security policies and modes, Anonymous, UserName and X.509 identities, and a trust decision on first contact with a server's certificate. MQTT client certificates warn a month before they expire.
Serial ports that keep their names
On Linux, connections save the stable /dev/serial/by-id path, so a port keeps its name when the adapter is re-plugged; your user needs the dialout group (uucp on Arch). On macOS only /dev/cu.* ports are listed.
Passwords stay out of files
Connection and project files never hold a password. Saved ones go to the system's credential store.
The app's sample plant. Every name and address is fictional.

Serial ports on Linux

Join the dialout group once (log out and back in after). Many USB serial adapters hold every short reply for 16 ms by default; lowering the latency timer to 1 ms speeds up every transaction, until the adapter is re-plugged.

sudo usermod -aG dialout $USERecho 1 | sudo tee /sys/bus/usb-serial/devices/ttyUSB0/latency_timer

Projects are files

Review a plant like code.

Sites, tags and gateway pairs are one text file; register maps, watch lists and topic maps sit next to it, owned by their protocols. Keep them in git, diff them, review the change that renamed a tag before it reaches the plant.

  • plant-floor.iiot.yamlThe project: sites, named tags across protocols, and the pairs a gateway must carry.
  • MBthree-phase-meter.mbmap.jsonA Modbus register map: kinds, types, byte orders, scales and validity rules.
  • UAintake-overview.uawatch.yamlAn OPC UA watch list: a subscription saved as a file, NodeIds by namespace URI.
  • MQcold-storage.mqmap.yamlAn MQTT topic map: Sparkplug metrics and JSON paths as named values, never aliases.
# IIoT Studio projectversion: 1name: Plant floorsites:  - { id: cold, name: Cold storage plant }tags:  - id: cr2.energy    label: cold_room_2.energy    connection: linea    unit: 2    reg: 12    eu: kWh  - id: cr2.energy.mq    label: cold_room_2.energy@broker    connection: broker    topic: spBv1.0/ColdStorage/DDATA/gw-line-a/cold-room-2    metric: energy_total    eu: kWhpairs:  - id: g3    label: Cold room 2 energy    source: cr2.energy    published: cr2.energy.mq    via: "Line-A edge gateway · Modbus RTU over TCP → Sparkplug B"    tolerance: 0.5
An excerpt of the app's sample project.

Simulators for all three

A plant on your laptop.

Every protocol ships a simulator inside the app, so the whole toolkit runs with no hardware: point a connection at it, then make it misbehave on purpose.

Serve any register map over TCP and, on Linux and macOS, over RTU on a virtual serial pair, with exceptions, delayed replies, silence and bad CRCs on demand.

The built-in Modbus simulator serving unit 10's cold-room controller map over RTU on a virtual serial port at 57600 8N1 and over TCP on 127.0.0.1:5020: each register with its value, raw hex and generator, a sine wave on the room temperature, noise on the evaporator, fixed values and the controller clock taken from the host, with tabs for faults and requests.

Light or dark, it is the same tool.

Twin dark and light themes, dark by default, built to sit next to your IDE. Drag to compare the MQTT topic tree.

The MQTT topics of the Plant broker: a topic tree browsed by level, 15 topics with their last payloads, QoS, rates and ages, Sparkplug births, data, a death and a retained command, and cold-room-1's DDATA in the inspector with its gateway lag, the decoded metric and a two-minute chart.

And the rest of the toolbox

Command palette
Ctrl K (Cmd K on macOS) reaches every connection, device, node, topic and tag, across the three protocols.
Problems first
Timeouts, exception codes, Bad status codes, stale metrics and dead edge nodes surface before the normal traffic, counted in the status bar.
Recordings
Record a session's values to CSV, to read later or hand to someone else.
SSH bastion
Reach a Modbus TCP device or a serial-to-Ethernet converter that only a bastion host can see, with host keys pinned on first use.
Certificates
OPC UA server certificates trusted or rejected on first contact, the app's own certificate, and MQTT client certificates that warn before they expire.
Alarms and history
OPC UA conditions you can acknowledge and confirm, and history reads of any node that keeps it.
Sparkplug commands
NCMD and DCMD with a typed metric, and Rebirth for an edge node, guarded like any other write.
Byte orders side by side
The same 32-bit reading in ABCD, CDAB, BADC and DCBA, so a manual's “little endian” is settled by the one plausible row.
Scanner
Finds the Modbus unit IDs that answer on a line and the address ranges each one serves.
Watch lists
An OPC UA subscription saved as a file, NodeIds by namespace URI, opened from the Project panel in one click.
Import and export
Move connections between machines as files, passwords only if you ask for them.
Export to CSV
Tags, traffic logs and topic lists export to CSV, to attach to a ticket or a commissioning report.

Nothing leaves your machine.

Read the privacy policy
No account
Install it and connect. There is nothing to sign into.
No telemetry
No analytics and no update checks. The app talks only to the devices, servers and brokers you set up, the SSH hosts you route through, and its own simulators.
Your files
Projects, register maps, watch lists, topic maps, recordings and exports are saved where you choose. Logs never hold values, payloads or secrets.
One app, three systems
The same app on macOS, Windows and Linux, with nothing else to install.

Download IIoT Studio

Version 0.1.0.

IIoT Studio is not released yet. Installers for Windows, macOS and Linux, and the apt repository, appear here as soon as the first build is out. Until then, every card below says what is coming.

Windows

x64 installer

Your system
Coming soon

The Windows installer is on its way.

macOS

Apple silicon

Your system
Coming soon

The disk image for Macs with Apple silicon is on its way.

Linux

x86_64

Your system
Coming soon

An apt repository, a .deb and an AppImage are on their way.

Builds are not code-signed yet, so the first launch shows a Gatekeeper warning on macOS and a SmartScreen warning on Windows.