#include "ua_server_internal.h"
#ifdef UA_GENERATED_NAMESPACE_ZERO
#include "open62541/namespace0_generated.h"
#endif
#include "ua_session.h"
#include "ua_subscription.h"
static UA_StatusCode
ns0_addNode_raw(UA_Server *server, UA_NodeClass nodeClass,
UA_UInt32 nodeId, char *name, void *attributes,
const UA_DataType *attributesType) {
UA_AddNodesItem item;
UA_AddNodesItem_init(&item);
item.nodeClass = nodeClass;
item.requestedNewNodeId.nodeId = UA_NODEID_NUMERIC(0, nodeId);
item.browseName = UA_QUALIFIEDNAME(0, name);
UA_ExtensionObject_setValueNoDelete(&item.nodeAttributes,
attributes, attributesType);
return addNode_raw(server, &server->adminSession, NULL, &item, NULL);
}
static UA_StatusCode
ns0_addNode_finish(UA_Server *server, UA_UInt32 nodeId,
UA_UInt32 parentNodeId, UA_UInt32 referenceTypeId) {
const UA_NodeId sourceId = UA_NODEID_NUMERIC(0, nodeId);
const UA_NodeId refTypeId = UA_NODEID_NUMERIC(0, referenceTypeId);
const UA_NodeId targetId = UA_NODEID_NUMERIC(0, parentNodeId);
UA_StatusCode retval = addRef(server, sourceId, refTypeId, targetId, false);
if(retval != UA_STATUSCODE_GOOD)
return retval;
return addNode_finish(server, &server->adminSession, &sourceId);
}
static UA_StatusCode
addObjectNode(UA_Server *server, char* name, UA_UInt32 objectid,
UA_UInt32 parentid, UA_UInt32 referenceid, UA_UInt32 type_id) {
UA_ObjectAttributes object_attr = UA_ObjectAttributes_default;
object_attr.displayName = UA_LOCALIZEDTEXT("", name);
return addNode(server, UA_NODECLASS_OBJECT, UA_NODEID_NUMERIC(0, objectid),
UA_NODEID_NUMERIC(0, parentid), UA_NODEID_NUMERIC(0, referenceid),
UA_QUALIFIEDNAME(0, name), UA_NODEID_NUMERIC(0, type_id),
&object_attr, &UA_TYPES[UA_TYPES_OBJECTATTRIBUTES],
NULL, NULL);
}
static UA_StatusCode
addReferenceTypeNode(UA_Server *server, char* name, char *inverseName, UA_UInt32 referencetypeid,
UA_Boolean isabstract, UA_Boolean symmetric, UA_UInt32 parentid) {
UA_ReferenceTypeAttributes reference_attr = UA_ReferenceTypeAttributes_default;
reference_attr.displayName = UA_LOCALIZEDTEXT("", name);
reference_attr.isAbstract = isabstract;
reference_attr.symmetric = symmetric;
if(inverseName)
reference_attr.inverseName = UA_LOCALIZEDTEXT("", inverseName);
return addNode(server, UA_NODECLASS_REFERENCETYPE, UA_NODEID_NUMERIC(0, referencetypeid),
UA_NODEID_NUMERIC(0, parentid), UA_NODEID_NULL, UA_QUALIFIEDNAME(0, name),
UA_NODEID_NULL, &reference_attr,
&UA_TYPES[UA_TYPES_REFERENCETYPEATTRIBUTES], NULL, NULL);
}
static UA_StatusCode
createNS0_base(UA_Server *server) {
UA_StatusCode ret = UA_STATUSCODE_GOOD;
UA_ReferenceTypeAttributes references_attr = UA_ReferenceTypeAttributes_default;
references_attr.displayName = UA_LOCALIZEDTEXT("", "References");
references_attr.isAbstract = true;
references_attr.symmetric = true;
references_attr.inverseName = UA_LOCALIZEDTEXT("", "References");
ret |= ns0_addNode_raw(server, UA_NODECLASS_REFERENCETYPE, UA_NS0ID_REFERENCES, "References",
&references_attr, &UA_TYPES[UA_TYPES_REFERENCETYPEATTRIBUTES]);
UA_ReferenceTypeAttributes hassubtype_attr = UA_ReferenceTypeAttributes_default;
hassubtype_attr.displayName = UA_LOCALIZEDTEXT("", "HasSubtype");
hassubtype_attr.isAbstract = false;
hassubtype_attr.symmetric = false;
hassubtype_attr.inverseName = UA_LOCALIZEDTEXT("", "SubtypeOf");
ret |= ns0_addNode_raw(server, UA_NODECLASS_REFERENCETYPE, UA_NS0ID_HASSUBTYPE, "HasSubtype",
&hassubtype_attr, &UA_TYPES[UA_TYPES_REFERENCETYPEATTRIBUTES]);
UA_ReferenceTypeAttributes aggregates_attr = UA_ReferenceTypeAttributes_default;
aggregates_attr.displayName = UA_LOCALIZEDTEXT("", "Aggregates");
aggregates_attr.isAbstract = true;
aggregates_attr.symmetric = false;
aggregates_attr.inverseName = UA_LOCALIZEDTEXT("", "AggregatedBy");
ret |= ns0_addNode_raw(server, UA_NODECLASS_REFERENCETYPE, UA_NS0ID_AGGREGATES, "Aggregates",
&aggregates_attr, &UA_TYPES[UA_TYPES_REFERENCETYPEATTRIBUTES]);
ret |= addReferenceTypeNode(server, "HierarchicalReferences", NULL,
UA_NS0ID_HIERARCHICALREFERENCES, true, false, UA_NS0ID_REFERENCES);
ret |= addReferenceTypeNode(server, "NonHierarchicalReferences", NULL,
UA_NS0ID_NONHIERARCHICALREFERENCES, true, true, UA_NS0ID_REFERENCES);
ret |= addReferenceTypeNode(server, "HasChild", NULL, UA_NS0ID_HASCHILD,
true, false, UA_NS0ID_HIERARCHICALREFERENCES);
ret |= addReferenceTypeNode(server, "Organizes", "OrganizedBy", UA_NS0ID_ORGANIZES,
false, false, UA_NS0ID_HIERARCHICALREFERENCES);
ret |= addReferenceTypeNode(server, "HasEventSource", "EventSourceOf", UA_NS0ID_HASEVENTSOURCE,
false, false, UA_NS0ID_HIERARCHICALREFERENCES);
ret |= addReferenceTypeNode(server, "HasModellingRule", "ModellingRuleOf", UA_NS0ID_HASMODELLINGRULE,
false, false, UA_NS0ID_NONHIERARCHICALREFERENCES);
ret |= addReferenceTypeNode(server, "HasEncoding", "EncodingOf", UA_NS0ID_HASENCODING,
false, false, UA_NS0ID_NONHIERARCHICALREFERENCES);
ret |= addReferenceTypeNode(server, "HasDescription", "DescriptionOf", UA_NS0ID_HASDESCRIPTION,
false, false, UA_NS0ID_NONHIERARCHICALREFERENCES);
ret |= addReferenceTypeNode(server, "HasTypeDefinition", "TypeDefinitionOf", UA_NS0ID_HASTYPEDEFINITION,
false, false, UA_NS0ID_NONHIERARCHICALREFERENCES);
ret |= addReferenceTypeNode(server, "GeneratesEvent", "GeneratedBy", UA_NS0ID_GENERATESEVENT,
false, false, UA_NS0ID_NONHIERARCHICALREFERENCES);
ret |= ns0_addNode_finish(server, UA_NS0ID_AGGREGATES, UA_NS0ID_HASCHILD, UA_NS0ID_HASSUBTYPE);
ret |= ns0_addNode_finish(server, UA_NS0ID_HASSUBTYPE, UA_NS0ID_HASCHILD, UA_NS0ID_HASSUBTYPE);
ret |= addReferenceTypeNode(server, "HasProperty", "PropertyOf", UA_NS0ID_HASPROPERTY,
false, false, UA_NS0ID_AGGREGATES);
ret |= addReferenceTypeNode(server, "HasComponent", "ComponentOf", UA_NS0ID_HASCOMPONENT,
false, false, UA_NS0ID_AGGREGATES);
ret |= addReferenceTypeNode(server, "HasNotifier", "NotifierOf", UA_NS0ID_HASNOTIFIER,
false, false, UA_NS0ID_HASEVENTSOURCE);
ret |= addReferenceTypeNode(server, "HasOrderedComponent", "OrderedComponentOf",
UA_NS0ID_HASORDEREDCOMPONENT, false, false, UA_NS0ID_HASCOMPONENT);
ret |= addReferenceTypeNode(server, "HasInterface", "InterfaceOf",
UA_NS0ID_HASINTERFACE, false, false, UA_NS0ID_NONHIERARCHICALREFERENCES);
UA_DataTypeAttributes basedatatype_attr = UA_DataTypeAttributes_default;
basedatatype_attr.displayName = UA_LOCALIZEDTEXT("", "BaseDataType");
basedatatype_attr.isAbstract = true;
ret |= ns0_addNode_raw(server, UA_NODECLASS_DATATYPE, UA_NS0ID_BASEDATATYPE, "BaseDataType",
&basedatatype_attr, &UA_TYPES[UA_TYPES_DATATYPEATTRIBUTES]);
UA_VariableTypeAttributes basevar_attr = UA_VariableTypeAttributes_default;
basevar_attr.displayName = UA_LOCALIZEDTEXT("", "BaseVariableType");
basevar_attr.isAbstract = true;
basevar_attr.valueRank = UA_VALUERANK_ANY;
basevar_attr.dataType = UA_NS0ID(BASEDATATYPE);
ret |= ns0_addNode_raw(server, UA_NODECLASS_VARIABLETYPE,
UA_NS0ID_BASEVARIABLETYPE, "BaseVariableType",
&basevar_attr, &UA_TYPES[UA_TYPES_VARIABLETYPEATTRIBUTES]);
UA_VariableTypeAttributes bdv_attr = UA_VariableTypeAttributes_default;
bdv_attr.displayName = UA_LOCALIZEDTEXT("", "BaseDataVariableType");
bdv_attr.dataType = UA_NS0ID(BASEDATATYPE);
bdv_attr.valueRank = UA_VALUERANK_ANY;
ret |= addNode(server, UA_NODECLASS_VARIABLETYPE,
UA_NS0ID(BASEDATAVARIABLETYPE), UA_NS0ID(BASEVARIABLETYPE),
UA_NODEID_NULL, UA_QUALIFIEDNAME(0, "BaseDataVariableType"),
UA_NODEID_NULL, &bdv_attr, &UA_TYPES[UA_TYPES_VARIABLETYPEATTRIBUTES],
NULL, NULL);
UA_VariableTypeAttributes prop_attr = UA_VariableTypeAttributes_default;
prop_attr.displayName = UA_LOCALIZEDTEXT("", "PropertyType");
prop_attr.dataType = UA_NS0ID(BASEDATATYPE);
prop_attr.valueRank = UA_VALUERANK_ANY;
ret |= addNode(server, UA_NODECLASS_VARIABLETYPE,
UA_NS0ID(PROPERTYTYPE), UA_NS0ID(BASEVARIABLETYPE),
UA_NODEID_NULL, UA_QUALIFIEDNAME(0, "PropertyType"),
UA_NODEID_NULL, &prop_attr,
&UA_TYPES[UA_TYPES_VARIABLETYPEATTRIBUTES], NULL, NULL);
UA_ObjectTypeAttributes baseobj_attr = UA_ObjectTypeAttributes_default;
baseobj_attr.displayName = UA_LOCALIZEDTEXT("", "BaseObjectType");
ret |= ns0_addNode_raw(server, UA_NODECLASS_OBJECTTYPE,
UA_NS0ID_BASEOBJECTTYPE, "BaseObjectType",
&baseobj_attr, &UA_TYPES[UA_TYPES_OBJECTTYPEATTRIBUTES]);
UA_ObjectTypeAttributes folder_attr = UA_ObjectTypeAttributes_default;
folder_attr.displayName = UA_LOCALIZEDTEXT("", "FolderType");
ret |= addNode(server, UA_NODECLASS_OBJECTTYPE,
UA_NS0ID(FOLDERTYPE), UA_NS0ID(BASEOBJECTTYPE),
UA_NODEID_NULL, UA_QUALIFIEDNAME(0, "FolderType"),
UA_NODEID_NULL,
&folder_attr, &UA_TYPES[UA_TYPES_OBJECTTYPEATTRIBUTES], NULL, NULL);
ret |= addObjectNode(server, "Root", UA_NS0ID_ROOTFOLDER, 0, 0, UA_NS0ID_FOLDERTYPE);
ret |= addObjectNode(server, "Objects", UA_NS0ID_OBJECTSFOLDER, UA_NS0ID_ROOTFOLDER,
UA_NS0ID_ORGANIZES, UA_NS0ID_FOLDERTYPE);
ret |= addObjectNode(server, "Types", UA_NS0ID_TYPESFOLDER, UA_NS0ID_ROOTFOLDER,
UA_NS0ID_ORGANIZES, UA_NS0ID_FOLDERTYPE);
ret |= addObjectNode(server, "ReferenceTypes", UA_NS0ID_REFERENCETYPESFOLDER, UA_NS0ID_TYPESFOLDER,
UA_NS0ID_ORGANIZES, UA_NS0ID_FOLDERTYPE);
ret |= ns0_addNode_finish(server, UA_NS0ID_REFERENCES,
UA_NS0ID_REFERENCETYPESFOLDER, UA_NS0ID_ORGANIZES);
ret |= addObjectNode(server, "DataTypes", UA_NS0ID_DATATYPESFOLDER, UA_NS0ID_TYPESFOLDER,
UA_NS0ID_ORGANIZES, UA_NS0ID_FOLDERTYPE);
ret |= ns0_addNode_finish(server, UA_NS0ID_BASEDATATYPE,
UA_NS0ID_DATATYPESFOLDER, UA_NS0ID_ORGANIZES);
ret |= addObjectNode(server, "VariableTypes", UA_NS0ID_VARIABLETYPESFOLDER, UA_NS0ID_TYPESFOLDER,
UA_NS0ID_ORGANIZES, UA_NS0ID_FOLDERTYPE);
ret |= ns0_addNode_finish(server, UA_NS0ID_BASEVARIABLETYPE,
UA_NS0ID_VARIABLETYPESFOLDER, UA_NS0ID_ORGANIZES);
ret |= addObjectNode(server, "ObjectTypes", UA_NS0ID_OBJECTTYPESFOLDER, UA_NS0ID_TYPESFOLDER,
UA_NS0ID_ORGANIZES, UA_NS0ID_FOLDERTYPE);
ret |= ns0_addNode_finish(server, UA_NS0ID_BASEOBJECTTYPE,
UA_NS0ID_OBJECTTYPESFOLDER, UA_NS0ID_ORGANIZES);
ret |= addObjectNode(server, "EventTypes", UA_NS0ID_EVENTTYPESFOLDER, UA_NS0ID_TYPESFOLDER,
UA_NS0ID_ORGANIZES, UA_NS0ID_FOLDERTYPE);
ret |= addObjectNode(server, "Views", UA_NS0ID_VIEWSFOLDER, UA_NS0ID_ROOTFOLDER,
UA_NS0ID_ORGANIZES, UA_NS0ID_FOLDERTYPE);
UA_ObjectTypeAttributes eventtype_attr = UA_ObjectTypeAttributes_default;
eventtype_attr.displayName = UA_LOCALIZEDTEXT("", "BaseEventType");
ret |= addNode(server, UA_NODECLASS_OBJECTTYPE, UA_NS0ID(BASEEVENTTYPE),
UA_NS0ID(BASEOBJECTTYPE), UA_NODEID_NULL,
UA_QUALIFIEDNAME(0, "BaseEventType"), UA_NODEID_NULL, &eventtype_attr,
&UA_TYPES[UA_TYPES_OBJECTTYPEATTRIBUTES], NULL, NULL);
ret |= addRef(server, UA_NS0ID(EVENTTYPESFOLDER), UA_NS0ID(ORGANIZES),
UA_NS0ID(BASEEVENTTYPE), true);
if(ret != UA_STATUSCODE_GOOD)
ret = UA_STATUSCODE_BADINTERNALERROR;
return ret;
}
static UA_StatusCode
writeStatus(UA_Server *server, const UA_NodeId *sessionId,
void *sessionContext, const UA_NodeId *nodeId,
void *nodeContext, const UA_NumericRange *range,
const UA_DataValue *value) {
if(range)
return UA_STATUSCODE_BADINDEXRANGEINVALID;
if(nodeId->identifier.numeric != UA_NS0ID_SERVER_SERVERSTATUS_SECONDSTILLSHUTDOWN)
return UA_STATUSCODE_BADINTERNALERROR;
if(sessionId != &server->adminSession.sessionId)
return UA_STATUSCODE_BADUSERACCESSDENIED;
if(!UA_Variant_hasScalarType(&value->value, &UA_TYPES[UA_TYPES_UINT32]))
return UA_STATUSCODE_BADTYPEMISMATCH;
UA_EventLoop *el = server->config.eventLoop;
UA_UInt32 *endTime = (UA_UInt32*)value->value.data;
server->endTime = el->dateTime_now(el) + (UA_DateTime)(*endTime * UA_DATETIME_SEC);
return UA_STATUSCODE_GOOD;
}
static UA_StatusCode
readStatus(UA_Server *server, const UA_NodeId *sessionId, void *sessionContext,
const UA_NodeId *nodeId, void *nodeContext, UA_Boolean sourceTimestamp,
const UA_NumericRange *range, UA_DataValue *value) {
UA_EventLoop *el = server->config.eventLoop;
if(range) {
value->hasStatus = true;
value->status = UA_STATUSCODE_BADINDEXRANGEINVALID;
return UA_STATUSCODE_GOOD;
}
if(sourceTimestamp) {
value->hasSourceTimestamp = true;
value->sourceTimestamp = el->dateTime_now(el);
}
void *data = NULL;
UA_assert(nodeId->identifierType == UA_NODEIDTYPE_NUMERIC);
switch(nodeId->identifier.numeric) {
case UA_NS0ID_SERVER_SERVERSTATUS_SECONDSTILLSHUTDOWN: {
UA_UInt32 *shutdown = UA_UInt32_new();
if(!shutdown)
return UA_STATUSCODE_BADOUTOFMEMORY;
if(server->endTime != 0)
*shutdown = (UA_UInt32)((server->endTime - el->dateTime_now(el)) / UA_DATETIME_SEC);
value->value.data = shutdown;
value->value.type = &UA_TYPES[UA_TYPES_UINT32];
value->hasValue = true;
return UA_STATUSCODE_GOOD;
}
case UA_NS0ID_SERVER_SERVERSTATUS_STATE: {
UA_ServerState *state = UA_ServerState_new();
if(!state)
return UA_STATUSCODE_BADOUTOFMEMORY;
if(server->endTime != 0)
*state = UA_SERVERSTATE_SHUTDOWN;
value->value.data = state;
value->value.type = &UA_TYPES[UA_TYPES_SERVERSTATE];
value->hasValue = true;
return UA_STATUSCODE_GOOD;
}
case UA_NS0ID_SERVER_SERVERSTATUS: {
UA_ServerStatusDataType *statustype = UA_ServerStatusDataType_new();
if(!statustype)
return UA_STATUSCODE_BADOUTOFMEMORY;
statustype->startTime = server->startTime;
statustype->currentTime = el->dateTime_now(el);
statustype->state = UA_SERVERSTATE_RUNNING;
statustype->secondsTillShutdown = 0;
if(server->endTime != 0) {
statustype->state = UA_SERVERSTATE_SHUTDOWN;
statustype->secondsTillShutdown = (UA_UInt32)
((server->endTime - el->dateTime_now(el)) / UA_DATETIME_SEC);
}
value->value.data = statustype;
value->value.type = &UA_TYPES[UA_TYPES_SERVERSTATUSDATATYPE];
value->hasValue = true;
return UA_BuildInfo_copy(&server->config.buildInfo, &statustype->buildInfo);
}
case UA_NS0ID_SERVER_SERVERSTATUS_BUILDINFO:
value->value.type = &UA_TYPES[UA_TYPES_BUILDINFO];
data = &server->config.buildInfo;
break;
case UA_NS0ID_SERVER_SERVERSTATUS_BUILDINFO_PRODUCTURI:
value->value.type = &UA_TYPES[UA_TYPES_STRING];
data = &server->config.buildInfo.productUri;
break;
case UA_NS0ID_SERVER_SERVERSTATUS_BUILDINFO_MANUFACTURERNAME:
value->value.type = &UA_TYPES[UA_TYPES_STRING];
data = &server->config.buildInfo.manufacturerName;
break;
case UA_NS0ID_SERVER_SERVERSTATUS_BUILDINFO_PRODUCTNAME:
value->value.type = &UA_TYPES[UA_TYPES_STRING];
data = &server->config.buildInfo.productName;
break;
case UA_NS0ID_SERVER_SERVERSTATUS_BUILDINFO_SOFTWAREVERSION:
value->value.type = &UA_TYPES[UA_TYPES_STRING];
data = &server->config.buildInfo.softwareVersion;
break;
case UA_NS0ID_SERVER_SERVERSTATUS_BUILDINFO_BUILDNUMBER:
value->value.type = &UA_TYPES[UA_TYPES_STRING];
data = &server->config.buildInfo.buildNumber;
break;
case UA_NS0ID_SERVER_SERVERSTATUS_BUILDINFO_BUILDDATE:
value->value.type = &UA_TYPES[UA_TYPES_DATETIME];
data = &server->config.buildInfo.buildDate;
break;
default:
value->hasStatus = true;
value->status = UA_STATUSCODE_BADINTERNALERROR;
return UA_STATUSCODE_GOOD;
}
value->value.data = UA_new(value->value.type);
if(!value->value.data) {
value->value.type = NULL;
return UA_STATUSCODE_BADOUTOFMEMORY;
}
value->hasValue = true;
return UA_copy(data, value->value.data, value->value.type);
}
#ifdef UA_GENERATED_NAMESPACE_ZERO
static UA_StatusCode
readServiceLevel(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_EventLoop *el = server->config.eventLoop;
if(range) {
value->hasStatus = true;
value->status = UA_STATUSCODE_BADINDEXRANGEINVALID;
return UA_STATUSCODE_GOOD;
}
value->value.type = &UA_TYPES[UA_TYPES_BYTE];
value->value.arrayLength = 0;
UA_Byte *byte = UA_Byte_new();
if(!byte)
return UA_STATUSCODE_BADOUTOFMEMORY;
*byte = 255;
value->value.data = byte;
value->value.arrayDimensionsSize = 0;
value->value.arrayDimensions = NULL;
value->hasValue = true;
if(includeSourceTimeStamp) {
value->hasSourceTimestamp = true;
value->sourceTimestamp = el->dateTime_now(el);
}
return UA_STATUSCODE_GOOD;
}
static UA_StatusCode
readAuditing(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_EventLoop *el = server->config.eventLoop;
if(range) {
value->hasStatus = true;
value->status = UA_STATUSCODE_BADINDEXRANGEINVALID;
return UA_STATUSCODE_GOOD;
}
value->value.type = &UA_TYPES[UA_TYPES_BOOLEAN];
value->value.arrayLength = 0;
UA_Boolean *boolean = UA_Boolean_new();
if(!boolean)
return UA_STATUSCODE_BADOUTOFMEMORY;
*boolean = false;
value->value.data = boolean;
value->value.arrayDimensionsSize = 0;
value->value.arrayDimensions = NULL;
value->hasValue = true;
if(includeSourceTimeStamp) {
value->hasSourceTimestamp = true;
value->sourceTimestamp = el->dateTime_now(el);
}
return UA_STATUSCODE_GOOD;
}
#endif
static UA_StatusCode
readNamespaces(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_EventLoop *el = server->config.eventLoop;
setupNs1Uri(server);
if(range) {
value->hasStatus = true;
value->status = UA_STATUSCODE_BADINDEXRANGEINVALID;
return UA_STATUSCODE_GOOD;
}
UA_StatusCode retval;
retval = UA_Variant_setArrayCopy(&value->value, server->namespaces,
server->namespacesSize, &UA_TYPES[UA_TYPES_STRING]);
if(retval != UA_STATUSCODE_GOOD)
return retval;
value->hasValue = true;
if(includeSourceTimeStamp) {
value->hasSourceTimestamp = true;
value->sourceTimestamp = el->dateTime_now(el);
}
return UA_STATUSCODE_GOOD;
}
static UA_StatusCode
writeNamespaces(UA_Server *server, const UA_NodeId *sessionId, void *sessionContext,
const UA_NodeId *nodeid, void *nodeContext, const UA_NumericRange *range,
const UA_DataValue *value) {
if(!value->hasValue ||
value->value.type != &UA_TYPES[UA_TYPES_STRING])
return UA_STATUSCODE_BADTYPEMISMATCH;
if(!value->value.data)
return UA_STATUSCODE_BADTYPEMISMATCH;
if(range)
return UA_STATUSCODE_BADINTERNALERROR;
UA_String *newNamespaces = (UA_String*)value->value.data;
size_t newNamespacesSize = value->value.arrayLength;
if(newNamespacesSize <= server->namespacesSize)
return UA_STATUSCODE_BADTYPEMISMATCH;
setupNs1Uri(server);
for(size_t i = 0; i < server->namespacesSize; ++i) {
if(!UA_String_equal(&server->namespaces[i], &newNamespaces[i]))
return UA_STATUSCODE_BADINTERNALERROR;
}
for(size_t i = server->namespacesSize; i < newNamespacesSize; ++i)
addNamespace(server, newNamespaces[i]);
return UA_STATUSCODE_GOOD;
}
static UA_StatusCode
readCurrentTime(UA_Server *server, const UA_NodeId *sessionId, void *sessionContext,
const UA_NodeId *nodeid, void *nodeContext, UA_Boolean sourceTimeStamp,
const UA_NumericRange *range, UA_DataValue *value) {
UA_EventLoop *el = server->config.eventLoop;
if(range) {
value->hasStatus = true;
value->status = UA_STATUSCODE_BADINDEXRANGEINVALID;
return UA_STATUSCODE_GOOD;
}
UA_DateTime currentTime = el->dateTime_now(el);
UA_StatusCode retval = UA_Variant_setScalarCopy(&value->value, ¤tTime,
&UA_TYPES[UA_TYPES_DATETIME]);
if(retval != UA_STATUSCODE_GOOD)
return retval;
value->hasValue = true;
if(sourceTimeStamp) {
value->hasSourceTimestamp = true;
value->sourceTimestamp = currentTime;
}
return UA_STATUSCODE_GOOD;
}
#ifdef UA_GENERATED_NAMESPACE_ZERO
static UA_StatusCode
readOperationLimits(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_StatusCode retval = UA_STATUSCODE_GOOD;
if(nodeid->identifierType != UA_NODEIDTYPE_NUMERIC)
return UA_STATUSCODE_BADNOTSUPPORTED;
switch(nodeid->identifier.numeric) {
case UA_NS0ID_SERVER_SERVERCAPABILITIES_OPERATIONLIMITS_MAXNODESPERREAD:
retval = UA_Variant_setScalarCopy(&value->value, &server->config.maxNodesPerRead, &UA_TYPES[UA_TYPES_UINT32]);
break;
case UA_NS0ID_SERVER_SERVERCAPABILITIES_OPERATIONLIMITS_MAXNODESPERWRITE:
retval = UA_Variant_setScalarCopy(&value->value, &server->config.maxNodesPerWrite, &UA_TYPES[UA_TYPES_UINT32]);
break;
case UA_NS0ID_SERVER_SERVERCAPABILITIES_OPERATIONLIMITS_MAXNODESPERMETHODCALL:
retval = UA_Variant_setScalarCopy(&value->value, &server->config.maxNodesPerMethodCall, &UA_TYPES[UA_TYPES_UINT32]);
break;
case UA_NS0ID_SERVER_SERVERCAPABILITIES_OPERATIONLIMITS_MAXNODESPERBROWSE:
retval = UA_Variant_setScalarCopy(&value->value, &server->config.maxNodesPerBrowse, &UA_TYPES[UA_TYPES_UINT32]);
break;
case UA_NS0ID_SERVER_SERVERCAPABILITIES_OPERATIONLIMITS_MAXNODESPERREGISTERNODES:
retval = UA_Variant_setScalarCopy(&value->value, &server->config.maxNodesPerRegisterNodes, &UA_TYPES[UA_TYPES_UINT32]);
break;
case UA_NS0ID_SERVER_SERVERCAPABILITIES_OPERATIONLIMITS_MAXNODESPERTRANSLATEBROWSEPATHSTONODEIDS:
retval = UA_Variant_setScalarCopy(&value->value, &server->config.maxNodesPerTranslateBrowsePathsToNodeIds, &UA_TYPES[UA_TYPES_UINT32]);
break;
case UA_NS0ID_SERVER_SERVERCAPABILITIES_OPERATIONLIMITS_MAXNODESPERNODEMANAGEMENT:
retval = UA_Variant_setScalarCopy(&value->value, &server->config.maxNodesPerNodeManagement, &UA_TYPES[UA_TYPES_UINT32]);
break;
case UA_NS0ID_SERVER_SERVERCAPABILITIES_OPERATIONLIMITS_MAXMONITOREDITEMSPERCALL:
retval = UA_Variant_setScalarCopy(&value->value, &server->config.maxMonitoredItemsPerCall, &UA_TYPES[UA_TYPES_UINT32]);
break;
case UA_NS0ID_SERVER_SERVERCAPABILITIES_MAXMONITOREDITEMSQUEUESIZE:
#ifdef UA_ENABLE_SUBSCRIPTIONS
retval = UA_Variant_setScalarCopy(&value->value, &server->config.queueSizeLimits.max,
&UA_TYPES[UA_TYPES_UINT32]);
#else
{
UA_UInt32 maxQueueSize = 0;
retval = UA_Variant_setScalarCopy(&value->value, &maxQueueSize,
&UA_TYPES[UA_TYPES_UINT32]);
}
#endif
break;
default:
retval = UA_STATUSCODE_BADNOTSUPPORTED;
}
return retval;
}
static UA_StatusCode
readMinSamplingInterval(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_EventLoop *el = server->config.eventLoop;
if(range) {
value->hasStatus = true;
value->status = UA_STATUSCODE_BADINDEXRANGEINVALID;
return UA_STATUSCODE_GOOD;
}
UA_StatusCode retval;
UA_Duration minInterval;
#ifdef UA_ENABLE_SUBSCRIPTIONS
minInterval = server->config.samplingIntervalLimits.min;
#else
minInterval = 0.0;
#endif
retval = UA_Variant_setScalarCopy(&value->value, &minInterval, &UA_TYPES[UA_TYPES_DURATION]);
if(retval != UA_STATUSCODE_GOOD)
return retval;
value->hasValue = true;
if(includeSourceTimeStamp) {
value->hasSourceTimestamp = true;
value->sourceTimestamp = el->dateTime_now(el);
}
return UA_STATUSCODE_GOOD;
}
#endif
#if defined(UA_GENERATED_NAMESPACE_ZERO) && defined(UA_ENABLE_METHODCALLS) && defined(UA_ENABLE_SUBSCRIPTIONS)
static UA_StatusCode
resendData(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) {
if(inputSize != 1 ||
!UA_Variant_hasScalarType(input, &UA_TYPES[UA_TYPES_UINT32]))
return UA_STATUSCODE_BADSUBSCRIPTIONIDINVALID;
UA_UInt32 subscriptionId = *((UA_UInt32*)(input[0].data));
lockServer(server);
UA_Session *session = getSessionById(server, sessionId);
if(!session) {
unlockServer(server);
return UA_STATUSCODE_BADINTERNALERROR;
}
UA_Subscription *subscription = getSubscriptionById(server, subscriptionId);
if(!subscription) {
unlockServer(server);
return UA_STATUSCODE_BADSUBSCRIPTIONIDINVALID;
}
if(subscription->session != session) {
unlockServer(server);
return UA_STATUSCODE_BADUSERACCESSDENIED;
}
UA_Subscription_resendData(server, subscription);
unlockServer(server);
return UA_STATUSCODE_GOOD;
}
static UA_StatusCode
readMonitoredItems(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_Variant_setArray(&output[0], UA_Array_new(0, &UA_TYPES[UA_TYPES_UINT32]),
0, &UA_TYPES[UA_TYPES_UINT32]);
UA_Variant_setArray(&output[1], UA_Array_new(0, &UA_TYPES[UA_TYPES_UINT32]),
0, &UA_TYPES[UA_TYPES_UINT32]);
lockServer(server);
UA_Session *session = getSessionById(server, sessionId);
if(!session) {
unlockServer(server);
return UA_STATUSCODE_BADINTERNALERROR;
}
if(inputSize == 0 || !input[0].data) {
unlockServer(server);
return UA_STATUSCODE_BADSUBSCRIPTIONIDINVALID;
}
UA_UInt32 subscriptionId = *((UA_UInt32*)(input[0].data));
UA_Subscription *subscription = getSubscriptionById(server, subscriptionId);
if(!subscription) {
unlockServer(server);
return UA_STATUSCODE_BADSUBSCRIPTIONIDINVALID;
}
if(subscription->session != session) {
unlockServer(server);
return UA_STATUSCODE_BADUSERACCESSDENIED;
}
UA_UInt32 sizeOfOutput = 0;
UA_MonitoredItem* monitoredItem;
LIST_FOREACH(monitoredItem, &subscription->monitoredItems, listEntry) {
++sizeOfOutput;
}
if(sizeOfOutput == 0) {
unlockServer(server);
return UA_STATUSCODE_GOOD;
}
UA_UInt32 *clientHandles = (UA_UInt32*)
UA_Array_new(sizeOfOutput, &UA_TYPES[UA_TYPES_UINT32]);
if(!clientHandles) {
unlockServer(server);
return UA_STATUSCODE_BADOUTOFMEMORY;
}
UA_UInt32 *serverHandles = (UA_UInt32*)
UA_Array_new(sizeOfOutput, &UA_TYPES[UA_TYPES_UINT32]);
if(!serverHandles) {
unlockServer(server);
UA_free(clientHandles);
return UA_STATUSCODE_BADOUTOFMEMORY;
}
UA_UInt32 i = 0;
LIST_FOREACH(monitoredItem, &subscription->monitoredItems, listEntry) {
clientHandles[i] = monitoredItem->parameters.clientHandle;
serverHandles[i] = monitoredItem->monitoredItemId;
++i;
}
UA_Variant_setArray(&output[0], serverHandles, sizeOfOutput, &UA_TYPES[UA_TYPES_UINT32]);
UA_Variant_setArray(&output[1], clientHandles, sizeOfOutput, &UA_TYPES[UA_TYPES_UINT32]);
unlockServer(server);
return UA_STATUSCODE_GOOD;
}
#endif
static UA_StatusCode
writeNs0VariableArray(UA_Server *server, UA_UInt32 id, void *v,
size_t length, const UA_DataType *type) {
UA_Variant var;
UA_Variant_init(&var);
UA_Variant_setArray(&var, v, length, type);
return writeValueAttribute(server, UA_NODEID_NUMERIC(0, id), &var);
}
#ifdef UA_GENERATED_NAMESPACE_ZERO
static UA_StatusCode
writeNs0Variable(UA_Server *server, UA_UInt32 id, void *v, const UA_DataType *type) {
UA_Variant var;
UA_Variant_init(&var);
UA_Variant_setScalar(&var, v, type);
return writeValueAttribute(server, UA_NODEID_NUMERIC(0, id), &var);
}
#endif
#ifndef UA_GENERATED_NAMESPACE_ZERO
static UA_StatusCode
addVariableNode(UA_Server *server, char* name, UA_UInt32 variableid,
UA_UInt32 parentid, UA_UInt32 referenceid,
UA_Int32 valueRank, UA_UInt32 dataType) {
UA_VariableAttributes attr = UA_VariableAttributes_default;
attr.displayName = UA_LOCALIZEDTEXT("", name);
attr.dataType = UA_NODEID_NUMERIC(0, dataType);
attr.valueRank = valueRank;
attr.accessLevel = UA_ACCESSLEVELMASK_READ;
return addNode(server, UA_NODECLASS_VARIABLE, UA_NODEID_NUMERIC(0, variableid),
UA_NODEID_NUMERIC(0, parentid), UA_NODEID_NUMERIC(0, referenceid),
UA_QUALIFIEDNAME(0, name), UA_NS0ID(BASEDATAVARIABLETYPE),
&attr, &UA_TYPES[UA_TYPES_VARIABLEATTRIBUTES], NULL, NULL);
}
static UA_StatusCode
minimalServerObject(UA_Server *server) {
UA_StatusCode retval = addObjectNode(server, "Server", UA_NS0ID_SERVER, UA_NS0ID_OBJECTSFOLDER,
UA_NS0ID_ORGANIZES, UA_NS0ID_BASEOBJECTTYPE);
retval |= addVariableNode(server, "ServerArray", UA_NS0ID_SERVER_SERVERARRAY,
UA_NS0ID_SERVER, UA_NS0ID_HASPROPERTY,
UA_VALUERANK_ANY, UA_NS0ID_BASEDATATYPE);
retval |= addVariableNode(server, "NamespaceArray", UA_NS0ID_SERVER_NAMESPACEARRAY,
UA_NS0ID_SERVER, UA_NS0ID_HASPROPERTY,
UA_VALUERANK_ANY, UA_NS0ID_BASEDATATYPE);
retval |= addVariableNode(server, "ServerStatus", UA_NS0ID_SERVER_SERVERSTATUS,
UA_NS0ID_SERVER, UA_NS0ID_HASCOMPONENT,
UA_VALUERANK_SCALAR, UA_NS0ID_BASEDATATYPE);
retval |= addVariableNode(server, "StartTime", UA_NS0ID_SERVER_SERVERSTATUS_STARTTIME,
UA_NS0ID_SERVER_SERVERSTATUS, UA_NS0ID_HASCOMPONENT,
UA_VALUERANK_SCALAR, UA_NS0ID_BASEDATATYPE);
retval |= addVariableNode(server, "CurrentTime", UA_NS0ID_SERVER_SERVERSTATUS_CURRENTTIME,
UA_NS0ID_SERVER_SERVERSTATUS, UA_NS0ID_HASCOMPONENT,
UA_VALUERANK_SCALAR, UA_NS0ID_BASEDATATYPE);
retval |= addVariableNode(server, "State", UA_NS0ID_SERVER_SERVERSTATUS_STATE,
UA_NS0ID_SERVER_SERVERSTATUS, UA_NS0ID_HASCOMPONENT,
UA_VALUERANK_SCALAR, UA_NS0ID_BASEDATATYPE);
retval |= addVariableNode(server, "BuildInfo", UA_NS0ID_SERVER_SERVERSTATUS_BUILDINFO,
UA_NS0ID_SERVER_SERVERSTATUS, UA_NS0ID_HASCOMPONENT,
UA_VALUERANK_SCALAR, UA_NS0ID_BASEDATATYPE);
retval |= addVariableNode(server, "ProductUri", UA_NS0ID_SERVER_SERVERSTATUS_BUILDINFO_PRODUCTURI,
UA_NS0ID_SERVER_SERVERSTATUS_BUILDINFO, UA_NS0ID_HASCOMPONENT,
UA_VALUERANK_SCALAR, UA_NS0ID_BASEDATATYPE);
retval |= addVariableNode(server, "ManufacturerName",
UA_NS0ID_SERVER_SERVERSTATUS_BUILDINFO_MANUFACTURERNAME,
UA_NS0ID_SERVER_SERVERSTATUS_BUILDINFO, UA_NS0ID_HASCOMPONENT,
UA_VALUERANK_SCALAR, UA_NS0ID_BASEDATATYPE);
retval |= addVariableNode(server, "ProductName",
UA_NS0ID_SERVER_SERVERSTATUS_BUILDINFO_PRODUCTNAME,
UA_NS0ID_SERVER_SERVERSTATUS_BUILDINFO, UA_NS0ID_HASCOMPONENT,
UA_VALUERANK_SCALAR, UA_NS0ID_BASEDATATYPE);
retval |= addVariableNode(server, "SoftwareVersion",
UA_NS0ID_SERVER_SERVERSTATUS_BUILDINFO_SOFTWAREVERSION,
UA_NS0ID_SERVER_SERVERSTATUS_BUILDINFO, UA_NS0ID_HASCOMPONENT,
UA_VALUERANK_SCALAR, UA_NS0ID_BASEDATATYPE);
retval |= addVariableNode(server, "BuildNumber",
UA_NS0ID_SERVER_SERVERSTATUS_BUILDINFO_BUILDNUMBER,
UA_NS0ID_SERVER_SERVERSTATUS_BUILDINFO, UA_NS0ID_HASCOMPONENT,
UA_VALUERANK_SCALAR, UA_NS0ID_BASEDATATYPE);
retval |= addVariableNode(server, "BuildDate",
UA_NS0ID_SERVER_SERVERSTATUS_BUILDINFO_BUILDDATE,
UA_NS0ID_SERVER_SERVERSTATUS_BUILDINFO, UA_NS0ID_HASCOMPONENT,
UA_VALUERANK_SCALAR, UA_NS0ID_BASEDATATYPE);
return retval;
}
#else
static void
addModellingRules(UA_Server *server) {
UA_NodeId mrNodeId = UA_NS0ID(SERVER_SERVERCAPABILITIES_MODELLINGRULES);
const UA_Node *mrnode = UA_NODESTORE_GET(server, &mrNodeId);
if(!mrnode)
return;
UA_NODESTORE_RELEASE(server, mrnode);
addRef(server, UA_NS0ID(SERVER_SERVERCAPABILITIES_MODELLINGRULES),
UA_NS0ID(HASCOMPONENT), UA_NS0ID(MODELLINGRULE_EXPOSESITSARRAY), true);
addRef(server, UA_NS0ID(SERVER_SERVERCAPABILITIES_MODELLINGRULES),
UA_NS0ID(HASCOMPONENT), UA_NS0ID(MODELLINGRULE_MANDATORY), true);
addRef(server, UA_NS0ID(SERVER_SERVERCAPABILITIES_MODELLINGRULES),
UA_NS0ID(HASCOMPONENT), UA_NS0ID(MODELLINGRULE_MANDATORYPLACEHOLDER), true);
addRef(server, UA_NS0ID(SERVER_SERVERCAPABILITIES_MODELLINGRULES),
UA_NS0ID(HASCOMPONENT), UA_NS0ID(MODELLINGRULE_OPTIONAL), true);
addRef(server, UA_NS0ID(SERVER_SERVERCAPABILITIES_MODELLINGRULES),
UA_NS0ID(HASCOMPONENT), UA_NS0ID(MODELLINGRULE_OPTIONALPLACEHOLDER), true);
}
#endif
static UA_StatusCode connectNS0_dataSources(UA_Server *server);
static UA_StatusCode configureNS0(UA_Server *server);
UA_StatusCode
initNS0(UA_Server *server) {
UA_LOCK_ASSERT(&server->serviceMutex);
server->bootstrapNS0 = true;
UA_StatusCode retVal = createNS0_base(server);
#ifdef UA_GENERATED_NAMESPACE_ZERO
retVal |= namespace0_generated(server);
#else
retVal |= minimalServerObject(server);
#endif
server->bootstrapNS0 = false;
if(retVal != UA_STATUSCODE_GOOD) {
UA_LOG_ERROR(server->config.logging, UA_LOGCATEGORY_SERVER,
"Initialization of Namespace 0 failed with %s. "
"See previous outputs for any error messages.",
UA_StatusCode_name(retVal));
return UA_STATUSCODE_BADINTERNALERROR;
}
retVal |= connectNS0_dataSources(server);
retVal |= configureNS0(server);
if(retVal != UA_STATUSCODE_GOOD) {
UA_LOG_ERROR(server->config.logging, UA_LOGCATEGORY_SERVER,
"Initialization of Namespace 0 (after bootstrapping) "
"failed with %s. See previous outputs for any error messages.",
UA_StatusCode_name(retVal));
return UA_STATUSCODE_BADINTERNALERROR;
}
return UA_STATUSCODE_GOOD;
}
static UA_StatusCode
configureNS0(UA_Server *server) {
UA_StatusCode retVal = UA_STATUSCODE_GOOD;
retVal |= writeValueRankAttribute(server, UA_NS0ID(SERVER_NAMESPACEARRAY), 1);
retVal |= writeNs0VariableArray(server, UA_NS0ID_SERVER_SERVERARRAY,
&server->config.applicationDescription.applicationUri,
1, &UA_TYPES[UA_TYPES_STRING]);
retVal |= writeValueRankAttribute(server, UA_NS0ID(SERVER_SERVERARRAY), 1);
UA_NodeId currTime = UA_NS0ID(SERVER_SERVERSTATUS_CURRENTTIME);
retVal |= writeMinimumSamplingIntervalAttribute(server, currTime, 100.0);
#ifdef UA_GENERATED_NAMESPACE_ZERO
UA_LocalizedText shutdownReason;
UA_LocalizedText_init(&shutdownReason);
retVal |= writeNs0Variable(server, UA_NS0ID_SERVER_SERVERSTATUS_SHUTDOWNREASON,
&shutdownReason, &UA_TYPES[UA_TYPES_LOCALIZEDTEXT]);
#ifdef UA_ENABLE_DIAGNOSTICS
UA_Boolean enabledFlag = true;
#else
UA_Boolean enabledFlag = false;
#endif
retVal |= writeNs0Variable(server, UA_NS0ID_SERVER_SERVERDIAGNOSTICS_ENABLEDFLAG,
&enabledFlag, &UA_TYPES[UA_TYPES_BOOLEAN]);
retVal |= writeAccessLevelAttribute(server, UA_NS0ID(SERVER_SERVERDIAGNOSTICS_ENABLEDFLAG),
UA_ACCESSLEVELMASK_READ);
UA_RedundancySupport redundancySupport = UA_REDUNDANCYSUPPORT_NONE;
retVal |= writeNs0Variable(server, UA_NS0ID_SERVER_SERVERREDUNDANCY_REDUNDANCYSUPPORT,
&redundancySupport, &UA_TYPES[UA_TYPES_REDUNDANCYSUPPORT]);
deleteNode(server, UA_NS0ID(SERVER_SERVERREDUNDANCY_CURRENTSERVERID), true);
deleteNode(server, UA_NS0ID(SERVER_SERVERREDUNDANCY_REDUNDANTSERVERARRAY), true);
deleteNode(server, UA_NS0ID(SERVER_SERVERREDUNDANCY_SERVERURIARRAY), true);
deleteNode(server, UA_NS0ID(SERVER_SERVERREDUNDANCY_SERVERNETWORKGROUPS), true);
deleteNode(server, UA_NS0ID(SERVER_SERVERCAPABILITIES_CONFORMANCEUNITS), true);
deleteNode(server, UA_NS0ID(SERVER_URISVERSION), true);
deleteNode(server, UA_NS0ID(SERVER_SERVERCAPABILITIES_CONFORMANCEUNITS), true);
deleteNode(server, UA_NS0ID(SERVER_SERVERCAPABILITIES_MAXMONITOREDITEMS), true);
deleteNode(server, UA_NS0ID(SERVER_SERVERCAPABILITIES_MAXMONITOREDITEMSPERSUBSCRIPTION), true);
deleteNode(server, UA_NS0ID(SERVER_SERVERCAPABILITIES_MAXSELECTCLAUSEPARAMETERS), true);
deleteNode(server, UA_NS0ID(SERVER_SERVERCAPABILITIES_MAXSESSIONS), true);
deleteNode(server, UA_NS0ID(SERVER_SERVERCAPABILITIES_MAXSUBSCRIPTIONS), true);
deleteNode(server, UA_NS0ID(SERVER_SERVERCAPABILITIES_MAXSUBSCRIPTIONSPERSESSION), true);
deleteNode(server, UA_NS0ID(SERVER_SERVERCAPABILITIES_MAXWHERECLAUSEPARAMETERS), true);
UA_LocaleId locale_en = UA_STRING("en");
retVal |= writeNs0VariableArray(server, UA_NS0ID_SERVER_SERVERCAPABILITIES_LOCALEIDARRAY,
&locale_en, 1, &UA_TYPES[UA_TYPES_LOCALEID]);
UA_UInt16 maxBrowseContinuationPoints = UA_MAXCONTINUATIONPOINTS;
retVal |= writeNs0Variable(server, UA_NS0ID_SERVER_SERVERCAPABILITIES_MAXBROWSECONTINUATIONPOINTS,
&maxBrowseContinuationPoints, &UA_TYPES[UA_TYPES_UINT16]);
UA_String profileArray[3];
UA_UInt16 profileArraySize = 0;
#define ADDPROFILEARRAY(x) profileArray[profileArraySize++] = UA_STRING(x)
ADDPROFILEARRAY("http://opcfoundation.org/UA-Profile/Server/StandardUA2017");
#ifdef UA_ENABLE_NODEMANAGEMENT
ADDPROFILEARRAY("http://opcfoundation.org/UA-Profile/Server/NodeManagement");
#endif
#ifdef UA_ENABLE_METHODCALLS
ADDPROFILEARRAY("http://opcfoundation.org/UA-Profile/Server/Methods");
#endif
retVal |= writeNs0VariableArray(server, UA_NS0ID_SERVER_SERVERCAPABILITIES_SERVERPROFILEARRAY,
profileArray, profileArraySize, &UA_TYPES[UA_TYPES_STRING]);
UA_UInt16 maxQueryContinuationPoints = 0;
retVal |= writeNs0Variable(server, UA_NS0ID_SERVER_SERVERCAPABILITIES_MAXQUERYCONTINUATIONPOINTS,
&maxQueryContinuationPoints, &UA_TYPES[UA_TYPES_UINT16]);
UA_UInt16 maxHistoryContinuationPoints = 0;
retVal |= writeNs0Variable(server, UA_NS0ID_SERVER_SERVERCAPABILITIES_MAXHISTORYCONTINUATIONPOINTS,
&maxHistoryContinuationPoints, &UA_TYPES[UA_TYPES_UINT16]);
deleteNode(server, UA_NS0ID(SERVER_SERVERCAPABILITIES_OPERATIONLIMITS_MAXNODESPERHISTORYREADDATA), true);
deleteNode(server, UA_NS0ID(SERVER_SERVERCAPABILITIES_OPERATIONLIMITS_MAXNODESPERHISTORYREADEVENTS), true);
deleteNode(server, UA_NS0ID(SERVER_SERVERCAPABILITIES_OPERATIONLIMITS_MAXNODESPERHISTORYUPDATEDATA), true);
deleteNode(server, UA_NS0ID(SERVER_SERVERCAPABILITIES_OPERATIONLIMITS_MAXNODESPERHISTORYUPDATEEVENTS), true);
#ifndef UA_NODESET_INJECTOR_NEEDS_ROLESET
deleteNode(server, UA_NS0ID(SERVER_SERVERCAPABILITIES_ROLESET), true);
#endif
deleteNode(server, UA_NS0ID(SERVER_SERVERCAPABILITIES_MAXSTRINGLENGTH), true);
deleteNode(server, UA_NS0ID(SERVER_SERVERCAPABILITIES_MAXARRAYLENGTH), true);
deleteNode(server, UA_NS0ID(SERVER_SERVERCAPABILITIES_MAXBYTESTRINGLENGTH), true);
deleteNode(server, UA_NS0ID(SERVER_ESTIMATEDRETURNTIME), true);
deleteNode(server, UA_NS0ID(SERVER_LOCALTIME), true);
deleteNode(server, UA_NS0ID(SERVER_REQUESTSERVERSTATECHANGE), true);
deleteNode(server, UA_NS0ID(SERVER_SETSUBSCRIPTIONDURABLE), true);
deleteNode(server, UA_NS0ID(SERVERCONFIGURATION_CERTIFICATEGROUPS_DEFAULTHTTPSGROUP), true);
#ifdef UA_NS0ID_SERVERLOG
deleteNode(server, UA_NS0ID(SERVERLOG), true);
#endif
#ifdef UA_NS0ID_LLDP
deleteNode(server, UA_NS0ID(LLDP), true);
#endif
deleteNode(server, UA_NS0ID(PROVISIONABLEDEVICE), true);
deleteNode(server, UA_NS0ID(USERMANAGEMENT), true);
deleteNode(server, UA_NS0ID(SERVERCONFIGURATION_TRANSACTIONDIAGNOSTICS), true);
#ifdef UA_NS0ID_SERVERCONFIGURATION_CONFIGURATIONFILE
deleteNode(server, UA_NS0ID(SERVERCONFIGURATION_CONFIGURATIONFILE), true);
#endif
#ifndef UA_ENABLE_GDS_PUSHMANAGEMENT
deleteNode(server, UA_NS0ID(SERVERCONFIGURATION_CERTIFICATEGROUPS_DEFAULTAPPLICATIONGROUP), true);
deleteNode(server, UA_NS0ID(SERVERCONFIGURATION_CERTIFICATEGROUPS_DEFAULTUSERTOKENGROUP), true);
#endif
#ifndef UA_ENABLE_DIAGNOSTICS
deleteNode(server, UA_NS0ID(SERVER_SERVERDIAGNOSTICS_SESSIONSDIAGNOSTICSSUMMARY), true);
deleteNode(server, UA_NS0ID(SERVER_SERVERDIAGNOSTICS_SERVERDIAGNOSTICSSUMMARY), true);
deleteNode(server, UA_NS0ID(SERVER_SERVERDIAGNOSTICS_SUBSCRIPTIONDIAGNOSTICSARRAY), true);
#endif
deleteNode(server, UA_NS0ID(SERVER_SERVERDIAGNOSTICS_SAMPLINGINTERVALDIAGNOSTICSARRAY), true);
#ifndef UA_ENABLE_PUBSUB
deleteNode(server, UA_NS0ID(PUBLISHSUBSCRIBE), true);
#endif
#ifdef UA_GENERATED_NAMESPACE_ZERO_FULL
#ifdef UA_ENABLE_DISCOVERY_MULTICAST
retVal |= writeNs0Variable(server, UA_NS0ID_SERVERCONFIGURATION_MULTICASTDNSENABLED,
&server->config.mdnsEnabled, &UA_TYPES[UA_TYPES_BOOLEAN]);
#else
{
UA_Boolean mdnsEnabled = false;
retVal |= writeNs0Variable(server, UA_NS0ID_SERVERCONFIGURATION_MULTICASTDNSENABLED,
&mdnsEnabled, &UA_TYPES[UA_TYPES_BOOLEAN]);
}
#endif
#endif
#ifdef UA_GENERATED_NAMESPACE_ZERO_FULL
{
UA_Boolean hasSecureElement = false;
retVal |= writeNs0Variable(server, UA_NS0ID_SERVERCONFIGURATION_HASSECUREELEMENT,
&hasSecureElement, &UA_TYPES[UA_TYPES_BOOLEAN]);
}
retVal |= writeNs0Variable(server, UA_NS0ID_SERVERCONFIGURATION_APPLICATIONTYPE,
&server->config.applicationDescription.applicationType,
&UA_TYPES[UA_TYPES_APPLICATIONTYPE]);
{
UA_AccessRestrictionType defaultAccessRestrictions = UA_ACCESSRESTRICTIONTYPE_NONE;
retVal |= writeNs0Variable(server, UA_NS0ID_OPCUANAMESPACEMETADATA_DEFAULTACCESSRESTRICTIONS,
&defaultAccessRestrictions,
&UA_TYPES[UA_TYPES_ACCESSRESTRICTIONTYPE]);
}
#endif
#ifndef UA_ENABLE_HISTORIZING
deleteNode(server, UA_NS0ID(HISTORYSERVERCAPABILITIES), true);
#ifdef UA_NS0ID_DEFAULTHACONFIGURATION
deleteNode(server, UA_NS0ID(DEFAULTHACONFIGURATION), true);
#endif
#else
retVal |= writeNs0Variable(server, UA_NS0ID_HISTORYSERVERCAPABILITIES_ACCESSHISTORYDATACAPABILITY,
&server->config.accessHistoryDataCapability, &UA_TYPES[UA_TYPES_BOOLEAN]);
retVal |= writeNs0Variable(server, UA_NS0ID_HISTORYSERVERCAPABILITIES_MAXRETURNDATAVALUES,
&server->config.maxReturnDataValues, &UA_TYPES[UA_TYPES_UINT32]);
retVal |= writeNs0Variable(server, UA_NS0ID_HISTORYSERVERCAPABILITIES_ACCESSHISTORYEVENTSCAPABILITY,
&server->config.accessHistoryEventsCapability, &UA_TYPES[UA_TYPES_BOOLEAN]);
retVal |= writeNs0Variable(server, UA_NS0ID_HISTORYSERVERCAPABILITIES_MAXRETURNEVENTVALUES,
&server->config.maxReturnEventValues, &UA_TYPES[UA_TYPES_UINT32]);
retVal |= writeNs0Variable(server, UA_NS0ID_HISTORYSERVERCAPABILITIES_INSERTDATACAPABILITY,
&server->config.insertDataCapability, &UA_TYPES[UA_TYPES_BOOLEAN]);
retVal |= writeNs0Variable(server, UA_NS0ID_HISTORYSERVERCAPABILITIES_INSERTEVENTCAPABILITY,
&server->config.insertEventCapability, &UA_TYPES[UA_TYPES_BOOLEAN]);
retVal |= writeNs0Variable(server, UA_NS0ID_HISTORYSERVERCAPABILITIES_INSERTANNOTATIONCAPABILITY,
&server->config.insertAnnotationsCapability, &UA_TYPES[UA_TYPES_BOOLEAN]);
retVal |= writeNs0Variable(server, UA_NS0ID_HISTORYSERVERCAPABILITIES_REPLACEDATACAPABILITY,
&server->config.replaceDataCapability, &UA_TYPES[UA_TYPES_BOOLEAN]);
retVal |= writeNs0Variable(server, UA_NS0ID_HISTORYSERVERCAPABILITIES_REPLACEEVENTCAPABILITY,
&server->config.replaceEventCapability, &UA_TYPES[UA_TYPES_BOOLEAN]);
retVal |= writeNs0Variable(server, UA_NS0ID_HISTORYSERVERCAPABILITIES_UPDATEDATACAPABILITY,
&server->config.updateDataCapability, &UA_TYPES[UA_TYPES_BOOLEAN]);
retVal |= writeNs0Variable(server, UA_NS0ID_HISTORYSERVERCAPABILITIES_UPDATEEVENTCAPABILITY,
&server->config.updateEventCapability, &UA_TYPES[UA_TYPES_BOOLEAN]);
retVal |= writeNs0Variable(server, UA_NS0ID_HISTORYSERVERCAPABILITIES_DELETERAWCAPABILITY,
&server->config.deleteRawCapability, &UA_TYPES[UA_TYPES_BOOLEAN]);
retVal |= writeNs0Variable(server, UA_NS0ID_HISTORYSERVERCAPABILITIES_DELETEEVENTCAPABILITY,
&server->config.deleteEventCapability, &UA_TYPES[UA_TYPES_BOOLEAN]);
retVal |= writeNs0Variable(server, UA_NS0ID_HISTORYSERVERCAPABILITIES_DELETEATTIMECAPABILITY,
&server->config.deleteAtTimeDataCapability, &UA_TYPES[UA_TYPES_BOOLEAN]);
#ifdef UA_GENERATED_NAMESPACE_ZERO_FULL
{
UA_Boolean serverTimestampSupported = true;
retVal |= writeNs0Variable(server,
UA_NS0ID_HISTORYSERVERCAPABILITIES_SERVERTIMESTAMPSUPPORTED,
&serverTimestampSupported, &UA_TYPES[UA_TYPES_BOOLEAN]);
}
#endif
#ifdef UA_NS0ID_DEFAULTHACONFIGURATION_STEPPED
{
UA_Boolean bTrue = true, bFalse = false;
UA_Byte percentDataBad = 100, percentDataGood = 100;
UA_Duration zeroDuration = 0.0;
UA_Double zeroDouble = 0.0;
UA_UInt32 zeroUInt32 = 0;
UA_ExceptionDeviationFormat absValue = UA_EXCEPTIONDEVIATIONFORMAT_ABSOLUTEVALUE;
retVal |= writeNs0Variable(server,
UA_NS0ID_DEFAULTHACONFIGURATION_AGGREGATECONFIGURATION_TREATUNCERTAINASBAD,
&bTrue, &UA_TYPES[UA_TYPES_BOOLEAN]);
retVal |= writeNs0Variable(server,
UA_NS0ID_DEFAULTHACONFIGURATION_AGGREGATECONFIGURATION_PERCENTDATABAD,
&percentDataBad, &UA_TYPES[UA_TYPES_BYTE]);
retVal |= writeNs0Variable(server,
UA_NS0ID_DEFAULTHACONFIGURATION_AGGREGATECONFIGURATION_PERCENTDATAGOOD,
&percentDataGood, &UA_TYPES[UA_TYPES_BYTE]);
retVal |= writeNs0Variable(server,
UA_NS0ID_DEFAULTHACONFIGURATION_AGGREGATECONFIGURATION_USESLOPEDEXTRAPOLATION,
&bFalse, &UA_TYPES[UA_TYPES_BOOLEAN]);
retVal |= writeNs0Variable(server,
UA_NS0ID_DEFAULTHACONFIGURATION_STEPPED,
&bFalse, &UA_TYPES[UA_TYPES_BOOLEAN]);
retVal |= writeNs0Variable(server,
UA_NS0ID_DEFAULTHACONFIGURATION_MAXTIMEINTERVAL,
&zeroDuration, &UA_TYPES[UA_TYPES_DOUBLE]);
retVal |= writeNs0Variable(server,
UA_NS0ID_DEFAULTHACONFIGURATION_MINTIMEINTERVAL,
&zeroDuration, &UA_TYPES[UA_TYPES_DOUBLE]);
retVal |= writeNs0Variable(server,
UA_NS0ID_DEFAULTHACONFIGURATION_EXCEPTIONDEVIATION,
&zeroDouble, &UA_TYPES[UA_TYPES_DOUBLE]);
retVal |= writeNs0Variable(server,
UA_NS0ID_DEFAULTHACONFIGURATION_EXCEPTIONDEVIATIONFORMAT,
&absValue, &UA_TYPES[UA_TYPES_EXCEPTIONDEVIATIONFORMAT]);
retVal |= writeNs0Variable(server,
UA_NS0ID_DEFAULTHACONFIGURATION_SERVERTIMESTAMPSUPPORTED,
&bTrue, &UA_TYPES[UA_TYPES_BOOLEAN]);
retVal |= writeNs0Variable(server,
UA_NS0ID_DEFAULTHACONFIGURATION_MAXTIMESTOREDVALUES,
&zeroDuration, &UA_TYPES[UA_TYPES_DOUBLE]);
retVal |= writeNs0Variable(server,
UA_NS0ID_DEFAULTHACONFIGURATION_MAXCOUNTSTOREDVALUES,
&zeroUInt32, &UA_TYPES[UA_TYPES_UINT32]);
}
#endif
#endif
addModellingRules(server);
#endif
return retVal;
}
static UA_StatusCode
connectNS0_dataSources(UA_Server *server) {
UA_StatusCode retVal = UA_STATUSCODE_GOOD;
UA_CallbackValueSource namespaceDataSource = {readNamespaces, writeNamespaces};
retVal |= setVariableNode_callbackValueSource(server, UA_NS0ID(SERVER_NAMESPACEARRAY),
namespaceDataSource);
UA_CallbackValueSource serverStatus = {readStatus, writeStatus};
retVal |= setVariableNode_callbackValueSource(server, UA_NS0ID(SERVER_SERVERSTATUS), serverStatus);
UA_CallbackValueSource currentTime = {readCurrentTime, NULL};
retVal |= setVariableNode_callbackValueSource(server, UA_NS0ID(SERVER_SERVERSTATUS_CURRENTTIME), currentTime);
retVal |= setVariableNode_callbackValueSource(server, UA_NS0ID(SERVER_SERVERSTATUS_STATE), serverStatus);
retVal |= setVariableNode_callbackValueSource(server, UA_NS0ID(SERVER_SERVERSTATUS_BUILDINFO), serverStatus);
retVal |= setVariableNode_callbackValueSource(server, UA_NS0ID(SERVER_SERVERSTATUS_BUILDINFO_PRODUCTURI), serverStatus);
retVal |= setVariableNode_callbackValueSource(server, UA_NS0ID(SERVER_SERVERSTATUS_BUILDINFO_MANUFACTURERNAME), serverStatus);
retVal |= setVariableNode_callbackValueSource(server, UA_NS0ID(SERVER_SERVERSTATUS_BUILDINFO_PRODUCTNAME), serverStatus);
retVal |= setVariableNode_callbackValueSource(server, UA_NS0ID(SERVER_SERVERSTATUS_BUILDINFO_SOFTWAREVERSION), serverStatus);
retVal |= setVariableNode_callbackValueSource(server, UA_NS0ID(SERVER_SERVERSTATUS_BUILDINFO_BUILDNUMBER), serverStatus);
retVal |= setVariableNode_callbackValueSource(server, UA_NS0ID(SERVER_SERVERSTATUS_BUILDINFO_BUILDDATE), serverStatus);
#ifdef UA_GENERATED_NAMESPACE_ZERO
retVal |= setVariableNode_callbackValueSource(server, UA_NS0ID(SERVER_SERVERSTATUS_SECONDSTILLSHUTDOWN), serverStatus);
UA_CallbackValueSource serviceLevel = {readServiceLevel, NULL};
retVal |= setVariableNode_callbackValueSource(server, UA_NS0ID(SERVER_SERVICELEVEL), serviceLevel);
UA_CallbackValueSource auditing = {readAuditing, NULL};
retVal |= setVariableNode_callbackValueSource(server, UA_NS0ID(SERVER_AUDITING), auditing);
UA_CallbackValueSource samplingInterval = {readMinSamplingInterval, NULL};
retVal |= setVariableNode_callbackValueSource(server, UA_NS0ID(SERVER_SERVERCAPABILITIES_MINSUPPORTEDSAMPLERATE), samplingInterval);
UA_CallbackValueSource operationLimitRead = {readOperationLimits, NULL};
retVal |= setVariableNode_callbackValueSource(server, UA_NS0ID(SERVER_SERVERCAPABILITIES_OPERATIONLIMITS_MAXNODESPERREAD), operationLimitRead);
retVal |= setVariableNode_callbackValueSource(server, UA_NS0ID(SERVER_SERVERCAPABILITIES_OPERATIONLIMITS_MAXNODESPERWRITE), operationLimitRead);
retVal |= setVariableNode_callbackValueSource(server, UA_NS0ID(SERVER_SERVERCAPABILITIES_OPERATIONLIMITS_MAXNODESPERMETHODCALL), operationLimitRead);
retVal |= setVariableNode_callbackValueSource(server, UA_NS0ID(SERVER_SERVERCAPABILITIES_OPERATIONLIMITS_MAXNODESPERBROWSE), operationLimitRead);
retVal |= setVariableNode_callbackValueSource(server, UA_NS0ID(SERVER_SERVERCAPABILITIES_OPERATIONLIMITS_MAXNODESPERREGISTERNODES), operationLimitRead);
retVal |= setVariableNode_callbackValueSource(server, UA_NS0ID(SERVER_SERVERCAPABILITIES_OPERATIONLIMITS_MAXNODESPERTRANSLATEBROWSEPATHSTONODEIDS), operationLimitRead);
retVal |= setVariableNode_callbackValueSource(server, UA_NS0ID(SERVER_SERVERCAPABILITIES_OPERATIONLIMITS_MAXNODESPERNODEMANAGEMENT), operationLimitRead);
retVal |= setVariableNode_callbackValueSource(server, UA_NS0ID(SERVER_SERVERCAPABILITIES_OPERATIONLIMITS_MAXMONITOREDITEMSPERCALL), operationLimitRead);
retVal |= setVariableNode_callbackValueSource(server, UA_NS0ID(SERVER_SERVERCAPABILITIES_MAXMONITOREDITEMSQUEUESIZE), operationLimitRead);
#ifdef UA_ENABLE_DIAGNOSTICS
UA_CallbackValueSource serverDiagSummary = {readDiagnostics, NULL};
retVal |= setVariableNode_callbackValueSource(server, UA_NS0ID(SERVER_SERVERDIAGNOSTICS_SERVERDIAGNOSTICSSUMMARY), serverDiagSummary);
retVal |= setVariableNode_callbackValueSource(server, UA_NS0ID(SERVER_SERVERDIAGNOSTICS_SERVERDIAGNOSTICSSUMMARY_SERVERVIEWCOUNT), serverDiagSummary);
retVal |= setVariableNode_callbackValueSource(server, UA_NS0ID(SERVER_SERVERDIAGNOSTICS_SERVERDIAGNOSTICSSUMMARY_CURRENTSESSIONCOUNT), serverDiagSummary);
retVal |= setVariableNode_callbackValueSource(server, UA_NS0ID(SERVER_SERVERDIAGNOSTICS_SERVERDIAGNOSTICSSUMMARY_CUMULATEDSESSIONCOUNT), serverDiagSummary);
retVal |= setVariableNode_callbackValueSource(server, UA_NS0ID(SERVER_SERVERDIAGNOSTICS_SERVERDIAGNOSTICSSUMMARY_SECURITYREJECTEDSESSIONCOUNT), serverDiagSummary);
retVal |= setVariableNode_callbackValueSource(server, UA_NS0ID(SERVER_SERVERDIAGNOSTICS_SERVERDIAGNOSTICSSUMMARY_REJECTEDSESSIONCOUNT), serverDiagSummary);
retVal |= setVariableNode_callbackValueSource(server, UA_NS0ID(SERVER_SERVERDIAGNOSTICS_SERVERDIAGNOSTICSSUMMARY_SESSIONTIMEOUTCOUNT), serverDiagSummary);
retVal |= setVariableNode_callbackValueSource(server, UA_NS0ID(SERVER_SERVERDIAGNOSTICS_SERVERDIAGNOSTICSSUMMARY_SESSIONABORTCOUNT), serverDiagSummary);
retVal |= setVariableNode_callbackValueSource(server, UA_NS0ID(SERVER_SERVERDIAGNOSTICS_SERVERDIAGNOSTICSSUMMARY_CURRENTSUBSCRIPTIONCOUNT), serverDiagSummary);
retVal |= setVariableNode_callbackValueSource(server, UA_NS0ID(SERVER_SERVERDIAGNOSTICS_SERVERDIAGNOSTICSSUMMARY_CUMULATEDSUBSCRIPTIONCOUNT), serverDiagSummary);
retVal |= setVariableNode_callbackValueSource(server, UA_NS0ID(SERVER_SERVERDIAGNOSTICS_SERVERDIAGNOSTICSSUMMARY_PUBLISHINGINTERVALCOUNT), serverDiagSummary);
retVal |= setVariableNode_callbackValueSource(server, UA_NS0ID(SERVER_SERVERDIAGNOSTICS_SERVERDIAGNOSTICSSUMMARY_SECURITYREJECTEDREQUESTSCOUNT), serverDiagSummary);
retVal |= setVariableNode_callbackValueSource(server, UA_NS0ID(SERVER_SERVERDIAGNOSTICS_SERVERDIAGNOSTICSSUMMARY_REJECTEDREQUESTSCOUNT), serverDiagSummary);
#ifdef UA_ENABLE_SUBSCRIPTIONS
UA_CallbackValueSource serverSubDiagSummary = {readSubscriptionDiagnosticsArray, NULL};
retVal |= setVariableNode_callbackValueSource(server, UA_NS0ID(SERVER_SERVERDIAGNOSTICS_SUBSCRIPTIONDIAGNOSTICSARRAY), serverSubDiagSummary);
#endif
UA_CallbackValueSource sessionDiagSummary = {readSessionDiagnosticsArray, NULL};
retVal |= setVariableNode_callbackValueSource(server, UA_NS0ID(SERVER_SERVERDIAGNOSTICS_SESSIONSDIAGNOSTICSSUMMARY_SESSIONDIAGNOSTICSARRAY), sessionDiagSummary);
UA_CallbackValueSource sessionSecDiagSummary = {readSessionSecurityDiagnostics, NULL};
retVal |= setVariableNode_callbackValueSource(server, UA_NS0ID(SERVER_SERVERDIAGNOSTICS_SESSIONSDIAGNOSTICSSUMMARY_SESSIONSECURITYDIAGNOSTICSARRAY), sessionSecDiagSummary);
#endif
#if defined(UA_ENABLE_METHODCALLS) && defined(UA_ENABLE_SUBSCRIPTIONS)
retVal |= setMethodNode_callback(server, UA_NS0ID(SERVER_GETMONITOREDITEMS), readMonitoredItems);
retVal |= setMethodNode_callback(server, UA_NS0ID(SERVER_RESENDDATA), resendData);
#endif
#endif
return retVal;
}
UA_StatusCode
initNS0_dataSources(UA_Server *server) {
UA_LOCK_ASSERT(&server->serviceMutex);
UA_LOG_INFO(server->config.logging, UA_LOGCATEGORY_SERVER,
"Configuring pre-loaded NS0 nodes (data sources, values, deletions)");
UA_StatusCode retVal = connectNS0_dataSources(server);
retVal |= configureNS0(server);
if(retVal != UA_STATUSCODE_GOOD) {
UA_LOG_WARNING(server->config.logging, UA_LOGCATEGORY_SERVER,
"Some NS0 configuration operations failed: %s "
"(this may be normal if some nodes don't exist in ROM)",
UA_StatusCode_name(retVal));
}
return UA_STATUSCODE_GOOD;
}