UA_StatusCode __UA_Client_writeAttribute(UA_Client *client, const UA_NodeId *nodeId, UA_AttributeId attributeId, const void *in, const UA_DataType *inDataType) { if(!in) return UA_STATUSCODE_BADTYPEMISMATCH; UA_WriteValue wValue; UA_WriteValue_init(&wValue); wValue.nodeId = *nodeId; wValue.attributeId = attributeId; if(attributeId == UA_ATTRIBUTEID_VALUE) wValue.value.value = *(const UA_Variant*)in; else UA_Variant_setScalar(&wValue.value.value, (void*)(uintptr_t)in, inDataType); /* hack. is never written into. */ wValue.value.hasValue = true; UA_WriteRequest wReq; UA_WriteRequest_init(&wReq); wReq.nodesToWrite = &wValue; wReq.nodesToWriteSize = 1; UA_WriteResponse wResp = UA_Client_Service_write(client, wReq); UA_StatusCode retval = wResp.responseHeader.serviceResult; UA_WriteResponse_deleteMembers(&wResp); return retval; }
}END_TEST START_TEST(WriteSingleAttributeDataType) { UA_Server *server = makeTestSequence(); UA_WriteValue wValue; UA_WriteValue_init(&wValue); wValue.nodeId = UA_NODEID_STRING(1, "the.answer"); wValue.attributeId = UA_ATTRIBUTEID_DATATYPE; wValue.value.hasValue = UA_TRUE; UA_StatusCode retval = writeValue(server, &wValue); ck_assert_int_eq(retval, UA_STATUSCODE_BADWRITENOTSUPPORTED); }END_TEST
}END_TEST START_TEST(WriteSingleAttributeNoValue) { UA_Server *server = makeTestSequence(); UA_WriteValue wValue; UA_WriteValue_init(&wValue); wValue.nodeId = UA_NODEID_STRING(1, "the.answer"); wValue.attributeId = UA_ATTRIBUTEID_USEREXECUTABLE; wValue.value.hasValue = UA_FALSE; UA_StatusCode retval = writeValue(server, &wValue); ck_assert_int_eq(retval, UA_STATUSCODE_BADTYPEMISMATCH); }END_TEST
}END_TEST START_TEST(WriteSingleAttributeUserExecutable) { UA_Server *server = makeTestSequence(); UA_WriteValue wValue; UA_WriteValue_init(&wValue); UA_Boolean testValue = UA_TRUE; UA_Variant_setScalarCopy(&wValue.value.value, &testValue, &UA_TYPES[UA_TYPES_BOOLEAN]); wValue.nodeId = UA_NODEID_STRING(1, "the.answer"); wValue.attributeId = UA_ATTRIBUTEID_USEREXECUTABLE; wValue.value.hasValue = UA_TRUE; UA_StatusCode retval = writeValue(server, &wValue); ck_assert_int_eq(retval, UA_STATUSCODE_BADNODECLASSINVALID); }END_TEST
}END_TEST START_TEST(WriteSingleAttributeHistorizing) { UA_Server *server = makeTestSequence(); UA_WriteValue wValue; UA_WriteValue_init(&wValue); UA_Boolean testValue = UA_TRUE; UA_Variant_setScalarCopy(&wValue.value.value, &testValue, &UA_TYPES[UA_TYPES_BOOLEAN]); wValue.nodeId = UA_NODEID_STRING(1, "the.answer"); wValue.attributeId = UA_ATTRIBUTEID_HISTORIZING; wValue.value.hasValue = UA_TRUE; UA_StatusCode retval = writeValue(server, &wValue); ck_assert_int_eq(retval, UA_STATUSCODE_GOOD); }END_TEST
}END_TEST START_TEST(WriteSingleAttributeMinimumSamplingInterval) { UA_Server *server = makeTestSequence(); UA_WriteValue wValue; UA_WriteValue_init(&wValue); UA_Double testValue = 0.0; UA_Variant_setScalarCopy(&wValue.value.value, &testValue, &UA_TYPES[UA_TYPES_DOUBLE]); wValue.nodeId = UA_NODEID_STRING(1, "the.answer"); wValue.attributeId = UA_ATTRIBUTEID_MINIMUMSAMPLINGINTERVAL; wValue.value.hasValue = UA_TRUE; UA_StatusCode retval = writeValue(server, &wValue); ck_assert_int_eq(retval, UA_STATUSCODE_GOOD); }END_TEST
}END_TEST START_TEST(WriteSingleAttributeUserAccessLevel) { UA_Server *server = makeTestSequence(); UA_WriteValue wValue; UA_WriteValue_init(&wValue); UA_UInt32 testValue = 0; UA_Variant_setScalarCopy(&wValue.value.value, &testValue, &UA_TYPES[UA_TYPES_UINT32]); wValue.nodeId = UA_NODEID_STRING(1, "the.answer"); wValue.attributeId = UA_ATTRIBUTEID_USERACCESSLEVEL; wValue.value.hasValue = UA_TRUE; UA_StatusCode retval = writeValue(server, &wValue); ck_assert_int_eq(retval, UA_STATUSCODE_GOOD); }END_TEST
}END_TEST START_TEST(WriteSingleAttributeEventNotifier) { UA_Server *server = makeTestSequence(); UA_WriteValue wValue; UA_WriteValue_init(&wValue); UA_Byte testValue = 0; UA_Variant_setScalarCopy(&wValue.value.value, &testValue, &UA_TYPES[UA_TYPES_BYTE]); wValue.nodeId = UA_NODEID_STRING(1, "the.answer"); wValue.attributeId = UA_ATTRIBUTEID_EVENTNOTIFIER; wValue.value.hasValue = UA_TRUE; UA_StatusCode retval = writeValue(server, &wValue); ck_assert_int_eq(retval, UA_STATUSCODE_BADNODECLASSINVALID); }END_TEST
}END_TEST START_TEST(WriteSingleAttributeInverseName) { UA_Server *server = makeTestSequence(); UA_WriteValue wValue; UA_WriteValue_init(&wValue); UA_LocalizedText testValue = UA_LOCALIZEDTEXT("en_US", "not.the.answer"); UA_Variant_setScalarCopy(&wValue.value.value, &testValue, &UA_TYPES[UA_TYPES_LOCALIZEDTEXT]); wValue.nodeId = UA_NODEID_STRING(1, "the.answer"); wValue.attributeId = UA_ATTRIBUTEID_INVERSENAME; wValue.value.hasValue = UA_TRUE; UA_StatusCode retval = writeValue(server, &wValue); ck_assert_int_eq(retval, UA_STATUSCODE_BADNODECLASSINVALID); }END_TEST
}END_TEST START_TEST(WriteSingleAttributeBrowseName) { UA_Server *server = makeTestSequence(); UA_WriteValue wValue; UA_WriteValue_init(&wValue); UA_QualifiedName testValue = UA_QUALIFIEDNAME(1, "the.answer"); UA_Variant_setScalarCopy(&wValue.value.value, &testValue, &UA_TYPES[UA_TYPES_QUALIFIEDNAME]); wValue.nodeId = UA_NODEID_STRING(1, "the.answer"); wValue.attributeId = UA_ATTRIBUTEID_BROWSENAME; wValue.value.hasValue = UA_TRUE; UA_StatusCode retval = writeValue(server, &wValue); ck_assert_int_eq(retval, UA_STATUSCODE_GOOD); }END_TEST
}END_TEST START_TEST(WriteSingleAttributeArrayDimensions) { UA_Server *server = makeTestSequence(); UA_WriteValue wValue; UA_WriteValue_init(&wValue); UA_Int32 testValue[] = {-1,-1,-1}; UA_Variant_setArrayCopy(&wValue.value.value, &testValue, 3, &UA_TYPES[UA_TYPES_INT32]); wValue.nodeId = UA_NODEID_STRING(1, "the.answer"); wValue.attributeId = UA_ATTRIBUTEID_ARRAYDIMENSIONS; wValue.value.hasValue = UA_TRUE; UA_StatusCode retval = writeValue(server, &wValue); // Returns attributeInvalid, since variant/value may be writable ck_assert_int_eq(retval, UA_STATUSCODE_BADATTRIBUTEIDINVALID); }END_TEST
}END_TEST START_TEST(WriteSingleAttributeValueRank) { UA_Server *server = makeTestSequence(); UA_WriteValue wValue; UA_WriteValue_init(&wValue); UA_Int32 testValue = -1; UA_Variant_setScalarCopy(&wValue.value.value, &testValue, &UA_TYPES[UA_TYPES_INT32]); wValue.nodeId = UA_NODEID_STRING(1, "the.answer"); wValue.attributeId = UA_ATTRIBUTEID_VALUERANK; wValue.value.hasValue = UA_TRUE; UA_StatusCode retval = writeValue(server, &wValue); // Returns attributeInvalid, since variant/value may be writable ck_assert_int_eq(retval, UA_STATUSCODE_BADATTRIBUTEIDINVALID); }END_TEST
}END_TEST START_TEST(WriteSingleAttributeDescription) { UA_Server *server = makeTestSequence(); UA_WriteValue wValue; UA_WriteValue_init(&wValue); UA_LocalizedText testValue = UA_LOCALIZEDTEXT("en_EN", "the.answer"); UA_Variant_setScalarCopy(&wValue.value.value, &testValue, &UA_TYPES[UA_TYPES_LOCALIZEDTEXT]); wValue.value.hasValue = UA_TRUE; wValue.nodeId = UA_NODEID_STRING(1, "the.answer"); wValue.nodeId = UA_NODEID_STRING(1, "the.answer"); wValue.attributeId = UA_ATTRIBUTEID_DESCRIPTION; wValue.value.hasValue = UA_TRUE; UA_StatusCode retval = writeValue(server, &wValue); ck_assert_int_eq(retval, UA_STATUSCODE_GOOD); }END_TEST
/* Convenience function to be wrapped into inline functions */ UA_StatusCode __UA_Server_write(UA_Server *server, const UA_NodeId *nodeId, const UA_AttributeId attributeId, const UA_DataType *attr_type, const void *attr) { UA_WriteValue wvalue; UA_WriteValue_init(&wvalue); wvalue.nodeId = *nodeId; wvalue.attributeId = attributeId; wvalue.value.hasValue = true; if(attr_type != &UA_TYPES[UA_TYPES_VARIANT]) { /* hacked cast. the target WriteValue is used as const anyway */ UA_Variant_setScalar(&wvalue.value.value, (void*)(uintptr_t)attr, attr_type); } else { wvalue.value.value = *(const UA_Variant*)attr; } return UA_Server_write(server, &wvalue); }
}END_TEST START_TEST(WriteSingleAttributeValue) { UA_Server *server = makeTestSequence(); UA_WriteValue wValue; UA_WriteValue_init(&wValue); UA_Variant *myIntegerVariant = UA_Variant_new(); UA_Int32 myInteger = 20; UA_Variant_setScalarCopy(myIntegerVariant, &myInteger, &UA_TYPES[UA_TYPES_INT32]); wValue.nodeId = UA_NODEID_STRING(1, "the.answer"); wValue.attributeId = UA_ATTRIBUTEID_VALUE; wValue.value.hasValue = UA_TRUE; wValue.value.value = *myIntegerVariant; UA_StatusCode retval = writeValue(server, &wValue); UA_DataValue resp; UA_DataValue_init(&resp); UA_ReadRequest rReq; UA_ReadRequest_init(&rReq); rReq.nodesToRead = UA_ReadValueId_new(); rReq.nodesToReadSize = 1; rReq.nodesToRead[0].nodeId = UA_NODEID_STRING(1, "the.answer"); rReq.nodesToRead[0].attributeId = UA_ATTRIBUTEID_VALUE; readValue(server, UA_TIMESTAMPSTORETURN_NEITHER, &rReq.nodesToRead[0], &resp); ck_assert_int_eq(retval, UA_STATUSCODE_GOOD); ck_assert(wValue.value.hasValue); const UA_Node *node = UA_NodeStore_get(server->nodestore, &wValue.nodeId); ck_assert_int_eq(node->nodeClass, UA_NODECLASS_VARIABLE); const UA_VariableNode *vn = (const UA_VariableNode*)node; const UA_Variant *oldV = &vn->value.variant.value; ck_assert_ptr_eq(&oldV->type->typeId, &wValue.value.value.type->typeId); ck_assert_int_eq(20, *(UA_Int32* )resp.value.data); }END_TEST
UA_StatusCode UA_Client_writeArrayDimensionsAttribute(UA_Client *client, const UA_NodeId nodeId, const UA_Int32 *newArrayDimensions, size_t newArrayDimensionsSize) { if(!newArrayDimensions) return UA_STATUSCODE_BADTYPEMISMATCH; UA_WriteValue wValue; UA_WriteValue_init(&wValue); wValue.nodeId = nodeId; wValue.attributeId = UA_ATTRIBUTEID_ARRAYDIMENSIONS; UA_Variant_setArray(&wValue.value.value, (void*)(uintptr_t)newArrayDimensions, newArrayDimensionsSize, &UA_TYPES[UA_TYPES_INT32]); wValue.value.hasValue = true; UA_WriteRequest wReq; UA_WriteRequest_init(&wReq); wReq.nodesToWrite = &wValue; wReq.nodesToWriteSize = 1; UA_WriteResponse wResp = UA_Client_Service_write(client, wReq); UA_StatusCode retval = wResp.responseHeader.serviceResult; UA_WriteResponse_deleteMembers(&wResp); return retval; }