Avatar

Please consider registering
guest

sp_LogInOut Log In sp_Registration Register

Register | Lost password?
Advanced Search

— Forum Scope —




— Match —





— Forum Options —





Minimum search word length is 3 characters - maximum search word length is 84 characters

sp_Feed Topic RSS sp_TopicIcon
Creating a custom alarm instance
May 6, 2016
20:02, EEST
Avatar
Karri Kumara
Member
Members
Forum Posts: 3
Member Since:
May 1, 2016
sp_UserOfflineSmall Offline

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.

May 9, 2016
18:25, EEST
Avatar
Bjarne Boström
Moderator
Moderators
Forum Posts: 1026
Member Since:
April 3, 2012
sp_UserOfflineSmall Offline

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()

UaType exclusiveAlarmType = getServer().getNodeManagerRoot().getType(Identifiers.ExclusiveLevelAlarmType);
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

protected MyLevelAlarmType(NodeManagerUaNode nm, NodeId id, QualifiedName browseName, LocalizedText displayName) {
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

January 3, 2017
14:34, EET
Avatar
kapsl
Member
Members
Forum Posts: 57
Member Since:
December 20, 2016
sp_UserOfflineSmall Offline

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

January 3, 2017
15:34, EET
Avatar
Bjarne Boström
Moderator
Moderators
Forum Posts: 1026
Member Since:
April 3, 2012
sp_UserOfflineSmall Offline

The alarm must be triggered manually, please see the SampleConsoleServer example (MyNodeManager.simulate, .activateAlarm and .triggerEvent).

– Bjarne

January 3, 2017
16:13, EET
Avatar
kapsl
Member
Members
Forum Posts: 57
Member Since:
December 20, 2016
sp_UserOfflineSmall Offline

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)

January 3, 2017
17:06, EET
Avatar
Bjarne Boström
Moderator
Moderators
Forum Posts: 1026
Member Since:
April 3, 2012
sp_UserOfflineSmall Offline

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

January 3, 2017
17:11, EET
Avatar
Bjarne Boström
Moderator
Moderators
Forum Posts: 1026
Member Since:
April 3, 2012
sp_UserOfflineSmall Offline

This is something that you can also put into the afterCreate method which is generated for the XXXTypeNode classes

January 4, 2017
10:36, EET
Avatar
kapsl
Member
Members
Forum Posts: 57
Member Since:
December 20, 2016
sp_UserOfflineSmall Offline

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!

January 4, 2017
15:37, EET
Avatar
Bjarne Boström
Moderator
Moderators
Forum Posts: 1026
Member Since:
April 3, 2012
sp_UserOfflineSmall Offline

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

Forum Timezone: Europe/Helsinki

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, howardkennerley

Moderators: Jouni Aro: 1026, Pyry: 1, Petri: 0, Bjarne Boström: 1026, Jimmy Ni: 26, Matti Siponen: 346, Lusetti: 0

Administrators: admin: 1