C# / .NET · recipe
Subscribe to alarms and events in C#
Monitor the Server object's EventNotifier with an EventFilter whose select clause names the fields you want. The reference stack has helpers that build the filter and unpack the field values in order.
| Stack | OPCFoundation/UA-.NETStandard |
|---|---|
| Version | 1.5.378.156 stable, 2.0.0-preview.2 |
The code
var filter = new FilterDefinition
{
AreaId = ObjectIds.Server,
Severity = EventSeverity.Min,
IgnoreSuppressedOrShelved = true,
EventTypes = new NodeIdCollection { ObjectTypeIds.BaseEventType },
};
filter.SelectClauses = filter.ConstructSelectClauses(
session, ObjectTypeIds.BaseEventType);
var subscription = new Subscription(session.DefaultSubscription)
{
PublishingInterval = 500, KeepAliveCount = 10, LifetimeCount = 100,
};
session.AddSubscription(subscription);
subscription.Create();
var item = filter.CreateMonitoredItem(session);
item.Notification += (mi, e) =>
{
if (e.NotificationValue is not EventFieldList fields) return;
var ev = filter.GetFilterTargetValues(fields.EventFields);
Console.WriteLine($"[{ev.Severity}] {ev.SourceName}: {ev.Message?.Text}");
};
subscription.AddItem(item);
subscription.ApplyChanges();
await Task.Delay(10000);
What it prints
[500] MachineTool_1: Tool life below threshold
[800] MachineTool_1: Tool breakage detected
[100] Server: Session activated
Notes
- The select clause order determines the field order in every notification. Use the helper that maps them back by name rather than indexing positionally.
- Narrow EventTypes to what you care about. Subscribing to BaseEventType on a busy server delivers a lot of noise you then pay to discard.
- Call ConditionRefresh after a reconnect, or your client believes the plant is healthy while alarms are still active.
- Add ConditionClassId to the select clause for OEE work: it is what makes downtime reasons portable across machine vendors.
What breaks first
The subscription is created but no events arrive
A select clause field does not exist on the event types the server emits. Start from the base fields, confirm events flow, then add fields back individually.
BadEventFilterInvalidA select clause field does not exist on the event types the server emits. Start from the base fields, confirm events flow, then add fields back individually.
Other recipes in this stack
Concepts on this page
Last verified 7 September 2026 against OPC UA 1.05.07. OPC UA Connect is an educational resource and is not affiliated with the OPC Foundation.