19 Commits

Author SHA1 Message Date
Marc Schier 01d7162313 Part 9 Alarms & Conditions: complete server + client implementation (#3805)
Complete implementation of **OPC UA Part 9 ΓÇö Alarms & Conditions** for
both server and client, **OPC UA Part 16 ΓÇö State Machines** (generic
extensible client + server API), and the supporting infrastructure
(source-generated event records, source-generated ObjectType proxies,
`IAsyncEnumerable` streaming subscriptions, address-space model change
tracking, per-node `INodeCache` invalidation, unified DI integration).

### Server-side (Part 9 complete)

- **`AlarmConditionState`** ΓÇö every Part 9 method wired automatically
in `OnAfterCreate`: `Silence`, `Suppress`/`Suppress2`,
`Unsuppress`/`Unsuppress2`, `RemoveFromService`/`RemoveFromService2`,
`PlaceInService`/`PlaceInService2`, `Reset`/`Reset2`,
`GetGroupMemberships`. Each method generates the spec-mandated audit
event and supports an optional veto-delegate hook.
- **Latched alarms** ΓÇö `ActiveState` reflects real process state;
`LatchedState` persists until explicit `Reset` (with full precondition
validation).
- **Re-alarming** ΓÇö
`ProcessReAlarm`/`ResetReAlarmRepeatCount`/`IsReAlarmEnabled` helpers
(opt-in, no hidden timer).
- **Audible alarms** ΓÇö `UpdateAudibleState` for
`AudibleEnabled`/`AudibleSound`/`SilenceState` lifecycle.
- **Suppression + groups** ΓÇö `AlarmGroup`, `AlarmSuppressionEngine`
(with first-in-group), `AlarmRateTracker` (for `AlarmMetricsType`).
- **Spec-compliance fixes** ΓÇö `SuppressedOrShelved` now includes
`OutOfServiceState`; `GetRetainState` includes `LatchedState`;
`EffectiveDisplayName` composition includes `OutOfServiceState` +
`LatchedState`.

### Client-side Part 9 API

- **`AlarmClient`** ΓÇö typed Part 9 operations. Each method delegates
to the matching source-generated `*TypeClient` proxy
(`ConditionTypeClient`, `AcknowledgeableConditionTypeClient`,
`AlarmConditionTypeClient`, `DialogConditionTypeClient`,
`ShelvedStateMachineTypeClient`) ΓÇö one source of truth for every
method NodeId.
- **Interface hierarchy** — `IConditionOperations` →
`IAcknowledgeableConditionOperations` → `IAlarmOperations` +
`IDialogConditionOperations`.
- **Source-generated event records** ΓÇö new `EventRecordGenerator`
(alongside `ObjectTypeProxyGenerator`) emits `{Type}TypeRecord` per OPC
UA event type: `ConditionTypeRecord` →
`AcknowledgeableConditionTypeRecord` → `AlarmConditionTypeRecord` →
`LimitAlarmTypeRecord`/`ExclusiveLimitAlarmTypeRecord`/… all the way
to vendor subtypes. **Vendor alarm types get records automatically.**
- **`AlarmEventDecoder`** ΓÇö decodes `EventNotification.Fields` into
the most-specific generated record.
- **`AlarmEventFilterBuilder`** ΓÇö fluent builder for Part 9
`EventFilter`s.
- **`ISession.GetAlarmClient(telemetry)`** convenience extension.

### Part 16 state machines (generic, extensible)

- **Client**: extension methods on the source-generated
`StateMachineTypeClient` / `FiniteStateMachineTypeClient` ΓÇö
`GetCurrentStateAsync`, `ObserveFiniteTransitionsAsync`
(`IAsyncEnumerable<FiniteStateSnapshot>`), `WaitForStateAsync`,
`GetAvailableStatesAsync` / `GetAvailableTransitionsAsync`. **Vendor
proxies inherit the API automatically** through the generated
inheritance chain.
- **Server**: `StateMachineBuilder` (fluent: `AddState` /
`AddTransition` / `OnCause` / validation) +
`FluentFiniteStateMachineState` ΓÇö declare a Part 16 state machine
without subclassing the abstract base.
- **Alarms alignment**: `AlarmClient.GetShelvingStateAsync` /
`ObserveShelvingTransitionsAsync` surface the API for every alarm's
`ShelvingState` child.

### IAsyncEnumerable streaming subscription

- **`IStreamingSubscription`** with
`SubscribeDataChangesAsync`/`SubscribeEventsAsync` returning
`IAsyncEnumerable<T>` (Channel-backed).
- **`ManagedSession.DefaultStreaming`** ΓÇö lazy shared subscription;
disposed with the session.
- **Helpers** ΓÇö `TakeUntilAsync`, `WithTimeoutAsync`, `TakeAsync`,
`BufferedAsync` for state-machine waits and bounded observation windows.
- **`AlarmStreamExtensions`** ΓÇö
`SubscribeAlarmsAsync`/`SubscribeConditionsAsync`/`SubscribeDialogsAsync`
returning the source-generated record types.

### Address-space model change tracking

- **Server**: `RaiseGeneralModelChangeEvent` on both `CustomNodeManager`
and `AsyncCustomNodeManager`; `ModelChangeAggregator` (in
`Opc.Ua.Server.NodeManager`, used by every node manager) batches changes
per service call; **auto-emit** from `CreateNode`/`DeleteNode` (opt-out
via `ModelChangeEmissionEnabled = false`).
- **Client**: `IModelChangeTracker` subscribes to
`BaseModelChangeEventType` via the streaming subscription, decodes
`ModelChangeStructureDataType` payloads, invalidates the `INodeCache`
per-node.
- **`INodeCache.InvalidateNode(NodeId)`** ΓÇö new interface member (true
per-node eviction in `NodeCache`).
- **`ManagedSession.EnableModelChangeTrackingAsync()`** +
`ManagedSessionOptions.ModelChangeTracking` +
`ManagedSessionBuilder.WithModelChangeTracking()` fluent method.

### Dependency Injection integration

- **`services.AddOpcUa().AddClient(...).AddAlarms()`** ΓÇö registers
`AlarmClientFactory` so DI-hosted apps can resolve a Part 9 client per
session without `new`-ing one manually.
- Cross-link added to the unified DI surface (`AddServer` / `AddClient`
/ `AddComplexTypes` / `AddGdsServer` / `AddLdsServer` /
`AddWotConServer`).

### Quickstart server modernization

- `Quickstarts.Servers/Alarms/AlarmNodeManager.cs` ported to
`AsyncCustomNodeManager` and demonstrates the new `AlarmGroup` +
`AlarmSuppressionEngine` end-to-end via a writable `MaintenanceMode`
boolean that suppresses every member alarm.

### Documentation

- New: `Docs/AlarmsAndConditions.md`, `Docs/StreamingSubscription.md`,
`Docs/ModelChangeTracking.md`, `Docs/StateMachines.md` ΓÇö full
developer guides.
- Updated: `Docs/DependencyInjection.md` (`AddAlarms()` row + section),
`Docs/README.md` index, `Docs/MigrationGuide.md` (Part 9 / Part 16 /
model change tracking sections covering behavior changes + breaking API
surface).
- Sample: `Applications/ConsoleReferenceClient/AlarmClientSample.cs`.
2026-05-29 23:24:53 +02:00
romanett e49d17d706 [Server] Make MonitoredNode aware of IAsyncNodeManager and introduce channel-based queueing under load (#3804)
## Proposed changes

This PR updates the server monitored-item pipeline to be
`IAsyncNodeManager`-aware and introduces channel-based FIFO queueing in
the monitored-node path to improve behavior under load.

It also includes follow-up fixes from review/CI feedback:
- Adjusted
`AsyncCustomNodeManagerTests.WriteAsync_PublishesValueToMonitoredItemQueueAsync`
to account for channel-based delivery timing/coalescing while still
asserting the written value is observed.
- Merged latest `master` into this branch and resolved merge conflicts
(notably in `ConfigurationNodeManager`), keeping async address-space
lookup behavior intact.
- Applied small compile-safety corrections needed for successful
validation.
2026-05-27 10:12:17 +02:00
Marc Schier eb40a59566 More format and diagnostic fixes (#3780)
Drive the solution to zero warnings / zero errors with analyzers on,
promote the consistently-fixed rules to error, and lock in coverage
on the only line of new logic.
2026-05-26 06:06:09 +02:00
Marc Schier 3e5f129c6f Enable nullable in Stack, Libraries (9), and Applications projects (#3732) 2026-05-17 12:55:24 +02:00
Marc Schier 6c8c1a6d29 Enable dispose analyzers CA2000 and CA2213 and fix all issues (#3670) 2026-04-17 13:39:34 +02:00
Marc Schier 2960388560 Update headers and license files (#3388)
Update license headers to copy right year 2025, replace RCL/GPL headers with MIT, replace the nuget license with MIT (via license expression).
2025-12-04 19:44:40 +01:00
Marc Schier 4c651d05d2 Improve test stability of ValidateTransfer test, ensure thread safety in MonitoredItem (#3243)
* Improve thread safety and logging in MonitoredItem

Replaced Queue with ConcurrentQueue in MonitoredItemDataCache
for thread-safe operations. Updated Publish method to use
List<DataValue> for better handling of dequeued values. Enhanced
logging to include SourceTime and added logs for dropped values.

In DurableSubscriptionTest, added try-finally block to ensure
proper session closure and disposal, preventing memory leaks.
Introduced DurableSubscriptionTestLooper for stress testing
under debug mode. Refactored test code for improved readability.

* Improve logging and session management

Updated logging in `Session.cs`, `ServerBase.cs`, and `UaSCBinaryClientChannel.cs` to pass exceptions directly to the logger, enhancing error handling. Added connection state checks in `Session.cs` to prevent operations when the session is closed or never connected. Updated `Subscription.cs` to reflect session disconnection in `PublishingStopped`. Enhanced test outputs and renamed `DurableSubscriptionTestLooper` to `DurableSubscriptionTestDebug` in `DurableSubscriptionTest.cs`, reducing loop count for faster debug testing.

* Fix monitored item id factory producing collisions by first trying to allocate a free monitored item id in the table, then committing.

* Better diffing

* Enhance logging and session management

Added detailed logging in `AlarmNodeManager.cs` for lifecycle events and simulation control. Introduced a `Reconnecting` property in the `ISession` interface and `Session.cs` to manage session reconnection state, replacing the `m_reconnecting` field. Enhanced logging in `Session.cs` for reconnection and publish operations. Updated `DataGenerator.cs` to use `FrozenDictionary` for performance improvements. Replaced `SyncRoot` with `m_syncRoot` in `NamespaceTable.cs` for synchronization. Improved exception message formatting in `ServiceResult.cs`. Added necessary namespaces for new data structures. Made corrections and added debugging in `DurableSubscriptionTest.cs` for better session handling.

* Dispose simulation
2025-10-11 19:51:38 +02:00
Marc Schier 9830e5d53e Enable roslynizer and fix all analyzer issues (#3157)
* Fix warnings and suggestions
* Enable roslynator
2025-08-16 04:10:24 -07:00
romanett 1cce76861f [Server] Extend IMonitoredItem Interface and ensure it is used throughout the stack (#3103) 2025-08-08 10:06:29 +02:00
romanett f460736582 remove all obsolete methods from the stack (#3139) 2025-08-06 21:27:10 +02:00
romanett 2f0770c569 [Server] Restore durable subscriptions on Server Restart (#3025)
* Enable Durable Subscriptions (#9)

* [Server] Durable Subscriptions (#2683)

* Implement a system test for DurableSubscriptions (#2839)
* Client Side
Co-authored-by: ALTERNATE-DEV\Archie <archie@dreamsandadventures.ca>

* make a static Method CalculateRevisedQueueSize

* Adress review feedback

* fix FilterRetainTests

* Add MonitoredItem Id to Queues
Use NodeIdDictionary where possible

* first proto

* fix reference server

* implement store

* initialize early

* fix issues

* Move to Reference Server & start implementing queue restore

* Persist queues

* Register queues in factory after restore

* Add Docs

* minor fixes

* Test Subscription Restore & Transfer

* fix Durable Subscription Test Browse

* Fix conversion of extension objects

* use CustomConverter for NumericRange

* Adress review Feedback

* Documentation improvements

* Update Readme

* update sampling group manager to work without session

* remove launch settings
2025-03-24 11:45:09 +02:00
romanett ef9387b525 Enable Durable Subscriptions (#2978)
* Enable Durable Subscriptions (#9)

* [Server] Durable Subscriptions (#2683)

* Implement a system test for DurableSubscriptions (#2839)
* Client Side
Co-authored-by: ALTERNATE-DEV\Archie <archie@dreamsandadventures.ca>

* make a static Method CalculateRevisedQueueSize

* Adress review feedback

* fix FilterRetainTests

* Add MonitoredItem Id to Queues
Use NodeIdDictionary where possible
2025-02-28 13:46:49 +02:00
Martin Regen 4c0880c800 Fix codesmells. No functional changes and bug fixes. (#2368)
Fix many warnings to improve code quality or simplify the code.
2023-11-07 10:34:42 +01:00
Martin Regen 0ad5c4c3a3 Refactor audit events (#1895)
- Move the auditing flag to server internal
- Hook up new configuration setting to the Auditing node
- A Security Admin can change the Audit setting.
- Refactor audit events to be extensions in one class.
- enable auditing and diagnostics by default for higher test coverage.
- refactor dependency of some events to bindings, e.g. TcpServerChannel should not be used as reportevent parameter
2022-08-12 20:04:02 +02:00
Suciu Mircea Adrian 1e22c4d83f Filter events against Role-based permissions (#1798)
Events can be filtered against the Role-based permissions.
2022-05-06 09:30:43 -07:00
Suciu Mircea Adrian 3f04e9d370 Filter out audit events in case the ServerType_Auditing values is false or the channel is not encrypted (#1770)
* Filter out audit events in case the ServerType_Auditing values is false or the channel is not encrypted
2022-04-08 10:41:28 +03:00
Martin Regen 430ff70de7 Implement Transfersubscription service (#1649)
- Implement client and server side of Transfersubscription service calls.
- New Transcription service has been tested with CTT 1.04.9.398
- Unit tests for native service calls and client SDK
- Client implements multiple ways to transfer sessions:
  - Client saves subscriptions to xml stream, restarts, loads subscriptions from stream and transfers on server.
  - Client creates a new sessions and transfers into new session, while the old session is still active.
  - Client closes old session with `DeleteSubscriptionsOnClose = false`, creates new session and transfers subscriptions to new session.
  - `SessionReconnectHandler` tries to transfer subscription before recreating the subscriptions.
- breaking change: INodeManager got a new TransferMonitoredItems method

Co-authored-by: Alexander Koepke <alexander.koepke@microsoft.com>
Co-authored-by: Peter Bryntesson <pbrynt@microsoft.com>
2022-01-28 13:21:20 +01:00
AlinMoldovean 764c481405 Update Copyright year to 2020 2020-10-07 18:04:34 +03:00
Alin Moldovean 195521719e Move SDK folder to "Libraries" (#1013)
* Move Client library

* Move Server library

* Move Configuration library

* Move Complex Types library

* Update paths in project references
2020-06-09 18:46:08 +03:00