Skip to content
Architecture

Architecture

OpcSharp uses a layered architecture where each layer depends only on the layers below it.

Layer Stack

OpcSharp.Client          ← High-level API (OpcSharpClient, OpcSharpClientBuilder, DI)
OpcSharp.Services        ← Service wrappers (Attribute, Browse, Method, Subscription)
OpcSharp.Protocol        ← Session + SecureChannel (framing, request/response, token renewal)
OpcSharp.Security        ← Security policies, key derivation, crypto, certificates
OpcSharp.Transport.WebSocket ← WebSocket transport (opc.wss://, opc.ws://)
OpcSharp.Transport.Http  ← HTTPS transport
OpcSharp.Transport       ← TCP transport (Hello/ACK, chunking, buffer negotiation)
OpcSharp.Encoding        ← Binary encoder/decoder for all OPC UA types
OpcSharp.Types           ← Core types (NodeId, StatusCode, DataValue, Variant, etc.)

Key Interfaces

InterfaceLayerPurpose
IOpcSharpClientClientTop-level API for connecting, reading, writing, subscribing
ISessionProtocolSession lifecycle: Create, Activate, Close, SendRequest
ISecureChannelProtocolChannel lifecycle: Open, Close, SendRequest, RenewToken
ITransportTransportTCP, HTTPS, or WebSocket connection and message framing

Client Layer

The entry point for most users. OpcSharpClientBuilder provides a fluent API:

var client = new OpcSharpClientBuilder()
    .WithEndpoint("opc.tcp://localhost:4840")
    .WithSessionName("MySession")
    .WithSecurity(SecurityPolicyUris.Basic256Sha256, MessageSecurityMode.SignAndEncrypt)
    .WithUserIdentity(new UserNameIdentity("user", "pass"))
    .WithAutoAcceptUntrustedCertificates(true)
    .Build();

ConnectAsync() creates the full stack: Transport -> SecureChannel -> Session -> Services.

Services Layer

Each service wraps a set of OPC UA service calls:

  • IAttributeServiceReadAsync(), WriteAsync()
  • IBrowseServiceBrowseAsync(), BrowseNextAsync(), TranslateBrowsePathsToNodeIdsAsync()
  • IMethodServiceCallAsync()
  • ISubscriptionServiceCreateSubscriptionAsync(), ModifySubscriptionAsync(), DeleteSubscriptionsAsync()
  • IMonitoredItemServiceCreateMonitoredItemsAsync(), ModifyMonitoredItemsAsync(), DeleteMonitoredItemsAsync()
  • IDiscoveryServiceFindServersAsync(), GetEndpointsAsync()

All services use Session.SendRequestAsync(typeId, body, ct) with manual binary encoding/decoding.

Protocol Layer

Manages the OPC UA session and secure channel:

  • Session — CreateSession (TypeId=461), ActivateSession (TypeId=467), CloseSession
  • SecureChannel — OpenSecureChannel (OPN message), message signing and encryption, token renewal at 75% lifetime
  • State machinesSessionState and SecureChannelState enums track lifecycle transitions

Transport Layer

Handles the network connection and OPC UA message framing. Three transports are available:

  • TCP (opc.tcp://) — Hello/ACK handshake, chunking, buffer negotiation
  • HTTPS (https://) — OPC UA Binary over HTTP POST
  • WebSocket (opc.wss://, opc.ws://) — OPC UA Binary over WebSocket frames per Part 6 §7.5

All transports implement ITransport and are selected automatically based on the endpoint URL scheme. The SecureChannel layer consumes ITransport unchanged.

Common framing:

  • 8-byte message header: [Type:3][F/C:1][Size:4]
  • Message types: HEL, ACK, ERR, MSG, OPN, CLO

Encoding Layer

Binary encoder/decoder for all OPC UA built-in types:

  • NodeId (5 compressed encoding variants: TwoByte, FourByte, Numeric, String, Guid, Opaque)
  • Variant (all 25 built-in types + arrays)
  • DataValue (Value + StatusCode + timestamps)
  • DateTime as Windows FILETIME (100ns intervals since Jan 1, 1601)

Types Layer

Core OPC UA type definitions used throughout the stack:

  • Identifiers — NodeId, ExpandedNodeId, QualifiedName
  • Values — Variant, DataValue, StatusCode
  • Text — LocalizedText, DiagnosticInfo
  • Extension — ExtensionObject (TypeId + Encoding + Body)
  • Constants — AttributeIds, ObjectIds, DataTypeIds, ReferenceTypeIds