PLC Programming SAPLC ProgrammingSOUTH AFRICA

learn · South Africa

OPC UA basics: namespaces, nodes, and SA plant use

OPC UA basics for SA control engineers — namespaces, NodeIds, security policy, certificate trust, subscription rates, and the namespace-index drift trap.

OPC UA basics is the topic that every SA controls engineer eventually has to learn the hard way — usually on a Friday afternoon, usually during a SCADA migration, usually because the legacy DCOM-based OPC Classic gateway has finally died and the replacement Ignition gateway is sitting on the engineering laptop refusing to browse the new S7-1500's address space. The vendor support line is closed for the weekend, the production manager wants the historian back online before Monday morning, and the engineer has eight hours to learn enough about namespaces, NodeIds, certificate trust, and security policies to get a working subscription. This tutorial is the version of that knowledge written down before the Friday afternoon hits.

Try the simulator →

Why this matters on real plants

OPC UA is the protocol that almost every modern SCADA platform speaks underneath the binding dialog. Ignition, FactoryTalk Live Data, AVEVA System Platform, Wonderware Historian, Kepware, the Siemens TIA Portal SCADA gateways — all of them use OPC UA as the cross-vendor bridge between the PLC and the SCADA layer. A controls engineer who does not know the protocol is at the mercy of the binding dialog, which means the moment the binding does not resolve, the engineer has no diagnostic vocabulary and the troubleshooting is by trial and error. We have walked into a brownfield FMCG plant where the SCADA was reading 240 tags from a CompactLogix at a 100 ms publishing interval — except the actual update rate on the underlying device was 500 ms, the SCADA was polling four times faster than the data was changing, and the CPU comms scan was eating 40% of the CPU budget for no benefit. The fix took fifteen minutes once we understood the publishing-interval semantics. Without that understanding it would have been a four-day investigation.

The cost of getting OPC UA wrong is rarely a hard failure. It is performance creep — a SCADA that gets sluggish over a year as more screens are added, a CPU scan that drifts from 6 ms to 15 ms after a three-month commissioning, a historian that misses every transient because the publishing interval is set to two seconds. Each of those is recoverable but only if the engineer knows where to look. The vocabulary in this tutorial is what gives you those places to look.

The third reason OPC UA basics matters more in SA than in textbook examples: many plant networks here run on copper-fibre converters from three different vendors with switch rings that have evolved over a decade, and the OPC UA security policy choices interact in awkward ways with that. Sign-and-encrypt traffic across a switch ring with a 40 ms round-trip during a spanning-tree convergence event will time out and force a re-subscribe. Plain None security across the same ring works but exposes the subscription to anyone on the management VLAN. The right choice depends on the network, not on the textbook.

The mental model

An OPC UA server exposes its data as a tree of nodes. Every PLC tag, every diagnostic register, every device-level data structure — they are all nodes in the address space. Each node has a NodeId, a BrowseName, a typed value, and a set of references to other nodes. The tree is structured: the root has standard children for Objects, Types, Views, and the server-defined hierarchy hangs off Objects.

A NodeId has two parts: a namespace index and an identifier. The namespace index is a small integer (0 for the standard OPC UA core, 1 for the server-local namespace, 2 onwards for vendor-defined and user-defined namespaces). The identifier inside the namespace is one of four flavours — numeric, string, GUID, or opaque bytes. A typical NodeId for a PLC tag on a Siemens S7-1500 server looks like ns=3;s="Conveyor_Data"."Motor1"."Status" — namespace index 3, string identifier with the structure path. A NodeId on an Allen-Bradley OPC UA server looks like ns=2;s=Production.Motor1.Status — same idea, different vendor's namespace index.

The trap in the namespace index is that the index is assigned at server startup and is not stable across server restarts. A namespace at index 3 on Monday can be at index 4 on Tuesday after a firmware update added a new vendor namespace at index 3. A SCADA client that hard-coded ns=3 in its NodeIds is now reading the wrong namespace. The fix is to browse by namespace URI (a stable string like urn:Siemens:S7-1500:Conveyor_Data) and resolve to the current index at subscription time. Every modern OPC UA client library does this if you ask it to. The default templates in some legacy SCADA tools do not.

