KBUBComm.OpcUa 1.0.1

dotnet add package KBUBComm.OpcUa --version 1.0.1
                    
NuGet\Install-Package KBUBComm.OpcUa -Version 1.0.1
                    
This command is intended to be used within the Package Manager Console in Visual Studio, as it uses the NuGet module's version of Install-Package.
<PackageReference Include="KBUBComm.OpcUa" Version="1.0.1" />
                    
For projects that support PackageReference, copy this XML node into the project file to reference the package.
<PackageVersion Include="KBUBComm.OpcUa" Version="1.0.1" />
                    
Directory.Packages.props
<PackageReference Include="KBUBComm.OpcUa" />
                    
Project file
For projects that support Central Package Management (CPM), copy this XML node into the solution Directory.Packages.props file to version the package.
paket add KBUBComm.OpcUa --version 1.0.1
                    
#r "nuget: KBUBComm.OpcUa, 1.0.1"
                    
#r directive can be used in F# Interactive and Polyglot Notebooks. Copy this into the interactive tool or source code of the script to reference the package.
#:package KBUBComm.OpcUa@1.0.1
                    
#:package directive can be used in C# file-based apps starting in .NET 10 preview 4. Copy this into a .cs file before any lines of code to reference the package.
#addin nuget:?package=KBUBComm.OpcUa&version=1.0.1
                    
Install as a Cake Addin
#tool nuget:?package=KBUBComm.OpcUa&version=1.0.1
                    
Install as a Cake Tool

KBUBComm.OpcUa

Host-agnostic .NET 8 OPC UA client/server library built on the OPC Foundation .NET Standard stack.

1.0.1 capabilities

Client

  • explicit endpoint and security selection;
  • untrusted certificates rejected by default;
  • anonymous sessions;
  • stable NodeId reads and writes;
  • address-space browsing;
  • monitored-item subscriptions;
  • lifecycle state and bounded last-failure reporting; and
  • cancellation-aware connect/disconnect.

Server

  • secure SignAndEncrypt endpoint by default;
  • Aes256_Sha256_RsaPss recommended policy preset;
  • optional Basic256Sha256 compatibility preset;
  • explicit opt-in SecurityPolicy#None endpoint;
  • untrusted client certificates rejected by default;
  • stable configured variable NodeIds;
  • deterministic nested folder NodeIds;
  • explicit scalar data types and value ranks;
  • typed null initialization;
  • UInt16[] and String[] one-dimensional arrays;
  • description, initial status, and initial source timestamp mapping;
  • public certificate creation, inspection, public export, trust, and rejection operations;
  • bounded server diagnostics;
  • optional synchronous client-write mediation;
  • read-only and writable variables;
  • local value/status/source-timestamp updates; and
  • deterministic stop/restart behavior with certificate-store reuse.

Secure server example

OpcUaServerOptions options = new()
{
    ApplicationName = "Example OPC UA Server",
    ApplicationUri = new Uri("urn:example:opcua:server"),
    EndpointUrl = new Uri("opc.tcp://0.0.0.0:4840/Example"),
    SecurityPolicies = OpcUaServerSecurityPolicies.RecommendedSecure,
    AutoAcceptUntrustedClientCertificates = false,
    AllowAnonymous = true,
    CertificateStorePath = "pki/server",
    TrustedPeerStorePath = "pki/server/trusted",
    RejectedCertificateStorePath = "pki/server/rejected"
};

await using OpcUaServer server = new(options);
server.AddNode(new OpcUaNodeDefinition("s=Temperature", "Temperature", null)
{
    FolderPath = "Plant/Boiler/Measurements",
    Description = "Current boiler temperature.",
    DataType = OpcUaDataType.Double,
    ValueRank = OpcUaValueRank.Scalar
});

