Online Forums
Technical support is provided through Support Forums below. Anybody can view them; you need to Register/Login to our site (see links in upper right corner) in order to Post questions. You do not have to be a licensed user of our product.
Please read Rules for forum posts before reporting your issue or asking a question. OPC Labs team is actively monitoring the forums, and replies as soon as possible. Various technical information can also be found in our Knowledge Base. For your convenience, we have also assembled a Frequently Asked Questions page.
Do not use the Contact page for technical issues.
Alarm notifications for Siemens PLCs
1 and 2: This is very difficult to troubleshoot remotely. If I could not find the answer by other means and experiments, I would use Wireshark to analyze the communication between the client and server, and determine at which point it goes wrong and "who is to blame".
3: The client sends the filter to the server, and the server is supposed to do the filtering. Either the client (QuickOPC) does not send the filter properly, or the server is not interpreting it properly. I believe that QuickOPC is doing it right, but in order to tell with certainty, similar as in 1 & 2, we would have to analyze the communication.
4: Haven't you accidentally also removed the "selectClauses" from the filter? You still need the filter for them. What you are looking is a filter where you leave out the Where clause but keep the Select clauses. The UAEventFilterBuilder constructor should have an overload for this combination.
Best regards
Please Log in or Create an account to join the conversation.
thank you very much, it works!
Some last questions though..
1) I have more two alarms to be acknowledged, but only the first one is acknowledged by the client for some reason..
2) And after acknowledging, the client prints the first alarm twice. (the second alarm does not seem to be present in the client)
3) The first alarm has severity 600, the second sev. 100. Despite of the filter (sev. < 200), both are displayed by the client.
4) I do not want to use filter at all, but if I comment it out, I get an exception on the following line:
ValueResult ackedStateIdResult = eventData.FieldResults[ackedStateIdOperand];
My output is (with enabled filter sev. < 200):
Subscribing...
Waiting for an acknowledgeable event for 10 minutes...
[useralarms] 600! "DE: 01: My AlarmS Fault message - DE: Remark: Infotext Fault message" @2021-10-27 3:15:28 PM
AckedState/Id: False
[useralarms] 100! "DE: 02: AlarmS with process value BOOL: 1 - DE: Remark: BOOL: 1" @2021-10-27 3:15:28 PM
AckedState/Id: False
Acknowledging an event...
Waiting for 5 seconds...
[useralarms] 600! "DE: 01: My AlarmS Fault message - DE: Remark: Infotext Fault message" @2021-10-27 3:15:28 PM
AckedState/Id: True
[useralarms] 600! "DE: 01: My AlarmS Fault message - DE: Remark: Infotext Fault message" @2021-10-27 3:15:28 PM
AckedState/Id: True
Unsubscribing...
Please Log in or Create an account to join the conversation.
You can add the "/AckedState/Id" variable to your Select clauses. The acknowledged state will then be delivered with each event, and you can extract it from the FieldDictionary. The example below illustrates this approach:
// This example shows how to obtain acknowledged state of events, and acknowledge an event that is not acknowledged yet.
using System;
using System.Diagnostics;
using System.Threading;
using OpcLabs.BaseLib.OperationModel;
using OpcLabs.EasyOpc.UA;
using OpcLabs.EasyOpc.UA.AddressSpace;
using OpcLabs.EasyOpc.UA.AddressSpace.Standard;
using OpcLabs.EasyOpc.UA.AlarmsAndConditions;
using OpcLabs.EasyOpc.UA.Filtering;
using OpcLabs.EasyOpc.UA.OperationModel;
namespace UADocExamples.AlarmsAndConditions
{
partial class Acknowledge
{
public static void AckedState()
{
// Define which server we will work with.
UAEndpointDescriptor endpointDescriptor =
"opc.tcp://opcua.demo-this.com:62544/Quickstarts/AlarmConditionServer";
// Instantiate the client objects.
var client = new EasyUAClient();
IEasyUAAlarmsAndConditionsClient alarmsAndConditionsClient = client.AsAlarmsAndConditionsClient();
UANodeId nodeId = null;
byte[] eventId = null;
var anEvent = new ManualResetEvent(initialState: false);
// Prepare the Select clauses.
UAAttributeFieldCollection selectClauses = UABaseEventObject.AllFields;
UASimpleAttributeOperand ackedStateIdOperand = UAFilterElements.SimpleAttribute(UAObjectTypeIds.BaseEventType, "/AckedState/Id");
selectClauses.Add(ackedStateIdOperand);
Console.WriteLine("Subscribing...");
client.SubscribeEvent(
endpointDescriptor,
UAObjectIds.Server,
1000,
new UAEventFilterBuilder(
// We will auto-acknowledge an event with severity less than 200.
UAFilterElements.LessThan(UABaseEventObject.Operands.Severity, 200),
selectClauses),
(sender, eventArgs) =>
{
if (!eventArgs.Succeeded)
{
Console.WriteLine($"*** Failure: {eventArgs.ErrorMessageBrief}");
return;
}
UAEventData eventData = eventArgs.EventData;
if (!(eventData is null))
{
UABaseEventObject baseEventObject = eventData.BaseEvent;
Console.WriteLine(baseEventObject);
// Obtain the acknowledge state of the event.
ValueResult ackedStateIdResult = eventData.FieldResults[ackedStateIdOperand];
Debug.Assert(!(ackedStateIdResult is null));
if (!ackedStateIdResult.Succeeded)
return;
var ackedStateId = (bool)ackedStateIdResult.Value;
Console.WriteLine($"AckedState/Id: {ackedStateId}");
// Only attempt to acknowledge when not acknowledged yet.
if (ackedStateId)
return;
// Make sure we do not catch the event more than once.
if (anEvent.WaitOne(0))
return;
nodeId = baseEventObject.NodeId;
eventId = baseEventObject.EventId;
anEvent.Set();
}
},
state:null);
Console.WriteLine("Waiting for an acknowledgeable event for 10 minutes...");
if (!anEvent.WaitOne(10*60*1000))
{
Console.WriteLine("Event not received.");
return;
}
Console.WriteLine();
Console.WriteLine("Acknowledging an event...");
try
{
alarmsAndConditionsClient.Acknowledge(
endpointDescriptor,
nodeId,
eventId,
"Acknowledged by an automated example code.");
}
catch (UAException uaException)
{
Console.WriteLine($"*** Failure: {uaException.GetBaseException().Message}");
}
Console.WriteLine("Waiting for 5 seconds...");
Thread.Sleep(5 * 1000);
Console.WriteLine("Unsubscribing...");
client.UnsubscribeAllMonitoredItems();
Console.WriteLine("Waiting for 5 seconds...");
Thread.Sleep(5 * 1000);
Console.WriteLine("Finished.");
}
}
}
I hope it helps.
Best regards
Please Log in or Create an account to join the conversation.
thank you!
Now I succeeded to adapt the program AcknowledgeMain1.cs to work with SIMOTION PLCs. What I had to do was to modify the UANodeDescriptor parameter in the client.SubscribeEvent() call and to comment out the event filter parameter.
And after modifying the rest part of the program, I was able to acknowledge more than one alarm too.
Now I wanted to verify that the alarms have been successfully acknowledged indeed. But I do not know how to read out the "AckedState.Id" parameter of an alarm (I did not found this information in the documentation). Or would it be another question/topic in the forum?
Please Log in or Create an account to join the conversation.
I suggest that you have a look here:
- opclabs.doc-that.com/files/onlinedocs/QuickOpc/Latest/User%2...base%20event%20properties.html
- opclabs.doc-that.com/files/onlinedocs/QuickOpc/Latest/User%2...0of%20an%20event%20filter.html
- opclabs.doc-that.com/files/onlinedocs/QuickOpc/Latest/User%2...lds%20from%20event%20data.html
- opclabs.doc-that.com/files/onlinedocs/QuickOpc/Latest/User%2...ml#The%20Select%20clauses.html
- opclabs.doc-that.com/files/onlinedocs/QuickOpc/Latest/User%2...&C%20Notification%20Event.html
Let me know if you need further help
Best regards
Please Log in or Create an account to join the conversation.
Can you tell me which examples to use for this purpose from the "UADocExamples" project?
Please Log in or Create an account to join the conversation.
And, I assume the events you are looking for are in the output.
And, now the question comes: Is it OK that you receive *every event* generated by the notifier node (the Server object, in this case), or are you interested only in some of them?
If you are fine receiving every event (and maybe filter them on the client side - which is less efficient as doing it on the server side), you are basically done (you may want to all so-called Select clauses to specify which fields of the events you want - but they will still be the very same events).
If you only want to receive *some events*, you need to know the criteria for that, and then add the so-called Where clause.
Which of the two cases are we dealing with?
Best regards
Please Log in or Create an account to join the conversation.
thanks, so I tried to run the example "SubscribeEvent.CallbackLambda.cs" as suggested and it gave the following output, which seems to be working, as these two events came also in UaExpert:
Subscribing...
Processing event notifications for 30 seconds...
[] Success
[] Success; Refresh; RefreshInitiated
[] Success; Refresh; RefreshComplete
[] Success; (10 field results) [] 1! "CPU status message: CPU not in RUN Current CPU operating mode: STOP
PLC_1 / PLC_1
" @2021-10-01 8:16:50 AM
[] Success; (10 field results) [] 1! "CPU info: Communication initiated request: STOP
Pending startup inhibit(s):
- No startup inhibit set
CPU changes from RUN to STOP mode
PLC_1 / PLC_1
" @2021-10-01 8:16:50 AM
Unsubscribing...
Waiting for 2 seconds...
Press Enter to continue...
Please Log in or Create an account to join the conversation.
it is difficult to tell without having the serer available for testing, but it is not a good idea to start with an example that uses event filtering. You should start with a simple event subscription which receives all events from a given notifier, and check if it works. Only if it does, proceed to try to limit the number of events or their contents by adding filtering.
Such basic example looks like this:
public static void CallbackLambda()
{
UAEndpointDescriptor endpointDescriptor =
"opc.tcp://opcua.demo-this.com:62544/Quickstarts/AlarmConditionServer";
// Instantiate the client object
var client = new EasyUAClient();
Console.WriteLine("Subscribing...");
// The callback is a lambda expression the displays the event
client.SubscribeEvent(
endpointDescriptor,
UAObjectIds.Server,
1000,
(sender, eventArgs) => Console.WriteLine(eventArgs));
// Remark: Production code would check e.Exception before accessing e.EventData.
Console.WriteLine("Processing event notifications for 30 seconds...");
System.Threading.Thread.Sleep(30 * 1000);
Console.WriteLine("Unsubscribing...");
client.UnsubscribeAllMonitoredItems();
Console.WriteLine("Waiting for 2 seconds...");
System.Threading.Thread.Sleep(2 * 1000);
}
Modify it to fit your server, and report the results here. We can take it from there then.
Best regards
Please Log in or Create an account to join the conversation.
I'm very newbie in OPC UA, and currently could not find out how to use the sample client AcknowledgeMain1.cs for Siemens PLCs (SIMOTION, resp. S7-1500).
In UAExpert I can add the desired alarm&event node and observe the alarms. But the sample client does not catch them (timeout after 30 seconds).
In case of SIMOTION the node attributes are:
"ns=2;s=opcua/events.useralarms."
In case of S7-1500:
"ns=3;i=1814"
In the code I tried almost every possible combinations, but neither did work for me:
//SIMOTION:
new UANodeId(expandedText: "nsu=http://opcfoundation.org/Quickstarts/AlarmCondition ;ns=2;s=opcua/events.useralarms.")
new UANodeId(expandedText: "nsu=http://opcfoundation.org/Quickstarts/AlarmCondition ;ns=2;s=opcua/events.useralarms.1")
new UANodeId(expandedText: "ns=2;s=opcua/events.useralarms.")
new UANodeId(namespaceIndex: 2, identifier: "opcua/events.useralarms.")
new UANodeId(namespaceIndex: 2, identifier: "opcua/events.useralarms.1")
//SIMATIC S7-1500:
new UANodeId(expandedText: "nsu=http://opcfoundation.org/Quickstarts/AlarmCondition ;ns=3;i=1814")
new UANodeId(expandedText: "ns=3;i=1814")
new UANodeId(namespaceIndex: 3, identifier: 1814)
(see also screenshot)
What am I doing wrong?
Thanks!
Please Log in or Create an account to join the conversation.