From 7ab2096ab11c6aaa7f6f19f34c45a5cf67ac1a3d Mon Sep 17 00:00:00 2001 From: Julius Pfrommer Date: Mon, 21 Oct 2024 00:28:51 +0200 Subject: [PATCH] feat(pubsub): Support fields with arraydimensions for the raw encoding --- src/pubsub/ua_pubsub_networkmessage.c | 18 ++++++++++++------ src/pubsub/ua_pubsub_reader.c | 25 +++++++++++++++++-------- 2 files changed, 29 insertions(+), 14 deletions(-) diff --git a/src/pubsub/ua_pubsub_networkmessage.c b/src/pubsub/ua_pubsub_networkmessage.c index ea0765db144..ea9ae3153d8 100644 --- a/src/pubsub/ua_pubsub_networkmessage.c +++ b/src/pubsub/ua_pubsub_networkmessage.c @@ -1461,12 +1461,18 @@ UA_DataSetMessage_decodeBinary(const UA_ByteString *src, size_t *offset, UA_Data /* TODO The datatype reference should be part of the internal * pubsub configuration to avoid the time-expensive lookup */ const UA_DataType *type = - UA_findDataTypeWithCustom(&dsm->fields[i].dataType, - customTypes); - dst->data.keyFrameData.rawFields.length += type->memSize; - UA_STACKARRAY(UA_Byte, value, type->memSize); - rv = UA_decodeBinaryInternal(&dst->data.keyFrameData.rawFields, - &tmpOffset, value, type, NULL); + UA_findDataTypeWithCustom(&dsm->fields[i].dataType, customTypes); + size_t arraySize = 1; + for(size_t j = 0; j < dsm->fields[i].arrayDimensionsSize; j++) + arraySize *= dsm->fields[i].arrayDimensions[j]; + dst->data.keyFrameData.rawFields.length += arraySize * type->memSize; + UA_STACKARRAY(UA_Byte, value, arraySize * type->memSize); + UA_Byte *valpos = value; + for(size_t j = 0; j < arraySize; j++) { + rv |= UA_decodeBinaryInternal(&dst->data.keyFrameData.rawFields, + &tmpOffset, valpos, type, NULL); + valpos += type->memSize; + } UA_CHECK_STATUS(rv, return rv); if(dsm->fields[i].maxStringLength != 0) { if(type->typeKind == UA_DATATYPEKIND_STRING || diff --git a/src/pubsub/ua_pubsub_reader.c b/src/pubsub/ua_pubsub_reader.c index 9eb28711a99..409f7fe9c24 100644 --- a/src/pubsub/ua_pubsub_reader.c +++ b/src/pubsub/ua_pubsub_reader.c @@ -779,16 +779,25 @@ DataSetReader_processRaw(UA_Server *server, UA_ReaderGroup *rg, size_t offset = 0; msg->data.keyFrameData.rawFields.length = 0; for(size_t i = 0; i < dsr->config.dataSetMetaData.fieldsSize; i++) { + UA_FieldMetaData *fmd = &dsr->config.dataSetMetaData.fields[i]; /* TODO The datatype reference should be part of the internal * pubsub configuration to avoid the time-expensive lookup */ const UA_DataType *type = - UA_findDataTypeWithCustom(&dsr->config.dataSetMetaData.fields[i].dataType, - server->config.customDataTypes); - msg->data.keyFrameData.rawFields.length += type->memSize; - UA_STACKARRAY(UA_Byte, value, type->memSize); - UA_StatusCode res = - UA_decodeBinaryInternal(&msg->data.keyFrameData.rawFields, - &offset, value, type, NULL); + UA_findDataTypeWithCustom(&fmd->dataType, server->config.customDataTypes); + size_t arraySize = 1; + for(size_t j = 0; j < fmd->arrayDimensionsSize; j++) + arraySize *= fmd->arrayDimensions[j]; + msg->data.keyFrameData.rawFields.length += arraySize * type->memSize; + UA_STACKARRAY(UA_Byte, value, arraySize * type->memSize); + + UA_StatusCode res = UA_STATUSCODE_GOOD; + UA_Byte *valpos = value; + for(size_t j = 0; j < arraySize; j++) { + res |= UA_decodeBinaryInternal(&msg->data.keyFrameData.rawFields, + &offset, valpos, type, NULL); + valpos += type->memSize; + } + if(dsr->config.dataSetMetaData.fields[i].maxStringLength != 0) { if(type->typeKind == UA_DATATYPEKIND_STRING || type->typeKind == UA_DATATYPEKIND_BYTESTRING) { @@ -815,7 +824,7 @@ DataSetReader_processRaw(UA_Server *server, UA_ReaderGroup *rg, tv->beforeWrite(server, &dsr->identifier, &dsr->linkedReaderGroup, &tv->targetVariable.targetNodeId, tv->targetVariableContext, tv->externalDataValue); - memcpy((*tv->externalDataValue)->value.data, value, type->memSize); + memcpy((*tv->externalDataValue)->value.data, value, arraySize * type->memSize); if(tv->afterWrite) tv->afterWrite(server, &dsr->identifier, &dsr->linkedReaderGroup, &tv->targetVariable.targetNodeId,