Avatar
Please consider registering
guest
sp_LogInOut Log Insp_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 RSSsp_TopicIcon
Complex Types with custom NodeManager
June 28, 2012
14:17, EEST
Avatar
TimK
Member
Members
Forum Posts: 41
Member Since:
June 27, 2012
sp_UserOfflineSmall Offline

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?

July 2, 2012
11:23, EEST
Avatar
Otso Palonen
Espoo, Finland
Member
Members
Forum Posts: 32
Member Since:
December 21, 2011
sp_UserOfflineSmall Offline

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

Forum Timezone: Europe/Helsinki
Most Users Ever Online: 1919
Currently Online:
Guest(s) 52
Top Posters:
Heikki Tahvanainen: 402
hbrackel: 144
rocket science: 100
pramanj: 86
Francesco Zambon: 83
Ibrahim: 78
Sabari: 62
kapsl: 57
gjevremovic: 49
Xavier: 43
Member Stats:
Guest Posters: 0
Members: 773
Moderators: 7
Admins: 1
Forum Stats:
Groups: 3
Forums: 15
Topics: 1558
Posts: 6567
Newest Members:
aracelyhaley4, raphaelschonell, Ashmag, kathyreimann56, brittanylemos, dorthycundiff76, PromotionToold, CHHinrichs, rodricklienhop, jose_Wanderlei
Moderators: Jouni Aro: 1039, Pyry: 1, Petri: 1, Bjarne Boström: 1054, Jimmy Ni: 26, Matti Siponen: 359, Lusetti: 0
Administrators: admin: 1