Skip to content

How-to guide

Events

Receive, filter, and evaluate the events of a server, work with event nodes, and receive audit events.

This content was machine translated and may contain errors. Read in German

How-to guide

Events ​

This page shows how a client receives, filters, and evaluates the events (Alarms & Events) of a server. The page Alarms and conditions describes events with conditions and alarms.

Types usedOpcClientOpcObjectTypesOpcEventTypesOpcEventReceivedEventArgsOpcEventOpcAlarmConditionOpcSimpleAttributeOperandOpcFilterOpcEventFilterOpcEventSeverity

Receive global events ​

Events inform a subscriber, for example a client, about processes, states, and system-specific occurrences. Through global events, subscribers receive such information directly. A server always publishes a global event through its Server object. For this reason, the client also subscribes to global events through this node:

csharp
client.SubscribeEvent(OpcObjectTypes.Server, HandleGlobalEvents);
vbnet
client.SubscribeEvent(OpcObjectTypes.Server, AddressOf HandleGlobalEvents)

You usually handle an event with a method of this signature:

csharp
private static void HandleGlobalEvents(
        object sender,
        OpcEventReceivedEventArgs e)
{
    Console.WriteLine(e.Event.Message);
}
vbnet
Private Shared Sub HandleGlobalEvents( _
        ByVal sender As Object, _
        ByVal e As OpcEventReceivedEventArgs)
    Console.WriteLine(e.Event.Message)
End Sub

The Event property of the event arguments (class OpcEventReceivedEventArgs) returns the event data received. It always returns an instance of the OpcEvent class. If the event data belongs to a specialization of the OpcEvent class, simply cast it:

csharp
private static void HandleGlobalEvents(
        object sender,
        OpcEventReceivedEventArgs e)
{
    var alarm = e.Event as OpcAlarmCondition;
 
    if (alarm != null)
        Console.WriteLine("Alarm: " + alarm.Message);
}
vbnet
Private Shared Sub HandleGlobalEvents( _
        ByVal sender As Object, _
        ByVal e As OpcEventReceivedEventArgs)
    Dim alarm = TryCast(e.Event, OpcAlarmCondition)

    If alarm IsNot Nothing Then
        Console.WriteLine("Alarm: " & alarm.Message.Value)
    End If
End Sub

Filter events ​

The call above subscribes to all events that the server publishes globally. With an event filter, you restrict the information you receive and also the events that the server sends to the client at all. The client transmits the filter to the server when it creates the subscription:

csharp
// Define an attribute operand using the identifier of the type which defines the
// attribute / property including the name of the attribute / property to evaluate
// by the operand.
var severity = new OpcSimpleAttributeOperand(OpcEventTypes.Event, "Severity");
var conditionName = new OpcSimpleAttributeOperand(OpcEventTypes.Condition, "ConditionName");
 
var filter = OpcFilter.Using(client)
        .FromEvents(OpcEventTypes.AlarmCondition)
        .Where(severity > OpcEventSeverity.Medium & conditionName.Like("Temperature"))
        .Select();
 
client.SubscribeEvent(
        OpcObjectTypes.Server,
        filter,
        HandleGlobalEvents);
vbnet
'Define an attribute operand using the identifier of the type which defines the
'attribute / property including the name of the attribute / property to evaluate
'by the operand.
Dim severity = New OpcSimpleAttributeOperand(OpcEventTypes.Event, "Severity")
Dim conditionName = New OpcSimpleAttributeOperand(OpcEventTypes.Condition, "ConditionName")

Dim filter = OpcFilter.Using(client) _
        .FromEvents(OpcEventTypes.AlarmCondition) _
        .Where(severity > OpcEventSeverity.Medium And conditionName.Like("Temperature")) _
        .Select()

client.SubscribeEvent(
        OpcObjectTypes.Server,
        filter,
        AddressOf HandleGlobalEvents)

To create an event filter, you always need an instance of OpcClient that is already connected to the target server. While it builds the filter, the client retrieves the relevant type information from the server. In the example above, the client collects all properties of the node type OpcAlarmConditionNode recursively up to OpcNode. From the Where and Select clauses, it creates rules for selecting the event data. Pass the node types to analyze to the FromEvents method, separated by commas:

csharp
var severity = new OpcSimpleAttributeOperand(OpcEventTypes.Event, "Severity");
var conditionName = new OpcSimpleAttributeOperand(OpcEventTypes.Condition, "ConditionName");
 
