OPC-UA Explorer Documentation

Installation

MacTools OPC-UA 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 (unlike UA Expert), no Eclipse. One-time purchase, no subscription.

Download

System Requirements

RequirementMinimum
macOS12 Monterey or newer (Apple Silicon & Intel)
NetworkReachability to the OPC-UA server on TCP/4840
CertificatesFor SignAndEncrypt, the app generates a self-signed client cert in its keychain on first launch

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.

OPC-UA endpoints are URLs, not host:port. A connection string looks like opc.tcp://192.168.1.50:4840 — the scheme is opc.tcp, not tcp. Pasting 192.168.1.50:4840 without the scheme will fail.

Quick Start

1. Connect to an OPC-UA server (2 minutes)

This is the most common path — connecting to a PLC, an OPC server (Kepware, Matrikon), or a modern controller's built-in UA server.

  1. Open the app and create a new Endpoint.
  2. Enter the endpoint URL: opc.tcp://<ip>:4840.
  3. Set the Security Mode. Start with None to confirm reachability, then switch to SignAndEncrypt + Basic256Sha256 for production servers.
  4. Set authentication: Anonymous for most PLCs, or Username/Password if the server enforces it.
  5. Click Connect. The server's address space loads into the browse tree.

If the connection hangs or fails, jump to Troubleshooting — the most frequent cause is a security-mode mismatch or a server that only accepts signed certificates.

2. Browse the address space

  1. Expand Objects → the vendor's folder (e.g. Siemens, AllenBradley, Server).
  2. Drill into the variable folders. Each node shows its NodeId (e.g. ns=3;s="DataBlock"."Temperature"), data type, and current value.
  3. The Value column shows the last read. Right-click a node to read it once, subscribe, or write.

3. Subscribe to a variable (live updates)

  1. Right-click a Variable node → Subscribe.
  2. The node is added to the monitored-items list with a default publishing interval of 500 ms and sampling interval of 1000 ms.
  3. Values stream in the live-values panel; the timestamp and status code are shown alongside the value so you can see stale data.

4. Write a value

  1. Right-click a writable Variable → Write.
  2. Enter the value in the correct data type (the app validates against the node's DataType — don't write a decimal into an Int16 node).
  3. Confirm. A Good (0x00000000) status means the server accepted it; anything else is an error (see Troubleshooting).

Configuration

Endpoint Settings

ParameterOptions
Endpoint URLopc.tcp://<host>:4840 (default port 4840)
Security ModeNone, Sign, SignAndEncrypt
Security PolicyNone, Basic128Rsa15, Basic256, Basic256Sha256, Aes128Sha256RsaOaep, Aes256Sha256RsaPss
AuthenticationAnonymous, Username/Password, Certificate
Session timeoutDefault 600000 ms (10 min) — shorter if the server kills idle sessions

Security Matrix

Security mode and policy must both match what the server's GetEndpoints advertises. A mismatch produces a BadSecurityChecksFailed or BadSecurityPolicyRejected on connect.

CombinationWhen to Use
None + NoneIsolated OT network, quick commissioning only. No encryption, no auth.
SignAndEncrypt + Basic256Sha256The modern default. Required by OPC UA Part 2 conformance since 2018. Use this if the server supports it.
SignAndEncrypt + Basic128Rsa15Legacy servers (older Kepware, early S7-1500 firmware). Deprecated but still common.
Sign + Basic256Rare — integrity without confidentiality. Only if the server rejects encryption.

NodeIds

A NodeId uniquely identifies a node in the address space. It has a namespace index and an identifier that can be numeric, string, GUID, or opaque.

FormatExampleMeaning
Stringns=2;s=TemperatureNamespace 2, string identifier "Temperature"
Numericns=0;i=2258Namespace 0 (OPC standard), numeric 2258 = Server.ServerStatus.CurrentTime
Siemensns=3;s="DB1"."Temperature"Siemens symbol notation inside a data block

Subscription Tuning

