diff --git a/src/opcua/ua_server.cpp b/src/opcua/ua_server.cpp index f473dfecc551810d238d7e7635a9ea825b8a7b76..8ebd670ffd994959ef6f2873996bc16c93516d3f 100644 --- a/src/opcua/ua_server.cpp +++ b/src/opcua/ua_server.cpp @@ -29,6 +29,7 @@ extern volatile bool ServerRunning; extern Serverdat SD; UA_Server *mUaServer; +UA_UInt16 mUaLofarNameSpace; /* * Links of interest: @@ -85,6 +86,25 @@ static UA_StatusCode ua_read_DataSource(UA_Server *server, UA_LOG_INFO(UA_Log_Stdout, UA_LOGCATEGORY_USERLAND, "ua_read_DataSource: from node %s",regname); + UA_NodeId currentNodeId = UA_NODEID_STRING(mUaLofarNameSpace, (char *)regname); + UA_NodeId ntype; + //UA_StatusCode st = + UA_Server_readDataType(server, currentNodeId, &ntype); + // assert(st == UA_STATUSCODE_GOOD); + //printf("update_FPGA_Variable nodeid %s ns=%d DataType=%d numeric=%d\n",(char *)regname.c_str(), + // ntype.namespaceIndex,ntype.identifierType,ntype.identifier.numeric); + // output: update_FPGA_Variable nodeid fpga_version_R ns=0 DataType=0 numeric=12 + //ua_print_nodeid(&ntype); + // output: i=12 + + // ntype.identifier.numeric is the datatype e.g. for UA_Float=10, UA_String=12 + //printf("update_FPGA_Variable UA_TYPES_FLOAT=%d numeric=%d\n",UA_TYPES_FLOAT,ntype.identifier.numeric); + // output: update_FPGA_Variable UA_TYPES_FLOAT=9 numeric=10 + // weird... must do -1 + // see: https://open62541.org/doc/current/types.html + + + // Translator regnames start with "tr_" others "fpga_" bool regname_is_for_translator = false; if(strncmp(regname,"tr_",3) == 0) { @@ -105,6 +125,49 @@ static UA_StatusCode ua_read_DataSource(UA_Server *server, cerr << "ua_read_DataSource error: " << e.what() << endl; termout.strout << e.what(); } + + // tr_* has only scalars + switch(ntype.identifier.numeric-1) { + case UA_TYPES_STRING: { + char *ptr = (char *)termout.val; + UA_String value = UA_STRING_ALLOC((char *)ptr); + UA_Variant_setScalarCopy(&dataValue->value, &value, &UA_TYPES[UA_TYPES_STRING]); + dataValue->hasValue = true; + } + break; + case UA_TYPES_FLOAT: { + float *ptr = (float *)termout.val; + UA_Float value = (UA_Float)ptr[0]; + UA_Variant_setScalarCopy(&dataValue->value, &value, &UA_TYPES[UA_TYPES_FLOAT]); + dataValue->hasValue = true; + } + break; + case UA_TYPES_INT16: { + short *ptr = (short *)termout.val; + UA_Int16 value = (UA_Int16)ptr[0]; + UA_Variant_setScalarCopy(&dataValue->value, &value, &UA_TYPES[UA_TYPES_INT16]); + dataValue->hasValue = true; + } + break; + case UA_TYPES_INT32: { + int *ptr = (int *)termout.val; + UA_Int32 value = (UA_Int32)ptr[0]; + UA_Variant_setScalarCopy(&dataValue->value, &value, &UA_TYPES[UA_TYPES_INT32]); + dataValue->hasValue = true; + } + break; + case UA_TYPES_BOOLEAN: { + bool *ptr = (bool *)termout.val; + UA_Boolean value = (UA_Boolean)ptr[0]; + UA_Variant_setScalarCopy(&dataValue->value, &value, &UA_TYPES[UA_TYPES_BOOLEAN]); + dataValue->hasValue = true; + } + break; + default: + dataValue->hasValue = false; + } + + } else { if(!SD.control_mutex[UNB_client_ID].try_lock()) { cerr << "uaserver: mutex not ready !!!\n"; @@ -117,96 +180,63 @@ static UA_StatusCode ua_read_DataSource(UA_Server *server, termout.strout << e.what(); } SD.control_mutex[UNB_client_ID].unlock(); - } - - - UA_NodeId currentNodeId = UA_NODEID_STRING(1, (char *)regname); - UA_NodeId ntype; - //UA_StatusCode st = - UA_Server_readDataType(server, currentNodeId, &ntype); - // assert(st == UA_STATUSCODE_GOOD); - //printf("update_FPGA_Variable nodeid %s ns=%d DataType=%d numeric=%d\n",(char *)regname.c_str(), - // ntype.namespaceIndex,ntype.identifierType,ntype.identifier.numeric); - // output: update_FPGA_Variable nodeid fpga_version_R ns=0 DataType=0 numeric=12 - //ua_print_nodeid(&ntype); - // output: i=12 - - - UA_Variant nv_dims; - /*https://open62541.org/doc/0.2/server.html */ - UA_Server_readArrayDimensions(server, currentNodeId, &nv_dims); - size_t array_size = 0; - if(nv_dims.arrayLength >= 1) { - size_t *size = (size_t *)nv_dims.data; - //printf("update_FPGA_Variable nodeid %s dimensions=%d\n",(char *)regname.c_str(),*size); - array_size = *size; - } -// ntype.identifier.numeric is the datatype e.g. for UA_Float=10, UA_String=12 -//printf("update_FPGA_Variable UA_TYPES_FLOAT=%d numeric=%d\n",UA_TYPES_FLOAT,ntype.identifier.numeric); -// output: update_FPGA_Variable UA_TYPES_FLOAT=9 numeric=10 -// weird... must do -1 -// see: https://open62541.org/doc/current/types.html - - switch(ntype.identifier.numeric-1) { - case UA_TYPES_STRING: { - unsigned int size = (unsigned int)array_size; - UA_String *values = (UA_String *) UA_Array_new(size, &UA_TYPES[UA_TYPES_STRING]); - char *ptr = (char *)termout.val; - for(unsigned int i=0; i<size;i++) { - values[i] = UA_STRING_ALLOC((char *)ptr); - ptr += SIZE1STRING; - } - UA_Variant_setArray(&dataValue->value, values, size, &UA_TYPES[UA_TYPES_STRING]); - dataValue->hasValue = true; - } - break; - case UA_TYPES_FLOAT: { - if(array_size > termout.nof_vals) array_size = termout.nof_vals; - UA_Float *values = (UA_Float *) UA_Array_new(array_size, &UA_TYPES[UA_TYPES_FLOAT]); - float *ptr = (float *)termout.val; - for(unsigned int i=0; i<termout.nof_vals;i++) { - values[i] = UA_Float(ptr[i]); - } - UA_Variant_setArray(&dataValue->value, values, array_size, &UA_TYPES[UA_TYPES_FLOAT]); - dataValue->hasValue = true; - } - break; - case UA_TYPES_INT16: { - if(array_size > termout.nof_vals) array_size = termout.nof_vals; - UA_Int16 *values = (UA_Int16 *) UA_Array_new(array_size, &UA_TYPES[UA_TYPES_INT16]); - short *ptr = (short *)termout.val; - for(unsigned int i=0; i<termout.nof_vals;i++) { - values[i] = UA_Int16(ptr[i]); - } - UA_Variant_setArray(&dataValue->value, values, array_size, &UA_TYPES[UA_TYPES_INT16]); - dataValue->hasValue = true; - } - break; - case UA_TYPES_INT32: { - if(array_size > termout.nof_vals) array_size = termout.nof_vals; - UA_Int32 *values = (UA_Int32 *) UA_Array_new(array_size, &UA_TYPES[UA_TYPES_INT32]); - int *ptr = (int *)termout.val; - for(unsigned int i=0; i<termout.nof_vals;i++) { - values[i] = UA_Int32(ptr[i]); - } - UA_Variant_setArray(&dataValue->value, values, array_size, &UA_TYPES[UA_TYPES_INT32]); - dataValue->hasValue = true; - } - break; - case UA_TYPES_BOOLEAN: { - if(array_size > termout.nof_vals) array_size = termout.nof_vals; - UA_Boolean *values = (UA_Boolean *) UA_Array_new(array_size, &UA_TYPES[UA_TYPES_BOOLEAN]); - bool *ptr = (bool *)termout.val; - for(unsigned int i=0; i<termout.nof_vals;i++) { - values[i] = UA_Boolean(ptr[i]); - } - UA_Variant_setArray(&dataValue->value, values, array_size, &UA_TYPES[UA_TYPES_BOOLEAN]); - dataValue->hasValue = true; - } - break; - default: - dataValue->hasValue = false; + // fpga_* has only arrays + switch(ntype.identifier.numeric-1) { + case UA_TYPES_STRING: { + UA_String *values = (UA_String *) UA_Array_new(termout.nof_vals, &UA_TYPES[UA_TYPES_STRING]); + char *ptr = (char *)termout.val; + for(unsigned int i=0; i<termout.nof_vals;i++) { + values[i] = UA_STRING_ALLOC((char *)ptr); + ptr += SIZE1STRING; + } + UA_Variant_setArray(&dataValue->value, values, termout.nof_vals, &UA_TYPES[UA_TYPES_STRING]); + dataValue->hasValue = true; + } + break; + case UA_TYPES_FLOAT: { + UA_Float *values = (UA_Float *) UA_Array_new(termout.nof_vals, &UA_TYPES[UA_TYPES_FLOAT]); + float *ptr = (float *)termout.val; + for(unsigned int i=0; i<termout.nof_vals;i++) { + values[i] = UA_Float(ptr[i]); + } + UA_Variant_setArray(&dataValue->value, values, termout.nof_vals, &UA_TYPES[UA_TYPES_FLOAT]); + dataValue->hasValue = true; + } + break; + case UA_TYPES_INT16: { + UA_Int16 *values = (UA_Int16 *) UA_Array_new(termout.nof_vals, &UA_TYPES[UA_TYPES_INT16]); + short *ptr = (short *)termout.val; + for(unsigned int i=0; i<termout.nof_vals;i++) { + values[i] = UA_Int16(ptr[i]); + } + UA_Variant_setArray(&dataValue->value, values, termout.nof_vals, &UA_TYPES[UA_TYPES_INT16]); + dataValue->hasValue = true; + } + break; + case UA_TYPES_INT32: { + UA_Int32 *values = (UA_Int32 *) UA_Array_new(termout.nof_vals, &UA_TYPES[UA_TYPES_INT32]); + int *ptr = (int *)termout.val; + for(unsigned int i=0; i<termout.nof_vals;i++) { + values[i] = UA_Int32(ptr[i]); + } + UA_Variant_setArray(&dataValue->value, values, termout.nof_vals, &UA_TYPES[UA_TYPES_INT32]); + dataValue->hasValue = true; + } + break; + case UA_TYPES_BOOLEAN: { + UA_Boolean *values = (UA_Boolean *) UA_Array_new(termout.nof_vals, &UA_TYPES[UA_TYPES_BOOLEAN]); + bool *ptr = (bool *)termout.val; + for(unsigned int i=0; i<termout.nof_vals;i++) { + values[i] = UA_Boolean(ptr[i]); + } + UA_Variant_setArray(&dataValue->value, values, termout.nof_vals, &UA_TYPES[UA_TYPES_BOOLEAN]); + dataValue->hasValue = true; + } + break; + default: + dataValue->hasValue = false; + } } delete []regname; return UA_STATUSCODE_GOOD; @@ -225,6 +255,12 @@ static UA_StatusCode ua_write_DataSource(UA_Server *server, UA_LOG_INFO(UA_Log_Stdout, UA_LOGCATEGORY_USERLAND, "ua_write_DataSource: writing to %s",regname); + UA_NodeId currentNodeId = UA_NODEID_STRING(mUaLofarNameSpace, (char *)regname); + UA_NodeId ntype; + //UA_StatusCode st = + UA_Server_readDataType(server, currentNodeId, &ntype); + + // Translator regnames start with "tr_" others "fpga_" bool regname_is_for_translator = false; if(strncmp(regname,"tr_",3) == 0) { @@ -232,74 +268,122 @@ static UA_StatusCode ua_write_DataSource(UA_Server *server, UA_LOG_INFO(UA_Log_Stdout, UA_LOGCATEGORY_USERLAND,"ua_write_DataSource: for translator class"); } - UA_NodeId currentNodeId = UA_NODEID_STRING(1, (char *)regname); - UA_NodeId ntype; - //UA_StatusCode st = - UA_Server_readDataType(server, currentNodeId, &ntype); - - UA_Variant nv_dims; - /*https://open62541.org/doc/0.2/server.html */ - UA_Server_readArrayDimensions(server, currentNodeId, &nv_dims); - if(data->hasValue && data->value.arrayLength > 0) { - //data.value is a UA_Variant - cout << "data.value.arrayLength=" << data->value.arrayLength << endl; - unsigned int *data_sdp = new unsigned int[data->value.arrayLength]; + if(regname_is_for_translator) { + // tr_* has only scalars + if(data->hasValue) { + unsigned int array_length = 1; + unsigned int *data_sdp = new unsigned int[array_length]; - switch(ntype.identifier.numeric-1) { - case UA_TYPES_STRING: { - cout << "UA_TYPES_STRING: not implemented yet" << endl; - retval = false; - } - break; - case UA_TYPES_FLOAT: { - cout << "UA_TYPES_FLOAT: not implemented yet" << endl; - retval = false; - } - break; - case UA_TYPES_INT16: { - retval = true; - unsigned short *dptr = (unsigned short *)data->value.data; - for(unsigned int i=0;i<data->value.arrayLength;i++) { - data_sdp[i] = (unsigned int)dptr[i]; - } - } - break; - case UA_TYPES_INT32: { - retval = true; - unsigned int *dptr = (unsigned int *)data->value.data; - for(unsigned int i=0;i<data->value.arrayLength;i++) { - data_sdp[i] = (unsigned int)dptr[i]; - } - } - break; - case UA_TYPES_BOOLEAN: { - retval = true; - bool *dptr = (bool *)data->value.data; - for(unsigned int i=0;i<data->value.arrayLength;i++) { - data_sdp[i] = (unsigned int)dptr[i]; - } - } - break; - default: - cout << "UA_TYPES_?: not implemented yet" << endl; - retval = false; - break; - } - if(retval) { - TermOutput termout; - uint UNB_client_ID = c_CLIENT_ID_UASERVER; + switch(ntype.identifier.numeric-1) { + case UA_TYPES_STRING: { + retval = false; + } + break; + case UA_TYPES_FLOAT: { + retval = false; + } + break; + case UA_TYPES_INT16: { + retval = true; + unsigned short *dptr = (unsigned short *)data->value.data; + for(unsigned int i=0;i<array_length;i++) { + data_sdp[i] = (unsigned int)dptr[i]; + } + } + break; + case UA_TYPES_INT32: { + retval = true; + unsigned int *dptr = (unsigned int *)data->value.data; + for(unsigned int i=0;i<array_length;i++) { + data_sdp[i] = (unsigned int)dptr[i]; + } + } + break; + case UA_TYPES_BOOLEAN: { + retval = true; + bool *dptr = (bool *)data->value.data; + for(unsigned int i=0;i<array_length;i++) { + data_sdp[i] = (unsigned int)dptr[i]; + } + } + break; + default: + retval = false; + break; + } + if(retval) { + TermOutput termout; + uint UNB_client_ID = c_CLIENT_ID_UASERVER; - if(regname_is_for_translator) { try { - SD.tr->write(UNB_client_ID, termout, regname, 0, data_sdp, data->value.arrayLength); + SD.tr->write(UNB_client_ID, termout, regname, 0, data_sdp, array_length); } catch(runtime_error& e) { cerr << "write_TR_DataSource error: " << e.what() << endl; termout.strout << e.what(); retval = false; } - } else { + } + delete []data_sdp; + } + } else { + // fpga_* has only arrays + UA_Variant nv_dims; + /*https://open62541.org/doc/0.2/server.html */ + UA_Server_readArrayDimensions(server, currentNodeId, &nv_dims); + + if(data->hasValue && data->value.arrayLength > 0) { + //data.value is a UA_Variant + cout << "data.value.arrayLength=" << data->value.arrayLength << endl; + + unsigned int *data_sdp = new unsigned int[data->value.arrayLength]; + + switch(ntype.identifier.numeric-1) { + case UA_TYPES_STRING: { + cout << "UA_TYPES_STRING: not implemented yet" << endl; + retval = false; + } + break; + case UA_TYPES_FLOAT: { + cout << "UA_TYPES_FLOAT: not implemented yet" << endl; + retval = false; + } + break; + case UA_TYPES_INT16: { + retval = true; + unsigned short *dptr = (unsigned short *)data->value.data; + for(unsigned int i=0;i<data->value.arrayLength;i++) { + data_sdp[i] = (unsigned int)dptr[i]; + } + } + break; + case UA_TYPES_INT32: { + retval = true; + unsigned int *dptr = (unsigned int *)data->value.data; + for(unsigned int i=0;i<data->value.arrayLength;i++) { + data_sdp[i] = (unsigned int)dptr[i]; + } + } + break; + case UA_TYPES_BOOLEAN: { + retval = true; + bool *dptr = (bool *)data->value.data; + for(unsigned int i=0;i<data->value.arrayLength;i++) { + data_sdp[i] = (unsigned int)dptr[i]; + } + } + break; + default: + cout << "UA_TYPES_?: not implemented yet" << endl; + retval = false; + break; + } + + if(retval) { + TermOutput termout; + uint UNB_client_ID = c_CLIENT_ID_UASERVER; + while(!SD.control_mutex[UNB_client_ID].try_lock()) { cerr << "uaserver: mutex not ready\n"; usleep(100000); } try { SD.unb->write(UNB_client_ID, termout, regname, 0, data_sdp, data->value.arrayLength); @@ -310,33 +394,42 @@ static UA_StatusCode ua_write_DataSource(UA_Server *server, } SD.control_mutex[UNB_client_ID].unlock(); } + delete []data_sdp; } - delete []data_sdp; } + delete []regname; return UA_STATUSCODE_GOOD; } -static void ua_add_Variable_string(UA_Server *server, std::string regname, unsigned int size, std::string perm) +static void ua_add_Variable_string(UA_Server *server, std::string regname, unsigned int size, std::string perm, bool is_scalar) { UA_LOG_INFO(UA_Log_Stdout, UA_LOGCATEGORY_USERLAND, "ua_add_Variable_string: %s", (char *)regname.c_str()); UA_VariableAttributes vattr = UA_VariableAttributes_default; - UA_String *values = (UA_String *) UA_Array_new(size, &UA_TYPES[UA_TYPES_STRING]); - for(unsigned int i=0;i<size;i++) { - values[i] = UA_STRING_ALLOC((char *)"unknown"); - } - - UA_Variant_setArray(&vattr.value, values, size, &UA_TYPES[UA_TYPES_STRING]); if(perm == "RW") vattr.accessLevel = UA_ACCESSLEVELMASK_READ | UA_ACCESSLEVELMASK_WRITE; else if(perm == "RO") vattr.accessLevel = UA_ACCESSLEVELMASK_READ; - vattr.valueRank = UA_VALUERANK_ONE_DIMENSION; - vattr.dataType = UA_TYPES[UA_TYPES_STRING].typeId; - UA_UInt32 myArrayDimensions[1] = {size}; + if(is_scalar) { + UA_String value = UA_STRING_ALLOC((char *)"unknown"); + UA_Variant_setScalar(&vattr.value, &value, &UA_TYPES[UA_TYPES_STRING]); + + } else { + UA_String *values = (UA_String *) UA_Array_new(size, &UA_TYPES[UA_TYPES_STRING]); + for(unsigned int i=0;i<size;i++) { + values[i] = UA_STRING_ALLOC((char *)"unknown"); + } - vattr.arrayDimensions = myArrayDimensions; - vattr.arrayDimensionsSize = 1; + UA_Variant_setArray(&vattr.value, values, size, &UA_TYPES[UA_TYPES_STRING]); + + vattr.valueRank = UA_VALUERANK_ONE_DIMENSION; + UA_UInt32 myArrayDimensions[1] = {size}; + + vattr.arrayDimensions = myArrayDimensions; + vattr.arrayDimensionsSize = 1; + } + + vattr.dataType = UA_TYPES[UA_TYPES_STRING].typeId; vattr.displayName = UA_LOCALIZEDTEXT((char *)"locale", (char *)regname.c_str()); UA_DataSource DataSource; @@ -344,10 +437,10 @@ static void ua_add_Variable_string(UA_Server *server, std::string regname, unsig DataSource.write = ua_write_DataSource; UA_StatusCode retval = UA_Server_addDataSourceVariableNode(server, - UA_NODEID_STRING(1, (char *)regname.c_str()), // currentNodeId + UA_NODEID_STRING(mUaLofarNameSpace, (char *)regname.c_str()), // currentNodeId UA_NODEID_NUMERIC(0, UA_NS0ID_OBJECTSFOLDER), // parentNodeId UA_NODEID_NUMERIC(0, UA_NS0ID_ORGANIZES), // parentReferenceNodeId - UA_QUALIFIEDNAME(1, (char *)regname.c_str()), // node browse name + UA_QUALIFIEDNAME(mUaLofarNameSpace, (char *)regname.c_str()), // node browse name UA_NODEID_NUMERIC(0, UA_NS0ID_BASEDATAVARIABLETYPE), vattr, DataSource, NULL, NULL); if (retval != UA_STATUSCODE_GOOD) { @@ -355,25 +448,32 @@ static void ua_add_Variable_string(UA_Server *server, std::string regname, unsig printf("Error adding node"); } } -static void ua_add_Variable_integer(UA_Server *server, std::string regname, unsigned int size, std::string perm) +static void ua_add_Variable_integer(UA_Server *server, std::string regname, unsigned int size, std::string perm, bool is_scalar) { UA_LOG_INFO(UA_Log_Stdout, UA_LOGCATEGORY_USERLAND, "ua_add_Variable_integer: %s", (char *)regname.c_str()); UA_VariableAttributes vattr = UA_VariableAttributes_default; - UA_Int32 *values = (UA_Int32 *) UA_Array_new(size, &UA_TYPES[UA_TYPES_INT32]); - for(unsigned int i=0;i<size;i++) { - values[i] = UA_Int32(0); - } - UA_Variant_setArray(&vattr.value, values, size, &UA_TYPES[UA_TYPES_INT32]); if(perm == "RW") vattr.accessLevel = UA_ACCESSLEVELMASK_READ | UA_ACCESSLEVELMASK_WRITE; else if(perm == "RO") vattr.accessLevel = UA_ACCESSLEVELMASK_READ; - vattr.valueRank = UA_VALUERANK_ONE_DIMENSION; - vattr.dataType = UA_TYPES[UA_TYPES_INT32].typeId; - UA_UInt32 myArrayDimensions[1] = {size}; + if(is_scalar) { + UA_Int32 value = UA_Int32(0); + UA_Variant_setScalar(&vattr.value, &value, &UA_TYPES[UA_TYPES_INT32]); + } else { + UA_Int32 *values = (UA_Int32 *) UA_Array_new(size, &UA_TYPES[UA_TYPES_INT32]); + for(unsigned int i=0;i<size;i++) { + values[i] = UA_Int32(0); + } + UA_Variant_setArray(&vattr.value, values, size, &UA_TYPES[UA_TYPES_INT32]); - vattr.arrayDimensions = myArrayDimensions; - vattr.arrayDimensionsSize = 1; + vattr.valueRank = UA_VALUERANK_ONE_DIMENSION; + UA_UInt32 myArrayDimensions[1] = {size}; + + vattr.arrayDimensions = myArrayDimensions; + vattr.arrayDimensionsSize = 1; + } + + vattr.dataType = UA_TYPES[UA_TYPES_INT32].typeId; vattr.displayName = UA_LOCALIZEDTEXT((char *)"locale", (char *)regname.c_str()); UA_DataSource DataSource; @@ -381,10 +481,10 @@ static void ua_add_Variable_integer(UA_Server *server, std::string regname, unsi DataSource.write = ua_write_DataSource; UA_StatusCode retval = UA_Server_addDataSourceVariableNode(server, - UA_NODEID_STRING(1, (char *)regname.c_str()), // currentNodeId + UA_NODEID_STRING(mUaLofarNameSpace, (char *)regname.c_str()), // currentNodeId UA_NODEID_NUMERIC(0, UA_NS0ID_OBJECTSFOLDER), // parentNodeId UA_NODEID_NUMERIC(0, UA_NS0ID_ORGANIZES), // parentReferenceNodeId - UA_QUALIFIEDNAME(1, (char *)regname.c_str()), // node browse name + UA_QUALIFIEDNAME(mUaLofarNameSpace, (char *)regname.c_str()), // node browse name UA_NODEID_NUMERIC(0, UA_NS0ID_BASEDATAVARIABLETYPE), vattr, DataSource, NULL, NULL); if (retval != UA_STATUSCODE_GOOD) { @@ -393,25 +493,33 @@ static void ua_add_Variable_integer(UA_Server *server, std::string regname, unsi } } -static void ua_add_Variable_int16(UA_Server *server, std::string regname, unsigned int size, std::string perm) +static void ua_add_Variable_int16(UA_Server *server, std::string regname, unsigned int size, std::string perm, bool is_scalar) { UA_LOG_INFO(UA_Log_Stdout, UA_LOGCATEGORY_USERLAND, "ua_add_Variable_int16: %s", (char *)regname.c_str()); UA_VariableAttributes vattr = UA_VariableAttributes_default; - UA_Int16 *values = (UA_Int16 *) UA_Array_new(size, &UA_TYPES[UA_TYPES_INT16]); - for(unsigned int i=0;i<size;i++) { - values[i] = UA_Int16(0); - } - UA_Variant_setArray(&vattr.value, values, size, &UA_TYPES[UA_TYPES_INT16]); if(perm == "RW") vattr.accessLevel = UA_ACCESSLEVELMASK_READ | UA_ACCESSLEVELMASK_WRITE; else if(perm == "RO") vattr.accessLevel = UA_ACCESSLEVELMASK_READ; - vattr.valueRank = UA_VALUERANK_ONE_DIMENSION; - vattr.dataType = UA_TYPES[UA_TYPES_INT16].typeId; - UA_UInt32 myArrayDimensions[1] = {size}; + if(is_scalar) { + UA_Int16 value = UA_Int16(0); + UA_Variant_setScalar(&vattr.value, &value, &UA_TYPES[UA_TYPES_INT16]); + } else { + UA_Int16 *values = (UA_Int16 *) UA_Array_new(size, &UA_TYPES[UA_TYPES_INT16]); + for(unsigned int i=0;i<size;i++) { + values[i] = UA_Int16(0); + } + + UA_Variant_setArray(&vattr.value, values, size, &UA_TYPES[UA_TYPES_INT16]); + + vattr.valueRank = UA_VALUERANK_ONE_DIMENSION; + UA_UInt32 myArrayDimensions[1] = {size}; + + vattr.arrayDimensions = myArrayDimensions; + vattr.arrayDimensionsSize = 1; + } - vattr.arrayDimensions = myArrayDimensions; - vattr.arrayDimensionsSize = 1; + vattr.dataType = UA_TYPES[UA_TYPES_INT16].typeId; vattr.displayName = UA_LOCALIZEDTEXT((char *)"locale", (char *)regname.c_str()); UA_DataSource DataSource; @@ -419,10 +527,10 @@ static void ua_add_Variable_int16(UA_Server *server, std::string regname, unsign DataSource.write = ua_write_DataSource; UA_StatusCode retval = UA_Server_addDataSourceVariableNode(server, - UA_NODEID_STRING(1, (char *)regname.c_str()), // currentNodeId + UA_NODEID_STRING(mUaLofarNameSpace, (char *)regname.c_str()), // currentNodeId UA_NODEID_NUMERIC(0, UA_NS0ID_OBJECTSFOLDER), // parentNodeId UA_NODEID_NUMERIC(0, UA_NS0ID_ORGANIZES), // parentReferenceNodeId - UA_QUALIFIEDNAME(1, (char *)regname.c_str()), // node browse name + UA_QUALIFIEDNAME(mUaLofarNameSpace, (char *)regname.c_str()), // node browse name UA_NODEID_NUMERIC(0, UA_NS0ID_BASEDATAVARIABLETYPE), vattr, DataSource, NULL, NULL); if (retval != UA_STATUSCODE_GOOD) { @@ -431,36 +539,43 @@ static void ua_add_Variable_int16(UA_Server *server, std::string regname, unsign } } -static void ua_add_Variable_float(UA_Server *server, std::string regname, unsigned int size, std::string perm) +static void ua_add_Variable_float(UA_Server *server, std::string regname, unsigned int size, std::string perm, bool is_scalar) { UA_LOG_INFO(UA_Log_Stdout, UA_LOGCATEGORY_USERLAND, "ua_add_Variable_float: %s", (char *)regname.c_str()); UA_VariableAttributes vattr = UA_VariableAttributes_default; - UA_Float *values = (UA_Float *) UA_Array_new(size, &UA_TYPES[UA_TYPES_FLOAT]); - for(unsigned int i=0;i<size;i++) { - values[i] = UA_Float(0.0); - } - UA_Variant_setArray(&vattr.value, values, size, &UA_TYPES[UA_TYPES_FLOAT]); if(perm == "RW") vattr.accessLevel = UA_ACCESSLEVELMASK_READ | UA_ACCESSLEVELMASK_WRITE; else if(perm == "RO") vattr.accessLevel = UA_ACCESSLEVELMASK_READ; - vattr.valueRank = UA_VALUERANK_ONE_DIMENSION; - vattr.dataType = UA_TYPES[UA_TYPES_FLOAT].typeId; - UA_UInt32 myArrayDimensions[1] = {size}; + if(is_scalar) { + UA_Float value = UA_Float(0.0); + UA_Variant_setScalar(&vattr.value, &value, &UA_TYPES[UA_TYPES_FLOAT]); + } else { + UA_Float *values = (UA_Float *) UA_Array_new(size, &UA_TYPES[UA_TYPES_FLOAT]); + for(unsigned int i=0;i<size;i++) { + values[i] = UA_Float(0.0); + } - vattr.arrayDimensions = myArrayDimensions; - vattr.arrayDimensionsSize = 1; - vattr.displayName = UA_LOCALIZEDTEXT((char *)"locale", (char *)regname.c_str()); + UA_Variant_setArray(&vattr.value, values, size, &UA_TYPES[UA_TYPES_FLOAT]); + vattr.valueRank = UA_VALUERANK_ONE_DIMENSION; + UA_UInt32 myArrayDimensions[1] = {size}; + + vattr.arrayDimensions = myArrayDimensions; + vattr.arrayDimensionsSize = 1; + } + + vattr.dataType = UA_TYPES[UA_TYPES_FLOAT].typeId; + vattr.displayName = UA_LOCALIZEDTEXT((char *)"locale", (char *)regname.c_str()); UA_DataSource DataSource; DataSource.read = ua_read_DataSource; DataSource.write = ua_write_DataSource; UA_StatusCode retval = UA_Server_addDataSourceVariableNode(server, - UA_NODEID_STRING(1, (char *)regname.c_str()), // currentNodeId + UA_NODEID_STRING(mUaLofarNameSpace, (char *)regname.c_str()), // currentNodeId UA_NODEID_NUMERIC(0, UA_NS0ID_OBJECTSFOLDER), // parentNodeId UA_NODEID_NUMERIC(0, UA_NS0ID_ORGANIZES), // parentReferenceNodeId - UA_QUALIFIEDNAME(1, (char *)regname.c_str()), // node browse name + UA_QUALIFIEDNAME(mUaLofarNameSpace, (char *)regname.c_str()), // node browse name UA_NODEID_NUMERIC(0, UA_NS0ID_BASEDATAVARIABLETYPE), vattr, DataSource, NULL, NULL); if (retval != UA_STATUSCODE_GOOD) { @@ -469,25 +584,33 @@ static void ua_add_Variable_float(UA_Server *server, std::string regname, unsign } } -static void ua_add_Variable_boolean(UA_Server *server, std::string regname, unsigned int size, std::string perm) +static void ua_add_Variable_boolean(UA_Server *server, std::string regname, unsigned int size, std::string perm, bool is_scalar) { UA_LOG_INFO(UA_Log_Stdout, UA_LOGCATEGORY_USERLAND, "ua_add_Variable_boolean: %s", (char *)regname.c_str()); UA_VariableAttributes vattr = UA_VariableAttributes_default; - UA_Boolean *values = (UA_Boolean *) UA_Array_new(size, &UA_TYPES[UA_TYPES_BOOLEAN]); - for(unsigned int i=0;i<size;i++) { - values[i] = UA_Boolean(false); - } - UA_Variant_setArray(&vattr.value, values, size, &UA_TYPES[UA_TYPES_BOOLEAN]); if(perm == "RW") vattr.accessLevel = UA_ACCESSLEVELMASK_READ | UA_ACCESSLEVELMASK_WRITE; else if(perm == "RO") vattr.accessLevel = UA_ACCESSLEVELMASK_READ; - vattr.valueRank = UA_VALUERANK_ONE_DIMENSION; - vattr.dataType = UA_TYPES[UA_TYPES_BOOLEAN].typeId; - UA_UInt32 myArrayDimensions[1] = {size}; + if(is_scalar) { + UA_Boolean value = UA_Boolean(false); + UA_Variant_setScalar(&vattr.value, &value, &UA_TYPES[UA_TYPES_BOOLEAN]); + } else { + UA_Boolean *values = (UA_Boolean *) UA_Array_new(size, &UA_TYPES[UA_TYPES_BOOLEAN]); + for(unsigned int i=0;i<size;i++) { + values[i] = UA_Boolean(false); + } + + UA_Variant_setArray(&vattr.value, values, size, &UA_TYPES[UA_TYPES_BOOLEAN]); + + vattr.valueRank = UA_VALUERANK_ONE_DIMENSION; + UA_UInt32 myArrayDimensions[1] = {size}; + + vattr.arrayDimensions = myArrayDimensions; + vattr.arrayDimensionsSize = 1; + } - vattr.arrayDimensions = myArrayDimensions; - vattr.arrayDimensionsSize = 1; + vattr.dataType = UA_TYPES[UA_TYPES_BOOLEAN].typeId; vattr.displayName = UA_LOCALIZEDTEXT((char *)"locale", (char *)regname.c_str()); UA_DataSource DataSource; @@ -495,10 +618,10 @@ static void ua_add_Variable_boolean(UA_Server *server, std::string regname, unsi DataSource.write = ua_write_DataSource; UA_StatusCode retval = UA_Server_addDataSourceVariableNode(server, - UA_NODEID_STRING(1, (char *)regname.c_str()), // currentNodeId + UA_NODEID_STRING(mUaLofarNameSpace, (char *)regname.c_str()), // currentNodeId UA_NODEID_NUMERIC(0, UA_NS0ID_OBJECTSFOLDER), // parentNodeId UA_NODEID_NUMERIC(0, UA_NS0ID_ORGANIZES), // parentReferenceNodeId - UA_QUALIFIEDNAME(1, (char *)regname.c_str()), // node browse name + UA_QUALIFIEDNAME(mUaLofarNameSpace, (char *)regname.c_str()), // node browse name UA_NODEID_NUMERIC(0, UA_NS0ID_BASEDATAVARIABLETYPE), vattr, DataSource, NULL, NULL); if (retval != UA_STATUSCODE_GOOD) { @@ -507,23 +630,23 @@ static void ua_add_Variable_boolean(UA_Server *server, std::string regname, unsi } } -static void ua_add_Variable(UA_Server *server, std::string regname, int format, unsigned int size, std::string perm) +static void ua_add_Variable(UA_Server *server, std::string regname, int format, unsigned int size, std::string perm, bool is_scalar) { switch(format) { case REG_FORMAT_STRING: - ua_add_Variable_string(server, regname, size, perm); + ua_add_Variable_string(server, regname, size, perm, is_scalar); break; case REG_FORMAT_INTEGER: - ua_add_Variable_integer(server, regname, size, perm); + ua_add_Variable_integer(server, regname, size, perm, is_scalar); break; case REG_FORMAT_INT16: - ua_add_Variable_int16(server, regname, size, perm); + ua_add_Variable_int16(server, regname, size, perm, is_scalar); break; case REG_FORMAT_FLOAT: - ua_add_Variable_float(server, regname, size, perm); + ua_add_Variable_float(server, regname, size, perm, is_scalar); break; case REG_FORMAT_BOOLEAN: - ua_add_Variable_boolean(server, regname, size, perm); + ua_add_Variable_boolean(server, regname, size, perm, is_scalar); break; default: return; // not yet supported @@ -536,6 +659,11 @@ int ua_server_init(bool warm_start) mUaServer = UA_Server_new(); UA_ServerConfig_setDefault(UA_Server_getConfig(mUaServer)); +#define UA_LOFAR_NAMESPACE "http://lofar.eu" + mUaLofarNameSpace = UA_Server_addNamespace(mUaServer, UA_LOFAR_NAMESPACE); + UA_LOG_INFO(UA_Log_Stdout, UA_LOGCATEGORY_USERLAND, "UA Server ns=%d for %s\n", + mUaLofarNameSpace,UA_LOFAR_NAMESPACE); + TermOutput termout; std::vector<int> nodes = SD.unb->get_nodes(); // all nodes @@ -548,7 +676,7 @@ int ua_server_init(bool warm_start) int format = pointmap->getFormat(m); unsigned int size = pointmap->getSpan(m); std::string perm = pointmap->getPerm(m); - ua_add_Variable(mUaServer, m, format, size, perm); + ua_add_Variable(mUaServer, m, format, size, perm, false); } RegisterMap *trmap = SD.tr->getTranslatorMap(); @@ -557,7 +685,7 @@ int ua_server_init(bool warm_start) int format = trmap->getFormat(m); unsigned int size = trmap->getSpan(m); std::string perm = trmap->getPerm(m); - ua_add_Variable(mUaServer, m, format, size, perm); + ua_add_Variable(mUaServer, m, format, size, perm, true); } } return 0; diff --git a/src/sdpunb.cpp b/src/sdpunb.cpp index d8ed1f3ff85754f575cf7d5cf49e3edfd98f8a22..f4364c3b257647b09b1c53245bd544fea21df479 100644 --- a/src/sdpunb.cpp +++ b/src/sdpunb.cpp @@ -85,7 +85,7 @@ void monitor(const int clientId) struct timeval current_time; SD.t0.tv_sec = SD.t0.tv_sec + SD.timetick; // specify next position in time - SD.t0.tv_nsec = 499999999L; // 0..999999999 // adjust in the middle of a second + SD.t0.tv_nsec = 10000000L; // 0..999999999 // offset 10ms in a new second pthread_mutex_lock(&SD.newpoint_lock); pthread_cond_timedwait(&SD.newpoint_cond, &SD.newpoint_lock,(const struct timespec *)&SD.t0); pthread_mutex_unlock(&SD.newpoint_lock); @@ -98,7 +98,12 @@ void monitor(const int clientId) SD.tod = current_time.tv_sec; while(!SD.control_mutex[clientId].try_lock()) { cerr << "monitor: mutex not ready\n"; usleep(10000); } - if(SD.unb != NULL) SD.unb->monitor(clientId, termout); + if(SD.unb != NULL) { + SD.unb->monitor(clientId, termout); + + // Do PPS monitor here too, see: https://support.astron.nl/jira/browse/L2SDP-225 + } + SD.control_mutex[clientId].unlock(); if(cmdstatusnew.status != CMD_EMPTY) cmdstatus = cmdstatusnew; diff --git a/test/py/Client.py b/test/py/Client.py index f3fba047b4465bc13721c9a5679324408766b0b7..43da4935cdcc0cfc8ed7504189da9ff001e15764 100644 --- a/test/py/Client.py +++ b/test/py/Client.py @@ -128,55 +128,18 @@ if __name__ == "__main__": print("\t\tchild", i, ": ", children[i].get_browse_name()) - #exit(1) - print("\t\t\t", "child 9 has a value of: ", children[9].get_value()) - print("\t\t\t", "child 9 has a datatype of: ", children[9].get_data_type()) - print("\t\t\t", "child 9 has a datatypevar of: ", children[9].get_data_type_as_variant_type()) - print("\t\t\t", "child 9 has a descr of: ", children[9].get_description()) - print("\t\t\t", "child 9 has a dimensions of: ", children[9].get_array_dimensions()) - print("\t\t\t", "child 9 has a rank of: ", children[9].get_value_rank()) - - print("\t\t\t", "child 11 has a value of: ", children[11].get_value()) - print("\t\t\t", "child 11 has a datatype of: ", children[11].get_data_type()) - print("\t\t\t", "child 11 has a datatypevar of: ", children[11].get_data_type_as_variant_type()) - print("\t\t\t", "child 11 has a descr of: ", children[11].get_description()) - print("\t\t\t", "child 11 has a dimensions of: ", children[11].get_array_dimensions()) - print("\t\t\t", "child 11 has a rank of: ", children[11].get_value_rank()) - - print("\t\t\t", "child 12 has a value of: ", children[12].get_value()) - print("\t\t\t", "child 12 has a datatype of: ", children[12].get_data_type()) - print("\t\t\t", "child 12 has a datatypevar of: ", children[12].get_data_type_as_variant_type()) - print("\t\t\t", "child 12 has a descr of: ", children[12].get_description()) - print("\t\t\t", "child 12 has a dimensions of: ", children[12].get_array_dimensions()) - print("\t\t\t", "child 12 has a rank of: ", children[12].get_value_rank()) - -# #print("\t\t\t", "child 0 has a value of: ", children[0].get_value()) -# print("\t\t\t", "child 1 has a value of: ", children[1].get_value()) -# print("\t\t\t", "child 1 has a datatype of: ", children[1].get_data_type()) -# print("\t\t\t", "child 1 has a datatypevar of: ", children[1].get_data_type_as_variant_type()) -# print("\t\t\t", "child 1 has a descr of: ", children[1].get_description()) -# #print("\t\t\t", "child 1 has a datavalue of: ", children[1].get_data_value()) -# print("\t\t\t", "child 1 has a dimensions of: ", children[1].get_array_dimensions()) -# print("\t\t\t", "child 1 has a rank of: ", children[1].get_value_rank()) -# -# -# -# print("\t\t\t", "child 2 has a value of: ", children[2].get_value()) -# print("\t\t\t", "child 2 has a datatype of: ", children[2].get_data_type()) -# print("\t\t\t", "child 2 has a datatypevar of: ", children[2].get_data_type_as_variant_type()) -# print("\t\t\t", "child 2 has a descr of: ", children[2].get_description()) -# print("\t\t\t", "child 2 has a datavalue of: ", children[2].get_data_value()) -# print("\t\t\t", "child 2 has a dimensions of: ", children[2].get_array_dimensions()) -# print("\t\t\t", "child 2 has a rank of: ", children[2].get_value_rank()) -## children[2].set_value(value=cnt, varianttype=ua.VariantType.Int32) -## while True: -## print("\t\t\t", "child 2 has a value of: ", children[2].get_value()) -## children[2].set_value(value=mask, varianttype=ua.VariantType.Boolean) -## sys.sleep(1) -# -# cnt = cnt + 1 -# print("\t\t\t", "child 2 has a value of: ", children[2].get_value()) -# + for i in range(len(children)): + if i == 0: continue + if i == 7: continue # too much output + if i == 8: continue # too much output + print("\t\t\t", "child ", i, " has a value of: ", children[i].get_value()) + print("\t\t\t", "child ", i, " has a datatype of: ", children[i].get_data_type()) + print("\t\t\t", "child ", i, " has a datatypevar of: ", children[i].get_data_type_as_variant_type()) + print("\t\t\t", "child ", i, " has a descr of: ", children[i].get_description()) + print("\t\t\t", "child ", i, " has a dimensions of: ", children[i].get_array_dimensions()) + print("\t\t\t", "child ", i, " has a rank of: ", children[i].get_value_rank()) + + # print("WRITE SCRAP"); # children[3].set_value(value=scraps, varianttype=ua.VariantType.Int32) # @@ -188,44 +151,7 @@ if __name__ == "__main__": # print("\t\t\t", "child 3 has a datavalue of: ", children[3].get_data_value()) # print("\t\t\t", "child 3 has a dimensions of: ", children[3].get_array_dimensions()) # print("\t\t\t", "child 3 has a rank of: ", children[3].get_value_rank()) -# -# print("\t\t\t", "child 4 has a value of: ", children[4].get_value()) -# print("\t\t\t", "child 4 has a value of: ", children[4].get_value()) -# print("\t\t\t", "child 4 has a datatype of: ", children[4].get_data_type()) -# print("\t\t\t", "child 4 has a datatypevar of: ", children[4].get_data_type_as_variant_type()) -# print("\t\t\t", "child 4 has a descr of: ", children[4].get_description()) -# print("\t\t\t", "child 4 has a datavalue of: ", children[4].get_data_value()) -# print("\t\t\t", "child 4 has a dimensions of: ", children[4].get_array_dimensions()) -# print("\t\t\t", "child 4 has a rank of: ", children[4].get_value_rank()) -# -# print("\t\t\t", "child 5 has a value of: ", children[5].get_value()) -# print("\t\t\t", "child 5 has a value of: ", children[5].get_value()) -# print("\t\t\t", "child 5 has a datatype of: ", children[5].get_data_type()) -# print("\t\t\t", "child 5 has a datatypevar of: ", children[5].get_data_type_as_variant_type()) -# print("\t\t\t", "child 5 has a descr of: ", children[5].get_description()) -# print("\t\t\t", "child 5 has a datavalue of: ", children[5].get_data_value()) -# print("\t\t\t", "child 5 has a dimensions of: ", children[5].get_array_dimensions()) -# print("\t\t\t", "child 5 has a rank of: ", children[5].get_value_rank()) -# -# print("\t\t\t", "child 6 has a value of: ", children[6].get_value()) -# print("\t\t\t", "child 6 has a value of: ", children[6].get_value()) -# print("\t\t\t", "child 6 has a datatype of: ", children[6].get_data_type()) -# print("\t\t\t", "child 6 has a datatypevar of: ", children[6].get_data_type_as_variant_type()) -# print("\t\t\t", "child 6 has a descr of: ", children[6].get_description()) -# print("\t\t\t", "child 6 has a datavalue of: ", children[6].get_data_value()) -# print("\t\t\t", "child 6 has a dimensions of: ", children[6].get_array_dimensions()) -# print("\t\t\t", "child 6 has a rank of: ", children[6].get_value_rank()) -# -# print("\t\t\t", "child 7 has a value of: ", children[7].get_value()) -# print("\t\t\t", "child 7 has a value of: ", children[7].get_value()) -# print("\t\t\t", "child 7 has a datatype of: ", children[7].get_data_type()) -# print("\t\t\t", "child 7 has a datatypevar of: ", children[7].get_data_type_as_variant_type()) -# print("\t\t\t", "child 7 has a descr of: ", children[7].get_description()) -# print("\t\t\t", "child 7 has a datavalue of: ", children[7].get_data_value()) -# print("\t\t\t", "child 7 has a dimensions of: ", children[7].get_array_dimensions()) -# print("\t\t\t", "child 7 has a rank of: ", children[7].get_value_rank()) -# -# + # print("WRITE WEIGHTS"); # tic = time.time() # children[8].set_value(value=weights, varianttype=ua.VariantType.Int16) @@ -242,14 +168,6 @@ if __name__ == "__main__": # print("\t\t\t", "child 8 has a rank of: ", children[8].get_value_rank()) - - #while Temp_only: - #explore_temp(children[1]) - #time.sleep(1) - - - - #explore(children[1]) clientRunning = False break; #sys.exit(0)