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
Custom Object Types
March 19, 2026
14:23, EET
Avatar
Patrick
Member
Members
Forum Posts: 12
Member Since:
October 15, 2020
sp_UserOfflineSmall Offline

Hi,

I’m trying to define custom object types and use them to create objects but run into some problems with that. I know the standard way is to have a NodeSet.xml defining the types import that with LoadModel into the AddressSpace, the part after that is a bit fuzzy for me though.

Do I need to actually create custom classes derived from TUaObject to use those? Or how is that supposed to work?

The concrete example I’m working on right now would be the PackML Specification:

https://reference.opcfoundatio…..odesets/56

Specifically the PackMLStatusObjectType

https://reference.opcfoundatio…..s/56/22059

The other topic related to this is, how can I dynamically, at runtime, create new ObjectTypes and use them? The definition for those types stem from data a user enters as a configuration for the type that should be created. I tried using TUaType like this:

MyType := TUaType.Create(MyNodeManager);
MyType.SuperType := MyNodeManager.GetType(Id_BaseObjectType);

p := TUaVariable.Create(MyNodeManager);
p.Name := ‘Test’;
p.DataTypeId := Id_Int32;

MyType.AddComponent(p);
MyType.Name := ‘MyTestType’;
MyType.NodeId := TUaNodeId.Create(MyNodeManager.Namespace, 9999);

MyNodeManager.RegisterType(MyType.NodeId, TUaObject);

MyObj := MyNodeManager.CreateObject(‘MyTestObj’);
MyObjectsFolder.AddOrganizes(MyObj);
MyObj.TypeDefinition := MyType;

but that runs into an abstract error at runtime. I guess because TUaType has the abstract Method GetNodeClass.
So that seems to be the wrong approach. Any hints on how this could be done?

Greetings
Patrick

March 19, 2026
16:00, EET
Avatar
Jouni Aro
Moderator
Moderators
Forum Posts: 1050
Member Since:
December 21, 2011
sp_UserOfflineSmall Offline

Once you have the type loaded into the address space, you can create new instances of that type with ‘TUaNodeManager.CreateInstance’.

Take a look at ‘TUaSampleServerForm.CreateAlarmNode’ in the UaSampleServer, for an example.

You will just need the NodeId of the type for that.

Creating types dynamically at runtime is a bit more tricky, but basically, you just need to construct the nodes as you have done. Just use ‘TUaObjectType’ (in ProsysOPC.UaServer.Nodes), instead of ‘TUaType’. We haven’t tried that very much, but I believe it should work…

And again, you should be able to use ‘CreateInstance’ to create the whole structure that corresponds to the type definition.

For types, you should also define the ModellingRule for each InstanceDeclaration (Object and Variable component), to instruct how it should be created: only Mandatory nodes are created by default. For example:

MyComponent.AddReference(Id_ModellingRule_Mandatory, Id_HasModellingRule);
March 19, 2026
17:11, EET
Avatar
Patrick
Member
Members
Forum Posts: 12
Member Since:
October 15, 2020
sp_UserOfflineSmall Offline

Using the CreateInstance works if the NodeSet.xml is present. It does not create optional entries though, even when I add the NodeBuilderConfiguration as shown in the CreateAlarmNode function.

the following code:

UaServer.AddressSpace.LoadModel(‘PackMLNamespace.xml’);

