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
ExtensionObject Migration to Structure in 5.3.0. Read history.
April 15, 2025
1:15, EEST
Avatar
mithun
Member
Members
Forum Posts: 9
Member Since:
September 11, 2024
sp_UserOfflineSmall Offline

Hello,

I am using the latest clientserver jar version 5.3.0-181. I used to use 5.2.8-159 before and I used to use the following classes to get history data values

HistoryReadResult[] results = client.historyRead(details, TimestampsToReturn.Source, false, valueId);
HistoryReadResult result = results[0];
ExtensionObject historyDataObject = result.getHistoryData();
EncoderContext encoderContext = client.getEncoderContext();
HistoryData historyData = historyDataObject.decode(encoderContext);
DataValue[] historyDataValues = historyData.getDataValues();

Now in 5.3.0, the HistoryReadResult.getHistoryData function now returns Structure instead of ExtensionObject and I get error on the line
historyDataObject.decode(encoderContext)

As the structure class does not have a decode function.

Can some one help me on how to get there?
Thank you!

April 15, 2025
9:41, EEST
Avatar
Bjarne Boström
Moderator
Moderators
Forum Posts: 1044
Member Since:
April 3, 2012
sp_UserOfflineSmall Offline

Hi,

In 5.3.0 you should only need to do this:

HistoryReadResult[] results = client.historyRead(details, TimestampsToReturn.Source, false, valueId);
HistoryReadResult result = results[0];
HistoryData historyData = (HistoryData)result.getHistoryData()
DataValue[] historyDataValues = historyData.getDataValues();

https://documentation.prosysopc.com/JSDK/tutorial/html/Prosys_OPC_UA_SDK_for_Java_4_To_5_Migration_Guide.html#sdk-api-changes “In most cases the type should just be directly equivalent than what obtained from ExtensionObject.decode(EncoderContext), i.e. in short this step no longer need to be performed.”

I might write a longer technical explanation below, since the benefits might not be that visible in this case, but even here it removes a step, though you still need to “magically know” it can be casted to HistoryData (basically from the OPC UA Specification).

April 15, 2025
13:21, EEST
Avatar
Bjarne Boström
Moderator
Moderators
Forum Posts: 1044
Member Since:
April 3, 2012
sp_UserOfflineSmall Offline

The longer technical explanation.

First a note that it might be useful to look at the full javadocs https://documentation.prosysopc.com/JSDK/javadoc/index.html, which is part of the web documentation added in 5.3.0 at https://documentation.prosysopc.com/JSDK/, the below uses direct links to methods in the javadoc.

Using PubSubConnectionDataType DataType as an example, in SDK versions below 5.3.0 the https://documentation.prosysopc.com/JSDK/javadoc/com/prosysopc/ua/stack/core/PubSubConnectionDataType.html#getAddress– used to return ExtensionObject. However, now it returns a https://documentation.prosysopc.com/JSDK/javadoc/com/prosysopc/ua/stack/core/NetworkAddressDataType.html. The PubSubConnectionDataType is an “AllowSubTypes Structure” type, the fields can be marked (in the information model) as allowing a subtype to be used. Normally subtypes aren’t allowed in Structure fields (or they anyway are encoded only as the defined type, not the subtype), because this would change the binary format thus breaking it. AllowSubTypes fields are encoded differently, using an ExtensionObject.

The OPC UA Specification also defines some “Extensible Parameter X” for some of the services parameters, for example here https://reference.opcfoundation.org/Core/Part4/v105/docs/5.11.3 has have “historyData Extensible Parameter HistoryData”. This concept pre-dates the AllowSubTypes fields concept. All the Extensible Parameter types used (and still use) the raw Structure type (i=22) as their DataType (in the information model). That has a special rule that it behaves similarly to modern an AllowSubTypes fields: the field is encoded as an ExtensionObject (https://reference.opcfoundation.org/Core/Part6/v105/docs/5.2.2.15 ), that retains the type information (thus decoder can decode it back). Non-Structure allowsubtypes fields are encoded as Variant (but skipped in this explanation).

The 5.3.0 changes that our Codegen tool now creates the exact type defined for a field. Thus for i=22 it creates ‘Structure’. For AllowSubTypes fields it is the fields defined type. However, this is only now possibly, since we added the ability for generated Structures to represent their non-generated subtypes. Otherwise for example if a (non-generated and then loaded) model would define a subtype of NetworkAddressDataType for PubSubConnectionDataType, it wouldn’t be “representable” as NetworkAddressDataType (since it is DynamicStructure since not generated) and the generated getter/setter would break. However, now all Structures are DynamicStructures thus NetworkAddressDataType can now represent the extra fields (you will need to use the generic processing APIs of Structure interface to access them) and the getter/setter works.

So for normal Structures it doesn’t do that much (except skipping the ExtensionObject.decode call), but for AllowSubTypes Structures the experience is improved more (since the getter/setter shows the actual type). Though, one change that didn’t make into the release was that I think we’ll probably try to add some annotation to generated setters that more clearly defines which fields are AllowSubType fields. For general processing it isn’t necessary (since that uses FieldSpecifications from the StructureSpecification i.e. Structure.specification()), but it would be a nice documentation addition.

P.S.
Who knows, maybe some-day in the OPC UA Specification the services-structures could be reworked as allowsubtypes structures, I think that should be a binary-compatible change at least for ones whose DataTypes aren’t visible in the address space. Or maybe we’ll add a way to somehow enhance the Codegen to be able to tell this information outside of the information model so that it would “magically know” that the ‘HistoryReadResult.getHistoryData()’ should always return a ‘HistoryData’ (but currently the information doesn’t exist in the core nodeset to my knowledge; it only exist for allowsubtypes structures and HistoryReadResult is not one).

Forum Timezone: Europe/Helsinki

Most Users Ever Online: 1919

Currently Online:
20 Guest(s)

Currently Browsing this Page:
1 Guest(s)

Top Posters:

Heikki Tahvanainen: 402

hbrackel: 144

rocket science: 90

pramanj: 86

Francesco Zambon: 83

Ibrahim: 78

Sabari: 62

kapsl: 57

gjevremovic: 49

Xavier: 43

Member Stats:

Guest Posters: 0

Members: 743

Moderators: 8

Admins: 1

Forum Stats:

Groups: 3

Forums: 15

Topics: 1544

Posts: 6513

Newest Members:

SamuelGed, Joseph, GregoryLet, CharlesDum, cbd gummies, Keithwearp, Williamcor, jodiexae492966, fayetozer72, anglea06o05589

Moderators: Jouni Aro: 1029, Pyry: 1, Petri: 0, Bjarne Boström: 1044, Jimmy Ni: 26, Matti Siponen: 353, Lusetti: 0, Elias: 0

Administrators: admin: 1