OPC UA
Driver: opc_ua
OPC UA (Unified Architecture, IEC 62541) client. Reads, writes, browses, and subscribes to nodes on industrial controllers, building-management systems, and any vendor speaking opc.tcp. Supports anonymous and username/password auth, and the three OPC UA security modes (None / Sign / SignAndEncrypt). Built on node-opcua.
Open OPC UA Explorer
Once an opc_ua device is configured, the explorer can browse the server's address space, read and write node values, subscribe to value-change events, and run endpoint discovery. Unlike BACnet, KNX, and Modbus, OPC UA is a core integration — it does not require a separate license product to add a device or open the explorer.
Prerequisites
- An OPC UA server reachable from the GEM host via
opc.tcp. - For non-
Nonesecurity modes: the server's application certificate must be trusted by GEM (or auto-accepted viaauto_trust_server_certon initial connect). - For username/password auth: credentials provisioned on the server.
Setup
- From Open Devices, add a device and pick driver type opc_ua, then set its
endpoint_urlattribute toopc.tcp://host:port[/path]. The conventional OPC UA discovery port is 4840, but always use the host and port the server documents — some servers return session endpoints on a different port, which the Endpoints tab will reveal. - Optionally set
security_mode+security_policyand credentials. Many servers expose an unsecuredNone / Noneendpoint AND secured endpoints on the same URL — pick the pair the server advertises (use the Endpoints tab to enumerate). Reload the device after changing any connection, security, or credential attribute. - Open Open OPC UA Explorer, pick your server from the OPC UA Server selector at the top, then browse the address space from the Objects folder and identify the NodeIds you care about.
- To bind a NodeId to a GEM zone, use the explorer's Map to Zone tab — or set the zone attribute
opc_ua_nodeto the NodeId (e.g.ns=2;s=Temperature) andopc_ua_data_typeto the OPC UA DataType name (Boolean,Int32,Double,String, …) by hand. The data type is required for writes so stringified values coerce correctly. Mapped nodes are auto-monitored so value changes reflect onto the zone — see Binding nodes to zones below.
Attribute reference
Device
| Attribute | Required | Default | Description |
|---|---|---|---|
endpoint_url | yes | — | opc.tcp://host:port[/path] |
security_mode | no | None | None, Sign, or SignAndEncrypt. Must match an endpoint the server advertises. |
security_policy | no | None | None, Basic256Sha256, Aes128_Sha256_RsaOaep, or Aes256_Sha256_RsaPss. |
username | no | — | Leave blank for anonymous auth. |
password | no | — | Required when username is set. Stored encrypted via the secure-attribute pipeline. |
auto_trust_server_cert | no | false | When true, the server's certificate is auto-added to the trusted store on first connect. Lab / dev only — production should pre-trust certs explicitly. |
session_timeout_ms | no | 60000 | How long the server may keep the session alive without activity. |
requested_publishing_interval_ms | no | 1000 | How often the server publishes monitored-item updates for our subscription. |
op_failure_threshold | no | 5 | Consecutive op failures before the watchdog considers recycling the client. |
op_staleness_ms | no | 120000 | How long without a successful op before the threshold can trip a recycle. |
Zone
| Attribute | Required | Default | Description |
|---|---|---|---|
opc_ua_node | no | — | NodeId in standard form, e.g. ns=2;s=MyVariable or ns=0;i=2253. A read_value / write_value / subscribe_node command aimed at this zone (with no explicit node_id) targets this node — see Binding nodes to zones below. |
opc_ua_data_type | no | — | OPC UA DataType name (Boolean, Int16, UInt32, Float, Double, String, …). Required for writes so stringified values coerce correctly; reads infer from the server response. Used as the fallback data_type when a write_value aimed at this zone omits it. |
Binding nodes to zones
The easiest path is the Map to Zone tab in the OPC UA Explorer: select a node in the Explorer tab, switch to Map to Zone, pick (or inline-create) a subsystem/zone, optionally choose the write DataType, Test Read to confirm the live value, and Map Node. The mapper warns when the chosen zone isn't bound to the OPC UA device (with a one-click bind), writes the opc_ua_node + opc_ua_data_type attributes, and immediately subscribes the node.
A mapped zone gets two behaviors:
- Zone-scoped commands —
read_value,write_value,subscribe_node, orunsubscribe_nodeaimed at the zone (from a macro, trigger, or the command surface) without an explicitnode_idtarget the zone'sopc_ua_node. Forwrite_value, an omitteddata_typefalls back to the zone'sopc_ua_data_type. - Live value reflection — the driver monitors every bound zone's mapped node (auto-subscribed on connect, and immediately when mapped from the UI). Change notifications are written to the zone's
valueattribute, so triggers, history, and widgets can consume the live reading.
The driver still does not poll nodes on a timer — reflection is change-of-value via the server's subscription mechanism. For servers that don't support subscriptions, schedule a macro that runs read_value instead.
Commands
| Command | Args | Notes |
|---|---|---|
get_endpoints | — | Discover what security configurations the server advertises. Useful when connect fails with BadSecurityModeRejected. |
browse_root | — | Browse from the OPC UA Objects folder (the standard entry point). |
browse_node | node_id, direction | Browse a specific node's references. Direction is Forward (default), Inverse, or Both. |
read_value | node_id | Read the present-value attribute of a node. |
read_values | node_ids | Batch read several nodes in a single request. Array or CSV. |
write_value | node_id, value, data_type | Write to a writable node. data_type is required for correct coercion. |
subscribe_node | node_id, sampling_interval | Set up a change-of-value monitored item. |
unsubscribe_node | node_id | Drop a previously-subscribed monitored item. |
call_method | object_id, method_id, input_arguments | Invoke an OPC UA Method node. |
get_diagnostics | — | Snapshot of client health: connection state, watchdog counters, active subscriptions, last client error. |
OPC UA Explorer (/admin/opc_ua)
Live operator surface for the configured opc_ua device. Pick the device from the OPC UA Server selector at the top of the page — the toolbar then shows its endpoint and configured security mode/policy, and Refresh devices re-reads the device list. The page has five tabs:
- Explorer — split-pane view. The left panel is a tree of the server's address space starting at the Objects folder; click any node to load its details on the right (Reload re-browses the root). The detail panel shows the current value — auto-read on selection, with a Read button to re-read — plus its DataType and status code, for any node class. Variable nodes additionally get a Write form (pick the DataType, type the value) and a Subscribe / Unsubscribe control with a configurable sampling interval (100 ms minimum).
- Map to Zone — bind the node selected in the Explorer to a GEM zone (see Binding nodes to zones above): pick or inline-create a subsystem/zone, optionally choose the write DataType, Test Read to confirm the live value, and Map Node. Existing mappings are listed below the form with a per-row remove.
- Endpoints — the Run GetEndpoints button queries the server and lists every endpoint URL, security mode, security policy, and accepted user-token policy. Use this when
connectfails withBadSecurityModeRejected— it shows exactly what the server offers. - Diagnostics — session up/down, watchdog counters (consecutive failures, client recycles, last successful op, last client error), active monitored items with their last cached value, and the configured endpoint / security settings. Refresh reloads on demand; Auto-refresh polls every 5 seconds.
- Settings — read-only summary of the device's current attribute values. Edit the values themselves from the Devices page; most changes need a device reload to take effect.
Value Coercion
OPC UA is strongly typed on the wire (every value carries a DataType tag), so the driver coerces stringified arguments at the boundary. A saved macro that passes value='false' with data_type='Boolean' produces false on the wire — not the JS-truthy string. Garbage values throw an explicit error and do not send the write.
write_value requires explicit data_type (refuses to guess from the JS type) — without it the underlying library's type inference is unreliable for stringified arguments.
Known limitations
- No certificate management UI in v1. Trusted/rejected certs live on disk under the GEM PKI directory.
auto_trust_server_cert=trueis the easy path for lab/dev; production deployments should pre-trust the server cert out of band. - One shared subscription per device. Every monitored item lives on a single shared OPC UA subscription. Matches the recommended pattern and is more efficient on the server, but means all monitored items share one publishing interval (
requested_publishing_interval_ms). - Manual subscriptions are in-memory and not restored on reload. Monitored items created with
subscribe_node(or the explorer's Subscribe button) live only for the current session. If the device reloads, or the connection drops and reconnects, the subscription list starts empty — re-issuesubscribe_node(for example from a macro that runs on connect) if you need it to persist. The exception is zone-mapped nodes (opc_ua_node): those are re-subscribed automatically on every connect. - Methods addressable by NodeId only.
call_methodrequires both an object NodeId and a method NodeId — browse-name-only addressing is not supported. Input arguments are passed to the server as supplied (an array of already-typed values); they are not coerced from strings the waywrite_valuecoerces its value.
Troubleshooting
| Symptom | Check |
|---|---|
connect fails with BadSecurityModeRejected | security_mode / security_policy don't match any endpoint the server advertises. Run get_endpoints (or open the Endpoints tab) and pick a matching pair. |
connect fails with BadCertificateUntrusted | Either set auto_trust_server_cert=true (dev/lab only) or copy the server cert into GEM's PKI trusted/certs directory. |
Read returns null with status BadNodeIdUnknown | The NodeId does not exist on this server. Browse from the root to find the correct identifier — namespace indexes are server-specific. |
Write returns BadTypeMismatch / BadValueOutOfRange | Specify data_type explicitly on the write — the driver coerces stringified args to the named OPC UA type. Without it the library tries to infer and often gets it wrong for numeric strings. |
| Subscription "stops working" | Check the active monitored items in the Diagnostics tab. Sampling intervals well below the server's publishingInterval won't produce more frequent updates. Remember monitored items reset on a device reload — re-issue subscribe_node if the list is empty. |
A zone bound with opc_ua_node never shows a value | The mapped node is monitored via the server's subscription mechanism (auto-subscribed on connect) and the zone's value attribute only updates on change — run read_value once, or wait for the value to change on the server. If nothing ever arrives, check the Diagnostics tab for the monitored item; servers that don't support subscriptions need a macro-driven read_value instead. If the mapping was added by hand-editing attributes, reload the zone so the driver picks it up. |
Related Documentation
- Devices — Creating the OPC UA device
- Zones — Binding NodeIds via
opc_ua_node - Attributes — Zone attribute mapping