KBUBComm.OpcUa
1.0.1
dotnet add package KBUBComm.OpcUa --version 1.0.1
NuGet\Install-Package KBUBComm.OpcUa -Version 1.0.1
<PackageReference Include="KBUBComm.OpcUa" Version="1.0.1" />
<PackageVersion Include="KBUBComm.OpcUa" Version="1.0.1" />
<PackageReference Include="KBUBComm.OpcUa" />
paket add KBUBComm.OpcUa --version 1.0.1
#r "nuget: KBUBComm.OpcUa, 1.0.1"
#:package KBUBComm.OpcUa@1.0.1
#addin nuget:?package=KBUBComm.OpcUa&version=1.0.1
#tool nuget:?package=KBUBComm.OpcUa&version=1.0.1
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
SignAndEncryptendpoint by default; Aes256_Sha256_RsaPssrecommended policy preset;- optional
Basic256Sha256compatibility preset; - explicit opt-in
SecurityPolicy#Noneendpoint; - 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[]andString[]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:
SignAndEncryptAes256_Sha256_RsaPss
OpcUaServerSecurityPolicies.CompatibleSecure exposes:
SignAndEncryptwithAes256_Sha256_RsaPssSignAndEncryptwithBasic256Sha256
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.ScalarOpcUaValueRank.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 = trueadds an insecure endpoint; it no longer defines the entire server security configuration by itself.- Use
SecurityPolicies = Array.Empty<OpcUaServerSecurityPolicy>()withEnableInsecureEndpoint = trueonly for intentional insecure-only test behavior. - Existing flat scalar node construction remains valid when
FolderPath,DataType, andValueRankare omitted. - Explicit types are required for null startup values that must not default to String.
- Decimal-to-Double publication requires
AllowDecimalToDouble = true. UInt16[]andString[]requireOpcUaValueRank.OneDimension.- Certificate trust is explicit by default; use
OpcUaCertificateStoreManagerinstead 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[]andString[]; - 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 | Versions 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. |
-
net8.0
- OPCFoundation.NetStandard.Opc.Ua.Client (>= 1.5.378.156)
- OPCFoundation.NetStandard.Opc.Ua.Server (>= 1.5.378.156)
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.