A site replacing an OPC DA historian or HMI with an OPC UA one finds that the new client cannot open the old server. A component must translate between them, and the choice of component decides whether a Windows host and a COM server stay on site after the cutover.
OPC DA (Data Access) uses Microsoft COM on one computer and DCOM between computers. The connection opens on TCP 135, the RPC endpoint mapper, and then moves to a dynamically assigned port. On Windows Vista, Windows Server 2008 and later, that range is 49152 to 65535 by default. A DA subscription also sends data back from the server to the client, so the firewall must allow DCOM in both directions.
Microsoft's DCOM hardening for CVE-2021-26414 (KB5004442) now requires the packet-integrity authentication level (RPC_C_AUTHN_LEVEL_PKT_INTEGRITY) for DCOM activation. It was on by default from 14 June 2022 and has been impossible to turn off since 14 March 2023. A patched Windows client raises its own level automatically. A client on an unpatched host, or on a DCOM stack that is not Windows, fails to activate the server. The server logs event 10036, and the client logs 10037 or 10038. Remote DA links that were never set up for this level stopped working, and that is a common reason to start a migration.
OPC UA uses a binary protocol over one TCP port, 4840 by default, with X.509 application certificates. It runs on any operating system.
What OPC Classic includes
Each Classic specification has its own address space and its own services. OPC UA puts all three into one address space with one set of services (OPC 10000-1, clause 4.3).
| Classic specification | Purpose | UA equivalent | Standard mapping |
|---|---|---|---|
| DA (Data Access) | Current values | Part 8, Data Access | Part 8, Annex A |
| A&E (Alarms and Events) | Alarms, events and acknowledgement | Part 9, Alarms and Conditions | Part 9, Annex D |
| HDA (Historical Data Access) | Historical values | Part 11, Historical Access | No annex; the wrapper vendor defines it |
List which of the three the current system uses. A DA wrapper moves current values only. It does not move alarm acknowledgement or historical queries.
A&E needs the most care. Part 9 Annex D maps A&E event categories to UA event types when the wrapper knows what they mean. For example, a Level condition with the name HI HI can become a NonExclusiveLevelAlarmType. The annex defines no generic mapping for A&E sub-conditions, so configure the wrapper for each alarm category that the operators use, and check the result.
Three ways to migrate
| Route | What it does | Use when |
|---|---|---|
| Wrapper | A DA client to the old server, and a UA server to new clients | The old DA server must stay; new systems need UA |
| Proxy | A DA server to an old client, and a UA client to the new server | An old DA client must stay; the source moves to UA |
| Native | The product itself offers a UA server | The vendor supports UA in a version you can install |
The OPC Foundation publishes a COM UA Wrapper and a COM UA Proxy as sample components (Part 8, A.1). Commercial products use the same words loosely. An "OPC tunneller", for example, usually carries DA between two computers without DCOM and gives DA at both ends, so it removes the DCOM problem but does not give you a UA server. Write down the client role and the server role on each side of every product.
A wrapper keeps the old dependencies: the Windows host, the DA server and its licence, the service accounts and the start-up order. Install the wrapper on the same host as the DA server. COM then stays local, and no DCOM traffic crosses the network. Give the host an owner and a patch schedule.
Test the start-up order. After a Windows reboot, the wrapper service can start before the DA server is ready. Some wrappers do not retry, and their items stay Bad until someone restarts the wrapper.
The DA version of the old server changes what the wrapper can do (Part 8, A.3.3 and A.3.4). With a DA 2.05a server, every UA Read goes to the device, and the wrapper ignores the maxAge parameter. A UA write that includes a status code or a timestamp fails with Bad_WriteNotSupported. With a DA 3.0 server, a Read can come from the device or from the server cache, and maxAge selects which. A write can carry the value, quality and timestamp together.
Map items to nodes
Build the map point by point:
| From (DA) | To (UA) | Also record |
|---|---|---|
| Server ProgID and host | Endpoint URL and security settings | Who trusts which certificate |
ItemID, such as BoilerA.Flow | Namespace URI and NodeId | The rule the wrapper used to create the NodeId |
| Canonical data type | UA data type and value rank | Arrays, enums, strings and dates |
| EU Units, High EU and Low EU properties | EngineeringUnits and EURange properties | Which component applies any scaling |
| Access rights | AccessLevel and user permissions | Read-only unless control is approved |
| Scan rate | MinimumSamplingInterval | The fastest rate the source can supply |
Part 8, A.3.1.5 describes three ways to build a NodeId. A wrapper that browses the whole DA address space and keeps an offline copy can use the ItemID as the identifier. A wrapper that splits each ItemID at a configured delimiter can do the same, but only for servers whose ItemIDs are paths. A third kind of wrapper encodes the ItemID and the item name together in the NodeId. Then the NodeId no longer matches the ItemID, and a person cannot easily pair the two.
For example, the DA item BoilerA.Flow can become ns=2;s=BoilerA.Flow. The 2 is a position in the server's NamespaceArray, not a fixed name. The index can change when the wrapper's configuration changes, but the namespace URI stays the same. Store the URI and the identifier for every point, and resolve the index each time the client connects. The node identity guide explains this in detail. Keep the wrapper's configuration in the rollback package, because a rebuilt wrapper that assigns new identifiers breaks every consumer.
Check the data types in Part 8, Table A.2. Most types map one to one, such as VT_R4 to Float and VT_I4 to Int32. VT_DATE maps to Double, not DateTime. A DA date item therefore arrives as a number of days since 30 December 1899, and a consumer that expects a timestamp shows a number such as 46289.5.
An item with High EU and Low EU properties becomes an AnalogItemType with EURange and EngineeringUnits. Check scaling end to end. A flow of 21.7 m³/h must not become 2.17 because the new collector repeats a conversion that the DA server already did.
Quality and time
A DA value has a 16-bit quality. The low byte has the form QQSSSSLL: two bits of main quality, four bits of substatus and two limit bits. The high byte is vendor-specific. Common low-byte values are 0xC0 (Good), 0x40 (Uncertain) and 0x00 (Bad).
A UA value has a 32-bit StatusCode. The top two bits give the severity: 0x00000000 is Good, 0x40000000 is Uncertain and 0x80000000 is Bad. Part 8, A.3.2.3 maps the DA main quality to the severity, the substatus to the subcode and the limit bits to the limit bits. It discards the vendor byte.
| DA quality (low byte) | Meaning | UA StatusCode after the standard mapping |
|---|---|---|
| 0xC0 | Good | Good |
| 0xD8 | Good, local override | Good_LocalOverride |
| 0x44 | Uncertain, last usable value | Uncertain_LastUsableValue |
| 0x54 | Uncertain, engineering units exceeded | Uncertain_EngineeringUnitsExceeded |
| 0x08 | Bad, not connected | Bad_NotConnected |
| 0x18 | Bad, communication failure | Bad_NoCommunication |
| 0x14 | Bad, last known value | Bad_OutOfService |
Two rows need attention. First, the vendor byte is lost. If a DA server marks a hand-entered value with a bit in the high byte, for example quality 0x80C0, the wrapped value arrives as plain Good. Second, Table A.3 maps the DA "last known value" state to Bad_OutOfService. A consumer that reads OutOfService as "switched off on purpose" then reports a communication fault as a planned outage. Part 8, A.1 allows vendor-specific mappings, so read the wrapper's own documentation too. If an application uses the vendor byte, agree another way to carry it, or accept the loss in writing.
For time, the wrapper sets the DA timestamp as the UA SourceTimestamp. It sets the ServerTimestamp to the time that the Read started (Part 8, A.3.2.4). The DA timestamp is usually the time that the DA server last received the value from the device. It is not the time that the sensor sampled, unless the source system defines it that way.
A wrapper can give a detailed UA status that the next collector drops, so check the record in the historian or analytics system, not only the wrapper. Decide how stale, missing and invalid values affect charts, totals and alarms before the cutover.
Update rates and deadbands
A DA client sets an update rate and a percent deadband on each group, and the server calls back when a value changes. In the Foundation's wrapper, a UA MonitoredItem creates the DA subscription. The UA SamplingInterval and deadband set the DA callback (Part 8, A.3.5).
The wrapper supports only the PercentDeadband filter. A percent deadband is a percentage of EURange, so it needs an item that had High EU and Low EU in the DA server. An item without them has no EURange, and the filter cannot apply.
A client that polls with the UA Read service does not use any of this. It gets one value for each point at each poll. With a DA 2.05a server behind the wrapper, each poll is also a device read, so size the poll interval for the load on the DA server and on its field network.
Security on both sides
On the UA side, set the endpoint to SignAndEncrypt with a current policy, such as Basic256Sha256, Aes128_Sha256_RsaOaep or Aes256_Sha256_RsaPss. Do not accept the None mode, even when the wrapper offers it. Set up application certificate trust in both directions, and give the client user only the operations that it needs. Part 2 of the specification describes the model.
Certificates have a validity period, so the clocks matter. A certificate that has expired, or that is not valid yet because a clock is wrong, causes Bad_CertificateTimeInvalid. The client then stops reading until someone renews the certificate or corrects the clock. Put the expiry date of each application certificate in the maintenance plan.
On the DA side, COM DA has no user identity of its own (Part 8, A.2). A wrapper can accept a UA user name and password and impersonate that Windows user before it connects to the DA server. Many wrappers connect as their own service account instead. Record which Windows account the DA server sees and what that account can write. If a DA link stays remote, it must meet the DCOM packet-integrity rule above.
Do not fix a commissioning problem by switching security off, or by turning a read account into a write account.
Test the cutover
Test one point of each data type before you migrate the rest. Include one scaled analogue value, one Boolean, one string and, where the project has them, one array and one date. For each test point:
- Record the namespace URI and the NodeId that the wrapper created.
- Read the value on the DA path and the UA path within one DA scan period, and compare them. Look for double scaling.
- With approval, stop the device or its driver. Record the DA quality, the UA StatusCode and what the final consumer shows. The last value must not appear as a new Good sample.
- Reboot the wrapper host. Confirm that the items return to Good with no change to the point list, and record how long they take.
- Read an ItemID that does not exist, and write to an item without write access. Expect Bad_NodeIdUnknown and Bad_NotWritable.
Then run both paths in parallel for at least one full operating cycle, such as a shift, a batch or a week. Include one planned restart of the source. The DA path reports on change with a deadband, and a UA client may poll, so the two paths give different numbers of messages. Compare values and the age of the latest value at each moment. Agree the permitted difference and the recovery time before the test.
Keep control separate. Do not let the old and new paths command the same equipment at the same time, and check the physical result of every write. The BACnet priority array guide shows how a shared command can outlast its owner.
OPC UA with Edge
Edge on the ZGW-20 Gateway is an OPC UA client. It connects to up to five opc.tcp endpoints, native or wrapped, and does not connect to OPC DA. A DA-only system needs a wrapper first.
Edge reads each point with the Read service on a schedule, from once a second to once a day. It does not create subscriptions, so the deadband rules above do not apply. It stamps each value with the Gateway's scheduled read time, not the SourceTimestamp. It also applies its own multiplier and offset to each point, so set them to 1 and 0 when the DA server already scales the value.
Edge accepts None, Sign and SignAndEncrypt, and a new endpoint slot starts at None. Set SignAndEncrypt with Basic256Sha256 or an Aes policy yourself, and keep the Gateway clock correct for certificate checks.
Common questions
What is the difference between OPC DA and OPC UA?
OPC DA (Data Access) is the OPC Classic specification for current values. It uses Microsoft COM, and DCOM between computers, so the server runs on Windows. OPC UA is a separate architecture with a binary TCP protocol on port 4840 by default, X.509 application certificates, typed nodes with properties such as EngineeringUnits and EURange, and 32-bit status codes. It also replaces the separate Classic specifications for alarms and history.
Can an OPC UA client read an OPC DA server?
Not directly. It needs a wrapper: a component that is a DA client to the old server and a UA server to the new client. OPC 10000-8 Annex A defines how a wrapper maps DA items, quality and timestamps to UA nodes and status codes.
Does migrating from OPC DA to UA include alarms and history?
No. OPC Classic has separate specifications for Alarms and Events (A&E) and Historical Data Access (HDA). A DA wrapper does not move alarm acknowledgement or historical queries. A&E needs its own wrapper, mapped as in OPC 10000-9 Annex D.