server.AddNode(new OpcUaNodeDefinition("s=ActiveAlarmCodes", "ActiveAlarmCodes", Array.Empty<ushort>())
{
    FolderPath = "Plant/Boiler/Alarms",
    Description = "Active alarm identifiers.",
    DataType = OpcUaDataType.UInt16,
    ValueRank = OpcUaValueRank.OneDimension
});

await server.StartAsync();

Security policy presets

OpcUaServerSecurityPolicies.RecommendedSecure exposes only:

  • SignAndEncrypt
  • Aes256_Sha256_RsaPss

OpcUaServerSecurityPolicies.CompatibleSecure exposes:

  • SignAndEncrypt with Aes256_Sha256_RsaPss
  • SignAndEncrypt with Basic256Sha256

No insecure endpoint is added unless EnableInsecureEndpoint is true.

For an intentionally insecure-only local loopback server:

OpcUaServerOptions options = new()
{
    ApplicationName = "Local Test Server",
    ApplicationUri = new Uri("urn:example:opcua:test"),
    EndpointUrl = new Uri("opc.tcp://127.0.0.1:4840/Test"),
    SecurityPolicies = Array.Empty<OpcUaServerSecurityPolicy>(),
    EnableInsecureEndpoint = true
};

Do not use the insecure-only configuration for production deployments.

Certificate operations

OpcUaCertificateStoreManager uses the same application identity and directory stores as the client or server options.

OpcUaCertificateStoreManager certificates = new(options);
OpcUaCertificateInfo applicationCertificate =
    await certificates.EnsureApplicationCertificateAsync();

byte[] publicDer = await certificates.ExportPublicCertificateAsync(
    OpcUaPublicCertificateFormat.Der);

IReadOnlyList<OpcUaCertificateInfo> rejected =
    await certificates.ListRejectedPeerCertificatesAsync();

if (rejected.Count > 0)
{
    await certificates.TrustRejectedCertificateAsync(rejected[0].Thumbprint);
}

await certificates.RemoveTrustedCertificateAsync(trustedPeerThumbprint);

RemoveTrustedCertificateAsync(string, CancellationToken) removes only the selected certificate from the configured trusted peer directory store and throws KeyNotFoundException when it is absent. Restart or refresh the OPC UA server before testing the changed trust state. A subsequently rejected connection is recorded naturally by the OPC UA stack; this method does not create rejected-store entries.

Public DER and PEM export never include a private key. The API intentionally exposes no private-key export operation.

Hierarchy, types, and arrays

FolderPath is slash-delimited. The server trims leading/trailing separators, collapses repeated separators, deduplicates shared folders, and rejects . and .. segments.

Folder NodeIds are deterministic string identifiers:

folder:Plant
folder:Plant/Boiler
folder:Plant/Boiler/Measurements

A variable browse path cannot also be used as a folder path.

Supported scalar declarations:

  • Boolean
  • SByte / Byte
  • Int16 / UInt16
  • Int32 / UInt32
  • Int64 / UInt64
  • Float / Double
  • String
  • DateTime
  • Guid
  • ByteString

Supported ranks:

  • OpcUaValueRank.Scalar
  • OpcUaValueRank.OneDimension

One-dimensional array support is intentionally limited to:

  • UInt16[]
  • String[]

Empty arrays retain their declared element type. Scalar/array mismatches and wrong array element types are rejected before publication.

DateTimeOffset values are normalized to UTC DateTime. decimal is accepted as OPC UA Double only when AllowDecimalToDouble = true is explicitly configured.

Local updates

Server-side updates preserve the node's declared data type and rank:

await server.UpdateValueAsync(new OpcUaNodeValueUpdate(
    "s=ActiveAlarmCodes",
    new ushort[] { 4, 12 },
    StatusCodes.Good,
    DateTimeOffset.UtcNow));

Local UpdateValueAsync calls never invoke the client-write callback.

Optional client-write callback

