20:02, EEST
May 1, 2016
I am testing out the alarm functionality of the Java SDK. I am using version 2.0.2-275. My goal is simple: Create an alarm for a variable, that will trigger if the variable’s value goes under a low limit or over a high limit. However, I have had some issues.
Here is the closest I’ve gotten to a working solution:
Regardless of the alarm, this is my starting point. It follows the example very closely.
final NodeId li1DataId = new NodeId(ns, “LI” + number + “001” + “Data”);
UaType doubleType = this.getServer().getNodeManagerRoot().getType(Identifiers.Double);
UaVariableNode li1data = new CacheVariable(this, li1DataId, “DataItem”,
LocalizedText.NO_LOCALE);
li1data.setDataType(doubleType);
li1data.setTypeDefinitionId(Identifiers.BaseDataVariableType);
li1data.setValue(0.5);
li1.addComponent(li1data);this.createAlarmNode(li1data, boiler, 500, 0.2, 0.3, 0.8, 0.9);
// + EventSource, the target of the EventSource is normally the
// source of the HasCondition reference
boiler.addReference(li1data, Identifiers.HasEventSource, false);// + HasNotifier, these are used to link the source of the EventSource
// up in the address space hierarchy
myObjectsFolder.addReference(li1data, Identifiers.HasNotifier, false);
public void createAlarmNode(UaVariable source, UaObjectNode myDevice, int severity, double lowLowLimit, double lowLimit, double highLimit, double highHighLimit) throws StatusException,
UaInstantiationException {// Level Alarm from the LevelMeasurement
// See the Spec. Part 9. Appendix B.2 for a similar example
int ns = this.getNamespaceIndex();
final NodeId myAlarmId = new NodeId(ns, source.getNodeId().getValue()
+ “.Alarm”);
String name = source.getBrowseName().getName() + “Alarm”;
//MyLevelAlarmType myAlarm = new MyLevelAlarmType(this, this, myAlarmId, new QualifiedName(name), new LocalizedText(name));
//MyLevelAlarmType myAlarm = createInstance(MyLevelAlarmType.class, name, myAlarmId);
ExclusiveLevelAlarmTypeNode myAlarm= createInstance(ExclusiveLevelAlarmTypeNode.class, name, myAlarmId);// ConditionSource is the node which has this condition
myAlarm.setSource(source);
// Input is the node which has the measurement that generates the alarm
myAlarm.setInput(source);myAlarm.setMessage(“Level exceeded”); // Default locale
myAlarm.setSeverity(severity); // Medium level warning
myAlarm.setHighHighLimit(highHighLimit);
myAlarm.setHighLimit(highLimit);
myAlarm.setLowLowLimit(lowLowLimit);
myAlarm.setLowLimit(lowLimit);
myAlarm.setEnabled(true);
myDevice.addComponent(myAlarm); // addReference(…Identifiers.HasComponent…)// + HasCondition, the SourceNode of the reference should normally
// correspond to the Source set above
source.addReference(myAlarm, Identifiers.HasCondition, false);}
As you can see, I have three different possibilities for creating the actual alarm node. Here, MyLevelAlarmType is exactly the same as the one in the samples.
MyLevelAlarmType myAlarm = new MyLevelAlarmType(this, this, myAlarmId, new QualifiedName(name), new LocalizedText(name));
MyLevelAlarmType myAlarm = createInstance(MyLevelAlarmType.class, name, myAlarmId);
ExclusiveLevelAlarmTypeNode myAlarm= createInstance(ExclusiveLevelAlarmTypeNode.class, name, myAlarmId);
Using MyLevelAlarmType, I run into two possible problems:
When creating as new MyLevelAlarmType(…), an error is thrown because NodeBuilder was not used.
When creating as createInstance(MyLevelAlarmType.class …), an eror is thrown because the custom class MyLevelAlarmType does not have a TypeDefinition.
Using ExclusiveLevelAlarmTypeNode, I succesfully create the alarm node with the right values but it does not trigger (ActiveState= “Inactive”, does not change) when I change the variable’s value so that it exceeds the limits. I assume this is because the Node does not have the right kind of DataChangeListener. However, I cannot create a DataChangeListener that can access the alarm’s variables and methods, except in a custom class, which I haven’t been able to get to work (see above).
So, how will I be able to make a working alarm? Should I be working on creating a non-error-throwing custom Alarm, or somehow get the ExclusiveLevelAlarmTypeNode to work? It is also entirely possible that I have missed or misunderstood something very basic, I am new to this.
18:25, EEST
April 3, 2012
Hi,
Thanks for noticing, it would seem that example is outdated for 2.x (even in current version 2.2.2…), i.e. that class (MyLevelAlarmType) is not used at all.
I don’t exaclty remember how it was in the 2.0.2. but currently the easiest workflow to create custom types is to create a NodeSet2.xml formatted file (either by hand or with UaModeler) and codegen the types.
The ExclusiveLevelAlarmTypeNode does not have any logic, you need to trigger the events similarly as in the samples (because the values could be from a source the SDK cannot monitor, but I guess we could consider automatically monitoring those that are UaNode-based, the MyAlarmType example would do just that..).
You could attach the listener to the node and trigger it manually.
You could also try to create type by hand in that version, the following should work:
Put this in MyNodeManager.createAddressSpace()
NodeId myAlarmTypeId = new NodeId(ns, "MyAlarmTypeNode");
this.addType(myAlarmTypeId, "MyAlarmTypeNode", exclusiveAlarmType);
getServer().registerClass(MyLevelAlarmType.class, myAlarmTypeId);
MyLevelAlarmType node = (MyLevelAlarmType) createInstance(myAlarmTypeId, "Test1");
myObjectsFolder.addOrganizes(node);
You also need to change the constructor signature to be
super(nm, id, browseName, displayName);
this.myNodeManager = (MyNodeManager) nm; // will work in this case
}
Note that I tested that with 2.2.2 and only as far as getting the node to be displayed in the address space.
– Bjarne
14:34, EET
December 20, 2016
Hi,
I have a very similar problem: Over the UaModeler I created an ExclusiveLevelAlarmType. Over the codegeneration I can now access it over
ExclusiveLevelAlarmType alarm = …getAxisNode().getOutOfBoundsAlarmNode()
but actually I have no clue, how to activate the alarm. It seems, like if I add the nodeIds in inputNode and sourceNode it is not tracked automatically and I don’t see, how I can add a listener.
Is it anyway better to do this alarm generation over uamodeler or create it programmatically?
lg Manu
15:34, EET
April 3, 2012
16:13, EET
December 20, 2016
Yes, i thought, that it works taht way, but when calling this I get a NullPointerException?
ExclusiveLevelAlarmTypeNode alarm = (ExclusiveLevelAlarmTypeNode) lbrAddressSpace.getAxisNode().getOutOfBoundsAlarmNode();
alarm.setActive(true);
java.lang.NullPointerException
at com.prosysopc.ua.types.opcua.server.AlarmConditionTypeNode.isActive(Unknown Source)
at com.prosysopc.ua.types.opcua.server.AlarmConditionTypeNode.setActive(Unknown Source)
at com.prosysopc.ua.types.opcua.server.AlarmConditionTypeNode.setActive(Unknown Source)
at com.kuka.basys.opcua.server.opcua.LBRNodeManager.addAlarm(LBRNodeManager.java:61)
at com.kuka.basys.opcua.server.opcua.BaSysOpcUaServer.addAlarm(BaSysOpcUaServer.java:199)
at com.kuka.basys.opcua.server.application.OpcUaThread.start(OpcUaThread.java:49)
at com.kuka.basys.opcua.server.application.RobotApplication.initialize(RobotApplication.java:44)
at com.kuka.roboticsAPI.applicationModel.RoboticsAPIApplication.runApplication(RoboticsAPIApplication.java:81)
17:06, EET
April 3, 2012
How are you creating that type? Is that type part of a bigger object, or are just instantiating it by itself. If you look at the address space via our graphical Ua Client (or UaExpert), is the ActiveState node present under that alarm node? if yes, is the value of the node named Id under that Null, if yes then it is the cause of the problem.
In case that is part of a bigger type (based on your above code I suspect this is the case), you might need to initialize it’s value. By default it might be null, and converting a null Boolean to boolean causes NPE, i.e. call alarm.getActiveStateNode().setId(false). You might want to set also these to the same node.
.setTrueState(“Active”, LocalizedText.NO_LOCALE);
.setFalseState(“Inactive”, LocalizedText.NO_LOCALE);
The SDK does define these as special cases when instantiating nodes, i.e. they are contained in a DefaultNodeBuilderConfiguration which is by default in NodeManagerUaNode. However if they are part of bigger type their NodeIds are different (i.e. they are so called InstanceDeclarations) and wont be covered by the default logic.
– Bjarne
17:11, EET
April 3, 2012
10:36, EET
December 20, 2016
Hi Bjarne,
I tried your suggestions and
alarm.getActiveStateNode().setId(false) this worked. Additionally I had to set it for alarm.getAckedStateNode().setId(false).
.setTrueState(“Active”, LocalizedText.NO_LOCALE);
This didn’t work. It sayed, that the optional nodes are not initialized. But I couldn’t find a way, to add those nodes in UaModeler, at least i didn’t find them.
Then I had the problem that triggerEvent() caused another Exception. It said, that the eventId Node could not be found.
So finally i switched back to add the alarm object by code. I don’t see an advantage in using codegeneration, when so much initialization has to be done by hand.
Thanks!
15:37, EET
April 3, 2012
Doing it by hand might be the easiest way here after all.
It should be possible to do what you want but modeling and configuring the instantiation is non-trivial. We hope to improve the SDK in this area. In practice this would need an example and better documentation regarding the instantiation logic as it is hard to remember every detail.
While it does not directly help in this case, I could mention that we are working on an improved codegenerator for future 2.3.0 version which should allow us to do improvements regarding this issue also(but probably those wont be part of 2.3.0).
– Bjarne
Most Users Ever Online: 1919
Currently Online:
15 Guest(s)
Currently Browsing this Page:
1 Guest(s)
Top Posters:
Heikki Tahvanainen: 402
hbrackel: 144
rocket science: 88
pramanj: 86
Francesco Zambon: 83
Ibrahim: 78
Sabari: 62
kapsl: 57
gjevremovic: 49
Xavier: 43
Member Stats:
Guest Posters: 0
Members: 737
Moderators: 7
Admins: 1
Forum Stats:
Groups: 3
Forums: 15
Topics: 1524
Posts: 6450
Newest Members:
fannielima, kristiewinkle8, rust, christamcdowall, redaahern07571, nigelbdhmp, travistimmons, AnnelCib, dalenegettinger, howardkennerleyModerators: Jouni Aro: 1026, Pyry: 1, Petri: 0, Bjarne Boström: 1026, Jimmy Ni: 26, Matti Siponen: 346, Lusetti: 0
Administrators: admin: 1