A subscription is the mechanism by which the client receives value updates from the server. The client sends CreateSubscription with a publishing interval, then CreateMonitoredItems with the NodeIds it wants to watch and a sampling interval per item. The server samples each item at its sampling interval, queues changes, and pushes the queue to the client at the publishing interval. The publishing interval is the floor on how fast the client can see changes. Set it to 500 ms and the client cannot see anything faster, even if the underlying tag changes every 10 ms.

The security policy is the last piece of the model. OPC UA defines three policies: None (no encryption, no signing, no certificate exchange — fastest, no security), Sign (messages are signed with the server's certificate but not encrypted — tampering detected, eavesdropping possible), and SignAndEncrypt (signed and encrypted — full protection, highest CPU cost). Each policy requires a certificate exchange between client and server with mutual trust — the client trusts the server's certificate, the server trusts the client's certificate. Both certs must be in the trusted directory at both ends. Get the directory wrong and the handshake fails with a non-obvious error.

Worked example

Open the simulator. Drop a Siemens S7-1500 CPU on the rack with a DI16, a DO16, and an AI8 module. Enable the OPC UA server in the CPU properties — the simulator's S7-1500 ships with a built-in OPC UA server on port 4840, exactly as the real CPU does in TIA Portal. Configure a few tags in a global DB and tick the OPC UA accessibility flag for each.

Now we connect a client. The simulator includes a built-in UA Expert-style client window — it mirrors the same connect / browse / subscribe workflow as the real Unified Automation UA Expert. Open the client and create a new connection:

Endpoint URL:   opc.tcp://localhost:4840
Security:       None              // for now — we will tighten this later
User auth:      Anonymous
Application:    SimUAExpert
Session name:   commissioning

Click Connect. The first connect attempt will fail with a certificate error — the server has issued its self-signed certificate but the client has not yet trusted it. Open the client's PKI directory (~/sim/pki/trusted/certs/ on the simulator), drop the server certificate file in, and reconnect. This is the certificate-trust step. Most engineers hit it the first time and assume the network is broken. The error in the client log is BadCertificateUntrusted and the fix is always the same: copy the server cert from the rejected directory to the trusted directory. (The reverse is also required for Sign and SignAndEncrypt — the server has to trust the client's cert too. The client cert lives in the simulator's ~/sim/pki/own/cert/ directory and gets copied to the server's trusted directory at first connect.)

Once connected, browse the address space. The root has the standard Objects folder. Inside Objects is the server's vendor namespace — for the simulator's S7-1500 server the path is Objects > DeviceSet > S7-1500 > Conveyor_Data > Motor1 > Status. The NodeId for Status is ns=3;s="Conveyor_Data"."Motor1"."Status". Note the ns=3 — that is the index assigned to the user namespace this session. Restart the server and reconnect — the index might be ns=2 or ns=4 depending on what other namespaces are loaded. The string identifier survives the restart; the index does not.

Now create a subscription. Right-click Status and choose "Add to subscription". The client opens the subscription dialog:

Publishing interval:    500 ms
Sampling interval:      500 ms     // per item, can be < publishing
Queue size:             10         // messages buffered if publish skipped
Discard oldest:         true

Click OK. The subscription is now live. Toggle the simulator's Motor1.Status bit by pushing the start-stop button on the panel — the value in the client's Data Access view updates every time you push the button, with a server timestamp on each update. The publishing interval of 500 ms means you cannot see two changes inside the same 500 ms window — if you flick the button at 200 Hz, you see one update every 500 ms, the latest value at each publish.

Tighten the security. Disconnect, change the security policy from None to Basic256Sha256 - Sign, reconnect. The handshake now requires both certificates in both trusted directories. The first attempt fails again — BadCertificateUntrusted from the server side this time, because the client's cert has not been moved into the server's trusted store yet. Copy it across. Reconnect. The signed handshake succeeds and the subscription resumes. Switch to SignAndEncrypt — the same certificate-trust applies, the connection is now fully encrypted, and the simulator's CPU diagnostic page shows the comms-scan cost per subscription rising by about 30%. That cost is the price of encryption and it is real on a constrained CPU.

