Installation
MacTools EtherNet/IP 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, no Kepware. One-time purchase, no subscription.
Download
- Direct purchase: buy direct ($14.99 one-time) — you receive a download link by email
- Product page: /enip-explorer/
System Requirements
| Requirement | Minimum |
|---|---|
| macOS | 12 Monterey or newer (Apple Silicon & Intel) |
| Network | TCP/IP reachability to the device on EtherNet/IP's implicit port 44818 (also explicit messaging on the same port) |
| Firewall note | Some ICS firewalls block 44818 by default — verify before commissioning |
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. ListIdentity scan the subnet
Every EtherNet/IP device responds to the broadcast ListIdentity command on UDP 0.0.0.0:59972 (forwarded to 44818). Use it to find devices you didn't know were there.
- Open the app and click Discover in the toolbar.
- Choose the network interface on the ICS subnet (the app sends UDP broadcast on that interface only).
- Click Scan. Every responding device shows up with IP, port, vendor, product name, device type, serial number, and product code.
- Double-click a device to open a CIP session over TCP 44818.
2. Open an explicit session and read the identity
- Right-click the device → Open Session. The app issues RegisterSession over TCP.
- Once the session is established (status pill turns green), the Identity Object (Class 0x01) tree appears on the left.
- Browse attributes 1–7: Vendor ID, Product Type, Product Code, Revision, Status, Serial Number, Product Name. Vendor IDs decode to readable names (Rockwell = 1, Schneider Electric = 116, etc.).
3. Read a controller tag (Logix family)
Allen-Bradley ControlLogix, CompactLogix, and Micro800 controllers expose user tags through the Symbolic Object (class 0x6B) and the tag database.
- Expand Controller Tags in the device tree.
- The app reads the tag list (attribute 1 of the tag-symbols object) and shows every user tag with its data type and array dimensions.
- Click a tag to issue a CIP Read Tag service (0x4C for ≤4 bytes; 0x52 Read Tag Fragmented for arrays and UDTs larger than ~490 bytes).
- Atomic tags (BOOL, DINT, REAL) show inline; UDT instances expand their member breakdown.
4. Decode CIP classes on a non-Logix device
For drives, motor controllers, and non-Allen-Bradley devices, the app walks the Object List (attribute 3 of Class 0x02). Each class lists its instances and attributes. For motor drives, look at Class 0x28 (Motor Data), 0x68 (Control Supervisor), and 0x69 (AC/DC Drive).
Configuration
Session & transport
| Setting | Purpose / Typical Value |
|---|---|
| Encapsulation protocol | TCP 44818 (default), UDP 2222 for implicit I/O |
| Session timeout | Default per device — usually 120 s; the app re-registers if idle |
| Path | CIP path to the target object, e.g. 1 0 (backplane, slot 0) for a local Logix CPU |
| Multi-hop | For ControlLogix gateways: backplane, slot → bridge, port → target |
| RegisterSession interface handle | 0x00 default for CIP; some legacy devices require 0xA1 (legacy backplane) |
Read Tag parameters
| Parameter | Notes |
|---|---|
| Service | 0x4C Read Tag, 0x4E Read Modify Write, 0x52 Read Tag Fragmented, 0x4D Write Tag |
| Element count | Number of array elements (default 1) |
| Element size | Auto-derived from the tag's data type — BOOL=1, DINT=4, REAL=4, array=n×base |
| Fragment size | For Read Tag Fragmented — typically 480 bytes to fit CIP payload in one TCP segment |
CIP path syntax
CIP addressing uses port-segment/segment-value pairs. Common paths:
| Path | Meaning |
|---|---|
1 0 | Backplane, slot 0 (local Logix CPU) |
1 1 | Backplane, slot 1 |
2 192.168.1.5 | Ethernet module port 2 → device at 192.168.1.5 |
1 0 → 2 192.168.5.10 → 1 0 | Multi-hop: local backplane → Ethernet → remote backplane slot 0 |
| Symbolic | "MyTag" or "Program:Main.Counter[3].ACC" — ANSI Symbol segment |
Implicit I/O connections (RPI mode)
For periodic data exchange with a drive or remote I/O block, configure a ForwardOpen connection: O→T (output to target) and T→O (target to output) paths, RPI (Requested Packet Interval) per direction, and the connection size. Typical RPIs are 5–20 ms for motion, 50–100 ms for I/O blocks. Connection size must match the assembly instance size or the connection will reject with path/parameter error.
Key Features
ListIdentity discovery across subnets
Broadcast scan picks up every device running the EtherNet/IP encapsulation layer — Allen-Bradley, Schneider Electric, Yaskawa, Omron, B&R, and any ODVA-conformant device. Results decode the vendor ID (per ODVA's assigned list), device type, product code, and a hex serial number, so you know what you found before opening a session.
Full Logix tag database walk
For ControlLogix, CompactLogix, and Micro800 families, the app fetches the entire user-tag list with data types, array dimensions, and scope (controller vs program). No manual entry of tag names — discover them, then read/write with one click. UDT member breakdowns are rendered tree-style.
Symbolic and instance addressing
Read tags by symbolic name ("MyTag[2].Member") or by class/instance/attribute triple (Class 0x6B / Instance 1 / Attribute 1). Switch freely between the two — symbolic for Logix, instance for generic CIP devices. Both render with the same decoded payload view.
Multi-hop path traversal
Reach devices behind ControlLogix Ethernet modules, DLR rings, and backplane bridges. The path editor builds the byte-segment string for you (port segment, logical segment, data segment) and validates the encoding before sending — no off-by-one in path-byte math.
ForwardOpen / ForwardClose inspector
For implicit I/O, the inspector shows the connection parameters the device accepted (or rejected): O→T and T→O connection IDs, RPI, connection timeout multiplier, and the configured assembly instances. When a connection rejects, the CIP status decode shows exactly which parameter was out of range.
Live capture with CIP decode
Every explicit message and implicit I/O packet is logged with timestamps, decoded through encapsulation → CIP → service → class/instance/attribute layers. Filter by status (success vs extended status) to isolate a flaky tag or a device that intermittently returns Resource Not Available.
Troubleshooting
ListIdentity finds nothing
Symptom: Scan returns zero devices.
Fix: Three likely causes. (1) Wrong interface — confirm the selected interface is on the ICS subnet, not Wi-Fi. (2) Broadcast blocked — many managed switches filter UDP broadcast; try a directed scan at a known IP instead. (3) Devices respond but your firewall drops the return packets; on macOS, allow the app through System Settings → Network → Firewall.
RegisterSession fails / connection refused
Symptom: "Connection refused" or "No route to host" when opening a session.
Fix: The device either isn't reachable on TCP 44818 or EtherNet/IP is disabled. Test from Terminal:
nc -zv 192.168.1.50 44818
If nc succeeds but RegisterSession fails, the device may be in a non-CIP mode (Modbus TCP bridge only). Verify in the device's config that EtherNet/IP is enabled and that you're targeting the right protocol port.
CIP extended status: Path Destination Unknown (0x0315)
Symptom: Read Tag returns CIP status 0x06 0x0315 (Path Destination Unknown).
Fix: The CIP path doesn't reach the target object. For a Logix CPU in slot 0, the path is 1 0 (backplane, slot 0). If the CPU is in slot 2, the path is 1 2. For a remote CPU through an Ethernet module, multi-hop: 1 0 → 2 192.168.x.x → 1 0. Verify the slot number physically — Allen-Bradley backplanes count from the leftmost slot.
CIP status: Symbol Not Found (0x0721)
Symptom: Read Tag returns 0x06 0x0721.
Fix: The tag name doesn't exist or the case doesn't match — Logix tags are case-sensitive. Refresh the tag list (the program may have been re-downloaded with a different symbol set). For scoped tags, prefix the program name: "Program:MainProgram.MyTag". Tags inside Add-On Instructions or UDTs need full dot-notation paths.
ForwardOpen fails: Connection Not Scheduled
Symptom: Implicit I/O connection rejects with extended status 0x0117 (Connection Not Scheduled) or 0x0110 (RPI too small).
Fix: Connection size or RPI is out of the device's supported range. For a motion control drive, RPI must be ≥ the coordinator's coarse update period (typically 2 ms). For a remote I/O block, the connection size must equal the assembly instance byte count exactly — check the EDS file or the device's connection tab and match the bytes.
Encapsulation status codes
| Code | Name | Likely Cause |
|---|---|---|
| 0x0001 | Invalid Command | Wrong encapsulation command — verify you sent RegisterSession (0x65), not ListServices |
| 0x0002 | Insufficient Memory | Device out of session slots — close stale sessions |
| 0x0003 | Incorrect Data | Malformed protocol data — interface handle or context mismatch |
| 0x0006 | Invalid Session Handle | Session dropped; the app re-registers automatically |
| 0x0007 | Invalid Command Length | Encapsulation length field doesn't match payload bytes — almost always a path-segment encoding bug |
Support
- Email: support@voltrus.id
- Product page: /enip-explorer/
When reporting a comms issue, attach the exported CIP capture (redact any sensitive tag values or device IPs) and include the device vendor, product code, firmware revision, and the exact CIP path you used.