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
Need example how to encode/decode custom structures/ExtensionObjects with generated code
June 7, 2018
12:26, EEST
Avatar
Thomas Reuther
Member
Members
Forum Posts: 33
Member Since:
September 18, 2017
sp_UserOfflineSmall Offline

Hi Prosys team,

I use the SDK 3.0.0-454. My goal is to write a variable on a server where the data type is a custom structure.
I have the model which was created with UA Modeler, and I generated the code from the model. I used the target “common” to get classes, interfaces, enumerations a.s.o. So far so good.

But i don’t know how to use these generated classes, especially the serializer. The serializer XYDataTypeSerializer is a public static class within the outer class Serializers. This serializer has the required methods calcEncodeable, getEncodeable and putEncodeable. How can I call these methods? There is no instance of this serializer, and I cannot created an instance because the constructor is hidden!

I also looked for examples and found the ComplexDataTypeExample1 which only contains how to create a serializer instance but not how to use it. And the serializer is what I already have. (By the way the example seems to be outdated. It overrides a method IEncodeable getEncodeable(IDecoder decoder) but the current interface is void getEncodeable(IDecoder decoder, IEncodeable encodeable)).

I also looked at the sample code. In the SampleConsoleClient I found this:

DynamicStructure ds = client.getTypeDictionary().decode((ExtensionObject) v);

So I tried to encode similarly:

uaClient.getTypeDictionary().binaryEncode(XYDataType xy);

Which fails because it expects an DynamicStructure but generator has created XYDataType which extends AbstractStructure.

I am unhappy that the client manual does not cover this topic. 🙁

How can I achieve writing custom structures?

Best regards,
Thomas Reuther

June 7, 2018
13:04, EEST
Avatar
Bjarne Boström
Moderator
Moderators
Forum Posts: 983
Member Since:
April 3, 2012
sp_UserOfflineSmall Offline

Hi,

Hmm.. it could maybe use more documentation..

Anyway, you will also need to additionally create the client side classes as well, easiest by target ‘client_all’. This will create a class ClientInformationModel, and then you will call UaClient.registerModel(ClientInformationModel.MODEL). Then you can read and write the generated structures as if they were normal Structures (i.e. you do not need to make any serializers etc. yourself, the SDK will take care of that). Registering the model is explained in the Client tutorial chapter 18, however it could maybe be explained bit better.

The reason why there are separate targets: common, client_base, client_impl, server_base, server_impl is because you might have separate modules for common, client and server code which means only that part must be generated for that module. Additionally client and server targets are split in two to allow editing the ‘impl’ part while majority of the generated code is in the ‘base’ part, therefore the edited code can be put to version control and the ‘base’ part be generated as part of the build. Note that both ‘base’ and ‘impl’ needs to be present for compiling as they extend each others (‘impl’ extends ‘base’, ‘base’ extends supertype ‘impl’; this somewhat emulates C# partial classes. There is also combination targets to avoid specifying all targets one by one if you have a simpler workflow, these are explained in the Codegenerator Manual.

P.S. as an additional note for server side developers reading this, there is an additiona target server_model, that can be used to copy the NodeSet XML, it is separated because in normally the folders for code and resources are separated (e.g. in maven projects), therefore a separate output folder might be needed.

June 8, 2018
11:14, EEST
Avatar
Thomas Reuther
Member
Members
Forum Posts: 33
Member Since:
September 18, 2017
sp_UserOfflineSmall Offline

Hi,

Thank you for your information. I tried this out. But it seems it doesn’t do what I want (or do I don’t understand?)!

The challenge in this case is that the node with the structure data type has sub-components of the same name. (Similar to BuildInfo where the variable BuildInfo (i=2260) has the data type BuildInfo (i=338) as well as components e.g. BuildDate, SoftwareVersion etc.) In my case the structure variable is writeable, but the sub-components are read-only.
The generated code of this structure variable has getters and setters for the elements of this structure. But actually they read/write the sub-nodes. But I need to write the structure at once!

Going back to my first post: Is it possible to write the structure at once using generated code, or do I have to encode an ExtensionObject on my own. If yes: how?

Best regards,
Thomas

June 8, 2018
12:14, EEST
Avatar
Bjarne Boström
Moderator
Moderators
Forum Posts: 983
Member Since:
April 3, 2012
sp_UserOfflineSmall Offline

Hi

At this point I suggest you read the tutorials and look at the SampleConsoleClient. However we are aware that this area of the SDK needs improvement.

At the end of the Client tutorial at section 18.4. there is few notes:
1. “Calling the getter for component values will internally get the node from the
AddressSpaceand get the value from it. It does not directly make a read call to the
server, unless the node is not present in the AddressSpace’s NodeCache. You need to
use read()methods in the UaClientif you need the latest values.”

2. “Calling the setter for component values sets the value to the local node, i.e. it is not
written to the server. You need to use write()methods in the UaClient to write the
value to the server.”

So technically the answer to “Is it possible to write the structure at once using generated code” is: Not possible with generated code due to the point 2. above. But you can write it via UaClient object normally. And the answer to “do I have to encode an ExtensionObject on my own.” is: No, the SDK does that for you when you read/write the Structures. Please see the following code:

NodeId id = … // This points to the node where you want to write the complete Structure value
UaClient client = …

client.registerModel(your.generated.package.ClientInformationModel.MODEL);

BuildInfo structureValue = … //Using BuildInfo as example, but after the registerModel you can use your generated Structure classes
client.writeValue(id, structureValue);
June 8, 2018
13:40, EEST
Avatar
Thomas Reuther
Member
Members
Forum Posts: 33
Member Since:
September 18, 2017
sp_UserOfflineSmall Offline

Hi,

your code example works fine!!! 🙂 🙂 🙂 That’s what I needed!
Thank you very much for your support!!!

But I don’t understand what the cache is good for!?! When I write to the cache it is *not* written to the server!?!.

Thomas

June 18, 2018
12:27, EEST
Avatar
Bjarne Boström
Moderator
Moderators
Forum Posts: 983
Member Since:
April 3, 2012
sp_UserOfflineSmall Offline

Hi,

The cache is the client side representation of the address space as graph of nodes (obtainable via AddressSpace.getCache()). It is equivalent to NodeManagerTable/NodeManagers in the server side. It is a cache, as the address space of a database-backed server could be more that can be fit into memory. In general it reduces the number of calls the client has to make to the server.

If we take the UaNode/generated interfaces at it’s “raw”est form, it works as intended, i.e. the setXXX sets things to the UaNode, getXXX gets things from the UaNode. On the server side this causes no issues. However on the client side it is a bit more complex. The way it currently works is that the setValue methods are called by the SDK internally when the node is get from the AddressSpace.getNode. Also if you have the nodes already, you could set a newer value manually.

If you have the client UaNode of a variable, it can be cast to UaVariableImpl, which has readValue; reads a new value from the server (and calls setValue internally) and writeValue; writes the value to the server (and calls setValue internally, assuming the call did not fail).

P.S. In general we have some rough ideas on improving this a lot, but they require time, experimenting and most likely API changes, and we try to avoid making big changes.

Forum Timezone: Europe/Helsinki

Most Users Ever Online: 518

Currently Online:
24 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

fred: 41

Member Stats:

Guest Posters: 0

Members: 681

Moderators: 16

Admins: 1

Forum Stats:

Groups: 3

Forums: 15

Topics: 1467

Posts: 6261

Newest Members:

graciela2073, sagarchau, elviralangwell4, Donnavek, Eddiefauth, DonaldPooma, fidelduke938316, Jan-Pfizer, DavidROunc, fen.pang@woodside.com

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