END_TEST START_TEST(Client_methodcall) { UA_Client *client = UA_Client_new(UA_ClientConfig_default); UA_StatusCode retval = UA_Client_connect(client, "opc.tcp://localhost:4840"); ck_assert_uint_eq(retval, UA_STATUSCODE_GOOD); UA_UInt32 subId; retval = UA_Client_Subscriptions_new(client, UA_SubscriptionSettings_default, &subId); ck_assert_uint_eq(retval, UA_STATUSCODE_GOOD); /* monitor the server state */ UA_UInt32 monId; retval = UA_Client_Subscriptions_addMonitoredItem(client, subId, UA_NODEID_NUMERIC(0, 2259), UA_ATTRIBUTEID_VALUE, NULL, NULL, &monId); ck_assert_uint_eq(retval, UA_STATUSCODE_GOOD); /* call a method to get monitored item id */ UA_Variant input; UA_Variant_init(&input); UA_Variant_setScalarCopy(&input, &subId, &UA_TYPES[UA_TYPES_UINT32]); size_t outputSize; UA_Variant *output; retval = UA_Client_call(client, UA_NODEID_NUMERIC(0, UA_NS0ID_SERVER), UA_NODEID_NUMERIC(0, UA_NS0ID_SERVER_GETMONITOREDITEMS), 1, &input, &outputSize, &output); ck_assert_uint_eq(retval, UA_STATUSCODE_GOOD); ck_assert_uint_eq(outputSize, 2); ck_assert_uint_eq(output[0].arrayLength, 1); ck_assert_uint_eq(*((UA_UInt32*)output[0].data), monId); UA_Array_delete(output, outputSize, &UA_TYPES[UA_TYPES_VARIANT]); UA_Variant_deleteMembers(&input); /* call with invalid subscription id */ UA_Variant_init(&input); subId = 0; UA_Variant_setScalarCopy(&input, &subId, &UA_TYPES[UA_TYPES_UINT32]); retval = UA_Client_call(client, UA_NODEID_NUMERIC(0, UA_NS0ID_SERVER), UA_NODEID_NUMERIC(0, UA_NS0ID_SERVER_GETMONITOREDITEMS), 1, &input, &outputSize, &output); ck_assert_uint_eq(retval, UA_STATUSCODE_BADSUBSCRIPTIONIDINVALID); UA_Variant_deleteMembers(&input); UA_Client_disconnect(client); UA_Client_delete(client); }
UA_StatusCode __UA_Client_writeAttribute(UA_Client *client, UA_NodeId nodeId, UA_AttributeId attributeId, void *in, const UA_DataType *inDataType) { if(in == NULL) return UA_STATUSCODE_BADTYPEMISMATCH; UA_Variant *tmp = (UA_Variant *) in; if (tmp == NULL) return 1; UA_WriteRequest *wReq = UA_WriteRequest_new(); wReq->nodesToWrite = UA_WriteValue_new(); wReq->nodesToWriteSize = 1; UA_NodeId_copy(&nodeId, &wReq->nodesToWrite[0].nodeId); wReq->nodesToWrite[0].attributeId = attributeId; if (attributeId == UA_ATTRIBUTEID_VALUE) { UA_Variant_copy((UA_Variant *) in, &wReq->nodesToWrite[0].value.value); wReq->nodesToWrite[0].value.hasValue = true; } else { if( ! UA_Variant_setScalarCopy(&wReq->nodesToWrite[0].value.value, in, inDataType) ) wReq->nodesToWrite[0].value.hasValue = true; } UA_WriteResponse wResp = UA_Client_Service_write(client, *wReq); UA_StatusCode retval = wResp.responseHeader.serviceResult; UA_WriteRequest_delete(wReq); UA_WriteResponse_deleteMembers(&wResp); return retval; }
static UA_StatusCode readTemperature(void *handle, const UA_NodeId nodeId, UA_Boolean sourceTimeStamp, const UA_NumericRange *range, UA_DataValue *value) { if(range) { value->hasStatus = true; value->status = UA_STATUSCODE_BADINDEXRANGEINVALID; return UA_STATUSCODE_GOOD; } rewind(temperatureFile); fflush(temperatureFile); UA_Double currentTemperature; if(fscanf(temperatureFile, "%lf", ¤tTemperature) != 1){ UA_LOG_WARNING(logger, UA_LOGCATEGORY_USERLAND, "Can not parse temperature"); exit(1); } currentTemperature /= 1000.0; value->sourceTimestamp = UA_DateTime_now(); value->hasSourceTimestamp = true; UA_Variant_setScalarCopy(&value->value, ¤tTemperature, &UA_TYPES[UA_TYPES_DOUBLE]); value->hasValue = true; return UA_STATUSCODE_GOOD; }
static UA_Boolean fillHistoricalDataBackend(UA_HistoryDataBackend backend) { int i = 0; UA_DateTime currentDateTime = testData[i]; fprintf(stderr, "Adding to historical data backend: "); while (currentDateTime) { fprintf(stderr, "%lld, ", currentDateTime / UA_DATETIME_SEC); UA_DataValue value; UA_DataValue_init(&value); value.hasValue = true; UA_Int64 d = currentDateTime; UA_Variant_setScalarCopy(&value.value, &d, &UA_TYPES[UA_TYPES_INT64]); value.hasSourceTimestamp = true; value.sourceTimestamp = currentDateTime; value.hasServerTimestamp = true; value.serverTimestamp = currentDateTime; value.hasStatus = true; value.status = UA_STATUSCODE_GOOD; if (backend.serverSetHistoryData(server, backend.context, NULL, NULL, &outNodeId, UA_FALSE, &value) != UA_STATUSCODE_GOOD) { fprintf(stderr, "\n"); return false; } UA_DataValue_deleteMembers(&value); currentDateTime = testData[++i]; } fprintf(stderr, "\n"); return true; }
static UA_StatusCode readInteger(void *handle, const UA_NodeId nodeid, UA_Boolean sourceTimeStamp, const UA_NumericRange *range, UA_DataValue *dataValue) { dataValue->hasValue = UA_TRUE; UA_Variant_setScalarCopy(&dataValue->value, (UA_UInt32*)handle, &UA_TYPES[UA_TYPES_INT32]); //note that this is only possible if the identifier is a string - but we are sure to have one here UA_LOG_INFO(logger, UA_LOGCATEGORY_USERLAND, "Node read %.*s",nodeid.identifier.string.length, nodeid.identifier.string.data); UA_LOG_INFO(logger, UA_LOGCATEGORY_USERLAND, "read value %i", *(UA_UInt32*)handle); return UA_STATUSCODE_GOOD; }
static UA_StatusCode getMonitoredItems(void *methodHandle, const UA_NodeId objectId, size_t inputSize, const UA_Variant *input, size_t outputSize, UA_Variant *output) { UA_String tmp = UA_STRING("Hello World"); UA_Variant_setScalarCopy(output, &tmp, &UA_TYPES[UA_TYPES_STRING]); return UA_STATUSCODE_GOOD; }
static UA_StatusCode onRead(void *handle, const UA_NodeId nodeid, UA_Boolean sourceTimeStamp, const UA_NumericRange *range, UA_DataValue *dataValue) { UA_LOG_INFO(logger, UA_LOGCATEGORY_USERLAND, "VALUE READ!!! %i", *(UA_UInt32*)handle); handle = &ButtonValue; UA_Variant_setScalarCopy(&dataValue->value, (UA_UInt32*)handle, &UA_TYPES[UA_TYPES_INT32]); }
int main(void) { UA_Client *client = UA_Client_new(); UA_ClientConfig_setDefault(UA_Client_getConfig(client)); UA_StatusCode retval = UA_Client_connect_username(client, "opc.tcp://localhost:4840", "paula", "paula123"); if(retval != UA_STATUSCODE_GOOD) { UA_Client_delete(client); return EXIT_FAILURE; } UA_NodeId newVariableIdRequest = UA_NODEID_NUMERIC(1, 1001); UA_NodeId newVariableId = UA_NODEID_NULL; UA_VariableAttributes newVariableAttributes = UA_VariableAttributes_default; newVariableAttributes.accessLevel = UA_ACCESSLEVELMASK_READ; newVariableAttributes.description = UA_LOCALIZEDTEXT_ALLOC("en-US", "NewVariable desc"); newVariableAttributes.displayName = UA_LOCALIZEDTEXT_ALLOC("en-US", "NewVariable"); newVariableAttributes.dataType = UA_TYPES[UA_TYPES_UINT32].typeId; UA_UInt32 value = 50; UA_Variant_setScalarCopy(&newVariableAttributes.value, &value, &UA_TYPES[UA_TYPES_UINT32]); UA_StatusCode retCode; retCode = UA_Client_addVariableNode(client, newVariableIdRequest, UA_NODEID_NUMERIC(0, UA_NS0ID_OBJECTSFOLDER), UA_NODEID_NUMERIC(0, UA_NS0ID_ORGANIZES), UA_QUALIFIEDNAME(1, "newVariable"), UA_NODEID_NUMERIC(0, UA_NS0ID_BASEDATAVARIABLETYPE), newVariableAttributes, &newVariableId); printf("addVariable returned: %s\n", UA_StatusCode_name(retCode)); UA_ExpandedNodeId extNodeId = UA_EXPANDEDNODEID_NUMERIC(0, 0); extNodeId.nodeId = newVariableId; retCode = UA_Client_addReference(client, UA_NODEID_NUMERIC(0, UA_NS0ID_OBJECTSFOLDER), UA_NODEID_NUMERIC(0, UA_NS0ID_HASCOMPONENT), UA_TRUE, UA_STRING_NULL, extNodeId, UA_NODECLASS_VARIABLE); printf("addReference returned: %s\n", UA_StatusCode_name(retCode)); retCode = UA_Client_deleteReference(client, UA_NODEID_NUMERIC(0, UA_NS0ID_OBJECTSFOLDER), UA_NODEID_NUMERIC(0, UA_NS0ID_ORGANIZES), UA_TRUE, extNodeId, UA_TRUE); printf("deleteReference returned: %s\n", UA_StatusCode_name(retCode)); retCode = UA_Client_deleteNode(client, newVariableId, UA_TRUE); printf("deleteNode returned: %s\n", UA_StatusCode_name(retCode)); /* Clean up */ UA_VariableAttributes_clear(&newVariableAttributes); UA_Client_delete(client); /* Disconnects the client internally */ return EXIT_SUCCESS; }
static UA_StatusCode outargMethod(UA_Server *server, const UA_NodeId *sessionId, void *sessionContext, const UA_NodeId *methodId, void *methodContext, const UA_NodeId *objectId, void *objectContext, size_t inputSize, const UA_Variant *input, size_t outputSize, UA_Variant *output) { UA_Int32 out = 42; UA_Variant_setScalarCopy(output, &out, &UA_TYPES[UA_TYPES_INT32]); return UA_STATUSCODE_GOOD; }
static UA_StatusCode readInteger(void *handle, const UA_NodeId nodeid, UA_Boolean sourceTimeStamp, const UA_NumericRange *range, UA_DataValue *dataValue) { dataValue->hasValue = true; UA_Variant_setScalarCopy(&dataValue->value, (UA_UInt32*)handle, &UA_TYPES[UA_TYPES_INT32]); // we know the nodeid is a string UA_LOG_INFO(logger, UA_LOGCATEGORY_USERLAND, "Node read %.*s", nodeid.identifier.string.length, nodeid.identifier.string.data); UA_LOG_INFO(logger, UA_LOGCATEGORY_USERLAND, "read value %i", *(UA_UInt32*)handle); return UA_STATUSCODE_GOOD; }
static UA_Server* makeTestSequence(void) { UA_Server *server = UA_Server_new(UA_ServerConfig_standard); /* VariableNode */ UA_Variant *myIntegerVariant = UA_Variant_new(); UA_Int32 myInteger = 42; UA_Variant_setScalarCopy(myIntegerVariant, &myInteger, &UA_TYPES[UA_TYPES_INT32]); const UA_QualifiedName myIntegerName = UA_QUALIFIEDNAME(1, "the answer"); const UA_NodeId myIntegerNodeId = UA_NODEID_STRING(1, "the.answer"); UA_NodeId parentNodeId = UA_NODEID_NUMERIC(0, UA_NS0ID_OBJECTSFOLDER); UA_NodeId parentReferenceNodeId = UA_NODEID_NUMERIC(0, UA_NS0ID_ORGANIZES); UA_Server_addVariableNode(server, myIntegerNodeId, myIntegerName, UA_LOCALIZEDTEXT("en_US","the answer"), UA_LOCALIZEDTEXT("en_US","the answer"), 0, 0, parentNodeId, parentReferenceNodeId, myIntegerVariant, NULL); /* ObjectNode */ UA_Server_addObjectNode(server, UA_NODEID_NUMERIC(1, 50), UA_QUALIFIEDNAME(1, "Demo"), UA_LOCALIZEDTEXT("en_US","Demo"), UA_LOCALIZEDTEXT("en_US","Demo"), 0, 0, UA_NODEID_NUMERIC(0, UA_NS0ID_OBJECTSFOLDER), UA_NODEID_NUMERIC(0, UA_NS0ID_ORGANIZES), UA_EXPANDEDNODEID_NUMERIC(0, UA_NS0ID_FOLDERTYPE), NULL); /* ReferenceTypeNode */ UA_ReferenceTypeNode *organizes = UA_ReferenceTypeNode_new(); copyNames((UA_Node*)organizes, "Organizes"); organizes->inverseName = UA_LOCALIZEDTEXT_ALLOC("", "OrganizedBy"); organizes->nodeId.identifier.numeric = UA_NS0ID_ORGANIZES; organizes->isAbstract = UA_FALSE; organizes->symmetric = UA_FALSE; UA_Server_addNode(server, (UA_Node*)organizes, UA_EXPANDEDNODEID_NUMERIC(0, UA_NS0ID_HIERARCHICALREFERENCES), UA_NODEID_NUMERIC(0, UA_NS0ID_HASSUBTYPE)); /* ViewNode */ UA_ViewNode *viewtest = UA_ViewNode_new(); copyNames((UA_Node*)viewtest, "Viewtest"); viewtest->nodeId.identifier.numeric = UA_NS0ID_VIEWNODE; UA_Server_addNode(server, (UA_Node*)viewtest, UA_EXPANDEDNODEID_NUMERIC(0, UA_NS0ID_VIEWSFOLDER), UA_NODEID_NUMERIC(0, UA_NS0ID_HASSUBTYPE)); /* MethodNode */ UA_MethodNode *methodtest = UA_MethodNode_new(); copyNames((UA_Node*)methodtest, "Methodtest"); methodtest->nodeId.identifier.numeric = UA_NS0ID_METHODNODE; UA_Server_addNode(server, (UA_Node*)methodtest, UA_EXPANDEDNODEID_NUMERIC(0, 3), UA_NODEID_NUMERIC(0, UA_NS0ID_HASSUBTYPE)); return server; }
static UA_StatusCode helloWorldMethod(const UA_NodeId objectId, const UA_Variant *input, UA_Variant *output, void *handle) { UA_String *inputStr = (UA_String*)input->data; UA_String tmp = UA_STRING_ALLOC("Hello "); if(inputStr->length > 0) { tmp.data = realloc(tmp.data, tmp.length + inputStr->length); memcpy(&tmp.data[tmp.length], inputStr->data, inputStr->length); tmp.length += inputStr->length; } UA_Variant_setScalarCopy(output, &tmp, &UA_TYPES[UA_TYPES_STRING]); UA_String_deleteMembers(&tmp); UA_LOG_INFO(logger, UA_LOGCATEGORY_SERVER, "Hello World was called"); return UA_STATUSCODE_GOOD; }
}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
UA_StatusCode temperature_sensor_read(void * handle, const UA_NodeId node_id, UA_Boolean source_timestamp, const UA_NumericRange *range, UA_DataValue * data_value) { UA_DateTime sourceTimestamp = UA_DateTime_now(); int result = 0; if(i2c_fd < 0) return UA_STATUSCODE_BADNOTREADABLE; if(!temperature_get(i2c_fd, CONVERSION_CURRENT, &result)) return UA_STATUSCODE_BADNOTREADABLE; data_value->hasValue = true; data_value->hasSourceTimestamp = true; data_value->hasServerTimestamp = true; data_value->sourceTimestamp = sourceTimestamp; UA_Variant_setScalarCopy(&data_value->value, &result, &UA_TYPES[UA_TYPES_INT32]); return UA_STATUSCODE_GOOD; }
}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(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(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(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
/* Example 3 */ static UA_StatusCode fooBarMethod(void *handle, const UA_NodeId objectId, size_t inputSize, const UA_Variant *input, size_t outputSize, UA_Variant *output) { /* the same as helloWorld, but returns foobar */ UA_String *inputStr = (UA_String*)input->data; UA_String tmp = UA_STRING_ALLOC("FooBar! "); if(inputStr->length > 0) { tmp.data = realloc(tmp.data, tmp.length + inputStr->length); memcpy(&tmp.data[tmp.length], inputStr->data, inputStr->length); tmp.length += inputStr->length; } UA_Variant_setScalarCopy(output, &tmp, &UA_TYPES[UA_TYPES_STRING]); UA_String_deleteMembers(&tmp); UA_LOG_INFO(logger, UA_LOGCATEGORY_SERVER, "FooBar was called"); return UA_STATUSCODE_GOOD; }
static UA_StatusCode readTimeData(void *handle, const UA_NodeId nodeId, UA_Boolean sourceTimeStamp, const UA_NumericRange *range, UA_DataValue *value) { if(range) { value->hasStatus = true; value->status = UA_STATUSCODE_BADINDEXRANGEINVALID; return UA_STATUSCODE_GOOD; } UA_DateTime currentTime = UA_DateTime_now(); UA_Variant_setScalarCopy(&value->value, ¤tTime, &UA_TYPES[UA_TYPES_DATETIME]); value->hasValue = true; if(sourceTimeStamp) { value->hasSourceTimestamp = true; value->sourceTimestamp = currentTime; } return UA_STATUSCODE_GOOD; }
}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
static UA_StatusCode readInteger(UA_Server *server, const UA_NodeId *sessionId, void *sessionContext, const UA_NodeId *nodeId, void *nodeContext, UA_Boolean includeSourceTimeStamp, const UA_NumericRange *range, UA_DataValue *value) { UA_Int32 *myInteger = (UA_Int32*)nodeContext; value->hasValue = true; UA_Variant_setScalarCopy(&value->value, myInteger, &UA_TYPES[UA_TYPES_INT32]); // we know the nodeid is a string UA_LOG_INFO(logger, UA_LOGCATEGORY_USERLAND, "Node read %.*s", (int)nodeId->identifier.string.length, nodeId->identifier.string.data); UA_LOG_INFO(logger, UA_LOGCATEGORY_USERLAND, "read value %i", *(UA_UInt32 *)myInteger); return UA_STATUSCODE_GOOD; }
}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
static UA_StatusCode helloWorld(UA_Server *server, const UA_NodeId *sessionId, void *sessionContext, const UA_NodeId *methodId, void *methodContext, const UA_NodeId *objectId, void *objectContext, size_t inputSize, const UA_Variant *input, size_t outputSize, UA_Variant *output) { /* input is a scalar string (checked by the server) */ UA_String *name = (UA_String *)input[0].data; UA_String hello = UA_STRING("Hello "); UA_String greet; greet.length = hello.length + name->length; greet.data = (UA_Byte *)UA_malloc(greet.length); memcpy(greet.data, hello.data, hello.length); memcpy(greet.data + hello.length, name->data, name->length); UA_Variant_setScalarCopy(output, &greet, &UA_TYPES[UA_TYPES_STRING]); UA_String_deleteMembers(&greet); return UA_STATUSCODE_GOOD; }
static UA_StatusCode readLedStatus(void *handle, UA_NodeId nodeid, UA_Boolean sourceTimeStamp, const UA_NumericRange *range, UA_DataValue *value) { if(range) return UA_STATUSCODE_BADINDEXRANGEINVALID; value->hasValue = true; UA_StatusCode retval = UA_Variant_setScalarCopy(&value->value, &ledStatus, &UA_TYPES[UA_TYPES_BOOLEAN]); if(retval != UA_STATUSCODE_GOOD) return retval; if(sourceTimeStamp) { value->sourceTimestamp = UA_DateTime_now(); value->hasSourceTimestamp = true; } return UA_STATUSCODE_GOOD; }
//################################################BUTTON########################## static UA_StatusCode readIntegerB(void *handle, const UA_NodeId nodeid, UA_Boolean sourceTimeStamp, const UA_NumericRange *range, UA_DataValue *dataValue) { // Let LED BLink gpioPWM(17,255); usleep( 1000 ); gpioPWM(17,0); // Read Digital value of GPIO 22 and set as Node Value handle = &ButtonValue; dataValue->hasValue = true; UA_Variant_setScalarCopy(&dataValue->value, (UA_UInt32*)handle, &UA_TYPES[UA_TYPES_INT32]); // we know the nodeid is a string UA_LOG_INFO(logger, UA_LOGCATEGORY_USERLAND, "Node read %.*s", nodeid.identifier.string.length, nodeid.identifier.string.data); UA_LOG_INFO(logger, UA_LOGCATEGORY_USERLAND, "read value %i", *(UA_UInt32*)handle); return UA_STATUSCODE_GOOD; }
}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
static UA_StatusCode getVariableNodeDataType(const UA_VariableNode *vn, UA_DataValue *v) { UA_StatusCode retval = UA_STATUSCODE_GOOD; if(vn->valueSource == UA_VALUESOURCE_VARIANT) { forceVariantSetScalar(&v->value, &vn->value.variant.value.type->typeId, &UA_TYPES[UA_TYPES_NODEID]); } else { if(vn->value.dataSource.read == NULL) return UA_STATUSCODE_BADINTERNALERROR; /* Read from the datasource to see the data type */ UA_DataValue val; UA_DataValue_init(&val); val.hasValue = UA_FALSE; // always assume we are not given a value by userspace retval = vn->value.dataSource.read(vn->value.dataSource.handle, vn->nodeId, UA_FALSE, NULL, &val); if(retval != UA_STATUSCODE_GOOD) return retval; if (val.hasValue && val.value.type != NULL) retval = UA_Variant_setScalarCopy(&v->value, &val.value.type->typeId, &UA_TYPES[UA_TYPES_NODEID]); UA_DataValue_deleteMembers(&val); } return retval; }