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
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
Moderator
Moderators
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: 518

Currently Online:
23 Guest(s)

Currently Browsing this Page:
1 Guest(s)

Top Posters:

hbrackel: 135

pramanj: 86

Francesco Zambon: 81

rocket science: 77

Ibrahim: 76

Sabari: 62

kapsl: 57

gjevremovic: 49

Xavier: 43

TimK: 41

Member Stats:

Guest Posters: 0

Members: 682

Moderators: 16

Admins: 1

Forum Stats:

Groups: 3

Forums: 15

Topics: 1467

Posts: 6261

Newest Members:

karrimacvitie5, graciela2073, sagarchau, elviralangwell4, Donnavek, Eddiefauth, DonaldPooma, fidelduke938316, Jan-Pfizer, DavidROunc

Moderators: Jouni Aro: 1010, Otso Palonen: 32, Tuomas Hiltunen: 5, Pyry: 1, Petri: 0, Bjarne Boström: 983, Heikki Tahvanainen: 402, Jukka Asikainen: 1, moldzh08: 0, Jimmy Ni: 26, Teppo Uimonen: 21, Markus Johansson: 42, Niklas Nurminen: 0, Matti Siponen: 321, Lusetti: 0, Ari-Pekka Soikkeli: 5

Administrators: admin: 1