Files
Marc Schier cdb4d82d58 Unify DI companion composition, placement and resource ownership (#4915)
# Description

DI companion models can share one address-space owner without depending
on the Machinery server pipeline or creating another DeviceSet. This
implements steps A-E of #4872.

- Add `IDiModelProvider` and neutral model registration. DI-owning
managers merge neutral providers with their family registrations, retain
each instance once by reference identity, and preserve the original
provider's type-name ordering through adapters. Robot Intent and Vision
without Assets load only their family providers because they do not own
DI. Vision's Assets dependency loader runs before neutral providers,
including providers with `Order = int.MinValue`.
- Add `AddDiModel<TProvider, TNodeManager>(configure)` with synchronous
and awaited callbacks through the existing DI post-setup pipeline. Model
registration is shared; callbacks target the selected manager type and
run in registration order. Register Machinery configuration before
dependent AutoID configuration. No registration-only AutoID/Machinery
package is needed. The existing
`OpcUaAutoIdCompositionExtensions.AddAutoIdToMachinery` API remains in
the AutoID server assembly as an obsolete forwarder to `AddAutoIdModel`.
- Centralize companion lifetime on `DiNodeManager`. Final shutdown
atomically closes registration and joins pending drains before manager
teardown, including their failures. Ordinary explicit drains permit
later batches. Machinery rearms its cached cleanup bridge when adopting
another machine-resource batch.
- Add shared DeviceSet reachability and placement helpers. Runtime DI
components link through the outermost composed component rather than
each nested device. Public organization and notifier hooks replace
companion friend-assembly access. Pumps and Scales resolve Machines
through its generated model identifier; the protected compatibility
helper remains namespace-qualified.
- Consolidate composition examples, ordering, ownership and
specification-based placement in the existing [Device Integration
guide](docs/DeviceIntegration.md#composing-companion-models). Add
summaries to the changed internal types and their public members.

The generic helper and explicit callback ordering replace the earlier
registration-only package design in response to review feedback. All
thirteen review threads have a reply describing the published correction
and are resolved.

### Validation

The latest correction passed both affected net10.0 suites and the
focused net48
regressions. Commands used `TEMP=TMP=D:\temp`, without warning
demotions:

```powershell
dotnet test tests\Opc.Ua.AutoID.Tests\Opc.Ua.AutoID.Tests.csproj -p:CustomTestTarget=net10.0 -f net10.0 -m:1 -p:BuildInParallel=false --logger trx --results-directory D:\temp\issue4872-feedback2-net10.0 -v quiet --no-restore
# Passed 358; exit 0.
dotnet test tests\Opc.Ua.Vision.Tests\Opc.Ua.Vision.Tests.csproj -p:CustomTestTarget=net10.0 -f net10.0 -m:1 -p:BuildInParallel=false --logger trx --results-directory D:\temp\issue4872-feedback2-net10.0 -v quiet --no-restore
# Passed 713; one existing skip; exit 0.
dotnet test tests\Opc.Ua.AutoID.Tests\Opc.Ua.AutoID.Tests.csproj -p:CustomTestTarget=net48 -f net48 -m:1 -p:BuildInParallel=false --logger trx --results-directory D:\temp\issue4872-feedback2-net48 -v quiet --filter 'FullyQualifiedName~LegacyMachineryRegistration'
# Passed 2; exit 0.
dotnet test tests\Opc.Ua.Vision.Tests\Opc.Ua.Vision.Tests.csproj -p:CustomTestTarget=net48 -f net48 -m:1 -p:BuildInParallel=false --logger trx --results-directory D:\temp\issue4872-feedback2-net48 -v quiet --filter 'FullyQualifiedName~VisionFactoriesLoadNeutralProvidersOnlyWhenOwningDiAsync|FullyQualifiedName~VisionAdaptersPreserveOriginalProviderTypeNameTies'
# Passed 17; exit 0.
```


`LegacyMachineryRegistrationForwardsOptionsAndDeduplicatesTheNeutralModel`
and
`LegacyMachineryRegistrationPreservesNeutralValidation` cover the legacy
entry
point's options, provider deduplication, owner preservation and
validation.
`VisionFactoriesLoadNeutralProvidersOnlyWhenOwningDiAsync` includes four
minimum-priority Assets cases across both factories and both
registration orders.

Full-solution validation remains incomplete. The earlier net10.0 attempt
had a
Windows clipboard access failure and stopped during Stress.Tests without
a final
result. The earlier net48 solution attempt failed because target assets
were
missing; the focused commands above restore successfully. Coverage
percentages
and current CI/CodeQL results were not collected locally.

## Related Issues

Implements the proposal and maintainer answers in the tracking issue,
with the generic helper and configuration order confirmed during review.

- Fixes #4872

## 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.
- [x] 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.
- [x] I have addressed **all** PR feedback received.
2026-10-27 14:34:54 +01:00
..

OPC Foundation UA .NET Standard Reference Server

Additional samples

  • Device Integration — a simulated pump line with alarms, history, software update and OpenUSD assets.
  • Fluent API — a Generic Host server and fluent node manager.
  • ISA-95 — Common Model and Job Control V1/V2.
  • Local Discovery Server — console LDS and multicast discovery.
  • PubSub — publisher, subscriber and external-server adapter modes.
  • MachineTool and wireless peripherals — independently selected machine/peripheral models, per-instance simulation, typed clients, jobs/files, measurements and record/configuration workflows.
  • GMS — native systems, environmental warnings and result/characteristic workflows with explicitly simulated providers.
  • AutoID — a simulated OPC 30010 RFID reader: synchronous and asynchronous scans, tag memory access and presence events.
  • Cranes and Hoists — observed crane topology and authorized simulated limit requests, never physical motion commands.
  • Combined companion suite — MachineTool, WMTP, GMS, CranesHoists and MachineVision on one DI/Machinery owner.
  • OPC 10000-21 onboarding registrar/client — loads the generated Onboarding companion model, binds the standard registrar administration methods to an injected ticket store, and drives a secure register/unregister round trip with a PowerShell script.

Introduction

This document is referring to the CTT version 1.04.9.398.

This OPC Server is designed to be the default OPC UA Server when opening the OPC UA Compliance Test Tool and it uses an address-space that matches the design of the UACTT and the requirements for OPC UA compliance testing.

It uses the OPC Foundation UA .NET Standard Library. Therefore it supports both the opc.tcp and https transports. There is a .NET framework based server with UI and a .NET Core console version of the server which runs on any OS supporting .NET 8.0 and later.

How to build and run the Windows OPC UA Reference Server with UACTT

  1. Open the solution UA.slnx with Visual Studio 2026.
  2. Choose the project Reference Server in the Solution Explorer and set it with a right click as Startup Project.
  3. Hit F5 to build and execute the sample.

How to build and run the console OPC UA Reference Server on Windows, Linux and iOS

This section describes how to run the ConsoleReferenceServer.

Please follow instructions in this article to setup the dotnet command line environment for your platform.

Start the server

  1. Open a command prompt.
  2. Navigate to the folder samples/Reference/ConsoleReferenceServer.
  3. To run the server sample type dotnet run --project ConsoleReferenceServer.csproj. The server is now running and waiting for the connection of the UACTT.

UACTT test certificates

The reference server always rejects new client certificates and requires that the UACTT certificates are in appropriate folders.

  • The console server certificates are stored in %LocalApplicationData%/OPC Foundation/pki.
  • The Windows .NET framework server stores the certificates in %CommonApplicationData%\OPC Foundation\pki.
    • %CommonApplicationData% maps to the path set by the environment variable ProgramData on Windows.
    • %LocalApplicationData% maps to a hidden location in the user home folder and depends on the target platform. See Certificates for more information.

Certificate stores

Under pki, the following stores contain certificates under certs, CRLs under crl or private keys under private.

  • own contains the reference server public certificate and private key.
  • rejected contains the rejected client certificates. To trust a client certificate, copy the rejected certificate to the trusted/certs folder.
  • trusted contains trusted client and CAs certificates and CRLs.
  • issuer contains CAs certificates and CRLs needed for validation.
  • trustedUser contains trusted user and user CA certificates and CRLs.
  • issuerUser contains user CA certificates and CRLs needed for validation of the certificate chains.

Placing the UACTT certificates

CTT creates a PKI folder in a new project. There is a subfolder copyToServer which contains the application and user identity certificates. Copy the ApplicationInstance_PKI certificates for testing with the UACTT to the following stores:

  • trusted/certs: trusted certificates
  • trusted/crl: revocation lists of trusted certificates
  • issuer/certs: issuer certificates
  • issuer/crl: revocation lists of issuer certificates

Copy the X509UserIdentity_PKI certificates for testing with the UACTT to the following stores:

  • trustedUser/certs: trusted user certificates
  • trustedUser/crl: revocation lists of trusted user certificates
  • issuerUser/certs: user issuer certificates
  • issuerUser/crl: revocation lists of user issuer certificates

UACTT Testing

Download and install the OPC UA Compliance Test Tool.

Note: Access to the UACTT is granted to OPC Foundation Corporate Members.

UACTT sample configuration

A sample configuration for the UACTT Version 1.04.9.398 can be found in UAReferenceServer.ctt.xml. Originally the reference server was certified only against the Standard UA Server profile, the Method Server Facet and the DataAccess Server Facet, in addition to all security related profiles. During release testing all Conformance Units should be enabled / checked.

Enabling Alarms & Conditions

The address space for Alarms contains a Start method which needs to be called to produce alarms for CTT testing. The method is called from a connected client. The ConsoleReferenceServer has also a command line option -ctt which starts the Alarms when the server is started. The following Alarm instances are available for monitoring:

  • AlarmConditionType
  • DiscrepancyAlarmType
  • LimitAlarmType
  • ExclusiveLimitAlarmType
  • ExclusiveDeviationAlarmType
  • ExclusiveRateOfChangeAlarmType
  • NonExclusiveLimitAlarmType
  • NonExclusiveDeviationAlarmType
  • NonExclusiveRateOfChangeAlarmType
  • DiscreteAlarmType
  • SystemOffNormalAlarmType
  • ExclusiveLevelAlarmType
  • NonExclusiveLevelAlarmType
  • OffNormalAlarmType

Known missing Tests and Issues

Depending on the setup in the provided project configuration, unsupported profiles should be skipped. At the time of writing (1.4.368) the following tests, profiles or facets are not yet covered or not configured due to issues:

  • no support for events, historian and only a few basic Alarms & Conditions.
  • Decimal type causes crash of CTT (needs investigation)
  • no Image / Enumeration scalar test cases
  • Arrays may not include Variant (needs investigation)
  • no ArrayItemType implemented
  • multiple hierarchical references test node missing
  • deprecated security profiles support for SHA1/1k RSA keys implemented not according to certification. SHA1/1k keys can only be turned on/off for all profiles, not just for the deprecated profiles.
  • Monitored Items with array are failing a few test cases.

It is recommended to run the server as retail build with disabled logging, to avoid side effects due to timing artifacts when log entries are written to a disk drive.

Running the CTT against a Docker container

Please refer to the Docker container of the Reference Server documentation page. Once setup to map the certificate store and the configuration to a local folder, follow the instructions above to copy the certificates to the PKI and get started.

Finding the Address Space Configuration Code

  • Project: Reference Server
  • File: ReferenceNodeManager.cs
  • Method: CreateAddressSpace

Finding the UA Services

  • Project: Opc.Ua.Server
  • File: StandardServer.cs