OpcUaServerOptions options = new()
{
    // required identity, endpoint, and certificate options omitted
    ClientWriteCallback = request =>
    {
        if (request.NodeId != "s=WritableSetpoint")
        {
            return OpcUaNodeWriteResult.Reject(
                StatusCodes.BadUserAccessDenied,
                "This node is not host-writable.");
        }

        int proposed = (int)request.ProposedValue!;
        return OpcUaNodeWriteResult.Accept(Math.Clamp(proposed, 0, 100));
    }
};

The callback is synchronous by design. Do not perform blocking network, database, or long-running host I/O in it. The package validates the declared type/rank before and after the callback. Callback exceptions return a bad OPC UA status without faulting the server.

WRITE CALLBACK GATE = PASS

The gate is covered by tests for exactly-once client invocation, read-only rejection, scalar/array mismatch rejection, host rejection, accepted normalization, local-update bypass, and callback exception containment.

Diagnostics

OpcUaServerDiagnostics diagnostics = await server.GetDiagnosticsAsync();

The snapshot reports lifecycle, endpoint, configured security policies, active session/subscription counts, configured folder/variable counts, trusted/rejected peer counts, a bounded last-failure message, and the last observed session-count change. It does not expose OPC Foundation server/session/subscription objects.

Migration from 0.1.1

  • The server exposes a secure endpoint by default.
  • EnableInsecureEndpoint = true adds an insecure endpoint; it no longer defines the entire server security configuration by itself.
  • Use SecurityPolicies = Array.Empty<OpcUaServerSecurityPolicy>() with EnableInsecureEndpoint = true only for intentional insecure-only test behavior.
  • Existing flat scalar node construction remains valid when FolderPath, DataType, and ValueRank are omitted.
  • Explicit types are required for null startup values that must not default to String.
  • Decimal-to-Double publication requires AllowDecimalToDouble = true.
  • UInt16[] and String[] require OpcUaValueRank.OneDimension.
  • Certificate trust is explicit by default; use OpcUaCertificateStoreManager instead of duplicating store manipulation in a host.
  • Writable nodes can optionally be mediated through ClientWriteCallback; local host updates do not invoke it.

Known limitations

  • anonymous user identity only;
  • no methods, custom structures, multidimensional arrays, or durable audit;
  • one-dimensional arrays limited to UInt16[] and String[];
  • certificate manager targets the directory-store layout configured by this package;
  • no private-key export;
  • write mediation is synchronous and must remain fast;
  • diagnostics are bounded snapshots, not a durable telemetry stream; and
  • session-change time advances when a diagnostics snapshot observes a changed session count.

Thread safety

Client session operations are serialized by the underlying OPC UA session where required. Server value updates are synchronized through the node manager. Configure nodes before server startup.

Product Compatible and additional computed target framework versions.
.NET net8.0 is compatible.  net8.0-android was computed.  net8.0-browser was computed.  net8.0-ios was computed.  net8.0-maccatalyst was computed.  net8.0-macos was computed.  net8.0-tvos was computed.  net8.0-windows was computed.  net9.0 was computed.  net9.0-android was computed.  net9.0-browser was computed.  net9.0-ios was computed.  net9.0-maccatalyst was computed.  net9.0-macos was computed.  net9.0-tvos was computed.  net9.0-windows was computed.  net10.0 was computed.  net10.0-android was computed.  net10.0-browser was computed.  net10.0-ios was computed.  net10.0-maccatalyst was computed.  net10.0-macos was computed.  net10.0-tvos was computed.  net10.0-windows was computed. 
Compatible target framework(s)
Included target framework(s) (in package)
Learn more about Target Frameworks and .NET Standard.

NuGet packages (1)

Showing the top 1 NuGet packages that depend on KBUBComm.OpcUa:

Package Downloads
KBUBComm.NET8

Dependency-only bundle for KBUBComm.Modbus and KBUBComm.OpcUa.

GitHub repositories

This package is not used by any popular GitHub repositories.

Version Downloads Last Updated
1.0.1 117 8/3/2026
1.0.0 130 7/31/2026
0.1.1 144 7/16/2026