Use OPC UA method with complex input parameters |OPC UA Implementation: Stacks, Tools, and Samples|Forum|OPC Foundation

Avatar
Search
Forum Scope


Match



Forum Options



Minimum search word length is 3 characters - maximum search word length is 84 characters
Lost password?
sp_Feed sp_PrintTopic sp_TopicIcon
Use OPC UA method with complex input parameters
Avatar
Vinc REM
Member
Members
Forum Posts: 10
Member Since:
02/09/2023
sp_UserOfflineSmall Offline
1
02/09/2023 - 04:03
sp_Permalink sp_Print

Hi everyone,

I work on a Siemens RF188C with a RF210R (reader RFID tags). I communic by OPC UA protocol with a Python program.

The goal is to get data tag when we call the opc-ua method "ReadTag". I can watch the opc-ua server via a opc-ua browser and I can easily call the method in question by directly filling in the input data (there are 6 parameters and 5 of them are "null" or equal to 0) . I then receive the correct values written on the RFID label which I scan.

Now I make a python program to catch this data. So I manage to connect to the server. But the problem is when i call the "ReadTag" method, we must pass him 6 input parameter and two of then are complex data type.

The first one is "ScanData" type, a array of 4 differents types : "ByteString", "String", "Epc"(custom type), "Custom"(custom type). He can be located with the NodeID "ns=3;i=3020".

The second is "CodeTypeDataType" type located with the NodeID "ns=3;i=3031".

Here the python code :

---------------------------------------------------------------------------------------------------------

import sys
from opcua import Client, ua
from opcua.common.ua_utils import data_type_to_variant_type

try:
    # Connect to the OPC-UA server
    client = Client("opc.tcp://10.1.40.26:4840")
    client.connect()

    # Get the parent node and the method node
    parent = client.get_node("ns=4;i=5002")
    method = parent.get_child("3:ReadTag")

    # Get the input argument nodes
    ScanData = client.get_node("ns=3;i=3020")
    CodeTypeDataType = client.get_node("ns=3;i=3031")

    # Define the values for each input argument
    scan_data = ua.Variant(ua.get_default_value(data_type_to_variant_type(ScanData)), data_type_to_variant_type(ScanData))
    cd_data = ua.Variant(ua.get_default_value(data_type_to_variant_type(CodeTypeDataType)), data_type_to_variant_type(CodeTypeDataType))
    region = ua.Variant(ua.get_default_value(ua.VariantType.UInt16), ua.VariantType.UInt16)
    offset = ua.Variant(ua.get_default_value(ua.VariantType.UInt32), ua.VariantType.UInt32)
    length = ua.Variant(8, ua.VariantType.UInt32)
    password = ua.Variant(ua.get_default_value(ua.VariantType.ByteString), ua.VariantType.ByteString)

    # Call the method with the input argument values
    out = parent.call_method(method,
                            scan_data,
                            cd_data,
                            region,
                            offset,
                            length,
                            password)

    print( out[0] )

    # Disconnect from the OPC-UA server
    client.disconnect()
    client.close_session()

except Exception as error:

    exception_type, exception_object, exception_traceback = sys.exc_info()
    line_number = exception_traceback.tb_lineno
    print(error," , l.",line_number)

    try:
        client.disconnect()
        client.close_session()
        print("Disconnected")
    except:
        pass

----------------------------------------------------------------------------------------------------------------

When i run the python code, a error message spawn : "One or more arguments are invalid."(BadInvalidArgument) , l. 33

I think the problem is when i defined all parameters values (Particularly the ScanData and the CodeTypeDataType). 

Could you please help me to solve this problem ?

Avatar
Randy Armstrong
Admin
Forum Posts: 1564
Member Since:
05/30/2017
sp_UserOfflineSmall Offline
2
02/09/2023 - 04:50
sp_Permalink sp_Print

I am not sure what the line:

  scan_data = ua.Variant(ua.get_default_value(data_type_to_variant_type(ScanData)), data_type_to_variant_type(ScanData))

Does, however, what it should be doing is creating an ExtensionObject with the NodeId of a DataTypeEncoding Node (this is different from the DataType Node). Can you inspect the contents of scan_data and see if it looks right?

Avatar
Vinc REM
Member
Members
Forum Posts: 10
Member Since:
02/09/2023
sp_UserOfflineSmall Offline
3
02/09/2023 - 09:01
sp_Permalink sp_Print

Hi Randy,

Thank's for your answer. ScanData is compose of 4 differents parameters : ByteString ; String ; Epc ; Custom.

When I use an opc-ua browser (Prosys opcua browser), I directly enter the parameters when I want to call the method. For ScanData, you can select the "Null" option, which will automatically fill the entry with: ScanData [ByteString="null", String="null", Epc="null", Custom="null"] 

"Epc" is also a custom type : ScanDataEpc. It is available at NodeID : ns=3;i=3024.

