# OPC UA Server The OPC UA server component hosts the Galaxy-backed namespace on a configurable TCP endpoint and exposes deployed System Platform objects and attributes to OPC UA clients. ## Configuration `OpcUaConfiguration` defines the server endpoint and session settings. All properties have sensible defaults: | Property | Default | Description | |----------|---------|-------------| | `Port` | `4840` | TCP port the server listens on | | `EndpointPath` | `/LmxOpcUa` | URI path appended to the base address | | `ServerName` | `LmxOpcUa` | Application name presented to clients | | `GalaxyName` | `ZB` | Galaxy name used in the namespace URI | | `MaxSessions` | `100` | Maximum concurrent client sessions | | `SessionTimeoutMinutes` | `30` | Idle session timeout | | `AlarmTrackingEnabled` | `false` | Enables `AlarmConditionState` nodes for alarm attributes | The resulting endpoint URL is `opc.tcp://0.0.0.0:{Port}{EndpointPath}`, e.g., `opc.tcp://0.0.0.0:4840/LmxOpcUa`. The namespace URI follows the pattern `urn:{GalaxyName}:LmxOpcUa` and serves as both the `ApplicationUri` and `ProductUri`. ## Programmatic ApplicationConfiguration `OpcUaServerHost` builds the entire `ApplicationConfiguration` in code. There are no XML configuration files. This keeps deployment simple on factory floor machines where editing XML is error-prone. The configuration covers: - **ServerConfiguration** -- base address, session limits, security policies, and user token policies - **SecurityConfiguration** -- certificate store paths under `%LOCALAPPDATA%\OPC Foundation\pki\`, auto-accept enabled - **TransportQuotas** -- 4 MB max message/string/byte-string size, 120-second operation timeout, 1-hour security token lifetime - **TraceConfiguration** -- OPC Foundation SDK tracing is disabled (output path `null`, trace masks `0`); all logging goes through Serilog instead ## Security Policy The server runs with `MessageSecurityMode.None` and `SecurityPolicies.None`. Only anonymous user tokens are accepted: ```csharp SecurityPolicies = { new ServerSecurityPolicy { SecurityMode = MessageSecurityMode.None, SecurityPolicyUri = SecurityPolicies.None } }, UserTokenPolicies = { new UserTokenPolicy(UserTokenType.Anonymous) } ``` This is intentional for plant-floor deployments where the server sits on an isolated OT network. Galaxy-level security classification controls write access per attribute rather than at the transport layer. ## Certificate handling On startup, `OpcUaServerHost.StartAsync` calls `CheckApplicationInstanceCertificate(false, 2048)` to locate or create a 2048-bit self-signed certificate. The certificate subject follows the format `CN={ServerName}, O=ZB MOM, DC=localhost`. Certificate stores use the directory-based store type under `%LOCALAPPDATA%\OPC Foundation\pki\`: | Store | Path suffix | |-------|-------------| | Own | `pki/own` | | Trusted issuers | `pki/issuer` | | Trusted peers | `pki/trusted` | | Rejected | `pki/rejected` | `AutoAcceptUntrustedCertificates` is set to `true` so the server does not reject client certificates. ## Server class hierarchy ### LmxOpcUaServer extends StandardServer `LmxOpcUaServer` inherits from the OPC Foundation `StandardServer` base class and overrides two methods: - **`CreateMasterNodeManager`** -- Instantiates `LmxNodeManager` with the Galaxy namespace URI, the `IMxAccessClient` for runtime I/O, performance metrics, and an optional `HistorianDataSource`. The node manager is wrapped in a `MasterNodeManager` with no additional core node managers. - **`LoadServerProperties`** -- Returns server metadata: manufacturer `ZB MOM`, product `LmxOpcUa Server`, and the assembly version as the software version. ### Session tracking `LmxOpcUaServer` exposes `ActiveSessionCount` by querying `ServerInternal.SessionManager.GetSessions().Count`. `OpcUaServerHost` surfaces this for status reporting. ## Startup and Shutdown `OpcUaServerHost.StartAsync` performs the following sequence: 1. Build `ApplicationConfiguration` programmatically 2. Validate the configuration via `appConfig.Validate(ApplicationType.Server)` 3. Create `ApplicationInstance` and check/create the application certificate 4. Instantiate `LmxOpcUaServer` and start it via `ApplicationInstance.Start` `OpcUaServerHost.Stop` calls `_server.Stop()` and nulls both the server and application instance references. The class implements `IDisposable`, delegating to `Stop`. ## Key source files - `src/ZB.MOM.WW.LmxOpcUa.Host/OpcUa/OpcUaServerHost.cs` -- Application lifecycle and programmatic configuration - `src/ZB.MOM.WW.LmxOpcUa.Host/OpcUa/LmxOpcUaServer.cs` -- StandardServer subclass and node manager creation - `src/ZB.MOM.WW.LmxOpcUa.Host/Configuration/OpcUaConfiguration.cs` -- Configuration POCO