13:53, EET
January 27, 2012
Hello Support Team,
In my project I need several new DataTypes for Enumerations. What is the correct way to create such type and integrate it in an event?
For instance, MyCurrentStateType with possible values “OK”,”FAILURE”,”FAULT”, “ERROR”
At the moment I tried to create a new class extending UaDataTypeNode and put in an enum implementing Enumeration. Is this the correct way?
Thanks for any help.
14:09, EET
January 27, 2012
16:11, EET
December 21, 2011
7:21, EET
January 27, 2012
Well, you’re right. I thought I found the complete solution to my problem, but all I have now is my DataType shown as subtype of Enumeration.
What have I done?
1. Created a class MyCurrentStateType extending UaDataTypeNode
2. Created a LocalizedText[] enumStrings with my 4 possible values as written in first post
3. registerReflectiveInstanceProperty(“EnumStrings”, enumStringsId, Identifiers.Enumeration_EnumStrings);
4. Create Getter and Setter for Array.
Complete class:
private boolean typeNodesCreated = false;
private LocalizedText[] enumStrings = {
new LocalizedText("OK",Locale.ENGLISH)
, new LocalizedText("FAULT",Locale.ENGLISH)
, new LocalizedText("ERROR",Locale.ENGLISH)
, new LocalizedText("FAILURE",Locale.ENGLISH)
};
public MyCurrentStateTypeNode(NodeManagerUaNode nmun, NodeId nodeid, String string, Locale locale) throws StatusException {
super(nmun, nodeid, string, locale);
initialize();
}
public MyCurrentStateTypeNode(NodeManagerUaNode nmun, NodeId nodeid, QualifiedName qn, LocalizedText lt) throws StatusException {
super(nmun, nodeid, qn, lt);
initialize();
}
private void createTypes() throws StatusException {
if(typeNodesCreated == false) {
typeNodesCreated = true;
NodeId enumStringsId = new NodeId(getNodeManager().getNamespaceIndex(), getNodeManager().getNextDataTypeNodeId());
registerReflectiveInstanceProperty("EnumStrings", enumStringsId, Identifiers.Enumeration_EnumStrings);
}
}
private void initialize() throws StatusException {
if(typeNodesCreated == false) {
createTypes();
}
}
public LocalizedText[] getEnumStrings() {
return enumStrings;
}
public void setEnumStrings(LocalizedText[] enumStrings) {
this.enumStrings = enumStrings;
}
}
Question is now, how do I use this type as field in an event?
My Event looks like this:
private final NodeId myEventTypeId;
//Event fields
private MyCurrentStateTypeNode myState;
public MyEventType(NodeManagerUaNode nmun) throws StatusException {
super(nmun);
myEventTypeId = new NodeId(getNodeManager().getNamespaceIndex(), getNodeManager().getNextTypeNodeId());
}
@Override
protected NodeId getDefaultTypeDefinition() {
return myEventTypeId;
}
@Override
protected void initEventFields() throws StatusException, SecurityException, NoSuchMethodException {
super.initEventFields();
NodeId myStateId = new NodeId(getNodeManager().getNamespaceIndex(), getNodeManager().getNextObjectNodeId());
registerReflectiveInstanceProperty("MyState", myStateId, getNodeManager().getMyCurrentStateType().getNodeId());
}
public MyCurrentStateTypeNode getMyStatus() {
return myState;
}
public void setMyStatus(MyCurrentStateTypeNode state) {
this.myState = state;
}
}
12:10, EET
December 21, 2011
It looks like your enumeration class is OK, but you must use Int32 instead of MyCurrentStateTypeNode as the property type in MyEventType. For enumeration data types the actual value of the node is Int32, but it has a special semantic meaning as described by the EnumStrings property in the type node.
9:21, EET
January 27, 2012
Otso said
It looks like your enumeration class is OK, but you must use Int32 instead of MyCurrentStateTypeNode as the property type in MyEventType. For enumeration data types the actual value of the node is Int32, but it has a special semantic meaning as described by the EnumStrings property in the type node.
Thank you Otso. Does this mean the following:
1. Create MyCurrentStateTypeNode with the EnumStrings
2. Create the type node (MyEventType) for browsing in the address space and add the node called MyState and use MyCurrentStateNode as its DataType
final NodeId stateId = new NodeId(nsIdx, getNextVariableNodeId());
CacheProperty state = new CacheProperty(this, stateId , "MyState", Locale.ENGLISH);
state.setDataType(MyCurrentStateType);
state.setValue(new DataValue(new Variant(0)));
state.setValueRank(ValueRanks.Scalar);
state.setAccessLevel(AccessLevel.READONLY);
state.setUserAccessLevel(AccessLevel.READONLY);
myEventType.addProperty(state);
3. In MyEventType I change the MyState property type to be Int32.
registerReflectiveInstanceProperty("MyState", myStateId, Identifiers.Int32);
So, from server side I will only set the Int32 value, which corresponds to the entry in MyCurrentStateTypeNode. This means, that the client has to browse the data type itself to get the array of LocalizedText and to show the correct entry/state for my Int32 value.
Is this correct?
Thanks.
10:06, EET
January 27, 2012
12:31, EET
December 21, 2011
fred said
I think I found the answer in the book OPC Unified Architecture (Mahnke, Leitner, Damm) on page 63/64.
Yes it should be fine otherwise, except that when you define the property, you should use your enumeration type, even though the value is an Int32. This gives the hint to the client how the value should be interpreted.
13:12, EET
January 27, 2012
9:51, EET
January 16, 2013
Hello.
First thanks fred for posting your solution.
I still have some problems. I want to create a custom enum type to use as argument in a method.
I created my EnumString class similar to yours:
private NodeManagerUaNode nodeManager;
private NodeId nodeId;
private String displayName;
private LocalizedText[] enumStrings = {
new LocalizedText("Run", Locale.ENGLISH),
new LocalizedText("Stop", Locale.ENGLISH)
};
public StatusTypeNode(NodeManagerUaNode arg0, NodeId arg1, String arg2,
Locale arg3) throws StatusException {
super(arg0, arg1, arg2, arg3);
this.nodeManager = arg0;
this.nodeId = arg1;
this.displayName = arg2;
init();
}
private void init() throws StatusException {
NodeId enumStringsId = new NodeId(nodeManager.getNamespaceIndex(), displayName+"_enumStrings");
registerReflectiveInstanceProperty("EnumStrings", enumStringsId, Identifiers.EnumStrings);
}
public LocalizedText[] getEnumStrings() {
return enumStrings;
}
public void setEnumStrings(LocalizedText[] enumStrings) {
this.enumStrings = enumStrings;
}
}
My question is how do i create the “StatusTypeNode” as SubType from “Enumeration”? So i can use it as setDataType(StatusType);?
I tried to create i like this:
StatusTypeNode DataTypeNode = new StatusTypeNode(nodeManager, nodeId, "StatusType", Locale.ENGLISH);
DataTypeNode.setSuperType(LocalServer.getNodeManagerRoot().getType(Identifiers.Enumeration));
But it fails with:
at com.prosysopc.ua.server.nodes.UaVariableNode.setDataTypeId(Unknown Source)
at com.prosysopc.ua.server.nodes.BaseNode.registerReflectiveProperty(Unknown Source)
at com.prosysopc.ua.server.nodes.BaseNode.registerReflectiveInstanceProperty(Unknown Source)
at de.smartfactory.ua.AggregatedServer.StatusTypeNode.init(StatusTypeNode.java:34)
Thanks.
Most Users Ever Online: 1919
Currently Online:
18 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: 738
Moderators: 7
Admins: 1
Forum Stats:
Groups: 3
Forums: 15
Topics: 1529
Posts: 6471
Newest Members:
doylenewbery, mickey21654, donnyredmond08, keesha4235, cheribruce, candacekolb4, Garmcrypto7Zof, calebhardison, susannahdingle7, inilarythikibiaModerators: Jouni Aro: 1026, Pyry: 1, Petri: 0, Bjarne Boström: 1032, Jimmy Ni: 26, Matti Siponen: 349, Lusetti: 0
Administrators: admin: 1