static UA_StatusCode deleteHistory(UA_DateTime start, UA_DateTime end) { UA_DeleteRawModifiedDetails *details = UA_DeleteRawModifiedDetails_new(); details->startTime = start; details->endTime = end; details->isDeleteModified = false; UA_NodeId_copy(&outNodeId, &details->nodeId); UA_HistoryUpdateRequest request; UA_HistoryUpdateRequest_init(&request); request.historyUpdateDetailsSize = 1; request.historyUpdateDetails = UA_ExtensionObject_new(); UA_ExtensionObject_init(request.historyUpdateDetails); request.historyUpdateDetails[0].encoding = UA_EXTENSIONOBJECT_DECODED; request.historyUpdateDetails[0].content.decoded.type = &UA_TYPES[UA_TYPES_DELETERAWMODIFIEDDETAILS]; request.historyUpdateDetails[0].content.decoded.data = details; UA_HistoryUpdateResponse response; UA_HistoryUpdateResponse_init(&response); Service_HistoryUpdate(server, &server->adminSession, &request, &response); UA_HistoryUpdateRequest_deleteMembers(&request); UA_StatusCode ret = UA_STATUSCODE_GOOD; if (response.responseHeader.serviceResult != UA_STATUSCODE_GOOD) ret = response.responseHeader.serviceResult; else if (response.resultsSize != 1) ret = UA_STATUSCODE_BADUNEXPECTEDERROR; else if (response.results[0].statusCode != UA_STATUSCODE_GOOD) ret = response.results[0].statusCode; else if (response.results[0].operationResultsSize != 0) ret = UA_STATUSCODE_BADUNEXPECTEDERROR; UA_HistoryUpdateResponse_deleteMembers(&response); return ret; }
static UA_StatusCode updateHistory(UA_PerformUpdateType updateType, UA_DateTime *updateData, UA_StatusCode ** operationResults, size_t *operationResultsSize) { UA_UpdateDataDetails *details = UA_UpdateDataDetails_new(); details->performInsertReplace = updateType; UA_NodeId_copy(&outNodeId, &details->nodeId); int updateDataSize = -1; while(updateData[++updateDataSize]); fprintf(stderr, "updateHistory for %d values.\n", updateDataSize); details->updateValuesSize = (size_t)updateDataSize; details->updateValues = (UA_DataValue*)UA_Array_new(details->updateValuesSize, &UA_TYPES[UA_TYPES_DATAVALUE]); for (size_t i = 0; i < details->updateValuesSize; ++i) { UA_DataValue_init(&details->updateValues[i]); details->updateValues[i].hasValue = true; UA_Int64 d = updateType; UA_Variant_setScalarCopy(&details->updateValues[i].value, &d, &UA_TYPES[UA_TYPES_INT64]); details->updateValues[i].hasSourceTimestamp = true; details->updateValues[i].sourceTimestamp = updateData[i]; details->updateValues[i].hasServerTimestamp = true; details->updateValues[i].serverTimestamp = updateData[i]; details->updateValues[i].hasStatus = true; details->updateValues[i].status = UA_STATUSCODE_GOOD; } UA_HistoryUpdateRequest request; UA_HistoryUpdateRequest_init(&request); request.historyUpdateDetailsSize = 1; request.historyUpdateDetails = UA_ExtensionObject_new(); UA_ExtensionObject_init(request.historyUpdateDetails); request.historyUpdateDetails[0].encoding = UA_EXTENSIONOBJECT_DECODED; request.historyUpdateDetails[0].content.decoded.type = &UA_TYPES[UA_TYPES_UPDATEDATADETAILS]; request.historyUpdateDetails[0].content.decoded.data = details; UA_HistoryUpdateResponse response; UA_HistoryUpdateResponse_init(&response); Service_HistoryUpdate(server, &server->adminSession, &request, &response); UA_HistoryUpdateRequest_deleteMembers(&request); UA_StatusCode ret = UA_STATUSCODE_GOOD; if (response.responseHeader.serviceResult != UA_STATUSCODE_GOOD) ret = response.responseHeader.serviceResult; else if (response.resultsSize != 1) ret = UA_STATUSCODE_BADUNEXPECTEDERROR; else if (response.results[0].statusCode != UA_STATUSCODE_GOOD) ret = response.results[0].statusCode; else if (response.results[0].operationResultsSize != (size_t)updateDataSize) ret = UA_STATUSCODE_BADUNEXPECTEDERROR; else { if (operationResults) { *operationResultsSize = response.results[0].operationResultsSize; ret = UA_Array_copy(response.results[0].operationResults, *operationResultsSize, (void**)operationResults, &UA_TYPES[UA_TYPES_STATUSCODE]); } else { for (size_t i = 0; i < response.results[0].operationResultsSize; ++i) { if (response.results[0].operationResults[i] != UA_STATUSCODE_GOOD) { ret = response.results[0].operationResults[i]; break; } } } } UA_HistoryUpdateResponse_deleteMembers(&response); return ret; }
static UA_StatusCode register_server_with_discovery_server(UA_Server *server, const char* discoveryServerUrl, const UA_Boolean isUnregister, const char* semaphoreFilePath) { if(!discoveryServerUrl) { UA_LOG_ERROR(server->config.logger, UA_LOGCATEGORY_SERVER, "No discovery server url provided"); return UA_STATUSCODE_BADINTERNALERROR; } /* Create the client */ UA_Client *client = UA_Client_new(UA_ClientConfig_default); if(!client) return UA_STATUSCODE_BADOUTOFMEMORY; /* Connect the client */ UA_StatusCode retval = UA_Client_connect(client, discoveryServerUrl); if(retval != UA_STATUSCODE_GOOD) { UA_LOG_ERROR(server->config.logger, UA_LOGCATEGORY_CLIENT, "Connecting to the discovery server failed with statuscode %s", UA_StatusCode_name(retval)); UA_Client_delete(client); return retval; } /* Prepare the request. Do not cleanup the request after the service call, * as the members are stack-allocated or point into the server config. */ UA_RegisterServer2Request request; UA_RegisterServer2Request_init(&request); request.requestHeader.timestamp = UA_DateTime_now(); request.requestHeader.timeoutHint = 10000; request.server.isOnline = !isUnregister; request.server.serverUri = server->config.applicationDescription.applicationUri; request.server.productUri = server->config.applicationDescription.productUri; request.server.serverType = server->config.applicationDescription.applicationType; request.server.gatewayServerUri = server->config.applicationDescription.gatewayServerUri; if(semaphoreFilePath) { #ifdef UA_ENABLE_DISCOVERY_SEMAPHORE request.server.semaphoreFilePath = UA_STRING((char*)(uintptr_t)semaphoreFilePath); /* dirty cast */ #else UA_LOG_WARNING(server->config.logger, UA_LOGCATEGORY_CLIENT, "Ignoring semaphore file path. open62541 not compiled " "with UA_ENABLE_DISCOVERY_SEMAPHORE=ON"); #endif } request.server.serverNames = &server->config.applicationDescription.applicationName; request.server.serverNamesSize = 1; /* Copy the discovery urls from the server config and the network layers*/ size_t config_discurls = server->config.applicationDescription.discoveryUrlsSize; size_t nl_discurls = server->config.networkLayersSize; size_t total_discurls = config_discurls * nl_discurls; request.server.discoveryUrls = (UA_String*)UA_alloca(sizeof(UA_String) * total_discurls); request.server.discoveryUrlsSize = config_discurls + nl_discurls; for(size_t i = 0; i < config_discurls; ++i) request.server.discoveryUrls[i] = server->config.applicationDescription.discoveryUrls[i]; /* TODO: Add nl only if discoveryUrl not already present */ for(size_t i = 0; i < nl_discurls; ++i) { UA_ServerNetworkLayer *nl = &server->config.networkLayers[i]; request.server.discoveryUrls[config_discurls + i] = nl->discoveryUrl; } UA_MdnsDiscoveryConfiguration mdnsConfig; UA_MdnsDiscoveryConfiguration_init(&mdnsConfig); request.discoveryConfigurationSize = 1; request.discoveryConfiguration = UA_ExtensionObject_new(); UA_ExtensionObject_init(&request.discoveryConfiguration[0]); request.discoveryConfiguration[0].encoding = UA_EXTENSIONOBJECT_DECODED_NODELETE; request.discoveryConfiguration[0].content.decoded.type = &UA_TYPES[UA_TYPES_MDNSDISCOVERYCONFIGURATION]; request.discoveryConfiguration[0].content.decoded.data = &mdnsConfig; mdnsConfig.mdnsServerName = server->config.mdnsServerName; mdnsConfig.serverCapabilities = server->config.serverCapabilities; mdnsConfig.serverCapabilitiesSize = server->config.serverCapabilitiesSize; // First try with RegisterServer2, if that isn't implemented, use RegisterServer UA_RegisterServer2Response response; UA_RegisterServer2Response_init(&response); __UA_Client_Service(client, &request, &UA_TYPES[UA_TYPES_REGISTERSERVER2REQUEST], &response, &UA_TYPES[UA_TYPES_REGISTERSERVER2RESPONSE]); UA_StatusCode serviceResult = response.responseHeader.serviceResult; UA_RegisterServer2Response_deleteMembers(&response); UA_ExtensionObject_delete(request.discoveryConfiguration); if(serviceResult == UA_STATUSCODE_BADNOTIMPLEMENTED || serviceResult == UA_STATUSCODE_BADSERVICEUNSUPPORTED) { /* Try RegisterServer */ UA_RegisterServerRequest request_fallback; UA_RegisterServerRequest_init(&request_fallback); /* Copy from RegisterServer2 request */ request_fallback.requestHeader = request.requestHeader; request_fallback.server = request.server; UA_RegisterServerResponse response_fallback; UA_RegisterServerResponse_init(&response_fallback); __UA_Client_Service(client, &request_fallback, &UA_TYPES[UA_TYPES_REGISTERSERVERREQUEST], &response_fallback, &UA_TYPES[UA_TYPES_REGISTERSERVERRESPONSE]); serviceResult = response_fallback.responseHeader.serviceResult; UA_RegisterServerResponse_deleteMembers(&response_fallback); } if(serviceResult != UA_STATUSCODE_GOOD) { UA_LOG_ERROR(server->config.logger, UA_LOGCATEGORY_CLIENT, "RegisterServer/RegisterServer2 failed with statuscode %s", UA_StatusCode_name(serviceResult)); } UA_Client_disconnect(client); UA_Client_delete(client); return serviceResult; }
static UA_StatusCode register_server_with_discovery_server(UA_Server *server, UA_Client *client, const UA_Boolean isUnregister, const char* semaphoreFilePath) { /* Prepare the request. Do not cleanup the request after the service call, * as the members are stack-allocated or point into the server config. */ UA_RegisterServer2Request request; UA_RegisterServer2Request_init(&request); request.requestHeader.timestamp = UA_DateTime_now(); request.requestHeader.timeoutHint = 10000; request.server.isOnline = !isUnregister; request.server.serverUri = server->config.applicationDescription.applicationUri; request.server.productUri = server->config.applicationDescription.productUri; request.server.serverType = server->config.applicationDescription.applicationType; request.server.gatewayServerUri = server->config.applicationDescription.gatewayServerUri; if(semaphoreFilePath) { #ifdef UA_ENABLE_DISCOVERY_SEMAPHORE request.server.semaphoreFilePath = UA_STRING((char*)(uintptr_t)semaphoreFilePath); /* dirty cast */ #else UA_LOG_WARNING(&server->config.logger, UA_LOGCATEGORY_CLIENT, "Ignoring semaphore file path. open62541 not compiled " "with UA_ENABLE_DISCOVERY_SEMAPHORE=ON"); #endif } request.server.serverNames = &server->config.applicationDescription.applicationName; request.server.serverNamesSize = 1; /* Copy the discovery urls from the server config and the network layers*/ size_t config_discurls = server->config.applicationDescription.discoveryUrlsSize; size_t nl_discurls = server->config.networkLayersSize; size_t total_discurls = config_discurls + nl_discurls; UA_STACKARRAY(UA_String, urlsBuf, total_discurls); request.server.discoveryUrls = urlsBuf; request.server.discoveryUrlsSize = total_discurls; for(size_t i = 0; i < config_discurls; ++i) request.server.discoveryUrls[i] = server->config.applicationDescription.discoveryUrls[i]; /* TODO: Add nl only if discoveryUrl not already present */ for(size_t i = 0; i < nl_discurls; ++i) { UA_ServerNetworkLayer *nl = &server->config.networkLayers[i]; request.server.discoveryUrls[config_discurls + i] = nl->discoveryUrl; } #ifdef UA_ENABLE_DISCOVERY_MULTICAST request.discoveryConfigurationSize = 1; request.discoveryConfiguration = UA_ExtensionObject_new(); UA_ExtensionObject_init(&request.discoveryConfiguration[0]); // Set to NODELETE so that we can just use a pointer to the mdns config request.discoveryConfiguration[0].encoding = UA_EXTENSIONOBJECT_DECODED_NODELETE; request.discoveryConfiguration[0].content.decoded.type = &UA_TYPES[UA_TYPES_MDNSDISCOVERYCONFIGURATION]; request.discoveryConfiguration[0].content.decoded.data = &server->config.discovery.mdns; #endif // First try with RegisterServer2, if that isn't implemented, use RegisterServer UA_RegisterServer2Response response; __UA_Client_Service(client, &request, &UA_TYPES[UA_TYPES_REGISTERSERVER2REQUEST], &response, &UA_TYPES[UA_TYPES_REGISTERSERVER2RESPONSE]); UA_StatusCode serviceResult = response.responseHeader.serviceResult; UA_RegisterServer2Response_deleteMembers(&response); UA_Array_delete(request.discoveryConfiguration, request.discoveryConfigurationSize, &UA_TYPES[UA_TYPES_EXTENSIONOBJECT]); request.discoveryConfiguration = NULL; request.discoveryConfigurationSize = 0; if(serviceResult == UA_STATUSCODE_BADNOTIMPLEMENTED || serviceResult == UA_STATUSCODE_BADSERVICEUNSUPPORTED) { /* Try RegisterServer */ UA_RegisterServerRequest request_fallback; UA_RegisterServerRequest_init(&request_fallback); /* Copy from RegisterServer2 request */ request_fallback.requestHeader = request.requestHeader; request_fallback.server = request.server; UA_RegisterServerResponse response_fallback; __UA_Client_Service(client, &request_fallback, &UA_TYPES[UA_TYPES_REGISTERSERVERREQUEST], &response_fallback, &UA_TYPES[UA_TYPES_REGISTERSERVERRESPONSE]); serviceResult = response_fallback.responseHeader.serviceResult; UA_RegisterServerResponse_deleteMembers(&response_fallback); } if(serviceResult != UA_STATUSCODE_GOOD) { UA_LOG_ERROR(&server->config.logger, UA_LOGCATEGORY_CLIENT, "RegisterServer/RegisterServer2 failed with statuscode %s", UA_StatusCode_name(serviceResult)); } return serviceResult; }