14:17, EEST
June 27, 2012
I’m trying to create a complex type inside my custom NodeManager. My NodeManager class is based on the one from the demo. Right now I’m just trying to hard-code a single complex variable called udt1, which will have a single member that is a String called m1.
Here’s what I did in getReferences():
private static final String UDT_NAME = “udt1”;
private static final String UDT_TYPE = “t:udttype”;
private static final String UDT_M1 = “t:udttype:m1”;
@Override
protected UaReference[] getReferences(NodeId nodeId, UaNode node) {
ExpandedNodeId folder = cont.getFolder();
try {
// TODO: remove dummy UDT
// Define reference from and to our Folder for the DataItems
if (nodeId.equals(getNamespaceTable().toNodeId(folder))) {
UaReference[] folderItems = new UaReference[dataItems.size() + 2 + 1];
// Inverse reference to the ObjectsFolder
folderItems[0] = new ClxReference(new ExpandedNodeId(
Identifiers.ObjectsFolder), folder,
Identifiers.Organizes);
// Type definition reference
folderItems[1] = new ClxReference(folder,
getTypeDefinition(
getNamespaceTable().toExpandedNodeId(nodeId),
node), Identifiers.HasTypeDefinition);
folderItems[2] = new ClxReference(folder,
new ExpandedNodeId(null, getNamespaceIndex(),
UDT_NAME), Identifiers.HasComponent);
int i = 3;
// Reference to all items in the folder
for (DataItem d : dataItems.values()) {
folderItems[i] = new ClxReference(folder,
new ExpandedNodeId(null, getNamespaceIndex(),
d.getName()), Identifiers.HasComponent);
i++;
}
return folderItems;
}
} catch (ServiceResultException e) {
throw new RuntimeException(e);
}
// TODO: Remove dummy UDT
final ExpandedNodeId udtId = new ExpandedNodeId(null, getNamespaceIndex(), UDT_NAME);
final ExpandedNodeId udtTypeId = new ExpandedNodeId(null, getNamespaceIndex(), UDT_TYPE);
final ExpandedNodeId udtM1Id = new ExpandedNodeId(null, getNamespaceIndex(), UDT_M1);
final ExpandedNodeId udtM1TypeId = getNamespaceTable().toExpandedNodeId(Identifiers.String);
if(nodeId.getValue().equals(UDT_NAME))
{
return new UaReference[] {
// Inverse reference to the folder
new ClxReference(folder, udtId,
Identifiers.HasComponent),
// Type definition
new ClxReference(udtId, udtTypeId,
Identifiers.HasTypeDefinition) };
}
if(nodeId.getValue().equals(UDT_TYPE))
{
return new UaReference[] {
// Inverse reference to the variable
new ClxReference(udtId, udtTypeId,
Identifiers.HasTypeDefinition),
// Members
new ClxReference(udtTypeId, udtM1Id,
Identifiers.HasComponent) };
}
if(nodeId.getValue().equals(UDT_M1))
{
return new UaReference[] {
// Inverse reference to the udt type
new ClxReference(udtTypeId, udtM1Id,
Identifiers.HasComponent),
// Data Type
new ClxReference(udtM1Id, udtM1TypeId,
Identifiers.HasTypeDefinition) };
}
// Define references from our DataItems
DataItem dataItem = getDataItem(nodeId);
if (dataItem == null)
return null;
final ExpandedNodeId dataItemId = new ExpandedNodeId(null,
getNamespaceIndex(), dataItem.getName());
final ExpandedNodeId dataTypeId = getNamespaceTable().toExpandedNodeId(dataItem.getDataType());
return new UaReference[] {
// Inverse reference to the folder
new ClxReference(folder, dataItemId,
Identifiers.HasComponent),
// Type definition
new ClxReference(dataItemId, dataTypeId,
Identifiers.HasTypeDefinition) };
}
I also made changes to readNonValue:
// TODO: Remove hard-coded udt stuff
else if(expandedNodeId.getValue().equals(UDT_NAME))
{
final ExpandedNodeId udtTypeId = new ExpandedNodeId(null, getNamespaceIndex(), UDT_TYPE);
if (attributeId.equals(Attributes.DataType))
value = udtTypeId;
else if (attributeId.equals(Attributes.ValueRank))
value = ValueRanks.OneDimension;
else if (attributeId.equals(Attributes.ArrayDimensions))
value = null;
else if (attributeId.equals(Attributes.AccessLevel))
value = AccessLevel.getMask(AccessLevel.READONLY);
else if (attributeId.equals(Attributes.Historizing))
value = false;
else if (attributeId.equals(Attributes.EventNotifier))
value = EventNotifierClass.getMask(EventNotifierClass.NONE);
}
else if(expandedNodeId.getValue().equals(UDT_M1))
{
final ExpandedNodeId udtM1TypeId = getNamespaceTable().toExpandedNodeId(Identifiers.String);
if (attributeId.equals(Attributes.DataType))
value = udtM1TypeId;
else if (attributeId.equals(Attributes.ValueRank))
value = ValueRanks.OneDimension;
else if (attributeId.equals(Attributes.ArrayDimensions))
value = null;
else if (attributeId.equals(Attributes.AccessLevel))
value = AccessLevel.getMask(AccessLevel.READONLY);
else if (attributeId.equals(Attributes.Historizing))
value = false;
else if (attributeId.equals(Attributes.EventNotifier))
value = EventNotifierClass.getMask(EventNotifierClass.NONE);
}
And I added this to getTypeDefinition():
String name = (String)nodeId.getValue();
if(nodeId.getValue().equals(UDT_NAME))
return new ExpandedNodeId(null, getNamespaceIndex(), UDT_TYPE);
else if(nodeId.getValue().equals(UDT_M1))
return getNamespaceTable().toExpandedNodeId(Identifiers.String);
It seems like there are some things I’m missing. When I use UAExpert to browse the tree, I see udt1, but in its properties, the value and datatype properties show errors. It seems that getTypeDefinition() is being called for the udt type node “t:udttype”, and I’m not sure what it should be returning. I’m also not sure if other references are needed that I’ve left out. Can you either tell me what I’m doing wrong here, or point me to an example with a complex type in a custom NodeManager?
11:23, EEST
December 21, 2011
Hi TimK,
You’re right that we unfortunately don’t have a good example of using complex types with custom NodeManagers yet, the only example of making non-UaNode NodeManagers is MyBigNodeManager and the data there is very simple.
Using custom NodeManagers generally requires in-depth knowledge of the UA specifications and unfortunately going over and debugging your project in depth is out of scope for this forum. For the most part, the minimum necessary references are the hierarchical ones that allow UA clients to see your nodes. If you can see udt1, you’ve created the hierarchical reference to it OK. When you talk about Properties, I think you mean Attributes. (Properties are child nodes, whereas Attributes are like fields of the node itself). The errors you get for Value and DataType should give you some clue as to what is going wrong when they are read. getTypeDefinition() should return the TypeDefinition (as ExpandedNodeId) of the parameter node.
We will be making a general example of creating Complex DataTypes and using them with your own custom NodeManagers, and publishing that on the blog in the future.
BR,
– Otso
Most Users Ever Online: 1919
Currently Online:
22 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: 744
Moderators: 7
Admins: 1
Forum Stats:
Groups: 3
Forums: 15
Topics: 1529
Posts: 6471
Newest Members:
guadalupechastai, joleenbunnell, WilliamViego, edwardobeckenbau, Charlesslota, hilda21x1388, bertZok, Bernardclila, doylenewbery, mickey21654Moderators: Jouni Aro: 1026, Pyry: 1, Petri: 0, Bjarne Boström: 1032, Jimmy Ni: 26, Matti Siponen: 349, Lusetti: 0
Administrators: admin: 1