Installation
MacTools DNP3 Explorer is a native macOS app built with Rust and Tauri. It runs natively on Apple Silicon and Intel Macs — no Rosetta, no Parallels, no Java, no .NET runtime. One-time purchase, no subscription.
Download
- Direct purchase: buy direct ($14.99 one-time) — you receive a download link by email
- Product page: /dnp3-explorer/
System Requirements
| Requirement | Minimum |
|---|---|
| macOS | 12 Monterey or newer (Apple Silicon & Intel) |
| Network | TCP/IP reachability to the outstation on the configured DNP3 TCP port (default 20000) |
| Serial DNP3 | Optional USB-to-RS232/RS-485 adapter (FTDI FT232, CH340/CH341, CP2102) for DNP3 over serial |
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.
Quick Start
1. Connect to a DNP3 TCP outstation (5 minutes)
The most common path — reading analog and binary points from an RTU, meter, or protection relay over Ethernet.
- Open the app and create a new TCP master connection.
- Enter the outstation IP address and port
20000(the DNP3 default; some vendors use 20001 or 47808). - Set Source Address (master, commonly
1) and Destination Address (outstation, commonly3or1024). These must match the device's config exactly — DNP3 will silently drop frames addressed to anyone else. - Click Connect. The link-layer link comes up; the status pill turns green.
- Click Class 0 Scan to read every static point the outstation has. Values populate the point table grouped by type.
2. Enable unsolicited (event) reporting
- In the connection settings, enable Listen for unsolicited responses.
- Right-click the outstation and choose Enable Unsolicited — this issues the function code 19 (ENABLE_UNSOLICITED) for classes 0–3.
- Generate a state change at the device (flip a digital input, change an analog value). The event arrives as an unsolicited response and lights up in the live event log.
3. Inspect object headers and flags
Click any point to expand the underlying object header: group/variation, qualifier code, and the raw bytes. For binary inputs, the Flags byte is decoded inline — ONLINE, RESTART, COMM_LOST, REMOTE_FORCED, LOCAL_FORCED, CHATTER, RESERVED — so you don't have to read DNP3 spec volume 1 to interpret them.
4. Run a serial outstation (optional)
For DNP3 over serial, create a new Serial master connection, pick the port (/dev/cu.usbserial-*), and set framing — DNP3 serial is almost always 9600 8N1 or 19200 8N1. The link-layer 10-byte header uses 0x0564 sync bytes and CRC-16 every 16 bytes; mismatched baud corrupts the sync and you'll see zero valid frames.
Configuration
Connection Types
| Transport | Parameters |
|---|---|
| DNP3 TCP | IP, port (default 20000), source/dest address, link timeout, application timeout |
| DNP3 Serial | Serial port, baud, data bits, parity, stop bits, source/dest address |
| DNP3 UDP | IP, port — used for some radio networks and low-overhead links |
Link & Application Layer
| Setting | Purpose / Typical Value |
|---|---|
| Source address | The master's link-layer address (commonly 1) |
| Destination address | The outstation's link-layer address (commonly 3, 10, or 1024) |
| Link timeout | Time to wait for link-layer ACK — 500 ms typical on TCP, longer on serial/radio |
| Application timeout | Time to wait for an application-layer response — 5000 ms typical |
| Unsolicited response | Enable/disable per class; bind a listen socket (default 20000) on the master |
| Class 0/1/2/3 scan | Integrity poll (Class 0) and event poll cadence (often 0=on demand, 1/2/3 every 1–5 s) |
Object Groups & Variations
DNP3 organizes data into groups (the data type) and variations (the encoding). The most-used groups:
| Group | Type | Common Variations |
|---|---|---|
| G0 | Device attributes | Var 0–255 — vendor, model, serial, firmware |
| G1 | Binary Input | Var 1 (single bit), Var 2 (with flags) |
| G2 | Binary Input Change | Events that drove a state flip — class 1/2/3 |
| G10 | Binary Output | Control status — read-back of a relay point |
| G12 | Binary Output Command | Operate / Direct Operate with Control Relay Output Block |
| G30 | Analog Input | Var 1–6 — 32/16-bit int or float, with/without flags |
| G32 | Analog Input Change | Events that exceeded deadband — class 2/3 |
| G40 | Analog Output Status | Read-back of an analog setpoint |
| G41 | Analog Output Command | Write an analog setpoint |
Control operations
Binary controls (Group 12) use a Control Relay Output Block with an operation type, count, on/off time, and status. For safety, configure Select-before-Operate (SBO) as the default; Direct Operate issues the command in a single exchange and should be reserved for trusted local networks. Always include a queue index when issuing SBO — a mismatched index rolls back the operation.
Key Features
Automatic point-map discovery
One Class 0 Scan enumerates every static point the outstation exposes, grouped by object/variation and indexed by point number. No need to know the device's point map up front — discover it live, then save the discovered layout as a named view.
Live event log with link + app layer decode
Every DNP3 exchange is logged with timestamps and decoded to its full layered structure: link-layer sync/CRC, transport-layer FIR/FIN/SEQ, and application-layer function code, objects, and qualifiers. Filter by direction, by function code, or by error responses to isolate a flaky outstation.
Flags inspector
The 8-bit Flags byte (Group 1 Var 2 / Group 30 Var 2+) carries the operational state of a point. The inspector decodes every bit — ONLINE (0x01), RESTART (0x02), COMM_LOST (0x04), REMOTE_FORCED (0x08), LOCAL_FORCED (0x10), CHATTER (0x20), and the analog-only OVERRANGE/REFERENCE_ERR — so you see "COMM_LOST" instead of "0x04".
Secure Authentication v5 (SAv5) support
Modern utilities mandate IEEE-1815-2012 Secure Authentication. The app supports SAv5 aggressive mode with pre-shared key, so you can authenticate against Schweitzer, GE, ABB, and Siemens relays that have authentication enabled. Legacy v2 (legacy challenge) is also supported.
Device attributes (G0) panel
One click reads Group 0 device attributes: vendor name, model, serial number, hardware/software/firmware versions, and the device's supported function codes. No more guessing whether a relay firmware supports a specific command — the panel shows what the device advertised.
Controlled outputs with SBO timing
Issue Group 12 binary controls and Group 41 analog controls with proper Select-before-Operate timing (configurable select timeout, default 1 s). The app reports APAP (already in progress) and BCR (control denied) status codes verbatim, so permission issues are visible immediately.
Troubleshooting
Link comes up but Class 0 returns no data
Symptom: TCP connection opens, link status shows LINK_OK, but the integrity poll returns an empty response or never completes.
Fix: Check source/destination addresses. DNP3 silently drops frames whose link-layer destination does not match the device's local address — the link can still establish if the device is permissive on source. Confirm source = master (commonly 1), destination = outstation (commonly 3, 10, or 1024). When in doubt, open the link-layer decode panel and verify the addresses on the wire.
Unsolicited responses never arrive
Symptom: Link is up, polling works, but flipping a digital input produces no event.
Fix: Three likely causes. (1) Unsolicited not enabled on the outstation — issue function code 19 (ENABLE_UNSOLICITED) for class 0–3. (2) The master's listen socket is firewalled — confirm the device can send to your IP on port 20000 (or the configured unsolicited port). (3) The point's class assignment is 0, so events go nowhere on the link; assign it to class 1/2/3 in the device config.
Serial DNP3: zero valid frames
Symptom: Connection opens but the link-layer decode shows no 0x0564 sync bytes.
Fix: Baud/parity mismatch. DNP3 serial framing uses 0x05 0x64 as the link sync — corrupt framing produces no valid sync, ever. Cycle 9600 8N1 and 19200 8N1 first (the two industrial defaults). Then check RS-485 polarity (A/B swapped is the single most common wiring fault on multidrop buses).
DNP3 link-layer error codes
Link-layer responses use a function byte. The ones you'll see in practice:
| Code | Name | Likely Cause |
|---|---|---|
| 0x01 | RESET_LINK_STATES | Sent on initial connect; should be followed by a link reset ACK |
| 0x09 | REQUEST_LINK_STATUS | Health probe — reply is 0x0B |
| 0x0E | NOT_LINKED | Link dropped; usually a link timeout, address mismatch, or device reboot |
| 0x10 | NOT_SUPPORTED | Device doesn't support this link function — rare; indicates a misconfigured device |
Application-layer IIN (Internal Indicators) bits
Every response carries a 2-byte IIN field. Decode them in the live event log:
| Byte.Bit | Meaning |
|---|---|
| IIN.1.0 | BROADCAST — response to a broadcast, not addressed to you |
| IIN.1.1 | CLASS_1_EVENTS — class 1 events queued, poll needed |
| IIN.1.2 / 1.3 | CLASS_2 / CLASS_3_EVENTS queued |
| IIN.1.4 | NEED_TIME — device clock needs setting |
| IIN.1.5 | LOCAL — device in local mode; remote control refused |
| IIN.1.7 | RESTART — device restarted since last comms; re-read point map and events |
| IIN.2.0 | NO_FUNC_CODE_SUPPORT — device doesn't support the function you sent |
| IIN.2.1 | OBJECT_UNKNOWN — group/variation not implemented |
| IIN.2.2 | PARAMETER_ERROR — qualifier or index out of range |
Secure Authentication v5: association rejected
Symptom: SAv5 handshake fails with "association not found" or "key wrap fail".
Fix: The pre-shared key (PSK) on the master must match the device's configured key byte-for-byte, and the association ID must match. Re-key using the device vendor's config tool, restart the session, and confirm the update method is GMAC-v5 (not legacy v2). Key change messages (function code 24) must use the correct key status word — mismatched status rolls back to the previous key.
Support
- Email: support@voltrus.id
- Product page: /dnp3-explorer/
When reporting a comms issue, attach the exported event log (redact any sensitive PSKs or device IP addresses) and include the source/destination addresses, transport (TCP/serial/UDP), and the device vendor and firmware version.