High Performance OPC UA Server SDK  1.7.1.383
Writing with IndexRange

In OPC UA it possible to read and write partial arrays by specifying and IndexRange parameter along with the usual Write parameters (NodeId, AttributeId, Value).

Background

Whereas Reading with IndexRange is mandatory in the CoreServerFacet, which is included in all UA Profiles, writing with IndexRange is an optional feature. Typically servers will only support this for in-memory data, or if the underlying system also supports writing partial arrays.

For many systems it is simply not possible to support this in a consistent way, because the UA server would need to read the whole array from the underlying systems, apply the change and write it again to the underlying system. If other parts of the array have changed in between this change would be lost.

Usage

When writing parts of arrays you need to specify the IndexRange parameter, which is a simple string describing what parts of the arrays should be changed. Such a range can be a simple index (zero-based) of the array element that should be modified, or a real range with a from and to position separated by a colon. Multiple ranges can be given as a comma separated list of ranges. Note the from must always be lower than to.

The value to write then consists of an array of values that should be written to the different locations specified by the range. This means even if you only write one value, the value to write needs to be an array of the same type as the target variable, otherwise a BadTypeMisMatch error is returned. If the server does not support writing using an IndexRange it will return the BadWriteNotSupported error.

For further details on the NumericRange datatype please consult the specification at https://reference.opcfoundation.org/v104/Core/docs/Part4/7.22/

Examples:

Range Description Required Array Length
"5" Index 5 1
"3:5" Elements from index 3 to 5. 3
"1,3:5,12" Elements at index 1, 3 to 5 and 12. 5
"5:5" Invalid range, use "5" instead.
"5:3" Invalid range. A reverse order is not supported by UA.

Example Code:

int sample_client_write_with_index_range(struct sample_client *ctx)
{
struct ua_writerequest req;
static uint8_t value = 123; /* value to write */
int ret;
if (ret != 0) return ret;
/* create nodeid to writing */
ua_nodeid_set_string(&req.nodes[0].node_id, 2, "Demo.Static.Arrays.Byte");
/* we want to write only the value attribute */
req.nodes[0].attribute_id = UA_ATTRIBUTEID_VALUE;
/* This demo byte array has 10 elements. We change only the last element with index 9 */
/* The value to write is still an array, even if it only has one element. */
ua_variant_set_byte_array(&req.nodes[0].value.value, &value, 1);
/* Send write request */
ret = ua_client_begin_write(&ctx->client, NULL, &req, my_client_write_cb, NULL);
if (ret != UA_EGOOD) {
/* if the operation fails we need to clear the memory, otherwise the SDK takes
* ownership of the memory.
*/
}
return ret;
}