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
Working with custom structures
November 29, 2021
14:11, EET
Avatar
fio65
Member
Members
Forum Posts: 4
Member Since:
November 29, 2021
sp_UserOfflineSmall Offline

I was trying to decode some extensionObject that I receive from some OPC UA server written
in python. For some custom structures, everything worked fine. Here, I automatically received a dynamicStructure
by calling

DynamicStructure dynamicStructure = uaValueNode.getValue().getValue().asClass(DynamicStructure.class, null);

For others, I only received an extensionObject. I tried to decode it using

uaClient.getTypeDictionary().decode()

This did not work. I looked into the typeDictionary, it did not contain the StructureSpecification for the structure in question.
I know that typeDictionary might not be used anymore since 1.04, so I tried

extensionObject.decode(uaClient.getEncoderContext()) and
uaClient.getEncoderContext().decode().

I am using the version 4.5.0.

I received
Caused by: com.prosysopc.ua.stack.encoding.DecodingException: Bad_DecodingError (code=0x80070000, description=”Cannot decode null”)
at com.prosysopc.ua.stack.encoding.utils.SerializerComposition.getEncodeable(SourceFile:107)
at com.prosysopc.ua.stack.builtintypes.ExtensionObject.decode(SourceFile:500)
at com.prosysopc.ua.stack.builtintypes.ExtensionObject.decode(SourceFile:396)
at com.prosysopc.ua.stack.builtintypes.ExtensionObject.decode(SourceFile:355)

The custom structure that doesn’t work was defined as follows:
structBuffer[‘my_type’], _ = await new_struct(opcuaServer, nsIdx, “my_type”, [
new_struct_field(“a”, ua.VariantType.String),
new_struct_field(“b”, ua.VariantType.String, array=True),
new_struct_field(“c”, ua.VariantType.String, array=True)
])

The difference to the working complex type is that they don’t contain arrays.

November 30, 2021
13:26, EET
Avatar
Bjarne Boström
Moderator
Moderators
Forum Posts: 1032
Member Since:
April 3, 2012
sp_UserOfflineSmall Offline

Hi,

By python you mean this https://github.com/FreeOpcUa/python-opcua or something else?

Anyway, your version of our SDK is kinda old. Could you please try with the latest release 4.6.2, some thing are fixed after the version you have (https://downloads.prosysopc.com/opcua/Prosys_OPC_UA_SDK_for_Java_4_Release_Notes.html).

Given that this functionality completely relies on the server to send the correct data, the most logical explanation would be that either the DataTypeDefinition (if the server uses that new 1.04 Attribute) or the old DataTypeDictionaries data is incorrect. I would need to see those for the structure type in question to know better. Alternatively the encoding might have been done incorrectly, for that typically the only practical way would be to check with wireshark: https://www.prosysopc.com/blog/opc-ua-wireshark/ i.e. what the actual binary was.

Or it is possible that it could be a bug in our SDK, custom structures is one of the more complicated OPC UA features.

In OPC UA 1.04 the structure fields can be multidimensional arrays, since your code just shows array=True, I’m assuming they are onedimensional.

You could try turning logging to DEBUG on the package ‘com.prosysopc.ua.typedictionary’. However, please do the SDK update to 4.6.2 before that, as the logging as also been improved in the later releases.

Also, note that in the encoded form the TypeId within an ExtensionObject is not the DataType NodeId of the type, but the NodeId of an ‘Encodings node’ below that (they are liked with non-hierarchical reference HasEncoding type, so they are typically not visible in trees that show the address space). So if custom Structure types are created, so must the encodings nodes. Then when the old DataTypeDictionaries are in use, the “path continues” sort of from the Encodings nodes to description nodes that then do link to the actual dictionary, which is an XML document as UTF-8 as ByteString in the dictionary node and within the dictionary xml namespaces are used i.e. it gets complicated quite fast).

The TypeDictionary class of the SDK in 4.x along with StructureSpecification etc. is an abstraction (initially it was just for the dictionaries). The TypeDictionary prefers DataTypeDefinition nowadays, but if not all types were successfully resolved via them it will revert to looking also the old DataTypeDictionaries. In practice all the ways you tried to decode is the same operation, but just accessed in a different way (and also what the SDK does internally whenever ExtensionObjects are received over the wire, thus in 4.x manual decoding pretty much cannot work if the automatic didn’t, unless you explicitly disable that automatic logic).

In 4.x, you should be fine with just asking Structure.class instead of DynamicStructure.class, as the API to use both should be pretty much the same.

P.S.
Not related to this, since you only have Strings as the type, but any ‘OptionSet’ Structure subtype would be a problem for us currently (as they use EnumDefition and not StructureDefinition and SDK sort of assumes every Structure type has a StructureDefinition in the DataTypeDefinition).

December 1, 2021
12:10, EET
Avatar
fio65
Member
Members
Forum Posts: 4
Member Since:
November 29, 2021
sp_UserOfflineSmall Offline

Hi,

thanks for the detailed answer!

By python I mean https://github.com/FreeOpcUa/opcua-asyncio.

I updated the sdk to 4.6.2, but the problem is still there.
I sent a mail with the dataTypeDefinition and with what I received from wireshark.

One information that I forgot: I also tried to read the value of the complex type with UaExpert and it did work.

From debugging, I received