Common mistakes

  • Trusting the server cert in the wrong directory. The OPC UA standard defines two PKI sub-directories per role: a rejected directory where unrecognised certs land on first connect, and a trusted directory where accepted certs live. Engineers often copy the cert from rejected into own/cert/ (the role's own private cert directory) instead of into trusted/certs/, and then wonder why the handshake still fails. The cert must go into the trusted directory of the opposite role — server cert into client trusted, client cert into server trusted. Both directions are required for Sign and SignAndEncrypt.

  • Hard-coded namespace index in NodeIds. The index is dynamic. Browsing by ns=3;s=... works on the SCADA project the day you commission it and breaks the day after the first firmware update changes the namespace order. The fix is to resolve the namespace URI to its current index at subscription time. In Ignition's OPC UA browser this is automatic if you drag-and-drop the tag from the live tree. In some legacy templates the NodeId is templated as a string and the namespace index gets baked in. Always browse, never type the NodeId by hand.

  • Polling at 100 ms when the actual update rate is 500 ms. The publishing interval on the subscription controls how often the client checks for updates, but the sampling interval on each MonitoredItem controls how often the server actually reads the underlying value. If the underlying tag is in a DB that updates every 500 ms, sampling at 100 ms gives you the same value four times in a row and burns CPU on the server's comms scan for nothing. Match the sampling interval to the underlying update rate, and set the publishing interval to the same or slightly lower.

  • Exposing tags without grouping into Objects. A flat namespace with 240 tags directly under the root of the user namespace is unreadable in any client browser. The OPC UA address space supports nested Objects — group your motor tags into a Motor1 Object, your conveyor tags into a Conveyor1 Object, your alarm records into an Alarms Object. The browse tree then mirrors the plant structure and a SCADA engineer six months later can find what they need without a tag-table dump.

  • Leaving the server on Security None in production. None is fine for commissioning on a closed network. It is not fine on a plant network where the management VLAN reaches the office LAN. An attacker on the office LAN can read every value the server publishes. SignAndEncrypt is the production default. The CPU cost is real but it is the price of a server that does not leak control data to anyone with a network sniffer.

  • No reconnection back-off in the client. A client that re-subscribes immediately after every failed connect attempt will hammer the server during a network partition. The OPC UA standard recommends an exponential back-off — 1 s, 2 s, 4 s, 8 s, capped at 60 s. Ignition's OPC UA driver does this by default; some hand-rolled clients in legacy SCADA do not. Check the back-off behaviour in your client config before deploying.

How to practise this in the simulator

The simulator's S7-1500 OPC UA server and its built-in UA Expert-style client are wired together for exactly this kind of practice. Open both, connect with None, browse the address space, subscribe to a tag, and watch the Data Access view update as you push the panel buttons. Then deliberately break each piece. Restart the server and watch the namespace index change. Move the trust certificate to the wrong directory and watch the handshake fail with BadCertificateUntrusted. Set the publishing interval to 50 ms and watch the CPU diagnostic page show the comms-scan cost climb. Switch from None to SignAndEncrypt and step through the certificate-trust handshake one cert at a time. Twenty minutes of breaking and fixing in the client teaches more about the protocol than reading the spec — and the simulator surfaces the CPU cost of each decision in numbers you can read.

Start the free tier →

Vendor reference

The cross-vendor reference for the protocol is the Wikipedia OPC Unified Architecture article, which covers the address space model, the subscription mechanism, the security policies, and the cross-platform implementations. It is more readable than the standard itself — the standard runs to thousands of pages across a dozen parts. The Wikipedia article is the right place to start, and once the vocabulary is familiar, the parts of the standard worth reading directly are Part 3 (Address Space Model) and Part 4 (Services). Every PLC vendor's OPC UA server documentation builds on those two.

What we don't claim

This site is not SAQA-registered, not MerSETA-accredited, and not an NQF-registered qualification provider. Our completion certificates are course-level only — they describe what you covered, not an NQF Level X qualification. The CCST cert from ISA is the portable industry credential we recommend; we are not an ISA cert delivery partner either, but our cert packs are CCST-aligned. OPC UA is covered at the integration-protocols level on the CCST Level 2 syllabus and the patterns shown here are the ones a junior engineer will see at every modern SA plant doing a SCADA migration.

By PLC Programming SA · Last updated 2026-05-20