17:40, EET
September 26, 2018
Hello all,
I am using “prosys-opc-ua-java-sdk-3.1.6-542-client-server-evaluation” to find out if we can replace our existing fixed-addressing-based PLC communication driver with an OPC-UA driver. As I posted in another thread, I can now (after 2 months, due to a certificate issue) successfully communicate with my S7-1512 PLC.
In the PLC, we have a number of ControlModules of some 15 different types. Each type of CM has a status-UDT (structure) in its instance DB, containing bits which represent the status of the CM (for instance “fRunningRight”, “fStopped”, “fManual” etc.).
In my test-program, I create a subscription and add a MonitoredItem with the nodeID (ns=3;s=”CO_540_M1″.”stSTATUS”) to the subscription. Like this:
dataItem = new MonitoredDataItem(nodeID,
Attributes.DataType);
Since I use the Attributes.DataType parameter, I get this Notification, when I change one of the bits in the PLC:
DataValue = DataValue(value=ns=3;s=DT_”SINAMICS_G120C_VA_STATUS”, statusCode=GOOD (0x00000000) “”, sourceTimestamp=11/25/18 15:21:07.4881829 GMT, sourcePicoseconds=0, serverTimestamp=null, serverPicoseconds=0)
As you can see, the Notification contains the nodeID of the UDT-definition in the server. Now my question is: how can I use this, to get the values for the bits in the UDT?
Is there any sample-code which shows how to obtain different DataTypes from the server and how to use them?
10:40, EET
April 17, 2013
Hello,
Nice to know that the certificate issue has been now solved and you can continue with the development.
In the above code snippet, you are subscribing to the changes of the DataType attribute. But actually it sounds like you are more interested in the Value attribute which will contain the actual variable values. So please define the MonitoredDataItem with
After this, you should start receiving the updated structure values from the server. Without further actions, the SDK won’t be able to decode the structures so you will receive ExtensionObjects in the client application.
To work with structures, you have basically two options, either:
– obtain a UaNodeSet2 XML model and utilize the Java SDK code generator to generate corresponding Java classes including encoders and decoders or
– utilize the TypeDictionary system and dynamically fetch the structure information from the server.
The Prosys OPC UA Java SDK has been designed primarily for the code generator approach. So what this means in practice is that you should start by obtaining a UaNodeSet XML model of the structures in question and then utilizing the code generator. You can obtain the UaNodeSet model either by exporting from Siemens TIA Portal or alternatively you can use modeling tools like UaModeler to re-create the structure information.
Previously we have had some problems with the information models exported from the TIA Portal. I’m not currently sure about the level of support so you might be better off with re-modeling the structures with UaModeler.
15:26, EET
September 26, 2018
Hello Heikki,
Thank you for your rapid response. Indeed, I tried Attributes.Value too and received decoder errors instead of actual data.
At this moment (using the old fixed address based communication) we have to maintain two “models”: one is the actual UDT (structure) in the PLC and the other is the model of our application, which defines the meaning of every bit in the UDT (using byte.bit offsets). Using the UaNodeSet solution would force us to maintain a third model, merely to retrieve the data from the PLC. I think that will give us too much overhead, especially when we want to change the model(s).
Therefore, I would like to use the TypeDictionary instead. How would I go about doing that? I assume there are SDK methods to receive the DataTypes and store them in the Dictionary?
As a benefit, when I am able to read the value from the elements in the structure, I will be able to match them to the bits in our application’s model “by name” and remove the byte.bit offsets altogether…
16:15, EET
April 3, 2012
Hi,
It is a bit more complex/experimental system, codegen way is much more preferred in general if possible. Assuming you got the ExtensionObject as the value from the read calls (if it was not possible to decode an ExtensionObject to a Structure, you should get the raw ExtensionObject):
It is important that the same TypeDictionary object is used in multiple calls. On the first decode call it will read the DataTypeDictionary nodes of the server. This might take a long while (it is quite many service calls due to how it works), but the result is cached in the given TypeDictionary object. Note that this relies entirely on the server to produce correct data in the nodes.
The resulted object is a DynamicStructure instance. It has a StructureSpecification (.getSpecification()) and a List of FieldSpecification (.getFields()). You can get/set values to it by field name or the given field specification.
P.S. 3.1.8 made some improvements https://downloads.prosysopc.com/opcua/Prosys_OPC_UA_Java_SDK_Release_Notes.html#version-3-1-8.
P.S.2. Generally speaking, once an UA model is published, the Structures within should never change. Doing so will break binary compatibility with all previous versions of the model. Assuming you control all the servers and clients dealing with this model, it is not an issue.
20:36, EET
September 26, 2018
Hello Bjarne,
I am a bit ‘disappointed’ by the fact that the DataTypeDictionary functionality is, as you say, ‘experimental’. Actually I hoped the UAClient would automatically retrieve a DataType, when it discovers that it cannot decode an ExtensionObject (future enhancement?). But I do think it is the way to go, since in the end the PLC contains the DataType(s) I need.
From your post I understand that the decode function must be called more than once? How do I achieve that? As I posted above, I receive the ExtensionObject in a Notification message (one-shot). Is it not possible to do a “Read” on the nodeID (ns=3;s=”CO_540_M1″.”stSTATUS”) and immediately get the ExtensionObject? Or maybe do a read on the nodeID of the DataType (ns=3;s=DT_”SINAMICS_G120C_VA_STATUS”) instead? How will I know the decode has succeeded?
From Heikki I understand that Prosys owns a S7-1500 PLC to communicate with, so you could experiment with that. I am convinced the server will give “good” data, since the example (.NET) client provided by Siemens can successfully (and quickly…) read the DataType(s). I would appreciate it, if your code-snippet could be a bit more comprehensive than the one you posted?
Of course I am willing to try it myself too. So we can both learn
12:57, EET
April 3, 2012
Hi,
That method will try it’s best to decode the given ExtensionObject. You call it once per ExtensionObject you which to decode. On the first decode call it will read the DataTypeDictionaries of the server, and this call may take long (see the end of this post). The result of reading those will be cached.
The decoding has been successful, if you will get the DynamicStructure object out of that call, otherwise you will get DecodingException as indicated by the method signature. If the call does not return, it is still processing it (the “take long” above can be minutes, depending on e.g. latency to the server). If either happens, let us know and hopefully we can make it better.
If the server is an UA 1.04 server and supports the new “DataTypeDefinition” Attribute defined in 1.04, this entire process could be skipped, as the DataTypeDefinition is the superior way. In practice the DataTypeDictionary system can be considered deprecated in 1.04, to quote the spec 1.04 Part 5 Annex D (for the DataTypeDictionary):
“This annex defines a way to provide encoding information for custom DataTypes. In previous
releases of t he specification this approach was defined in Part 3. In Part 3 a simplified approach
is now defined having a DataTypeDefinition Attribute on the DataType Node. The approach
using DataTypeDictionaries is provided for backwards compatibility and in case some specific
requirements cannot be fulfilled with the simplified approach. It is recommended to only use the
approach using the DataTypeDefinition Attribute.”
Our SDK as of 3.x supports only UA 1.03, and therefore cannot use that approach (assuming even the server would support it). We are currently working on SDK 4.x which will then support UA 1.04. 3.0.0 was released less than a year ago, it took longer than expected, but there we decided that we need some support for decoding unknown Structures, so the result of that is the TypeDictionary class. Most likely we will enchance the system to prefer the new Attribute in 4.x where possible.
Using the DataTypeDictionary approach you cannot simply “Read DataType”. The entire process goes like:
0.0. First call to decode; TypeDictionary will init itself.
1.1. Get all targets of HasComponent References under the OPCBinarySchema_TypeSystem (i=93 in standard namespace, the node is “Types/DataTypes/OPC Binary”).
1.2. If the given target is of a known namespace and codegen has been run for it and resulted classes are registered to the SDK, skip the rest for that target.
2.1. Read each target (they are DataTypeDictionaryType’s) Value Attribute. It is a ByteString containg an UTF-8 encoded XML document that adheres to the OPC Binary Type Description System, defined in 1.04 Part 5 Annex E. Basically it is a complex and completely parallel system to the normal binary encoding rules of OPC UA, as defined in the Part 6, but the resulted data is usually the same. Our SDK makes the assumption that the data actually is always the same, i.e. it is possible to decode/encode the data as per normal Structure encoding rules that are defined in Part 6, as the SDK “links” the dictionary system (unknown parts,”Names”) and the normal system (known parts, “NodeIds”).
2.2. Resolve each XML document obtained in 2.1. separate Enumeration and Structure datas.
3.1. Enumerations. We need to link a “Dictionary” Enum and a real Enumeration. The only way to do this with the dictionaries is in practice to guess the type per the names in the AddressSpace (BrowseNames) vs the Dictionary “Names” (Dictionaries do not use NodeIds, at all).
3.2. To resolve step 3.1, we in practice has to Browse all Enumeration types in the server.
4.1. Structures. To obtain the “linking mapping”, we need to browse the “chain” DataType node of the Structure DictionaryNode defining that Structure, so that we know which Dictionary “Name” means which NodeId. This information is provided as such that we Browse the Components of the dictionary node, these have reverse reference to a “Default Binary” node, which then has reverse reference to the DataType node. This has to be done for every Structure defined in the dictionary.
5.1. Making real StructureSpecifications. Given that Structures can refer to other Structures, Enumerations and other types, we have to read ALL dictionaries (since the dictionary Structures refer the types via XML namespaces, and this info is only present in the document itself).
If the DataTypeDefinition could be used instead, it would be simply another Attribute in the DataType node, and it would contain the information about what fields that Structure has and we could basically go directly to step 5.1., as that definition uses the NodeIds. It is possible that the .NET example you mentioned does this.
P.S. Generally we are aware that this could be a lot better. We might need to do some architectural changes before we can get to a point where “normal” and “unknown” Structures would behave exactly the same.
15:54, EET
September 26, 2018
Hello Bjarne,
Thank you for your detailed reply. I will have to try later this week, if I can get some results there.
In the mean time I have checked the TIA Portal documentation, to see where Siemens stands:
The following scheme files are used for TIA Portal version V15.1 or S7-1500 CPU firmware version V2.6:
https://opcfoundation.org/UA/schemas/1.04/UANodeSet.xsd (XML scheme for NodeSet data)
https://opcfoundation.org/UA/schemas/1.04/Opc.Ua.NodeSet2.xml (OPC UA (“CORE”) Model from 2018-06-20)
https://opcfoundation.org/UA/schemas/DI/1.1/Opc.Ua.Di.NodeSet2.xml (OPC UA for Devices (“DI”) Model from 2018-06-06)
Can you deduce from this, if TIA supports the DataTypeDefinition?
16:28, EET
April 3, 2012
Hi,
At least that is the 1.04 standard model, so it is a possibility (the model by itself does not tell it). The practical way is to use latest version (1.5.0) of UaExpert (https://www.unified-automation.com/products/development-tools/uaexpert.html), navigate to the DataType node of the custom Structure (under Root/Types/DataTypes/BaseDataType/Structure/your_type), and see if the Attributes widget displays something else than BadAttributeIdInvalid for the DataTypeDefinition Attribute. If it does, then it supports it (at least for that type, but generally I would assume for every Structure).
20:43, EET
September 26, 2018
Hello Bjarne,
I downloaded the UAExpert (which looks really nice BTW ) The folder ‘Structure’ contains a subfolder ‘SinamicStructures’ in which all of the DataTypes of the S7-1500 PLC are present. The DataType DT_”SINAMICS_G120C_VA_STATUS” contains a DataTypeDefinition with (in this case) 32 fields, representing all the bits (like fRunningRight etc).
Of course I would like to use this ‘state of the art’ way of handling structures. When will the SDK support it?
10:43, EET
April 3, 2012
12:36, EET
September 26, 2018
Hello Bjarne,
Hopefully Prosys realizes what huge selling-point optimal support for Structures and Arrays would be. I cannot think of any project in which you would not use them. Especially now Siemens has released the on-board OPCUA server in its S7-1500 series PLC’s.
Do the other platform SDK’s not support the 1.04 DataTypeDefinition stuff either? Is development of the different SDK’s “linked” in some way?
Anyway, if you need someone to test an alpha version of version 4.x, please let me know. For now, I will try to walk the UAmodeler path and try to generate encoders/decoders with them. Is there any tutorial in which this is explained clearly (In particular the Java part, since the rest seems to be documented well enough…)?
12:32, EET
April 3, 2012
Hi,
We are now talking about something that in the typical scope of OPC UA is considered bleeding edge or brand new, something that has existed a fraction of the time the technology has existed. For example (I checked that) this is not something that is currently supported in our S7 device here at the office. So probably this is something that is just done in latest firmware to those devices (same with the UaExpert).
We and Unified Automation are different companies, that do “cross-resell” eachothers products.
Basically the Java SDK documentation is what is found in the ‘tutorial’ folder of the SDK package + the codegen manual in the ‘codegen’ folder and the javadocs in the ‘javadoc’ folder. The sample applications SampleConsoleClient/Server demonstrates the use of the basic features. For the UaModeler part (that is Unified’s tool) you can output the model as the NodeSet2 XML and use that in our codegen. Note however that it might be easier to just export the model from TIA portal and tweak those parts that might not work with our codegen.
And generally yes, we want to support this new feature. We just need to support 1.04 by itself first in order to do that. The fact that such large player (Siemens) is supporting this will increase the priority of us making support of the feature (but generally we are choosing from a very large pool of stuff to do/support, due to the nature of OPC UA, of course we would like to support everything right now, but that in reality is not possible).
P.S. If you go the TypeDictionary way (based on another case) you have to call setTreatOpcStringAsOpcCharArray(true) for the TypeDictionary before the first decode. 1.04 + 1.03 errata introduced a somewhat breaking change and S7 appears to use the newer definition of opc:String in the context of the dictionaries.
17:25, EET
September 26, 2018
Hello Bjarne,
Thank you for your explanation. I understand that you cannot always use the latest technology and I can just hope that you will find the time for this (IMO) great novelty.
You are right about the fact that Siemens has made major changes to the OPC UA server in their PLC’s recently. Actually, you can now also build PLC-to-PLC communication using the on-board OPC-UA client in the PLC too. I am rather excited about the effort Siemens is putting into this and I think it will prove to be an important addition to our work. In fact, I believe other PLC-manufactorers will (have to) follow…
About codegen.
I did find the PDF in the codegen folder and understand that I need an XML-file first, to use as input for codegen. Since I suspected that Siemens would have a way to retrieve this XML from TIA portal, I have contacted them. My suspicions were correct. To enable ‘manual creation of the OPC-interface’, it is possible to export the entire OPC-server configuration in nodeset2 format. I have performed this for my PLC-program (which resulted in a rather large XML-file). In this file, I find (for instance) the DataType definition I described earlier. Unfortunately, my attempt to use this XML as input for codegen results in an error (2018-12-03 16:16:03.715 INFO – Using config file: plc1.xml
2018-12-03 16:16:04.028 ERROR – Cannot parse configuration
javax.xml.bind.UnmarshalException: unexpected element (uri:”http://opcfoundation.org/UA/2011/03/UANodeSet.xsd”, local:”UANodeSet”).
Expected elements are {}codegenConfiguration ) I hope you can help me with this?
P.S.: I think the first method I want to get working is the one the SDK supports primarily. I am a bit scared, that the TypeLibrary way is too slow…
18:04, EET
April 3, 2012
Hi,
Generally I recommend trying and not speculating.
You must use a configuration file (the model file is not a configuration file) as explained in the manual. Please see the manual and the sample configuration files (for the command line version) in the commandline/configexamples.
Then you will most likely run into one of the possible problems (explained previously by Heikki) with the model, unless Siemens has fixed those. First is that the models previously at least missed SymbolicName entries for ones having BrowseNames containing characters that cannot be used in code. Codegen of the SDK 3.1.8 workarounds this to some extent. The second is that the NodeSet2 models utilizes a “NamespaceTable” concept for mapping number to a String to avoid repeating namespaceuris. This is the same logic in general of UA that the NodeIds have index that points to the NamespaceArray of the server.
The model files typically only contain uris needed by the model, however the siemens model did contain all of them, including the one which is typically “1” in the server. Codegen needs all the models the model uses/depends on in order to work at the moment. But there is no model for this “1” namespace, as it in practice only contains dynamically generated nodes (this is a bit complex to explain, please let me know if this is not enough). Therefore you will need to either, edit the file so that it makes sense if you remove the first entry in the NamespaceUris XML block so that the namespace indexies match, or alternatively use a “dummy” entry of an namespace not used by the model, but one that is valid, so that the indexies stay the same.
Additionally, please note (as explained in the manual), that the codegen will work on most 1.03 models as the SDK uses/support 1.03. Therefore if the model uses types or features that are only introduced in 1.04, it might not work. Please let us know if there are problems.
15:07, EET
September 26, 2018
OK, small steps.
The Codegen manual suggests using UAModeler to create and/or manage the information model, which can then be exported and used as input for Codegen.
Unfortunately, UAModeler seems to be capable of doing much more, so I start with a small test.
1. I have created a new project in UAModeler. I named it plc1_opcua, chose “modeling/v1_0 (modeling only)” and then selected both NodeSet2.ua and Di.NodeSet.ua as Base Models.
2. Under Types/DataTypes/BaseDataType/Structure I add a new Structured DataType. I named it SIMATIC_G120_VA_STATUS and add a child name “fRunningRight”.
3. I select plc1_opcua, right-click and select “Export XML”. Status says “Exported 10 nodes to … plc1_opcua.xml”. i copy that to the bin folder of Codegen.
4 I start Windows command prompt, browse to the bin folder of Codegen and enter Codegen.bat -cplc1_opcua.xml. Same error as above (“Unexpected element (uri:”http:// etc.)
What am I doing wrong?
10:49, EET
April 17, 2013
The -c option of the Codegen command line tool expects to receive a path to a configuration XML file as an argument.
Instead, you are supplying a path to an information model XML.
Please take a look at the example configuration files in the “configexamples” folder. To verify that the Codegen is working as expected, run the Codegen with
And validate that sampletypes folder as well as subfolders output_code and output_resources are created in the codegen\commandline folder.
After this, put your own model file (plc1_opcua.xml) to the models folder and create a corresponding config file. You can use the sampletypesconf.xml as a template for creating your own configuration file.
20:54, EET
September 26, 2018
Hello Heikki and Bjarne,
Thanks for clarifying that part. Maybe this explanation could be added to the PDF of Codegen, because I would not have found out if you had not told me?
OK, so I have to place the model I exported from TIA Portal in the models folder and create a config file, in which I map the namespaces to packages and decide which code to generate and where.
As you suggested I tried the sampletypesconf.xml first and that generated fine.
Then I copied my TIA Portal V15.1 XML into the models folder and edited it. Like you and Bjarne mantioned before: the XML still contains an invalid uri for the first namespace. I replaced it with http://opcfoundation.org/UA/, so the model now loads. However, then the generator throws an error:
java.lang.IllegalArgumentException: part ‘”SINAMICS_G120C_TELEGRAM_VA_FEEDBACK”.”ZSW_1″‘ is keyword
at com.squareup.javapoet.Util.checkArgument(SourceFile:64)
at com.squareup.javapoet.ClassName.(SourceFile:49)
Any ideas? I think it’s some kind of syntax problem…
10:21, EET
April 3, 2012
Hi,
I guess it is not that clear then, should be improved in the future..
I previously mentioned (in some of the above posts) that this is one of the problems with the models exported from TIA portal, and that the codegen within 3.1.8 does some workarounds for this (see Codegen part of https://downloads.prosysopc.com/opcua/Prosys_OPC_UA_Java_SDK_Release_Notes.html#version-3-1-8), is this the output of the 3.1.8 codegen? (I would be assuming it is the output of 3.1.6, per your initial post). Alternatively the proper fix (for TIA Portal) would be to include SymbolicName entries for each BrowseName within the model that contains names that are suitable as variable names in code. The SymbolicName is defined in the 1.04 Part 6 Annex F.
“SymbolicName … String … A symbolic name for the Node that can be used as a class/field name in
auto generated code. It should only be specified if the BrowseName cannot
be used for this purpose.
This field does not appear in the AddressSpace and is intended for use by
design tools. Only letters, digits or the underscore (‘_’) are permitted”
Most Users Ever Online: 1919
Currently Online:
52 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: 736
Moderators: 7
Admins: 1
Forum Stats:
Groups: 3
Forums: 15
Topics: 1524
Posts: 6450
Newest Members:
fannielima, kristiewinkle8, rust, christamcdowall, redaahern07571, nigelbdhmp, travistimmons, AnnelCib, dalenegettinger, howardkennerleyModerators: Jouni Aro: 1026, Pyry: 1, Petri: 0, Bjarne Boström: 1026, Jimmy Ni: 26, Matti Siponen: 346, Lusetti: 0
Administrators: admin: 1