## Summary
### Documentation
- Stage the documentation index as a learning path: a first application,
independent client, server, and PubSub paths, then data and services,
companion models, production, advanced integration, and draft or
experimental capabilities.
- Add Getting started (repository samples or NuGet packages), OPC UA
concepts, Your first information model, and a production readiness
checklist.
- Add Native AOT application publishing, a first PubSub publisher and
subscriber exchange, and the UDP transport options.
- Add or expand contents navigation throughout `docs/`, and keep
contributor documentation separate.
- Correct outdated SDK examples and capability guidance, consolidate
repeated explanations into canonical guides, and repair local links and
heading structure.
- Rewrite What's New in 2.0 as a concise feature overview with short
linked details; keep migration instructions in the Migration Guide.
- Expand the feature catalogue with specification IDs, GDS, LDS, the OPC
10000-21 onboarding registrar, ISA-95, xRegistry, OpenUSD, and
sample-local models; distinguish draft status, explain crypto
pluggability, and bring performance guidance forward.
- Address review feedback on wording, active monitored items during
shadow reload, and the `Samples.md` filename and references.
- Regenerate the `opcua-v20-migration` plugin's bundled copy of the
migration guides so it matches the edited `docs/migrate/2.0.x` guides.
- Merge the latest `master`, preserving upstream resource-isolation
guidance within the task-based documentation index.
- Retain deferred Lingity findings where appropriate; this PR does not
claim that every document meets the Lingity score thresholds.
### Fixes found while verifying the guides
Each fix has regression tests that fail without it.
- **Client:** V2 subscriptions compared their lifetime with the
operation timeout instead of the session timeout, and logged a spurious
warning. `ISubscriptionEngineContext`, which is new in 2.0, gains a
`SessionTimeout` property; implementations must add it.
- **PubSub:** a subscriber now registers the `DataSetMetaData`
configured on its readers (OPC 10000-14 6.2.9.4), and the UADP decoder
decodes DataSetMessages that carry no ConfigurationVersion. Before, a
secured subscriber of the reference sample received no DataSets.
- **Source generator:** a ModelDesign method that declares its arguments
inline, without a method type, produced code that did not compile; it
now uses `MethodState`. The generated code of existing models is
unchanged.
- **MinimalClient sample:** waits for its first data-change notification
before it disconnects.
### Known issues, not addressed here
- UDP multicast: the publisher does not send on the interface that the
subscriber joins, and `MulticastLoopback` defaults to false. The PubSub
guide uses unicast for the exchange on one computer.
- The UDP metadata announcement is sent unsecured on secured writer
groups; a secured subscriber drops it with a warning.
- A server does not start in globalization-invariant mode, because
`ResourceManager` creates `CultureInfo("en-US")`. The Native AOT guide
cautions against the mode.
## Validation
- `git diff --check` and
`./.azurepipelines/validate-migration-plugin.ps1` (15 bundled migration
docs validated, plugin manifests synchronized).
- Local Markdown links, anchors, file-link casing, and contents lists
checked across all 87 documents under `docs/`. The index links every
top-level guide and every target of the previous index.
- Both Getting started routes, Your first information model, the PubSub
exchange, and the Native AOT publish of the Getting started client and
server were run as documented. The NuGet route and the tutorial use the
public `2.0.0-preview.5` packages.
- The changed libraries build for all target frameworks in Release
without warnings.
- Tests on .NET 10: Opc.Ua.SourceGeneration.Tests 199 passed;
Opc.Ua.SourceGeneration.Core.Tests 3,977 passed, 8 skipped;
Opc.Ua.Server.Tests `Fluent` category 621 passed; Opc.Ua.Client.Tests
subscription-engine tests 70 passed; Opc.Ua.PubSub.Tests 1,374 passed, 2
skipped; PubSub fuzz replay 145 passed. The new and affected tests also
pass on .NET Framework 4.8.
- Earlier merge validation: 174 resource-isolation tests passed on .NET
10.
- The full solution suite was not run locally.
Review and validation artifacts are maintained outside the repository.
---------
Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
13 KiB
OPC UA concepts for SDK users
This guide explains the ideas the rest of the documentation assumes. Read it alongside Getting started or immediately afterward. It describes the concepts and the matching SDK types without detailing each API. Each section links to the guide with complete contracts and examples.
Contents
- Applications
- Endpoints, secure channels, and sessions
- Application trust and user identity
- The address space
- Node identity and namespaces
- Values, status codes, and timestamps
- Service results and errors
- Subscriptions and monitored items
- Events and alarms
- Information models and companion specifications
- Client/server and PubSub
- How the SDK is organized
- Where to go next
Applications
An OPC UA application is a client, a server, or both. Each application instance has an application instance certificate and an ApplicationUri. The URI identifies that installed instance and must match the URI in its certificate. A product URI identifies the product rather than one installation.
In this SDK, you set the application name, URIs, and certificate-store root when you configure a client or server. The hosting builders create the application certificate on first start if the store does not contain one.
Endpoints, secure channels, and sessions
A server offers one or more endpoints. An endpoint combines:
- A URL, such as
opc.tcp://localhost:62541/MinimalBoilerServer. - A transport, such as UA-TCP (
opc.tcp), HTTPS, or WebSockets. - A security mode:
None,Sign, orSignAndEncrypt. - A security policy, such as
Basic256Sha256, which selects the algorithms. - The user-token types the server accepts.
A client usually calls the discovery service GetEndpoints and selects the
endpoint whose security matches its requirements. The client then establishes
two layers:
| Layer | Purpose | Authenticated by |
|---|---|---|
| Secure channel | Signs and encrypts the messages between the two application instances. | Application instance certificates. |
| Session | Carries the user identity, request context, and subscriptions. | A user token, such as anonymous, user name, X.509, or an issued token. |
A session can survive the loss of its channel: the client opens a new channel
and reactivates the same session. ManagedSession performs this recovery and,
if necessary, recreates the session. It is the recommended client entry point
for new applications. See Sessions and Transports.
Application trust and user identity
Application trust and user identity are separate decisions:
- Application trust decides whether this software instance may open a secure channel. Each application keeps certificate stores: its own certificates, trusted peers, issuers needed to validate chains, and rejected certificates. An administrator approves a peer by placing its certificate, or the CA that issued it, in the trusted store.
- User identity decides who is using the session and what that user may do. The server authenticates the user token when the session is activated and maps the identity to roles and permissions.
Accepting unknown certificates automatically is a local-testing shortcut only; it removes the protection against connecting to, or accepting, an impostor. See Certificates, Identity providers, and Role-based user management.
The address space
A server exposes its data as an address space: a graph of nodes connected by references. Each node has a node class:
| Node class | Represents |
|---|---|
| Object | A device, machine, or other entity; also folders. |
| Variable | A value that can be read, written, or monitored. |
| Method | An operation that a client can call on an object. |
| ObjectType, VariableType | The definitions that instances are based on. |
| DataType, ReferenceType | The definitions of value types and relationship types. |
| View | A subset of the address space. |
References have types. Hierarchical references, such as Organizes,
HasComponent, and HasProperty, form the tree you browse. Other references
describe relationships, such as HasTypeDefinition, which links an instance to
its type. Every server has a standard Objects folder (ObjectIds.ObjectsFolder)
that contains the Server object with status, capabilities, and diagnostics.
A server-side node manager owns part of the address space and implements its behavior. See Node managers.
Node identity and namespaces
A NodeId combines a namespace index with an identifier, which is a number,
a string, a GUID, or an opaque byte string. The index refers to an entry in the
server's namespace table (NamespaceArray), which lists namespace URIs:
- Index 0 is always the OPC UA namespace,
http://opcfoundation.org/UA/. - Index 1 is the server's own local namespace.
- Other indexes are assigned by the server and can differ between servers.
Store and exchange the namespace URI, not the index. Resolve the index from
the connected session's namespace table (session.NamespaceUris) when needed.
An ExpandedNodeId can carry the URI itself. Generated model constants use
this form; convert one with ExpandedNodeId.ToNodeId(id, session.NamespaceUris).
Standard node IDs such as VariableIds.Server_ServerStatus_CurrentTime are in
namespace 0 and need no conversion.
A node's BrowseName is a QualifiedName: a name with a namespace index.
Clients can translate a browse path of names into a NodeId.
NodeId, QualifiedName, Variant, DataValue, and several other built-in
types are value types in this SDK. Test them with IsNull rather than comparing
them with null. See Improved type safety for details.
Values, status codes, and timestamps
Reading a variable returns a DataValue, which contains four parts:
| Part | SDK member | Meaning |
|---|---|---|
| Value | WrappedValue (Variant) |
The value, or no value. |
| Status | StatusCode |
Whether the value can be used. |
| Source timestamp | SourceTimestamp (DateTimeUtc) |
When the value was produced at its source. |
| Server timestamp | ServerTimestamp (DateTimeUtc) |
When the server last received or confirmed the value. |
Always check the status before you use the value. A status is Good,
Uncertain (usable with caution), or Bad (do not use the value). Use
StatusCode.IsGood, StatusCode.IsUncertain, and StatusCode.IsBad, or compare
with a constant such as status == StatusCodes.BadNodeIdUnknown.
A Variant holds any OPC UA built-in type, an array (ArrayOf<T>), a matrix
(MatrixOf<T>), or a structure (ExtensionObject). Extract a value with the
checked TryGetValue pattern:
if (!StatusCode.IsBad(value.StatusCode) &&
value.WrappedValue.TryGetValue(out DateTimeUtc time))
{
Console.WriteLine($"{time} ({value.StatusCode})");
}
All OPC UA date and time values are UTC and use DateTimeUtc. Binary data uses
ByteString. Server-defined structures can be decoded at run time with
Complex types, or compiled with
Source-generated data types.
Service results and errors
Clients call services, such as Read, Write, Browse, and Call. Most
services process a list of operations and return one result per operation, so
one failed item does not fail the whole call. Check each result's status.
A failure of the whole request, such as a timeout or a security error, raises a
ServiceResultException. Its StatusCode identifies the cause.
Convenience helpers can convert a Bad operation result into an exception; for
example, ReadValueAsync throws when the value's status is Bad.
Subscriptions and monitored items
Polling with Read is inefficient for values that change. A subscription
lets the server report changes instead:
- The client creates a subscription in its session. The publishing interval controls how often the server sends notifications.
- The client adds monitored items. Each one watches a node attribute, usually a variable's value, or an event source. The sampling interval controls how often the server checks for changes; the queue size controls how many changes it keeps between notifications.
- The server sends data-change or event notifications, and keep-alive messages when nothing has changed. If the client stops requesting notifications, the subscription expires after its lifetime.
The SDK offers callback subscriptions for long-lived application monitoring and
IAsyncEnumerable streams for short observations, such as waiting for a state
change. See Subscriptions.
Events and alarms
Objects that are event notifiers report events, such as audit events or state changes. A client subscribes to them with an event filter that selects the event fields and types it needs. Alarms and conditions extend events with state that operators acknowledge, confirm, or shelve. See Alarms and conditions.
Information models and companion specifications
An information model is a set of types and instances for a domain. The base OPC UA model defines the server object, core types, and standard services. Companion specifications build domain models on top of it, such as Device Integration (OPC 10000-100) or Machinery (OPC 40001-1).
Models are exchanged as NodeSet2 XML files. This SDK can use a model in two ways:
- Generate typed code at build time, including a server node manager and typed client proxies for object types. See Node managers.
- Load NodeSet2 files into a running server without generated code. See Runtime NodeSets.
Models depend on other models; for example, Device Integration depends on the base model. See Model dependencies.
Client/server and PubSub
OPC UA defines two communication patterns:
| Client/server | PubSub | |
|---|---|---|
| Connection | A session between one client and one server. | No session; publishers send messages to a transport. |
| Interaction | Requests (read, write, browse, call) and subscriptions. | One-way dataset messages, plus optional actions. |
| Security | Secure channel plus per-session user identity. | Message security with group keys from a Security Key Service. |
| Transports | UA-TCP, HTTPS, WebSockets. | UDP, MQTT, Kafka, Ethernet. |
In PubSub, a publisher's DataSetWriter turns a published dataset into dataset messages, and a WriterGroup sends them in network messages at a configured interval over a PubSubConnection. A subscriber's DataSetReader selects messages by publisher, writer group, and dataset writer identifiers, and decodes them with the dataset metadata. Messages use UADP (binary) or JSON encoding. PubSub applications do not need a client or server. See PubSub.
How the SDK is organized
- Packages. Start with
OPCFoundation.NetStandard.Opc.Ua.ClientorOPCFoundation.NetStandard.Opc.Ua.Server. Optional packages add transports, complex types, PubSub, redundancy, and companion models. See Packages, platform support, and versioning. - Hosting.
services.AddOpcUa()registers clients, servers, and features with .NET dependency injection and the Generic Host. Direct construction, such asManagedSessionBuilderornew StandardServer(telemetry), remains available. See Dependency injection. In this documentation, dependency injection refers to the .NET pattern, while DI in Device Integration refers to OPC 10000-100. - Asynchronous APIs. Operations are asynchronous and accept a
CancellationToken. Await them; do not block on their results. - Telemetry. Components obtain loggers, metrics, and traces from an
ITelemetryContext. With hosting, the SDK adapts the host's logging. See Diagnostics. - Ownership. Dispose sessions, subscriptions, and certificate handles that
you create.
ManagedSessionand subscriptions supportawait using.
Where to go next
Return to the documentation index and follow the path for your role: a client, a server, or a PubSub application. If you have not yet run a client and server, start with Getting started. To add your own model to a server and use it from a client, continue with Your first information model.