How-to guide
Alarms and conditions
Provide event nodes with conditions: dialog and acknowledgeable conditions, alarm conditions up to limit alarms.
How-to guide
Alarms and conditions
Event nodes with conditions report events that are tied to the state of a condition. This page shows how a server provides event nodes for each kind of condition, from simple conditions to limit alarms.
Conditions
Types usedOpcServerOpcNodeManagerOpcConditionNodeOpcConditionRetainPolicy
The OpcConditionNode class is a specialization of OpcEventNode, which Provide events on a node introduces. With OpcConditionNode, you define events that are tied to specific conditions. The server should trigger such an event only if the condition of the event node applies. The information of the node also includes the state of this condition and information tied to the evaluation of the condition.
Depending on the use case, this information can vary in complexity. For this reason, OpcConditionNode is the base class of all event nodes tied to a condition. You create such a node like an OpcEventNode. The following sections therefore show only the additional properties.
The IsRetained property states whether a condition is of interest to a client and is reported on a ConditionRefresh. By default, the OPC UA .NET SDK updates it automatically from the states of the condition. The IsRetainedPolicy property defines the rule it follows (enumeration OpcConditionRetainPolicy):
EnabledOnly(default ofOpcConditionNode): set as long as the condition is enabled.ActiveOrUnacknowledged(default ofOpcAcknowledgeableConditionNodeandOpcAlarmConditionNode): set as long as the alarm is active or not yet acknowledged.ActiveOrUnconfirmed: set as long as the alarm is active or not yet confirmed.ActiveOnly: set as long as the alarm is active, regardless of acknowledgment.Manual: the SDK does not change the property; the application sets it itself.
Regardless of the rule, IsRetained is never set for a disabled condition. A value of the IsRetained property that you set manually is therefore kept only with the Manual rule:
var maintenanceEvent = new OpcConditionNode(machineOne, "Maintenance");
// Default: EnabledOnly for an OpcConditionNode,
// ActiveOrUnacknowledged for acknowledgeable conditions and alarms.
maintenanceEvent.IsRetainedPolicy = OpcConditionRetainPolicy.Manual;
// Interesting for a client yes or no (only kept in case of the Manual policy).
maintenanceEvent.IsRetained = true;
// Status of the source the condition is based upon.
maintenanceEvent.Quality = OpcStatusCode.Good;Dim maintenanceEvent = New OpcConditionNode(machineOne, "Maintenance")
'Default: EnabledOnly for an OpcConditionNode,
'ActiveOrUnacknowledged for acknowledgeable conditions and alarms.
maintenanceEvent.IsRetainedPolicy = OpcConditionRetainPolicy.Manual
'Interesting for a client yes or no (only kept in case of the Manual policy).
maintenanceEvent.IsRetained = True
'Status of the source the condition is based upon.
maintenanceEvent.Quality = OpcStatusCode.GoodWith the AddComment method and the child node of the same name, a client can change the Comment property of the node. The server responds to the call through the AddCommentCallback property. You evaluate the result of the change with the following properties:
// Identifier of the user who supplied the Comment
maintenanceEvent.ClientUserId = ...;
// Last comment provided by a user
maintenanceEvent.Comment = ...;' Identifier of the user who supplied the Comment
maintenanceEvent.ClientUserId = ...
' Last comment provided by a user
maintenanceEvent.Comment = ...On the server side, you change the states of a condition with the methods whose names start with Change, for example ChangeIsEnabled or ChangeComment. These methods are available only once the node exists in the address space. Before that, they throw an InvalidOperationException. If the AutoReportChanges property is set (it is not by default), the node automatically reports an event after each of these changes:
// Use the Change methods once the node has been added to the address space.
maintenanceEvent.ChangeIsEnabled(this.SystemContext, value: false);
maintenanceEvent.ChangeComment(this.SystemContext, value: "Planned maintenance");
// Reports an event whenever one of the Change methods completes.
maintenanceEvent.AutoReportChanges = true;'Use the Change methods once the node has been added to the address space.
maintenanceEvent.ChangeIsEnabled(Me.SystemContext, value:=False)
maintenanceEvent.ChangeComment(Me.SystemContext, value:="Planned maintenance")
'Reports an event whenever one of the Change methods completes.
maintenanceEvent.AutoReportChanges = TrueIf the same event node should be processed on several tracks in parallel, you can open a new event branch. The CreateBranch method of the node does this. The node stores the unique key of the branch in the BranchId property. The following code shows the most important parts of OpcConditionNode for branches:
// Uses a new GUID as BranchId.
var maintenanceBranchA = maintenanceEvent.CreateBranch(this.SystemContext);
// Uses a custom NodeId as BranchId.
var maintenanceBranchB = maintenanceEvent.CreateBranch(
this.SystemContext,
branchId: new OpcNodeId(10001));'Uses a new GUID as BranchId.
Dim maintenanceBranchA = maintenanceEvent.CreateBranch(Me.SystemContext)
'Uses a custom NodeId as BranchId.
Dim maintenanceBranchB = maintenanceEvent.CreateBranch( _
Me.SystemContext, _
branchId:=New OpcNodeId(10001))The BranchId property identifies the branch an event belongs to. A null reference stands for the current state. The LastSeverity property returns the previous severity of the branch.
Dialog conditions
Types usedOpcServerOpcNodeManagerOpcDialogConditionNode
The OpcDialogConditionNode class is a specialization of OpcConditionNode. The condition of this node is a dialog with the subscribers. Such a condition consists of a prompt and response options. Three more details complete it: the option selected by default (DefaultResponse property), the option that confirms the dialog (OkResponse property), and the option that cancels it (CancelResponse property). When the server triggers such a dialog event, it waits until one of the subscribers responds. The response is a choice from the given response options.
The condition for further processing of the operations tied to the dialog is therefore the response to a task, a question, a piece of information, or a warning. Once you have created the node as usual, set the properties to fit the use case:
var outOfMaterial = new OpcDialogConditionNode(machineOne, "MaterialAlert");
outOfMaterial.Message = "Out of Material"; // Generic event message
outOfMaterial.Prompt = "The machine is out of material. Refill material supply to continue.";
outOfMaterial.ResponseOptions = new OpcText[] { "Continue", "Cancel" };
outOfMaterial.DefaultResponse = 0; // Index of ResponseOption to use
outOfMaterial.CancelResponse = 1; // Index of ResponseOption to use
outOfMaterial.OkResponse = 0; // Index of ResponseOption to useDim outOfMaterial As New OpcDialogConditionNode(machineOne, "MaterialAlert")
outOfMaterial.Message = "Out of Material" ' Generic event message
outOfMaterial.Prompt = "The machine is out of material. Refill material supply to continue."
outOfMaterial.ResponseOptions = New OpcText() {"Continue", "Cancel"}
outOfMaterial.DefaultResponse = 0 ' Index of ResponseOption to use
outOfMaterial.CancelResponse = 1 ' Index of ResponseOption to use
outOfMaterial.OkResponse = 0 ' Index of ResponseOption to useTo let the subscribers respond to the dialog, activate it with the ActivateDialog method once the node exists in the address space. You handle the response of a subscriber in the RespondCallback of the node. The RespondDialog method accepts the response and deactivates the dialog again. The LastResponse property returns the response accepted last:
outOfMaterial.RespondCallback = this.HandleOutOfMaterialResponse;
outOfMaterial.ActivateDialog(this.SystemContext);
...
private OpcStatusCode HandleOutOfMaterialResponse(
OpcNodeContext<OpcDialogConditionNode> context,
int selectedResponse)
{
// Handle the response.
if (context.Node.OkResponse == selectedResponse)
ContinueJob();
else
CancelJob();
// Apply the response.
context.Node.RespondDialog(context, selectedResponse);
return OpcStatusCode.Good;
}outOfMaterial.RespondCallback = AddressOf Me.HandleOutOfMaterialResponse
outOfMaterial.ActivateDialog(Me.SystemContext)
...
Private Function HandleOutOfMaterialResponse( _
ByVal context As OpcNodeContext(Of OpcDialogConditionNode), _
ByVal selectedResponse As Integer) As OpcStatusCode
'Handle the response.
If context.Node.OkResponse = selectedResponse Then
ContinueJob()
Else
CancelJob()
End If
'Apply the response.
context.Node.RespondDialog(context, selectedResponse)
Return OpcStatusCode.Good
End FunctionAcknowledgeable conditions
Types usedOpcServerOpcNodeManagerOpcAcknowledgeableConditionNode
The OpcAcknowledgeableConditionNode class is a specialization of OpcConditionNode. It is the base class for conditions that request feedback. When the condition of such an event is met, the server sends a kind of "message with return receipt". The return receipt, that is, the feedback, can control further processes or simply acknowledge notes and warnings. The OPC UA specification (Part 9) provides a feedback mechanism with two kinds of feedback for this. With Acknowledge, the operators confirm that they have taken note of the message. With the optional Confirm, they then report that the cause has been resolved. For both kinds of feedback, the node provides the Acknowledge and Confirm child nodes.
The SDK handles both kinds of feedback independently of each other: acknowledging sets only the Acked state, confirming sets only the Confirmed state. The application defines the order the server requires. With both kinds of feedback, the operators can optionally add a comment. You create such a node as usual. Here too, you can set the states only once the node exists in the address space:
var outOfProcessableBounds = new OpcAcknowledgeableConditionNode(machineOne, "OutOfBoundsAlert");
// Once the node has been added to the address space:
// Define the condition as: Needs to be acknowledged.
outOfProcessableBounds.ChangeIsAcked(this.SystemContext, value: false);
// Define the condition as: Needs to be confirmed.
outOfProcessableBounds.ChangeIsConfirmed(this.SystemContext, value: false);Dim outOfProcessableBounds = New OpcAcknowledgeableConditionNode(machineOne, "OutOfBoundsAlert")
'Once the node has been added to the address space:
'Define the condition as: Needs to be acknowledged.
outOfProcessableBounds.ChangeIsAcked(Me.SystemContext, value:=False)
'Define the condition as: Needs to be confirmed.
outOfProcessableBounds.ChangeIsConfirmed(Me.SystemContext, value:=False)Later in the process, you check received feedback with the IsAcked and IsConfirmed properties of the node:
if (outOfProcessableBounds.IsAcked) {
...
}
if (outOfProcessableBounds.IsConfirmed) {
...
}If outOfProcessableBounds.IsAcked Then
...
End If
If outOfProcessableBounds.IsConfirmed Then
...
End IfThe server responds to the feedback of a client through the AcknowledgeCallback and ConfirmCallback properties. The server itself acknowledges or confirms a condition with the Acknowledge and Confirm methods:
outOfProcessableBounds.AcknowledgeCallback = (context, eventId, comment) => {
Console.WriteLine("Acknowledged: {0}", comment);
return OpcStatusCode.Good;
};
// Acknowledge or confirm the condition on the server side.
outOfProcessableBounds.Acknowledge(this.SystemContext, comment: "Acknowledged by the server");
outOfProcessableBounds.Confirm(this.SystemContext);outOfProcessableBounds.AcknowledgeCallback = Function(context, eventId, comment)
Console.WriteLine("Acknowledged: {0}", comment)
Return OpcStatusCode.Good
End Function
'Acknowledge or confirm the condition on the server side.
outOfProcessableBounds.Acknowledge(Me.SystemContext, comment:="Acknowledged by the server")
outOfProcessableBounds.Confirm(Me.SystemContext)The server must always define its own interpretation of the feedback and the logic that follows. Whether a server uses both kinds of feedback or only one is up to the development team. A server should support at least Acknowledge. According to the specification, Confirm is optional.
Alarm conditions
Types usedOpcServerOpcNodeManagerOpcAlarmConditionNode
Probably the most important implementation of OpcAcknowledgeableConditionNode in OPC UA is the OpcAlarmConditionNode class. With it, you define event nodes that behave like a bedside alarm clock. The node becomes active (IsActive property) when the linked condition is met. For the alarm clock, this is reaching the wake-up time, for example. An alarm that has a wake-up time but should not become active when that time is reached is called a suppressed alarm (IsSuppressed and IsSuppressedOrShelved properties). You can shelve an active alarm (IsSuppressedOrShelved property). An alarm can be shelved once ("One Shot Shelving") or for a period of time ("Timed Shelving") (Shelving property). You can also unshelve an alarm again (Shelving property).
The following code shows an example of the OpcAlarmConditionNode API:
var overheating = new OpcAlarmConditionNode(machineOne, "OverheatingAlert");
var idle = new OpcAlarmConditionNode(machineOne, "IdleAlert");
...
overheating.ChangeIsActive(this.SystemContext, true);
idle.ChangeIsActive(this.SystemContext, true);
...
if (overheating.IsActive)
CancelJob();
if (!idle.IsActive)
ProcessJob();
else if (idle.IsSuppressed)
SimulateJob();Dim overheating As New OpcAlarmConditionNode(machineOne, "OverheatingAlert")
Dim idle As New OpcAlarmConditionNode(machineOne, "IdleAlert")
'...
overheating.ChangeIsActive(Me.SystemContext, True)
idle.ChangeIsActive(Me.SystemContext, True)
...
If overheating.IsActive Then
CancelJob()
End If
If Not idle.IsActive Then
ProcessJob()
ElseIf idle.IsSuppressed Then
SimulateJob()
End IfOn the server side, you suppress an alarm with the ChangeIsSuppressed method and shelve it with the ChangeShelving method:
// Suppress the alarm, e.g. while the machine is in maintenance.
overheating.ChangeIsSuppressed(this.SystemContext, value: true);
// Shelve the alarm for 30 minutes.
overheating.ChangeShelving(
this.SystemContext,
shelved: true,
oneShot: false,
shelvingTime: TimeSpan.FromMinutes(30));
// Unshelve the alarm.
overheating.ChangeShelving(this.SystemContext, shelved: false);'Suppress the alarm, e.g. while the machine is in maintenance.
overheating.ChangeIsSuppressed(Me.SystemContext, value:=True)
'Shelve the alarm for 30 minutes.
overheating.ChangeShelving( _
Me.SystemContext, _
shelved:=True, _
oneShot:=False, _
shelvingTime:=TimeSpan.FromMinutes(30))
'Unshelve the alarm.
overheating.ChangeShelving(Me.SystemContext, shelved:=False)Discrete alarms
Types usedOpcServerOpcNodeManagerOpcDiscreteAlarmNodeOpcOffNormalAlarmNodeOpcTripAlarmNode
There are several specializations of OpcAlarmConditionNode for specific kinds of alarms. For them, the kind of alarm itself describes its form, its cause, or its content in more detail. One subclass of such self-describing alarms are the discrete alarms. The base of a discrete alarm is the OpcDiscreteAlarmNode class. It defines an alarm state node that classifies types into alarm states. The input for the alarm can take only a certain number of possible values, for example true and false, or running, stopped, and finished. If an alarm should represent a discrete state that is considered not normal, you should use the OpcOffNormalAlarmNode class or one of its subclasses.
Building on this alarm class, the SDK provides a further specialization with the OpcTripAlarmNode class. An OpcTripAlarmNode becomes active when an abnormal fault occurs on a monitored device, for example when the motor shuts down because of overload. To create these nodes:
var x = new OpcDiscreteAlarmNode(machineOne, "discreteAlert");
var y = new OpcOffNormalAlarmNode(machineOne, "offNormalAlert");
var z = new OpcTripAlarmNode(machineOne, "tripAlert");Dim x As New OpcDiscreteAlarmNode(machineOne, "discreteAlert")
Dim y As New OpcOffNormalAlarmNode(machineOne, "offNormalAlert")
Dim z As New OpcTripAlarmNode(machineOne, "tripAlert")Limit alarms
Types usedOpcServerOpcNodeManagerOpcLimitAlarmNode
If the server should check process-specific limits and publish the result when a value exceeds or falls below them, the OpcLimitAlarmNode class is the entry point to the limit alarm classes. With it, you divide limits into up to four levels.
In the order of their metric ranking, the levels are called LowLow, Low, High, and HighHigh. By definition, not all limits have to be defined. For this reason, you can set the limits you need from the start:
var positionLimit = new OpcLimitAlarmNode(
machineOne, "PositionLimit", OpcLimitAlarmStates.HighHigh | OpcLimitAlarmStates.LowLow);
positionLimit.HighHighLimit = 120; // e.g. mm
positionLimit.LowLowLimit = 0; // e.g. mmDim positionLimit As New OpcLimitAlarmNode(
machineOne, "PositionLimit", OpcLimitAlarmStates.HighHigh Or OpcLimitAlarmStates.LowLow)
positionLimit.HighHighLimit = 120 ' e.g. mm
positionLimit.LowLowLimit = 0 ' e.g. mmExclusive limit alarms
Types usedOpcServerOpcNodeManagerOpcExclusiveLimitAlarmNode
The OpcExclusiveLimitAlarmNode class is a subclass of OpcLimitAlarmNode. As its name says, it defines limit alarms for exclusive limits. The limits of such an alarm are mutually exclusive. If one limit is exceeded or undershot, no other limit can be exceeded or undershot at the same time. The state machine in the Limit property of the node describes the violated limit. You set it with the ChangeLimitState method:
var temperatureLimit = new OpcExclusiveLevelAlarmNode(
machineOne,
"TemperatureLimit",
supportedLimits: OpcLimitAlarmStates.High | OpcLimitAlarmStates.HighHigh);
temperatureLimit.HighLimit = 80; // e.g. degree Celsius
temperatureLimit.HighHighLimit = 100; // e.g. degree Celsius
// Once the node has been added to the address space:
temperatureLimit.ChangeIsActive(this.SystemContext, value: true);
temperatureLimit.ChangeLimitState(this.SystemContext, value: OpcLimitAlarmStates.High);Dim temperatureLimit = New OpcExclusiveLevelAlarmNode( _
machineOne, _
"TemperatureLimit", _
supportedLimits:=OpcLimitAlarmStates.High Or OpcLimitAlarmStates.HighHigh)
temperatureLimit.HighLimit = 80 'e.g. degree Celsius
temperatureLimit.HighHighLimit = 100 'e.g. degree Celsius
'Once the node has been added to the address space:
temperatureLimit.ChangeIsActive(Me.SystemContext, value:=True)
temperatureLimit.ChangeLimitState(Me.SystemContext, value:=OpcLimitAlarmStates.High)OPC UA has three further specializations of OpcExclusiveLimitAlarmNode.
OpcExclusiveDeviationAlarmNode
Use this kind of alarm if the server monitors how far a value deviates from its setpoint. You specify the node of the setpoint with the SetpointNodeId property.
OpcExclusiveLevelAlarmNode
This kind of alarm usually reports that a limit is exceeded, typically on an instrument such as a temperature sensor. The alarm becomes active when the observed value is above an upper limit or below a lower limit.
OpcExclusiveRateOfChangeAlarmNode
This kind of alarm usually reports an unusual or missing change of a measured value, relative to the speed at which the value changes. The alarm becomes active when the rate of change of the value exceeds or falls below a defined limit.
Non-exclusive limit alarms
Types usedOpcServerOpcNodeManagerOpcNonExclusiveLimitAlarmNode
The OpcNonExclusiveLimitAlarmNode class is a subclass of OpcLimitAlarmNode. As its name says, it defines limit alarms for non-exclusive limits. The limits of such an alarm are not mutually exclusive. If one limit is exceeded or undershot, another limit can be exceeded or undershot at the same time. You check the violated limits with the IsLowLow, IsLow, IsHigh, and IsHighHigh properties of the node.
OPC UA has three further specializations of OpcNonExclusiveLimitAlarmNode.
OpcNonExclusiveDeviationAlarmNode
Use this kind of alarm if the server monitors how far a value deviates from its setpoint. You specify the node of the setpoint with the SetpointNodeId property.
OpcNonExclusiveLevelAlarmNode
This kind of alarm usually reports that a limit is exceeded, typically on an instrument such as a temperature sensor. The alarm becomes active when the observed value is above an upper limit or below a lower limit.
OpcNonExclusiveRateOfChangeAlarmNode
This kind of alarm usually reports an unusual or missing change of a measured value, relative to the speed at which the value changes. The alarm becomes active when the rate of change of the value exceeds or falls below a defined limit.