"Custom" can be a lot of type but i thinks it's not the problem.

It's maybe the way I initialize all parameters that aren't not correct. The fact is that I just need to inform the "length" parameter and that's it, the other parameters are useless for my utilisation.

Avatar
Randy Armstrong
Admin
Forum Posts: 1564
Member Since:
05/30/2017
sp_UserOfflineSmall Offline
4
02/09/2023 - 17:37
sp_Permalink sp_Print

The structure you need to see inside the variant would look something like this JSON object:

{
  "Type": "ns=3;i=<DataTypeEncodingId>"
  "Body": {
     "ByteString": "<bytedata>",
     "String": "<stringdata>",
     "Epc": {
          <epc fields>
       },
      "Custom": ????
  }
}

Do you see anything like this?

What is the DataType of Custom? 
Avatar
Vinc REM
Member
Members
Forum Posts: 10
Member Since:
02/09/2023
sp_UserOfflineSmall Offline
5
02/10/2023 - 00:50
sp_Permalink sp_Print

I not see exactly a JSON object (maybe i not find it with the browser).

I can visualize input argument of the method (it's the subsection of "ReadTag" method, the other subsection is the output argument). They inform me of 6 parameters :

Name DataType Value
InputArguments Argument Argument[6]
     [0]   Argument   Argument
         Name   String   Identifier
         DataType   NodeID   ns=3;i=3020
         ValueRank   Int32 -1
         ArrayDimensions   UInt32  UInt32[0]
         Description   LocalizedText  
     [1]   Argument   Argument
         Name   String   CodeType
         DataType   NodeID   ns=3;i=3031
         ...(same like [0])    
     [2]   Argument   Argument
         Name   String   Region
         DataType   NodeID   i=5
         ...(same like [0])    
     [3]   Argument   Argument
         Name   String   Offset
         DataType   NodeID   i=5
         ...(same like [0])    
     [4]   Argument   Argument
         Name   String   Length
         DataType   NodeID   i=7
         ...(same like [0])    
     [5]   Argument   Argument
         Name   String   Password
         DataType   NodeID   i=15
         ...(same like [0])    

The NodeID of [0] and [1] correspond respectively at "ScanData" type and "CodeTypeDataType" type. It's the only think i can see, apparently there are not defaults values. Also, I can’t change the method because I don’t have the right to do so. On the python code i try to put a JSON type for the "ScanData" parameter and he doesn't like (error like invalid argument).

The DataType of Custom can be a lot of type, String, UInt32, Int32, ...

It's possible to put directly a JSON type on input parameters when we use the "call_method" ?

How to make a custom type variable on a python program with the type stored in the opc-ua server ?

Avatar
Randy Armstrong
Admin
Forum Posts: 1564
Member Since:
05/30/2017
sp_UserOfflineSmall Offline
6
02/10/2023 - 01:11
sp_Permalink sp_Print

What I trying to do is verify that the python code is constructing the variant properly.

This is most likely source of error.

Can you locate the DataTypeEncoding node for ns=3;i=3020 in the AddressSapce?

It is linked by a HasEncoding reference from the DataType Node.

What is the NodeId?

Avatar
Vinc REM
Member
Members
Forum Posts: 10
Member Since:
02/09/2023
sp_UserOfflineSmall Offline
7
02/10/2023 - 01:49
sp_Permalink sp_Print

When I search the NodeID : "ns=3;i=3020" I find the ScanData type.

The section DataTypeDefinition give us : DefaultEncodingId : "ns=3;i=5030"

                                                          BaseDataType : "i=12756"

                                                          StructureType : "2(Union)"

                                                          Field :

"[StructureField [Name="ByteString", Description="", DataType="i=15", ValueRank="-1", ArrayDimensions="[]", MaxStringLength="0", IsOptional="false"], StructureField [Name="String", Description="", DataType="i=12", ValueRank="-1", ArrayDimensions="[]", MaxStringLength="0", IsOptional="false"], StructureField [Name="Epc", Description="", DataType="ns=3;i=3024", ValueRank="-1", ArrayDimensions="[]", MaxStringLength="0", IsOptional="false"], StructureField [Name="Custom", Description="", DataType="i=24", ValueRank="-1", ArrayDimensions="[]", MaxStringLength="0", IsOptional="false"]]"

When i research the NodeId of the Encoding, i find a NodeClass name "DataType" (NodeId : i=304).

Avatar
Randy Armstrong
Admin
Forum Posts: 1564
Member Since:
05/30/2017
sp_UserOfflineSmall Offline
8
02/10/2023 - 02:54
sp_Permalink sp_Print

So ns=3;i=5030 needs to be in the Variant.

Can you see it?

Avatar
Vinc REM
Member
Members
Forum Posts: 10
Member Since:
02/09/2023
sp_UserOfflineSmall Offline
9
02/13/2023 - 00:22
sp_Permalink sp_Print

ns=3;i=5030 name "Default Binary", more precisely the DataTypeEncodingType of the "ScanData" type. The NodeClass type is also "Object".

When you say "needs to be in the Variant", you talk about the input parameters ?

Avatar
Randy Armstrong
Admin
Forum Posts: 1564
Member Since:
05/30/2017
sp_UserOfflineSmall Offline
10
02/13/2023 - 00:49
sp_Permalink sp_Print

When you call a method you pass an array of Variants.

Structures are stored in Variant with wrapper called an ExtensionObject.

The ExtensionObject has a field called TypeId which is the NodeId of the DataTypeEncoding Node.

So if use wireshark to look CallRequest you are sending you should see the NodeId ns=3;i=5030.

If you don't it is problem with the python APIs or how you are using the python APIs.

If you do see the NodeId ns=3;i=5030 then this possible source of the problem can be eliminated and we move on to the next possible source of error.

Avatar
Vinc REM
Member
Members
Forum Posts: 10
Member Since:
02/09/2023
sp_UserOfflineSmall Offline
11
02/13/2023 - 00:58
sp_Permalink sp_Print

I should see the NodeId "ns=3;i=5030" even if I there are bugs when I call the method on python ?

Avatar
Randy Armstrong
Admin
Forum Posts: 1564
Member Since:
05/30/2017
sp_UserOfflineSmall Offline
12
02/13/2023 - 04:39
sp_Permalink sp_Print

If you don't see it then it is a problem.

If you do then there could be other problems.

Wireshark may be best in this case. It has a plugin that decodes UA messages.

Avatar
Vinc REM
Member
Members
Forum Posts: 10
Member Since:
02/09/2023
sp_UserOfflineSmall Offline
13
02/13/2023 - 07:47
sp_Permalink sp_Print

Sorry my company not allow me to download Wireshark (security reason).

Could you give me an exemple of Python code initialize an array of 4 parameters please ? The array type can be located with the NodeId ns=3;i=3020. 

Avatar
Randy Armstrong
Admin
Forum Posts: 1564
Member Since:
05/30/2017
sp_UserOfflineSmall Offline
14
02/14/2023 - 22:59
sp_Permalink sp_Print

I can't help you with python code. You need to try the forum where you got the code from.

Avatar
Vinc REM
Member
Members
Forum Posts: 10
Member Since:
02/09/2023
sp_UserOfflineSmall Offline
15
02/15/2023 - 00:17
sp_Permalink sp_Print

Maybe you could help me with a C/C++ program ?

If we can get this thing working, I’m interested.

Avatar
Vinc REM
Member
Members
Forum Posts: 10
Member Since:
02/09/2023
sp_UserOfflineSmall Offline
16
02/15/2023 - 07:30
sp_Permalink sp_Print

I have new information. The OPC-UA server respects the characteristics of OPC 30010: AutoID Devices (https://reference.opcfoundatio.....v101/docs/)

ScanData is actually a Union type

Avatar
Randy Armstrong
Admin
Forum Posts: 1564
Member Since:
05/30/2017
sp_UserOfflineSmall Offline
17
02/15/2023 - 18:47
sp_Permalink sp_Print

Union types are serialized like Structures. They still need the encoding id on the wire.

Avatar
Vinc REM
Member
Members
Forum Posts: 10
Member Since:
02/09/2023
sp_UserOfflineSmall Offline
18
02/16/2023 - 03:08
sp_Permalink sp_Print

I have the NodeId of the encoding type. But what to do with that.

I use open62541 in my C program and I have the same problem like Python. When I call the method, I need to pass a ScanData type but I don't know how to create this with only the nodeId of the encoding or the data type.

Avatar
Randy Armstrong
Admin
Forum Posts: 1564
Member Since:
05/30/2017
sp_UserOfflineSmall Offline
19
02/16/2023 - 06:23
sp_Permalink sp_Print sp_EditHistory

You need to find the definition of the ExtensionObject type and create instance.

To create a ExtensionObject the body must be serialized as a UA Binary blob.

For Server defined types this can be a manual step.

With SDKs like the .NET Standard SDK you can register the ScanData type with the stack and the stack will do the serialization for you.

Other SDKs will use different approaches:

This example seems to show how to pack a custom datatype into and get it out of a Variant:

https://github.com/open62541/o.....m_datatype

Avatar
Junwei Jin
New Member
Members
Forum Posts: 1
Member Since:
12/19/2021
sp_UserOfflineSmall Offline
20
06/01/2023 - 01:27
sp_Permalink sp_Print

I have the same problem, does anyone know how to implement the ScanData Union type in Python?

Forum Timezone: America/Phoenix
Most Users Ever Online: 510
Currently Online:
Guest(s) 52
Currently Browsing this Page:
1 Guest(s)
Top Posters:
Forum Stats:
Groups: 2
Forums: 10
Topics: 1435
Posts: 4855