open62541 / open62541

Open source implementation of OPC UA (OPC Unified Architecture) aka IEC 62541 licensed under Mozilla Public License v2.0
http://open62541.org
Mozilla Public License 2.0
2.59k stars 1.24k forks source link

reading a custom datatype array returns ExtensionObject #3197

Open schroeder- opened 5 years ago

schroeder- commented 5 years ago

Description

When you trie to read an array with type of custom datatypes, you get an ExtensionObject instead of the custom data type. You can extract the array from the ExtensionObject, but its not as expected. When reading a scalar value everything works fine.

It looks like it is a problem in the client code, because I found the problem when writing client code for a server that is using the Softing Toolkit.

Background Information / Reproduction Steps

Take examples/custom_datatype/client_types_custom.c and after UA_Client_readValueAttribute add:

    if(retval == UA_STATUSCODE_GOOD) {
        if (UA_Variant_hasArrayType(&value, &PointType)) {
            Point *p = (Point *)value.data;
            printf("Point = %f, %f, %f \n", p->x, p->y, p->z);
        }
        else
            printf("Error type: %s\n", value.type->typeName);
    }

in examples/custom_datatype/server_types_custom.c replace add3PointDataType and add3DPointVariable:

static void
add3PointDataType(UA_Server *server) {
    UA_VariableTypeAttributes dattr = UA_VariableTypeAttributes_default;
    dattr.description = UA_LOCALIZEDTEXT("en-US", "3D Point");
    dattr.displayName = UA_LOCALIZEDTEXT("en-US", "3D Point");
    dattr.dataType = PointType.typeId;
    dattr.valueRank = UA_VALUERANK_ONE_DIMENSION;
    UA_UInt32 arrayDims[1] = { 2 };
    dattr.arrayDimensions = arrayDims;
    dattr.arrayDimensionsSize = 1;
    Point p[2] = { { 3.0, 4.0, 5.0 },{ 1.0, 2.0, 5.0 } };
    UA_Variant_setArray(&dattr.value, p, 2, &PointType);

    UA_Server_addVariableTypeNode(server, PointType.typeId,
                                  UA_NODEID_NUMERIC(0, UA_NS0ID_BASEDATAVARIABLETYPE),
                                  UA_NODEID_NUMERIC(0, UA_NS0ID_HASSUBTYPE),
                                  UA_QUALIFIEDNAME(1, "3D.Point"),
                                  UA_NODEID_NUMERIC(0, UA_NS0ID_BASEDATAVARIABLETYPE),
                                  dattr, NULL, NULL);

}

static void
add3DPointVariable(UA_Server *server) {

    UA_VariableAttributes vattr = UA_VariableAttributes_default;
    vattr.description = UA_LOCALIZEDTEXT("en-US", "3D Point");
    vattr.displayName = UA_LOCALIZEDTEXT("en-US", "3D Point");
    vattr.dataType = PointType.typeId;

    vattr.valueRank = UA_VALUERANK_ONE_DIMENSION;
    UA_UInt32 arrayDims[1] = { 2 };
    vattr.arrayDimensions = arrayDims;
    vattr.arrayDimensionsSize = 1;
    Point p[2] = { { 3.0, 4.0, 5.0 },{ 1.0, 2.0, 5.0 } };
    UA_Variant_setArray(&vattr.value, p, 2, &PointType);

    UA_Server_addVariableNode(server, UA_NODEID_STRING(1, "3D.Point"),
        UA_NODEID_NUMERIC(0, UA_NS0ID_OBJECTSFOLDER),
        UA_NODEID_NUMERIC(0, UA_NS0ID_ORGANIZES),
        UA_QUALIFIEDNAME(1, "3D.Point"),
        PointType.typeId, vattr, NULL, NULL);
}

Checklist

Please provide the following information:

chuongvhn commented 4 years ago

@schroeder- Did you mean the code you provided above fix the issue ? I'm facing a problem in the receiver's side while receiving custom data structure. I receive ExtensionObject with data that is zero always, checking by wireshark and UA Expert I'm sure that the data is sending properly.