var filter = OpcFilter.Using(client)
        .FromEvents(
            OpcEventTypes.AlarmCondition,
            OpcEventTypes.ExclusiveLimitAlarm,
            OpcEventTypes.DialogCondition)
        .Where(severity > OpcEventSeverity.Medium & conditionName.Like("Temperature"))
        .Select();
 
client.SubscribeEvent(
        OpcObjectTypes.Server,
        filter,
        HandleGlobalEvents);
vbnet
Dim severity = New OpcSimpleAttributeOperand(OpcEventTypes.Event, "Severity")
Dim conditionName = New OpcSimpleAttributeOperand(OpcEventTypes.Condition, "ConditionName")

Dim filter = OpcFilter.Using(client) _
        .FromEvents( _
            OpcEventTypes.AlarmCondition, _
            OpcEventTypes.ExclusiveLimitAlarm, _
            OpcEventTypes.DialogCondition) _
        .Where(severity > OpcEventSeverity.Medium And conditionName.Like("Temperature")) _
        .Select()

client.SubscribeEvent(
        OpcObjectTypes.Server,
        filter,
        AddressOf HandleGlobalEvents)

With the Where method, you restrict the information that FromEvents collects through the properties of the node types. For this, the OPC UA .NET SDK offers several operator overloads (<=, <, >, >=, and ==). The operator != throws a NotSupportedException. Use (a < b) | (a > b) instead. To combine operands logically, the operators OR (|) and AND (&) are also available. For further restrictions, there are methods such as Like, Between, InList, IsNull, Not, OfType, Cast, and InView. For languages without these operators (such as Visual Basic), the equivalent methods EqualsTo, GreaterThan, GreaterThanOrEqualsTo, LessThan, and LessThanOrEqualsTo are available.

As of version 2.59, Between takes the operands in OPC UA order: a.Between(lower, upper) checks whether a lies between lower and upper. As of version 2.59, several Where calls in a row combine their conditions with AND, like a single Where with &. In older versions, only the condition of the last call applies.

Then use the Select method to choose the properties that the server additionally transmits to the client. The server does so when an event occurs that matches the conditions from Where.

The following example subscribes to all events that are currently active but not yet acknowledged:

csharp
var isActive = new OpcSimpleAttributeOperand(
        OpcEventTypes.AlarmCondition,
        "ActiveState", "Id");
var isAcked = new OpcSimpleAttributeOperand(
        OpcEventTypes.AcknowledgeableCondition,
        "AckedState", "Id");

var filter = OpcFilter.Using(client)
    .FromEvents(OpcEventTypes.AlarmCondition)
    .Where(OpcFilterOperand.OfType(OpcEventTypes.AlarmCondition)
        & isAcked == false
        & isActive == true)
    .Select();

var subscription = client.SubscribeEvent("ns=2;s=Machine", filter, (sender, e) => {
    if (e.Event is OpcAlarmCondition alarm) {
        Console.WriteLine(
                "{0}: {1}, IsActive = {2}, IsAcked = {3} ({4})",
                alarm.GetType().Name,
                alarm.Message,
                alarm.IsActive,
                alarm.IsAcked,
                alarm.Severity);
    }
});
vbnet
Dim isActive = New OpcSimpleAttributeOperand( _
        OpcEventTypes.AlarmCondition, _
        "ActiveState", "Id")
Dim isAcked = New OpcSimpleAttributeOperand( _
        OpcEventTypes.AcknowledgeableCondition, _
        "AckedState", "Id")

Dim filter = OpcFilter.Using(client) _
    .FromEvents(OpcEventTypes.AlarmCondition) _
    .Where(OpcFilterOperand.OfType(OpcEventTypes.AlarmCondition) _
        And isAcked = False _
        And isActive = True) _
    .Select()

Dim subscription = client.SubscribeEvent("ns=2;s=Machine", filter, _
    Sub(sender, e)
        Dim alarm = TryCast(e.Event, OpcAlarmCondition)

        If alarm IsNot Nothing Then
            Console.WriteLine( _
                    "{0}: {1}, IsActive = {2}, IsAcked = {3} ({4})", _
                    alarm.GetType().Name, alarm.Message, alarm.IsActive, alarm.IsAcked, alarm.Severity)
        End If
    End Sub)

Receive events of a node ​

