From d542e2cc9cb8b8b5859deaf0e97e73102231249b Mon Sep 17 00:00:00 2001 From: Jonas Green Date: Thu, 16 Jun 2022 14:49:19 +0200 Subject: [PATCH] fix(server): Reading a range when using ValueBackend External failed Changed to first read the complete DataValue to get timestamps and status. Then if a range is requested the requested range of the variant is copied into the DataValue. --- include/open62541/types.h | 12 ++++++++++++ src/server/ua_services_attribute.c | 8 ++++---- src/ua_types.c | 11 +++++++++++ 3 files changed, 27 insertions(+), 4 deletions(-) diff --git a/include/open62541/types.h b/include/open62541/types.h index bd0be5620..0d54d08b3 100644 --- a/include/open62541/types.h +++ b/include/open62541/types.h @@ -913,6 +913,18 @@ typedef struct { UA_Boolean hasServerPicoseconds : 1; } UA_DataValue; +/* Copy the DataValue, but use only a subset of the (multidimensional) array of + * of the variant of the source DataValue. Returns an error code if the variant + * of the DataValue is not an array or if the indicated range does not fit. + * + * @param src The source DataValue + * @param dst The target DataValue + * @param range The range of the variant of the DataValue to copy + * @return Returns UA_STATUSCODE_GOOD or an error code */ +UA_StatusCode UA_EXPORT +UA_DataValue_copyVariantRange(const UA_DataValue *src, UA_DataValue * UA_RESTRICT dst, + const UA_NumericRange range); + /** * DiagnosticInfo * ^^^^^^^^^^^^^^ diff --git a/src/server/ua_services_attribute.c b/src/server/ua_services_attribute.c index 9f996b771..2b2b2c249 100644 --- a/src/server/ua_services_attribute.c +++ b/src/server/ua_services_attribute.c @@ -216,10 +216,10 @@ readValueAttributeComplete(UA_Server *server, UA_Session *session, } /* Set the result */ if(rangeptr) - return UA_Variant_copyRange( - (const UA_Variant *)&vn->valueBackend.backend.external.value, - &v->value, *rangeptr); - retval = UA_DataValue_copy(*vn->valueBackend.backend.external.value, v); + retval = UA_DataValue_copyVariantRange( + *vn->valueBackend.backend.external.value, v, *rangeptr); + else + retval = UA_DataValue_copy(*vn->valueBackend.backend.external.value, v); break; case UA_VALUEBACKENDTYPE_NONE: /* Read the value */ diff --git a/src/ua_types.c b/src/ua_types.c index 5b281b25c..acd412032 100644 --- a/src/ua_types.c +++ b/src/ua_types.c @@ -947,6 +947,17 @@ DataValue_copy(UA_DataValue const *src, UA_DataValue *dst, return retval; } +UA_StatusCode +UA_DataValue_copyVariantRange(const UA_DataValue *src, UA_DataValue * UA_RESTRICT dst, + const UA_NumericRange range) { + memcpy(dst, src, sizeof(UA_DataValue)); + UA_Variant_init(&dst->value); + UA_StatusCode retval = UA_Variant_copyRange(&src->value, &dst->value, range); + if(retval != UA_STATUSCODE_GOOD) + DataValue_clear(dst, NULL); + return retval; +} + /* DiagnosticInfo */ static void DiagnosticInfo_clear(UA_DiagnosticInfo *p, const UA_DataType *_) {