Installation
Voltrus HMI is a desktop HMI/SCADA builder for industrial teams that want a native macOS authoring experience without licensing per-tag or per-seat. Design dashboards locally, then publish to a runtime instance running on the same Mac, a Linux box, or a VPS. One-time purchase, no subscription.
Download
- Product page: /voltrus-hmi/ — current download link and purchase options
System Requirements
| Requirement | Minimum |
|---|---|
| macOS (authoring) | 12 Monterey or newer (Apple Silicon & Intel) |
| RAM | 8 GB for small projects; 16 GB recommended for trend logging or 50+ screens |
| Runtime OS | macOS, Linux (Ubuntu 22.04+, Debian 12+), or any VPS with Node.js 20+ for the published runtime |
| Network | TCP reachability to your PLCs (port 502 Modbus, 4840 OPC-UA, 102 S7, 44818 EtherNet/IP) |
| Optional | USB-to-RS485 adapter for serial Modbus RTU polling from the runtime host |
First Launch
If you downloaded the direct build outside the App Store, macOS Gatekeeper may block the unsigned binary on first run. Right-click the app, choose Open, then confirm. This is only required once.
voltrus-hmi with no args for the authoring UI; voltrus-hmi serve ./project.vhmi --port 8080 for the headless runtime on a Linux box or VPS.
Quick Start
1. Connect to a Modbus TCP PLC (5 minutes)
- Open the app and create a new project (File → New Project). Save it as
line-a.vhmi. - In the Devices panel, click + and choose Modbus TCP.
- Enter the PLC IP (e.g.
192.168.1.50), port502, Unit ID1. - Click Test Connection. The status pill turns green when the first read succeeds.
- Expand the device to browse its register map. Drag a holding register onto the canvas — it becomes a live value widget bound to that address.
2. Build a screen with widgets
- Drag widgets from the left palette: Value, Button, Bar Gauge, Tank, Trend Chart, LED, Image Switch.
- Drop a Bar Gauge on the canvas. In the right-hand Properties panel, bind its
valueproperty to a register by clicking Bind… and picking the register from the device tree. - Drop a Button, bind its
On Pressaction to a Modbus write (FC05 / FC06) on a coil or holding register. - Save the project. The preview pane on the right shows live data immediately.
3. Add a trend chart with logged history
- Drag a Trend Chart to the canvas.
- In Properties, enable Log history and pick the sampling interval (1 s default; 100 ms for fast loops).
- Add 1–4 series, each bound to a register. Historical data persists to a local SQLite log under
./logs/<project>.db. - The chart auto-pans to "live tail" mode; scroll to scrub history, double-click to reset.
4. Publish to operators
- Project → Publish… packages the project with the runtime into a self-contained bundle.
- For local ops, publish to the same Mac as a runtime on port 8080. Operators open
http://your-mac.local:8080in any modern browser. - For a Linux/VPS runtime, scp the bundle to the host and run
voltrus-hmi serve line-a.vhmi --port 8080behind nginx/Caddy for TLS. - Set up the runtime as a systemd unit or
launchdplist so it restarts on reboot.
Configuration
Supported PLC protocols
| Driver | Transport | Common Devices |
|---|---|---|
| Modbus TCP | TCP 502 | Schneider M221/M241, Phoenix Contact, VFDs, power meters |
| Modbus RTU | Serial RS-485 | Energy analyzers, motor protections, legacy PLCs |
| OPC-UA | TCP 4840 | Siemens S7-1500 (OPC-UA server), Beckhoff, Ignition gateway |
| Siemens S7 | ISO-on-TCP 102 | S7-1200, S7-1500, S7-300/400 (with Put/Get enabled) |
| EtherNet/IP CIP | TCP 44818 | Allen-Bradley ControlLogix / CompactLogix / Micro800 |
| MQTT | TCP 1883 / TLS 8883 | IIoT gateways, Sparkplug B devices, telemetry brokers |
Connection settings
| Setting | Purpose / Typical Value |
|---|---|
| Poll interval | How often registers are read — 1000 ms default; 100 ms for fast loops |
| Timeout | Per-request timeout before retry — 3000 ms typical |
| Retry count | Retries before flagging the device offline — 3 default |
| Offline threshold | Consecutive failures before the device shows disconnected in the UI — 5 default |
| Byte order (32-bit / float) | Big-endian (ABCD), Little-endian, Swapped variants — must match the PLC |
| Scaling | y = mx + b per register; specify m (scale), b (offset), and unit label |
Widgets and bindings
| Widget | Bindable Properties |
|---|---|
| Value | value (number/string), visible (bool), alarmColor |
| LED / Indicator | state (bool), blinkOnAlarm (bool) |
| Bar Gauge / Tank | value, min, max, lowAlarm, highAlarm |
| Button | On Press / On Release actions (write register, run script) |
| Trend Chart | 1–4 series, each bound to a logged register with pan/zoom |
| Image Switch | state (bool); two-state image swap (e.g. valve open/closed) |
| Custom HTML | JavaScript snippet with access to the live tag namespace — for video walls or third-party widgets |
Runtime deployment modes
| Mode | Use Case |
|---|---|
| Same-Mac authoring + runtime | Single-seat HMI; operators open http://your-mac:8080 |
| Headless Linux runtime | Industrial PC or VPS; voltrus-hmi serve project.vhmi behind nginx/Caddy |
| Containerized | Official Docker image — docker run -p 8080:8080 -v ./project.vhmi:/app/project.vhmi voltrus/hmi |
| Read-only HMI display | Static export of the screens for a kiosk browser; no writes back to PLCs |
Key Features
Drag-and-drop screen builder
Industrial widgets designed for ops — gauges, tanks, valves, motors, trends, alarms — drop onto a canvas, snap to a grid, and bind to live tags with one click. No SVG wrangling, no CSS, no per-screen JavaScript unless you opt into the custom HTML widget.
Native multi-protocol PLC connectivity
Modbus TCP/RTU, OPC-UA, Siemens S7 (1200/1500/300/400), EtherNet/IP CIP, and MQTT (including Sparkplug B) are first-class drivers — not ODBC bridges, not OPC gateways. A single screen can mix tags from a Schneider PLC over Modbus, a Siemens PLC over S7, and a telemetry broker over MQTT in the same trend chart.
Trend logging with local SQLite history
Every bound tag is optionally logged to a per-project SQLite database. Default 1 s sample, configurable down to 100 ms. The trend chart reads the same database for historical scrubbing — no separate historian to deploy. For long-term retention, configure a daily export to CSV or Parquet.
Alarm management
Per-tag alarm thresholds (low-low, low, high, high-high) with configurable latching, acknowledgement, and severity colors. The alarm summary widget shows unacknowledged alarms in priority order with timestamps; operators acknowledge from the dashboard or via the API. Alarm events are written to the same SQLite log for audit.
Headless runtime deployment
Publish a project once and serve it anywhere — a Mac, a Linux industrial PC, a VPS, or a Docker container. The runtime is a single process that serves the screens over HTTP/WebSocket; operators need only a browser. No client install, no plugin, no .NET framework on the operator PC.
Role-based access for write operations
Tag writes (buttons, setpoints) can require a logged-in operator. Configure local users with roles (Operator, Engineer, Admin) or front the runtime with an OIDC provider (Authentik, Keycloak, Cloudflare Access) for SSO. Read-only access remains open by default for ops dashboards on the shop floor.
Troubleshooting
Modbus device shows "Offline" immediately
Symptom: New Modbus TCP device fails Test Connection with "Connection refused" or timeout.
Fix: Verify network reachability from the authoring Mac first:
nc -zv 192.168.1.50 502
If nc fails, the device is offline, on another subnet, or behind a firewall. If nc succeeds but the device still reads offline, the Unit ID is wrong — power meters commonly use 1, some Schneider devices use 255, and gateways may use the downstream slave's address.
Siemens S7 connection: "Cannot connect to PLC"
Symptom: S7 driver returns "TCP connection to 192.168.1.10:102 refused or no response".
Fix: Three likely causes. (1) Put/Get not enabled on the S7-1200/1500 — in TIA Portal under Protection & Security, enable "Permit access with PUT/GET communication". (2) Rack/slot wrong — most S7-1500 CPUs are rack 0 slot 1; S7-1200 is rack 0 slot 1. (3) The optimization level on the data block — symbolically-accessed-only blocks aren't readable; mark the DB as "optimized" with the right access or use absolute addressing.
OPC-UA: certificate rejected
Symptom: OPC-UA connect fails with BadCertificateInvalid or BadSecurityChecksFailed.
Fix: The runtime's self-signed certificate must be trusted by the OPC-UA server. Export the cert from ~/.voltrus-hmi/opcua-cert.pem, upload it to the server's trust list (Siemens TIA under OPC UA → Server → Trusted Clients), then reconnect. For development only, you can disable certificate validation by setting OPCUA_INSECURE=1 in the runtime env — never in production.
Trend chart shows no historical data
Symptom: Live values update, but the chart's history is empty.
Fix: Log history wasn't enabled on the tag when it was added — enabling it doesn't backfill data, only logs from now on. Confirm the property is on, then wait one poll interval. If still empty, check the SQLite log file exists and is writable: ls -la ./logs/<project>.db. A permissions mismatch on the runtime host is the usual cause.
Published runtime shows stale values
Symptom: Browser shows values that don't update; polling never starts.
Fix: WebSocket upgrade failed — the reverse proxy (nginx/Caddy) in front of the runtime isn't forwarding Upgrade: websocket. Add the upgrade headers:
# nginx
location / {
proxy_pass http://127.0.0.1:8080;
proxy_http_version 1.1;
proxy_set_header Upgrade $http_upgrade;
proxy_set_header Connection "upgrade";
}
Without WebSocket, the dashboard falls back to long-polling at 1 Hz — values move but look "stuttery".
32-bit values render as garbage
Symptom: A 230.0 V reading shows as 0.003 or 1.5e7.
Fix: Byte order mismatch. Modbus 32-bit floats span two registers and every vendor picks a different order. In the register binding, cycle through Big-endian (ABCD), Little-endian (DCBA), Swapped Big (BADC), Swapped Little (CDAB) — exactly one will produce a sane value. Apply the same setting to all 32-bit tags from the same device.
Support
- Email: support@voltrus.id
- Product page: /voltrus-hmi/
When reporting an issue, attach the project file (.vhmi, with sensitive IPs redacted), the runtime logs from ./logs/, and note the PLC vendor, protocol, and firmware version involved.