Could not resolve id http://…/customNamespace/:17 to StructureSpecification via DataTypeDefinition Attribute: java.lang.IllegalArgumentException: The given ValueRank must be either -1 or 1 or larger)
at com.prosysopc.ua.typedictionary.FieldSpecification$Builder.setValueRank(SourceFile:149)
at com.prosysopc.ua.typedictionary.TypeDictionary.b(SourceFile:660)
at com.prosysopc.ua.typedictionary.TypeDictionary.b(SourceFile:1460)
at com.prosysopc.ua.typedictionary.TypeDictionary.getStructureSpecification(SourceFile:426)
at com.prosysopc.ua.client.UaClient$3.get(SourceFile:6273)
at com.prosysopc.ua.stack.encoding.EncoderContext.getStructureSpecification(SourceFile:354)
at com.prosysopc.ua.stack.builtintypes.ExtensionObject.decode(SourceFile:488)
at com.prosysopc.ua.stack.builtintypes.ExtensionObject.decode(SourceFile:391)
at com.prosysopc.ua.stack.builtintypes.ExtensionObject.decode(SourceFile:350)
at com.prosysopc.ua.stack.encoding.binary.BinaryDecoder.getVariant(SourceFile:1758)
at com.prosysopc.ua.stack.encoding.binary.BinaryDecoder.getDataValue(SourceFile:694)
at com.prosysopc.ua.stack.encoding.binary.BinaryDecoder$17.s(SourceFile:276)
at com.prosysopc.ua.stack.encoding.binary.BinaryDecoder$17.c(SourceFile:272)
at com.prosysopc.ua.stack.encoding.binary.BinaryDecoder.get(SourceFile:498)
at com.prosysopc.ua.types.opcua.Serializers$ReadResponseSerializer.getEncodeable(SourceFile:11514)
at com.prosysopc.ua.StructureSerializer.getEncodeable(SourceFile:83)
at com.prosysopc.ua.stack.encoding.utils.AbstractSerializer.getEncodeable(SourceFile:155)
at com.prosysopc.ua.stack.encoding.utils.SerializerComposition.getEncodeable(SourceFile:109)
at com.prosysopc.ua.stack.encoding.binary.BinaryDecoder.getMessage(SourceFile:1306)
at com.prosysopc.ua.stack.transport.tcp.io.TcpConnection$b$1.run(SourceFile:783)
at java.base/java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1128)
at java.base/java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:628)
at java.base/java.lang.Thread.run(Thread.java:829)

December 1, 2021
12:47, EET
Avatar
fio65
Member
Members
Forum Posts: 4
Member Since:
November 29, 2021
sp_UserOfflineSmall Offline

The value rank of the array is 0. According to the specification, this means one or more dimensions, which is what we intended

December 2, 2021
9:56, EET
Avatar
Bjarne Boström
Moderator
Moderators
Forum Posts: 1032
Member Since:
April 3, 2012
sp_UserOfflineSmall Offline

(Note that I answered this without looking the mail, since it should be “solved” based on this)

Then this is really easy to answer: Structure fields are not allowed to have ValueRank of 0. See https://reference.opcfoundation.org/Core/docs/Part3/8.51/ the table 35 row ” valueRank Int32 The value rank for the field.It shall be Scalar (-1) or a fixed rank Array (>=1).” i.e. the dimensions of the field must be known.

It is basically an error in the python implementation if it allows you to do that.

While theoretically you could encode such structure, it would be impossible to decode. Structure fields are put to the binary “as-is” sequentially without any “headers”. This means the decoder would have no way to know if it is a scalar (get the value directly) or array (get first the Int32 for the array length). Multidim fields would be even more complicated as they have a sort of a custom form to decode.

You should be getting quite the same semantics by using ValueRank 1 and when it is “scalar” just put the array with single element there. Or you could do some crazy things like define an Union that has the scalar and array and use that as the field of the Structure, though I would only do this if there is semantic difference of scalar and array having the same scalar as the single element.

P.S.
UaExpert sometimes allows stuff which is incorrect. It is possible that your version of UaExpert is reading the old DataTypeDictionaries, in which I do not think there was a concept where one could accidentally model “ValueRank 0”, since the dictionary cannot even model multidimensional fields in the first place. So maybe UaExpert sort of just ignored the issue.

December 2, 2021
10:40, EET
Avatar
fio65
Member
Members
Forum Posts: 4
Member Since:
November 29, 2021
sp_UserOfflineSmall Offline

Thanks a lot for your help!

Forum Timezone: Europe/Helsinki

Most Users Ever Online: 1919

Currently Online:
14 Guest(s)

Currently Browsing this Page:
1 Guest(s)

Top Posters:

Heikki Tahvanainen: 402

hbrackel: 144

rocket science: 88

pramanj: 86

Francesco Zambon: 83

Ibrahim: 78

Sabari: 62

kapsl: 57

gjevremovic: 49

Xavier: 43

Member Stats:

Guest Posters: 0

Members: 727

Moderators: 7

Admins: 1

Forum Stats:

Groups: 3

Forums: 15

Topics: 1529

Posts: 6471

Newest Members:

ellis87832073466, zkxwilliemae, gabriellabachus, Deakin, KTP25Zof, Wojciech Kubala, efrennowell431, wilfredostuart, caitlynfajardo, jeromechubb7

Moderators: Jouni Aro: 1026, Pyry: 1, Petri: 0, Bjarne Boström: 1032, Jimmy Ni: 26, Matti Siponen: 349, Lusetti: 0

Administrators: admin: 1