Read structure array with a model

Questions regarding the use of the .NET SDK 2.0 for Server or Client development or integration into customer products ...

Moderator: uasdknet

Post Reply
Nathan
Jr. Member
Jr. Member
Posts: 2
Joined: 01 Dec 2022, 08:08

Read structure array with a model

Post by Nathan »

Hello

I wish to read an array of a custom structure using a model.
I would expect that I could do something like the following:

Code: Select all

var usersNodeId = new NodeId(OpcNodeIds.UsersPropertyId, this.NamespaceIndex());
var users = new List<UserModel>();
session.Model.Read(usersNodeId, users);
With the users model looking like this.

Code: Select all

[UaTypeDefinition(NamespaceUri = OpcNamespaces.ApplicationUri, NodeId = OpcNodeIds.UserDataType)]
public class UserModel
{
    [UaInstanceDeclaration(NamespaceUri = OpcNamespaces.ApplicationUri, BrowseName = "UserName")]
    public string Username { get; set; }
    
    [UaInstanceDeclaration(NamespaceUri = OpcNamespaces.ApplicationUri, BrowseName = "Description")]
    public string Description { get; set; }
}
This does of course not work.
So how do I accomplish what I am trying to do?

I am using the Nuget package version 3.1.1 on .NET Framework 4.6.2.

Thank you

User avatar
Support Team
Hero Member
Hero Member
Posts: 3064
Joined: 18 Mar 2011, 15:09

Re: Read structure array with a model

Post by Support Team »

Hi,

I think you are mixing here two concepts. In OPC UA, there is the address space in which the whole node hierarchy lives and there are attributes and values of those nodes. There are no structures and arrays in the address space. The Read method of the model manager, however, reads the values/attributes of several nodes into a C# class, so it works on the address space. To read an array of structured data types of one (single) node you simply use the Read method of the session.

In order for the decoder to know how to decode the value, you must create a class for the structure that implements the IEncodeable interface and register that class. There are many pitfalls you can run into, when implementing an IEncodeable class by hand. Fortunately, the UaModeler will create those DataTypes for you. Simply load the nodeset file of the server and let it generate the client code for you.
Best regards
Unified Automation Support Team

Nathan
Jr. Member
Jr. Member
Posts: 2
Joined: 01 Dec 2022, 08:08

Re: Read structure array with a model

Post by Nathan »

That helped a lot, thank you.

For anybody stumbling across this thread with the same/similar question a little more info:

A type implementing the IEncodeable interface (and therefore representing a type on the server), can be registered on the application instance after calling the start method.

Code: Select all

applicationInstance.Start();

// register a single type
applicationInstance.KnownTypeFactory.AddEncodeableType(typeof(AccUserType));

// register all IEncodeable types of the assembly
applicationInstance.KnownTypeFactory.AddEncodeableTypes(typeof(AccUserType).Assembly);
Any normal read call will then return an object of type ExtensionObject or an ExtensionObject array (in case the property on the server is an array).
This object then carries an instance the previously registered type.

Code: Select all

List<DataValue> dataValues = s.Read(new[] { new ReadValueId { NodeId = usersNodeId, AttributeId = Attributes.Value } });
ExtensionObject[] extensionObjects = (ExtensionObject[])dataValues[0].Value;
List<AccUserType> users = extensionObjects.Select(v => (AccUserType)v.Body).ToList();

@rt
Jr. Member
Jr. Member
Posts: 2
Joined: 26 Nov 2023, 06:11

Re: Read structure array with a model

Post by @rt »

I'm working with PLC server
Is there any way to generate nodeset file of the server's exposed data types?

User avatar
Support Team
Hero Member
Hero Member
Posts: 3064
Joined: 18 Mar 2011, 15:09

Re: Read structure array with a model

Post by Support Team »

Hi,

yes there is. UaExpert has plugin that (recursively) browses the complete server, and exports all the nodes being found into XML file (one file per each namespace).

With that you have "copy" of the actual type system, and can use it to program (specialize) you client implementation against this PLC server. You may re-use (import) in UaModeler and use for client-side code generation with Unified Automation Client SDKs.

In UaExpert you go: Menu -> Document -> Add... -> XML Nodeset Export View
Best regards
Unified Automation Support Team

Post Reply