PackMLNodeManager := UaServer.AddressSpace.GetNodeManager(
‘http://opcfoundation.org/UA/PackML/’)
as TUaNodeManagerUaNode;

PackMLNodeManager.NodeBuilderConfiguration :=
TUaTypeDefinitionBasedNodeBuilderConfiguration.Builder
.AddOptional(‘Parameter’)
.AddOptional(‘Product’)
.AddOptional(‘MaterialInterlocked’)
.Build;

MyStatus := PackMLNodeManager.CreateInstance(TUaNodeId.Create(PackMLNodeManager.Namespace, 4), ‘Status’);
MyObjectsFolder.AddOrganizes(MyStatus);

leads to the following object being created:
https://ibb.co/dwxK492R

It’s not adding the optional elements. Guess I misread something there?

For the dynamic type creation, just using TUaObjectType will eliminate the runtime error but it does not seem to work either. The type will not be visible in the type library of the server and creating an instance just creates an empty object.

If I do this on the other hand it does work a bit but still not completely:

MyType := MyNodeManager.GetType(Id_BaseObjectType).AddSubtype(TUaNodeId.Create(MyNodeManager.Namespace, 9999), ‘MyTestType’);

// MyType := TUaObjectType.Create(MyNodeManager);
// MyType.SuperType := MyNodeManager.GetType(id_BaseObjectType);
// MyType.NodeId := TUaNodeId.Create(MyNodeManager.Namespace, 9999);

p := TUaVariable.Create(MyNodeManager);
p.Name := ‘Test’;
p.DataTypeId := Id_Int32;
p.AddReference(Id_ModellingRule_Mandatory, Id_HasModellingRule);

MyType.AddComponent(p);
MyType.AddReference(p, Id_HasComponent);

MyType.AddProperty(‘TestProperty’);

MyObj2 := MyNodeManager.CreateInstance(MyType.NodeId, ‘MyTestObj’);
MyObjectsFolder.AddOrganizes(MyObj2);

Now the Type does show up under the type definition.
https://ibb.co/4w16DCT6

But the variable under it does not, only the property is there as you can see.

And the created instance looks like this:
https://ibb.co/4ZcFF1Rv

It is missing the property and the variable.

As loading a NodeSet.xml is basically creating types at runtime too, I figured it should be possible to simulate that without a NodeSet.xml as well.

What is already working today is to simply go with a BasicObjectType and manually add all the variables and stuff I want to build the type I need, just without a dedicated type. The problem I ran into with that is if I need an array of objects it should really be an array of a specific object type instead of an array of basic objects. Otherwise the client will have a hard time figuring out how the structure actually is supposed to be.

PS: I’m on version 7.8.0 Build 881 if that has any relevance for this topic.

Greetings
Patrick

March 19, 2026
17:58, EET
Avatar
Patrick
Member
Members
Forum Posts: 12
Member Since:
October 15, 2020
sp_UserOfflineSmall Offline

Update:
Seems like the trick to get the UaVariable added to the type definition is to use:

p := MyNodeManager.CreateVariable(‘Test’);
instead of
p := TUaVariable.Create(MyNodeManager);

March 19, 2026
18:36, EET
Avatar
Jouni Aro
Moderator
Moderators
Forum Posts: 1050
Member Since:
December 21, 2011
sp_UserOfflineSmall Offline

Good that you figured out the Variable creation. I don’t even recall what was the exact difference here, but CreateVariable is the proper way to do it…

When you create your object instances, you should not place them in the PackMLNodeManager, but your own. So always use

MyNodeManager.CreateInstance and TUaNodeId.Create(MyNodeManager, …)

for them. The PackMLNodeManager is hosting the types defined in that model and you should not extend it yourself.

Note that CreateInstance will also define a new NodeId based on the name, by default, if you omit the NodeId. But you can see which strategy works the best for you.

For the optional members, you need to define the names using the PackML Namespace. The default is the OPC UA Standard namespace, which works for those types only. And again, modify your own NodeManager. So, try this:

MyNodeManager.NodeBuilderConfiguration :=
TUaTypeDefinitionBasedNodeBuilderConfiguration.Builder
.AddOptional(TUaQualifiedName.Create(PackMLNodeManager.Namespace, ‘Parameter’))
.AddOptional(TUaQualifiedName.Create(PackMLNodeManager.Namespace, ‘Product’))
.AddOptional(TUaQualifiedName.Create(PackMLNodeManager.Namespace, ‘MaterialInterlocked’))
.Build;

March 19, 2026
18:38, EET
Avatar
Jouni Aro
Moderator
Moderators
Forum Posts: 1050
Member Since:
December 21, 2011
sp_UserOfflineSmall Offline

And for the subtypes, you need to have the HasSubtype reference in place. So, best to use the AddSubType method, which adds that, too.

Forum Timezone: Europe/Helsinki
Most Users Ever Online: 1919
Currently Online:
Guest(s) 54
Currently Browsing this Page:
1 Guest(s)
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:
fcbuycom, xyygeorgetta, srijithvijay, rudolfpigot8361, AndreiD, DonaldLoulk, beasweatman4, earthameredith5, SheilaNag, freddiehuntsman
Moderators: Jouni Aro: 1039, Pyry: 1, Petri: 1, Bjarne Boström: 1054, Jimmy Ni: 26, Matti Siponen: 359, Lusetti: 0
Administrators: admin: 1