OPC UA client - working with extensions objects with Beckhoff Server

1,127 views
Skip to first unread message

g.m.yeh...@gmail.com

unread,
Jul 18, 2018, 3:55:01 PM7/18/18
to open62541
Hi,

I'm working with Open62541 for several weeks. First of all I want to thank you for the very proffesional work you guys do.
I've implemented server and client on windows and linux platforms with customized types. I also succeeded to present this type in UA Expert by creating automatic dictionary implemntation for every new customize data structure (contact to dictionary byte string value).
When I started to work with Beckhoff server I came up against several problems. I've managed to solve them by monitoring wireshark transportation from UA expert and implementing them by hand. I would like your advise what is the correct way.

The issues:
1. Structure data types in Beckhoff are defined as string node ID and not Numeric.
2. All the structures are Extension Objects.

I've tried to follow the same concept of defining reflection of the structures in the client configuration, but it didn't work for me.
Finally I've implemnted the below:

Example for Write:
-------------------------

template <typename T>
static UA_StatusCode setOpcUaValue(UA_NodeId nodeId, T value)
{
UA_StatusCode retval = UA_STATUSCODE_GOOD;

UA_NodeId dataTypeNodeId{};
retval = UA_Client_readDataTypeAttribute(client, nodeId, &dataTypeNodeId);

if (retval != UA_STATUSCODE_GOOD)
return retval;
// This is quite true assumption that we don't have builtin support for other namespaces
if (dataTypeNodeId.namespaceIndex == 0)
{
UA_Variant myVariant; /* Variants can hold scalar values and arrays of any type */
UA_Variant_init(&myVariant);

// Maybe need to check validation of size etc.
// This is O(1) search - need to be optimized - maybe we can predict where is it in the array
const UA_DataType* dataType = UA_findDataType(&dataTypeNodeId);

UA_Variant_setScalarCopy(&myVariant, &value, dataType);
retval = UA_Client_writeValueAttribute(client, nodeId, &myVariant);
}
else
{
UA_Variant myVariant; /* Variants can hold scalar values and arrays of any type */
UA_Variant_init(&myVariant);

UA_ExtensionObject dataValue;
dataValue.encoding = UA_EXTENSIONOBJECT_ENCODED_BYTESTRING;
dataValue.content.encoded.typeId = dataTypeNodeId;
dataValue.content.encoded.body.data = (UA_Byte*)&value;
dataValue.content.encoded.body.length = sizeof(value);

UA_Variant_setScalarCopy(&myVariant, &dataValue, &UA_TYPES[UA_TYPES_EXTENSIONOBJECT]);
retval = UA_Client_writeValueAttribute(client, nodeId, &myVariant);
}

return retval;
}

Example for read:
-------------------------

       retval = UA_Client_readValueAttribute(client, nodeId, &value);

if (retval == UA_STATUSCODE_GOOD)
{
if (UA_Variant_hasScalarType(&value, &UA_TYPES[UA_TYPES_EXTENSIONOBJECT]))
{
UA_ExtensionObject dataValue;
dataValue = *(UA_ExtensionObject *)value.data;
raw_data = *(T*)dataValue.content.encoded.body.data;
                }
         }


Same trick also for monitored item callback.


I'll be glad to get your comments. Do we have other builtin way?

Best Regards,
Yehuda
Message has been deleted

Julius Pfrommer

unread,
Jul 24, 2018, 9:24:56 AM7/24/18
to open62541
> I'll be glad to get your comments. Do we have other builtin way?

This is two-fold. First, we can generate datatype definitions for the encoding/decoding layer.
Second, the type definition needs to be stored in the information model in a hierarchy of subtypes.
We have support for both. See the /tools folder and the examples.
But we currently do not auto-generate a type dictionary in the information model.

> Structure data types in Beckhoff are defined as string node ID and not Numeric.

Is there a publicly accessible example with a string NodeId for a DataType?

g.m.yeh...@gmail.com

unread,
Jul 24, 2018, 11:05:46 AM7/24/18
to open62541
Hi Julius,

Thank you for your reply.

I'm using beckhoff as server and I want to generate code for the client based on the live server.
Unfortunately, I don't have XML or bsd file to generate from (isn't supplied by Beckhoff).
I've tried to define by myself the structured type like the example of client custom_data_type and add to the config. I manually changed the data type node ID to the correct one. binary encoding Id I've put according to position in the custom types array.
If I get it right the binary encoding ID only works if the node ID of the data type is numeric, right? (below code)

/* Write the NodeId for the binary encoded type. The NodeId is always
     * numeric, so no buffer replacement is taking place. */
    UA_NodeId typeId = src->content.decoded.type->typeId;
    if(typeId.identifierType != UA_NODEIDTYPE_NUMERIC)
        return UA_STATUSCODE_BADENCODINGERROR;


Is it correct to change the binary encoding Id to be from UA_NodeId type? 

About:
> Second, the type definition needs to be stored in the information model in a hierarchy of subtypes.

Is it correct to the client side (except of the custom data types array)?


> But we currently do not auto-generate a type dictionary in the information model.
In the Server I've made with open62541 I defined it by myself in order to write and read structures from UA expert. (I generated xml file with all the structures in order to define the DataTypeDictionaryType bytestring)


> Is there a publicly accessible example with a string NodeId for a DataType?

I attached link for beckhoff documentation about structured types.

And example from the server:


Regards,
Yehuda


בתאריך יום שלישי, 24 ביולי 2018 בשעה 16:24:56 UTC+3, מאת Julius Pfrommer:
Reply all
Reply to author
Forward
0 new messages