ParameterDefaultGuidance
Publishing interval500 msHow often the server publishes a notification. Lower = more traffic. 100–250 ms for fast process; 1000–5000 ms for temps.
Sampling interval1000 msHow often the server samples the source. Must be ≤ publishing interval or you'll miss updates.
Queue size10How many value changes queue between publishes. Increase for bursty signals.
Discard policyOldestWhen the queue fills, drop the oldest changes (keep newest) or the newest (keep oldest).
Monitoring modeReportingReporting (push on change), Sampling (sample but don't push), Disabled.

Data Types

The app validates writes against the node's DataType. Common built-in types: Boolean, SByte/Byte, Int16/UInt16, Int32/UInt32, Int64/UInt64, Float, Double, String, DateTime, ByteString. Structured types (ExtensionObjects) are read-only in browse mode.

Key Features

Full address-space browse

Walk the tree from Objects, Types, and Views with reference following (HierarchicalReferences by default). Every node shows its NodeClass (Object, Variable, Method), DataType, AccessLevel, and current value inline — no separate read call per node.

Subscriptions with status codes

Every monitored value carries its OPC status code and source timestamp. A reading of Good with a 2-hour-old timestamp means the source went stale; a BadCommunicationError means the underlying PLC lost its connection. The value alone is not enough — the status is.

Method (function) calls

Browse to a Method node, supply its InputArguments, and invoke it server-side. Useful for triggering a recipe start, acknowledging an alarm, or running a diagnostic routine exposed by the server.

Historical read (HDA)

If a Variable is historized (HistoryRead = true), read its raw or processed history over a time range without a separate HDA server — the app uses the standard HistoryRead service on the same session.

Certificate management

For SignAndEncrypt, the app generates a self-signed client certificate and stores it in the macOS keychain. On first secure connect, the server is likely to reject the unknown cert — accept it (or have the admin trust your client cert in the server's trust list), and subsequent connects succeed.

Decoded service-level traffic

The traffic panel decodes OPC-UA services (Browse, Read, Write, Publish, CreateMonitoredItems) with their StatusCode, so you can see exactly which monitored item returned BadNodeIdUnknown or which write returned BadUserAccessDenied.

Troubleshooting

Common OPC-UA status codes

CodeNameLikely Cause
0x80010000BadInternalErrorServer hit an unexpected fault — check server logs
0x803B0000BadSecurityChecksFailedSignature didn't verify — wrong security mode/policy, or clock skew > a few minutes
0x803D0000BadSecurityPolicyRejectedServer doesn't accept the policy you selected — call GetEndpoints to list supported ones
0x801F0000BadUserAccessDeniedAuthenticated user lacks permission for that node's read/write
0x80350000BadIdentityTokenRejectedUsername/password wrong, or server requires a different auth scheme
0x803E0000BadCertificateUnknownServer doesn't trust your client cert — add it to the server's trusted list
0x80340000BadNoMatchNodeId doesn't exist — wrong namespace or the symbol was renamed

Connection refused / timeout on TCP/4840

Symptom: "Connection refused" or no response.
Fix: Confirm the server listens on 4840 and reachable. From Terminal:

nc -zv 192.168.1.50 4840

If nc fails, the server is offline, on another subnet, or behind a firewall. Siemens S7-1500 UA server must be explicitly enabled in TIA Portal (Protection & Security → "Permit access with OPC UA").

BadCertificateUnknown on first secure connect

Symptom: SignAndEncrypt connect fails with BadCertificateUnknown or BadCertificateUntrusted.
Fix: The server received your client certificate but doesn't trust it. Every UA server has a rejected/trusted certificate store. Find your client cert in the server's rejected folder (Kepware: in the Management Console; Siemens: under Certificate Management) and move it to Trusted. Then re-connect.

Subscription shows no updates

Symptom: You subscribed to a variable but the live panel shows a single value with no refresh.
Fix: Check the monitoring mode — if it's Disabled, the server isn't sampling. Confirm the publishing interval isn't absurdly long. Then verify the value is actually changing at the source — a static temperature reads once and never updates because nothing changed. The status code Good with a recent timestamp confirms the subscription is alive.

Write returns BadUserAccessDenied

Symptom: Reads succeed but writes return 0x801F0000 BadUserAccessDenied.
Fix: The node's AccessLevel or UserAccessLevel doesn't include CurrentWrite for your authenticated user. Either connect with higher-privilege credentials, or have the server admin raise the user's write permission on that node. The app shows the AccessLevel bitmask in the browse view — check that bit 1 (CurrentWrite) is set.

BadNodeIdUnknown after a server restart

Symptom: A NodeId that worked yesterday now returns BadNodeIdUnknown.
Fix: String NodeIds are volatile on some servers — they shift when the PLC program is recompiled or a new DB is added, renumbering namespaces. Re-browse to find the new NodeId. For stable addressing, prefer numeric NodeIds where the server assigns fixed identifiers, or use the server's import/export for NodeId mappings.

Support

When reporting a connection issue, attach the decoded traffic log (with IPs redacted), the server's GetEndpoints response, and the exact security mode/policy you used.