Types usedOpcClientOpcEventReceivedEventArgsOpcEventOpcSubscription

It does not always make sense for a server to send all events globally through the Server object to all subscribers. Often the context decides whether an event is of interest to a subscriber. For such local events, there are event nodes. If the server uses an event node to provide event data for a node, the event node is a notifier of that node. A HasNotifier reference therefore shows which event node reports event data to a node. An event node can be the notifier of multiple nodes. For this reason, the client always subscribes to local events through the notified nodes:

csharp
client.SubscribeEvent(machineNodeId, HandleLocalEvents);
vbnet
client.SubscribeEvent(machineNodeId, AddressOf HandleLocalEvents)

You usually handle an event with a method of this signature. The client processes the event data further the same way as for global events (see section Receive global events).

csharp
private static void HandleLocalEvents(
        object sender,
        OpcEventReceivedEventArgs e)
{
    Console.WriteLine(e.Event.Message);
}
vbnet
Private Shared Sub HandleLocalEvents( _
        ByVal sender As Object, _
        ByVal e As OpcEventReceivedEventArgs)
    Console.WriteLine(e.Event.Message)
End Sub

You can also filter local events, as shown in the section Filter events.

A subscriber (a client) only learns about events while it is connected to the server and has created a subscription. After it connects, it therefore does not know the current state of the conditions of the server (see Alarms and conditions). With the following call, it requests this state. The server then sends an event again for all conditions that are currently in a relevant state (IsRetained is true). This call does not return past events. If the server provides them, the client reads them through the event history, see Read the event history.

csharp
var subscription = client.SubscribeEvent(
        machineNodeId,
        HandleLocalEvents);
 
// Query most recent event information.
subscription.RefreshConditions();
vbnet
Dim subscription = client.SubscribeEvent( _
        machineNodeId, _
        AddressOf HandleLocalEvents)
 
'Query most recent event information.
subscription.RefreshConditions()

Receive audit events ​

Types usedOpcClientOpcFilterOpcEventFilterOpcObjectTypesOpcEvent

Audit events log the security-related actions of a server. A server developed with the SDK reports them through the Server object if auditing is turned on in the server (see Audit events). It reports them when a secure channel is opened and closed (AuditOpenSecureChannelEventType, AuditChannelEventType) and when a session is created (AuditCreateSessionEventType) and activated (AuditActivateSessionEventType). As defined by OPC UA, a client receives them only through an endpoint with the mode SignAndEncrypt or through HTTPS, and only if the logged-on user belongs to the SecurityAdmin role. A client subscribes to them like other events, through a filter on the event types, in the following example on the two event types of the session:

csharp
OpcEventFilter filter = OpcFilter.Using(client)
        .FromEvents(
                OpcObjectTypes.GetNodeId(OpcObjectType.AuditCreateSessionEventType),
                OpcObjectTypes.GetNodeId(OpcObjectType.AuditActivateSessionEventType))
        .Select();
 
client.SubscribeEvent(OpcObjectTypes.Server, filter, HandleAuditEvent);
...
private static void HandleAuditEvent(
        object sender,
        OpcEventReceivedEventArgs e)
{
    OpcEvent audit = e.Event;
 
    Console.WriteLine(
            "{0:u} {1} {2}: {3}",
            audit.Time,
            audit.EventTypeId,
            audit.SourceName,
            audit.Message);
}
vbnet
Dim filter As OpcEventFilter = OpcFilter.Using(client) _
        .FromEvents( _
                OpcObjectTypes.GetNodeId(OpcObjectType.AuditCreateSessionEventType), _
                OpcObjectTypes.GetNodeId(OpcObjectType.AuditActivateSessionEventType)) _
        .Select()

client.SubscribeEvent(OpcObjectTypes.Server, filter, AddressOf HandleAuditEvent)
...
Private Shared Sub HandleAuditEvent( _
        ByVal sender As Object, _
        ByVal e As OpcEventReceivedEventArgs)
    Dim audit As OpcEvent = e.Event

    Console.WriteLine( _
            "{0:u} {1} {2}: {3}", _
            audit.Time, _
            audit.EventTypeId, _
            audit.SourceName, _
            audit.Message)
End Sub

The client can read the general fields of an event, for example Time, EventTypeId, SourceName, and Message. The SDK does not provide the specific fields of audit events in the client, such as the identity of the user or the ID of the session.