11:51, EET
August 20, 2014
Hi,
we are using OPC UA Java SDK Version: 4.0.2-808. Our OPC UA Client App is connecting to S7-1500 (UA Spec 1.03) and initializing the typedictionary. After that we are reading and writing extensionobjects. All works fine. But after we change something in the structures of the S7-1500 and load it to the plc we see the follwoing messages in the prosys log. We reinitialize the typedictionary whenever the connection to S7 comes back from “communicationfalut” to “running”:
07-02-2020 21:05:55.316 [WARN] com.prosysopc.ua.typedictionary.DataTypeDictionaryComposition:43 – More than one GeneratedDataTypeDictionary contains the same dictionary TargetNamespace http://opcfoundation.org/UA/
07-02-2020 21:05:55.316 [WARN] com.prosysopc.ua.typedictionary.DataTypeDictionaryComposition:43 – More than one GeneratedDataTypeDictionary contains the same dictionary TargetNamespace http://opcfoundation.org/UA/GDS/
07-02-2020 21:06:04.301 [WARN] com.prosysopc.ua.typedictionary.TypeDictionary:627 – Could not parse the following Structure definitions from typedictionaries: [http://www.siemens.com/simatic-s7-opcua:3400, http://www.siemens.com/simatic-s7-opcua:3500%5D
I read in this forum, that it is preferred to use “DataTypeDefinition” (UA spec 1.04) instead. But my question is: Will the switch from typedictionary to DataTypeDefinition result in a change of the way we handle the extension object? Or can we use the same classes and methods like before?
13:11, EET
April 3, 2012
Hi,
I’ll describe first how it goes with the 4.2.0. I’m skipping some details here and there, but this matter is complicated one so this is … kinda long post.
0. UaClient made secure channel and session and activated it.
1. By default at this point before the connect() returns we initalize the TypeDictionary (i.e. UaClient.getTypeDictionary() instance, if you are still manually creating the TypeDictionary, you should not do that anymore but use the one from the UaClient instead).
2. TypeDictionary.init will read _all_ Enumerations and Structures (I’ll skip why we need all at once, will explain later if needed)
3. We separeate enums and structures to 2 groups, those that are codegenerated and thus “known”, and to those we do not yet thus have an internal EnumerationSpecification or StructureSpecification. Those that are known do not require any further processing. Also all abstract datatypes are skipped.
4. Next we check that can we get DataTypeDefinition (EnumDefinition or StructureDefinition) for the rest. Those are transformed to EnumerationSpecifications and StructureSpecifications (cannot do directly as they miss data, we need to Browse more data than DataTypeDefinition provides, can also explain later if needed..). We keep track if we can resolve every unknown with this way.
5. If all unknowns are resolved we stop, otherwise we are forced to read _all_ DataTypeDictionaries (I’ll have to skip details why as it would take a long post to explain why we need them all), which will basically revert to the old logic.
Therefore the TypeDictionary is still used, just the way it inits data is different, if server supports DataTypeDefinition (if not, it should return per the spec Bad_AttributeIdInvalid since it does not recognize the AttributeId). In practice you wont see DataTypeDefinition yourself (nor EnumDefinition or StructureDefinition), since the EnumerationSpecification or StructureSpecification abstract them out for you (unless you are building a generic client that displays all Attributes in which case you will probably operate on the raw DataTypeDefinions, or well since they are Structures themselves, you can use just a generic logic for _all_ Structure objects)
However, if everything goes well, you should never see an ExtensionObject, since the SDK does decode all codegen+TypeDictionary resolved Structures automatically when we decode messages. The DataValue’s Variant should then contain a DynamicStructure already, i.e. no need to manually call decode (and it probably shouldn’t be able to do it if our automatic one failed).
So you should only expect to see ExtensionObject if we could not decode the custom Structure and that should only happen if the server didn’t provide either DataTypeDefinition or DataTypeDictionaries containing it (or their data is invalid, all of this depends that the server returns exactly correct data).
All Structures can be handled “generally” just by the API of the Structure interface (see https://forum.prosysopc.com/forum/opc-ua-java-sdk/uaclient-reading-custom-structured-datatype-without-generated-code/#p4617)
However, if a server does change their Structure definitions, then it is really complicated. I would say a server should not preferably not do that at all if can be avoided. It should use a new NodeId for the Structure and it’s encoding. Or it should be known that no client is connecting to that server nor is processing any data from it that would touch the new versions of the definitions in _any way_, then you can change it.
Note that a call to TypeDictionary.init() does nothing, if you have not called TypeDictionary.clearCaches() (4.1.0 added .refresh() that does both for you https://downloads.prosysopc.com/opcua/Prosys_OPC_UA_SDK_for_Java_4_Release_Notes.html#version-4-1-0). Note that if you do that, then you should not use any Structure and/or StructureSpecification that is from before the refresh call, since they are now obsolete in their encodings and thus cannot be used (this is why the NodeId should change for the DataType and encoding node).
Those “More than one GeneratedDataTypeDictionary contains the same dictionary” you can ignore, would seem to happen if you call UaClient.connect more than once during it’s lifetime. Should probably be made differently…
The warning Could not parse the following Structure definitions from typedictionaries means TypeDictionary was unable to determine how those 2 Structures would be handled. The interesting this is that those 2 should be the Abstract “SimaticStructures” and “SimaticSystemStructures” which siemens for some reason uses to “group” their Structures. Thus it should not be a problem, but we should investigate at some point why did they appear there.
If Server supports DataTypeDefinions we can also read them dynamically from the server if we encounter a Structure which we do not know how to decode. This does obiviously not work if the encoding id is the same. In theory we could maybe re-read them if we encounter decoding errors, but that is future work (with some caveats that I’m not sure we really would want to do it automatically even if we were able to, as in theory it is possible to have 2 set of encoding rules with widely different data, but their binary form in theory could be decodeable with both rulesets and that could cause … problems).
Most Users Ever Online: 1919
Currently Online:
39 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: 735
Moderators: 7
Admins: 1
Forum Stats:
Groups: 3
Forums: 15
Topics: 1523
Posts: 6449
Newest Members:
rust, christamcdowall, redaahern07571, nigelbdhmp, travistimmons, AnnelCib, dalenegettinger, howardkennerley, Thomassnism, biancacraft16Moderators: Jouni Aro: 1026, Pyry: 1, Petri: 0, Bjarne Boström: 1026, Jimmy Ni: 26, Matti Siponen: 346, Lusetti: 0
Administrators: admin: 1