# Description Remove stock phrasing and correct misleading or inconsistent technical documentation. The initial two passes covered 367 Markdown files, followed by an interactive review of 169 editorial flags. The U5 interpretation originally deferred in that review has since received the upstream Mantis answer recorded by #4843; remaining server/spec follow-ups stay explicit in the CTT log. - Correct package responsibilities, migration steps, API names, ownership, protocol descriptions and links. Keep bundled migration guides synchronized. Preserve historical conclusions as historical records with separate re-check notes. - Provide at least two rendered TOC levels throughout `docs/`. Convert appropriate architecture figures to Mermaid without changing code examples, transcripts or historical quotations. - Address the October 19 feedback with concrete setup/migration instructions, corrected certificate paths and PubSub names, shorter repeated caveats, consistent XML comments, and a full review of the Concepts guide. Retain #4839's API corrections. - Integrate #4841's runtime/performance guidance and review incoming/recent prose. Preserve dated measurements rather than claiming new benchmark runs; clarify allocation ratios, startup-only processor settings, JIT warm-up and the benchmark commit's scope. Missing raw measurement artifacts and repeat ranges remain tracked by #4842. - Merge master through `e8c5d800a` in `32c6394b7`. Resolve the CTT log conflict using the updated Mantis states and OPC answers, retaining historical framing and re-checks for C28/C32/C43. - Address the latest naming/index feedback in `adb5bf693`: rename the guides to `docs/WotCon.md` and `docs/WotNodeSetConversion.md`; move the provider and DataType-declaration contracts into the conversion guide and remove `docs/WoT.md`. Rename `samples/DI` to `samples/Di` and `samples/Isa95` to `samples/ISA95`. Add content-index READMEs to Di, FluentApi, ISA95, Lds and PubSub; update solution entries, project references, Docker/CI paths, test fixture paths and documentation links with exact casing. **WoT guide scope.** This branch retains the detailed conversion guide that #4758 had replaced with an anchor stub. Conversion limits, verified document sets, preservation rules and provider ownership now live together in `WotNodeSetConversion.md`; binding/runtime guidance remains in `WotBindings.md` and `WotCon.md`. The design-rationale/test-ledger prose was shortened, the oversized argument-table cell moved into its section, and existing anchors preserved. **SDK policy is a separate, explicit user-directed change.** `global.json` sets a stable minimum of `10.0.400`, `rollForward: latestMajor`, and `allowPrerelease: false`. Newer major SDKs are permitted; CI's explicit SDK pins are unchanged. README, GettingStarted, DeveloperGuide and Recycling instructions reflect the possible analyzer differences. The image-contract regression fix accepts compatible stable SDK images instead of requiring exact equality with the floor. The latest four rename/index threads are resolved after publication. Three older threads remain open: universal obsolete-removal timing, unconditional nonce-strength wording, and a blanket Vision NativeAOT claim. Existing implementation/evidence constraints are explained in their inline replies. The two-level TOCs remain as requested. ## Validation - `git diff --check` and staged diff checks: passed. The untouched upstream AutoID NodeSet retains its provenance bytes, including two existing license-header trailing spaces. - `.\.azurepipelines\validate-migration-plugin.ps1`: passed; 15 bundled migration documents and manifests synchronized. - Documentation/path validation: **101** documents retain two rendered TOC levels (**2,228** entries), with idempotent formatting. **52** new relative links and their anchors passed exact-case checks. No tracked references to the old guide/sample paths remain. Both relocated provider-contract sections are preserved in the destination. - `dotnet sln UA.slnx list`: passed; shows the renamed Di/ISA95 projects and the existing FluentApi/Lds/PubSub projects. Updated solution and pump ProjectReference paths also passed exact-case existence checks. - Latest focused commands, run from the repository root: ```powershell # Passed: 61 channel send-order and reconnect tests. dotnet test tests\Opc.Ua.Core.Tests\Opc.Ua.Core.Tests.csproj -p:CustomTestTarget=net10.0 --filter 'FullyQualifiedName~UaSCBinaryChannelSendOrderTests|FullyQualifiedName~TcpReconnectKeyAgreementTests' --verbosity minimal # Passed: 5 pump datasheet tests; builds the renamed pump sample. dotnet test tests\Opc.Ua.Di.Tests\Opc.Ua.Di.Tests.csproj -p:CustomTestTarget=net10.0 --filter 'FullyQualifiedName~PumpDatasheetConformanceTests' --verbosity minimal # Passed: 4 repository NodeSet path/round-trip tests, including the moved pump models. dotnet test tests\Opc.Ua.Types.Tests\Opc.Ua.Types.Tests.csproj -p:CustomTestTarget=net10.0 --filter 'FullyQualifiedName~RepositorySourceSurvivesSerializedLinkedPartitionsAsync' --verbosity minimal # Passed: build, zero warnings/errors. dotnet build samples\ISA95\MinimalIsa95Server\MinimalIsa95Server.csproj -p:CustomTestTarget=net10.0 -f net10.0 --verbosity minimal # Passed: dependent sample-test project build, zero warnings/errors. dotnet build tests\Opc.Ua.WotCon.Samples.Tests\Opc.Ua.WotCon.Samples.Tests.csproj -p:CustomTestTarget=net10.0 -f net10.0 --verbosity minimal ``` Earlier focused integration checks passed 2,620 tests across AutoID, event queues/scheduling, source generation, MCP/package profiles and WoT. Both reviewed Mermaid diagrams rendered locally without network access. These checks are not a full solution run. The full solution has **not** been rerun for this review. Earlier `dotnet test UA.slnx -p:CustomTestTarget=net10.0 --verbosity quiet` did not pass: three AOT projects rejected VSTest and 20 Vision tests failed during graphics initialization with `OutOfMemoryException`. Remaining long-running tests were stopped at the user's request. A focused Vision rerun passed 558 tests and reproduced those 20 failures. The earlier `dotnet test UA.slnx -p:CustomTestTarget=net48 --verbosity quiet` was blocked by the former SDK pin and was not retried after the policy change. The user approved proceeding with those limitations documented; current remote CI is not claimed green. ## Related Issues - Follow-up #4842 tracks the requested 2.0.2+ benchmark/tuning and diagnostic-tool documentation refresh. #4841 supplies documentation and earlier results, not all newly requested measurements. - #4758 explains the conversion guide's earlier consolidation; the current provider contracts are now consolidated into `WotNodeSetConversion.md`. - #4839 supplies the reviewed API corrections; #4843 supplies the updated CTT issue record. - The original prose cleanup and SDK policy were user-requested without a source issue. No new runtime architecture is introduced by these documentation edits. ## Checklist _Put an `x` in the boxes that apply. You can complete these step by step after opening the PR._ - [ ] I have signed the [CLA](https://opcfoundation.org/license/cla/ContributorLicenseAgreementv1.0.pdf) and read the [CONTRIBUTING](https://github.com/OPCFoundation/UA-.NETStandard/blob/master/CONTRIBUTING.md) doc. - [ ] I have added tests that prove my fix is effective or that my feature works and increased code coverage. - [x] I have added all necessary documentation. - [ ] I have verified that my changes do not introduce (new) build or analyzer warnings. - [ ] I ran **all** tests locally using the **UA.slnx** solution against at least .net **framework** and .net **10**, and all passed. - [ ] I fixed **all** failing and flaky tests in the CI pipelines and **all** CodeQL warnings. - [ ] I have addressed **all** PR feedback received. --------- Co-authored-by: Roman Ettlinger <romanett98@gmail.com> Co-authored-by: Claude Opus 5.5 <noreply@anthropic.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
- OPC UA concepts for SDK users
- 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 ApplicationUri, which identifies that installed instance. An application instance certificate authenticates the instance when certificate-based security is used; its URI must match the ApplicationUri. 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 default hosting setup can create a missing application certificate. A custom certificate manager can instead require provisioning before startup.
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 | Protects messages according to the selected transport, security mode and policy; None provides no UA message signing or encryption. |
Application instance certificates when the selected security profile uses them. |
| 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, provide browse paths through the graph;
a node can have more than one parent. 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 when notifications are ready for pending
Publishrequests. - The client adds monitored items. Each one watches a node attribute, usually a variable's value, or an event source. For data changes, the sampling interval controls how often the server checks the value; events are reported when they occur. The queue size controls how many notifications it retains.
- 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 | Transport/channel security plus per-session user identity. | Optional message security with group keys, which a Security Key Service can distribute; transport security depends on the mapping. |
| 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.