brief introduction
target
Translation and supplement open62541v1 2 official manual.
Information model callback
There are three places where callbacks from the information model to user-defined code can occur.
- Custom node constructors and destructors
- Linking VariableNodes to external data sources
- Method node callback
void UA_Server_setAdminSessionContext(UA_Server *server, void *context); UA_StatusCode UA_THREADSAFE UA_Server_setNodeTypeLifecycle(UA_Server *server, UA_NodeId nodeId, UA_NodeTypeLifecycle lifecycle); UA_StatusCode UA_THREADSAFE UA_Server_getNodeContext(UA_Server *server, UA_NodeId nodeId, void **nodeContext); /* Careful! The user has to ensure that the destructor callbacks still work. */ UA_StatusCode UA_THREADSAFE UA_Server_setNodeContext(UA_Server *server, UA_NodeId nodeId, void *nodeContext);
Data source callback
The server has a unique way to handle the contents of variables** This node can point to a function with a local data provider instead of storing variants attached to the variable node** Whenever the value attribute is read, the function will be called and asked to provide a UA_DataValue returns a value that contains the content of the value and an additional timestamp.
The read callback is expected to be implemented. The write callback can be set to a null pointer.
UA_StatusCode UA_THREADSAFE UA_Server_setVariableNode_dataSource(UA_Server *server, const UA_NodeId nodeId, const UA_DataSource dataSource); UA_StatusCode UA_THREADSAFE UA_Server_setVariableNode_valueCallback(UA_Server *server, const UA_NodeId nodeId, const UA_ValueCallback callback); UA_StatusCode UA_THREADSAFE UA_Server_setVariableNode_valueBackend(UA_Server *server, const UA_NodeId nodeId, const UA_ValueBackend valueBackend);
Local monitoring items
MonitoredItems is used together with the subscription mechanism of OPC UA to transmit notifications of data changes and events. MonitoredItems can also be registered locally. The notification is then forwarded to a user-defined callback instead of the remote client.
#ifdef UA_ENABLE_SUBSCRIPTIONS typedef void (*UA_Server_DataChangeNotificationCallback) (UA_Server *server, UA_UInt32 monitoredItemId, void *monitoredItemContext, const UA_NodeId *nodeId, void *nodeContext, UA_UInt32 attributeId, const UA_DataValue *value); typedef void (*UA_Server_EventNotificationCallback) (UA_Server *server, UA_UInt32 monId, void *monContext, size_t nEventFields, const UA_Variant *eventFields); /* Create a local MonitoredItem with a sampling interval that detects data * changes. * * @param server The server executing the MonitoredItem * @timestampsToReturn Shall timestamps be added to the value for the callback? * @item The parameters of the new MonitoredItem. Note that the attribute of the * ReadValueId (the node that is monitored) can not be * ``UA_ATTRIBUTEID_EVENTNOTIFIER``. A different callback type needs to be * registered for event notifications. * @monitoredItemContext A pointer that is forwarded with the callback * @callback The callback that is executed on detected data changes * * @return Returns a description of the created MonitoredItem. The structure * also contains a StatusCode (in case of an error) and the identifier of the * new MonitoredItem. */ UA_MonitoredItemCreateResult UA_THREADSAFE UA_Server_createDataChangeMonitoredItem(UA_Server *server, UA_TimestampsToReturn timestampsToReturn, const UA_MonitoredItemCreateRequest item, void *monitoredItemContext, UA_Server_DataChangeNotificationCallback callback); /* UA_MonitoredItemCreateResult */ /* UA_Server_createEventMonitoredItem(UA_Server *server, */ /* UA_TimestampsToReturn timestampsToReturn, */ /* const UA_MonitoredItemCreateRequest item, void *context, */ /* UA_Server_EventNotificationCallback callback); */ UA_StatusCode UA_THREADSAFE UA_Server_deleteMonitoredItem(UA_Server *server, UA_UInt32 monitoredItemId); #endif
Method callback
When a method node is added over the network, the method callback is set to NULL (not executable). Theoretically, when you really need to add methods through the network, you can use UA_Server_setMethodNode_callback adds a callback to the global constructor. See Interact with objects Section to learn about calling methods on objects.
#ifdef UA_ENABLE_METHODCALLS UA_StatusCode UA_THREADSAFE UA_Server_setMethodNode_callback(UA_Server *server, const UA_NodeId methodNodeId, UA_MethodCallback methodCallback); #endif
Interact with objects
Objects in the information model are represented as ObjectNodes. We provide some convenient functions to simplify the interaction with objects.
/* Write an object property. The property is represented as a VariableNode with * a ``HasProperty`` reference from the ObjectNode. The VariableNode is * identified by its BrowseName. Writing the property sets the value attribute * of the VariableNode. * * @param server The server object * @param objectId The identifier of the object (node) * @param propertyName The name of the property * @param value The value to be set for the event attribute * @return The StatusCode for setting the event attribute */ UA_StatusCode UA_THREADSAFE UA_Server_writeObjectProperty(UA_Server *server, const UA_NodeId objectId, const UA_QualifiedName propertyName, const UA_Variant value); /* Directly point to the scalar value instead of a variant */ UA_StatusCode UA_THREADSAFE UA_Server_writeObjectProperty_scalar(UA_Server *server, const UA_NodeId objectId, const UA_QualifiedName propertyName, const void *value, const UA_DataType *type); /* Read an object property. * * @param server The server object * @param objectId The identifier of the object (node) * @param propertyName The name of the property * @param value Contains the property value after reading. Must not be NULL. * @return The StatusCode for setting the event attribute */ UA_StatusCode UA_THREADSAFE UA_Server_readObjectProperty(UA_Server *server, const UA_NodeId objectId, const UA_QualifiedName propertyName, UA_Variant *value); #ifdef UA_ENABLE_METHODCALLS UA_CallMethodResult UA_THREADSAFE UA_Server_call(UA_Server *server, const UA_CallMethodRequest *request); #endif
Addition and deletion of nodes
When creating a dynamic node instance at runtime, you may not care about the specific nodeid of the new node, as long as you can reference it later. When nodeid with numeric identifier 0 is passed, the stack evaluates it as "randomly select an unassigned numeric nodeid in this namespace". To know which nodeid is actually assigned to the new node, you can pass a pointer outNewNodeId, which will contain the nodeid of the new node (after successfully inserting the node). If you don't need this result, you can also pass a NULL pointer.
See Node lifecycle: constructor, destructor, and node context The section on constructors and attaching user-defined data to nodes in.
Constant parameters are mainly used to add and delete nodes, and these parameters will not be modified. When a node is created, a deep copy of the node identifier, node attributes, etc. is created. Therefore, for example, UA can be called_ Server_ Addvariablenode, its value attribute (one) variable )Points to a memory location on the stack. If you need to change the value of a variable in a specific memory location, use Data source callback or Value callback.
/* Protect against redundant definitions for server/client */ #ifndef UA_DEFAULT_ATTRIBUTES_DEFINED #define UA_DEFAULT_ATTRIBUTES_DEFINED /* The default for variables is "BaseDataType" for the datatype, -2 for the * valuerank and a read-accesslevel. */ extern const UA_VariableAttributes UA_VariableAttributes_default; extern const UA_VariableTypeAttributes UA_VariableTypeAttributes_default; /* Methods are executable by default */ extern const UA_MethodAttributes UA_MethodAttributes_default; /* The remaining attribute definitions are currently all zeroed out */ extern const UA_ObjectAttributes UA_ObjectAttributes_default; extern const UA_ObjectTypeAttributes UA_ObjectTypeAttributes_default; extern const UA_ReferenceTypeAttributes UA_ReferenceTypeAttributes_default; extern const UA_DataTypeAttributes UA_DataTypeAttributes_default; extern const UA_ViewAttributes UA_ViewAttributes_default; #endif /* Don't use this function. There are typed versions as inline functions. */ UA_StatusCode UA_THREADSAFE __UA_Server_addNode(UA_Server *server, const UA_NodeClass nodeClass, const UA_NodeId *requestedNewNodeId, const UA_NodeId *parentNodeId, const UA_NodeId *referenceTypeId, const UA_QualifiedName browseName, const UA_NodeId *typeDefinition, const UA_NodeAttributes *attr, const UA_DataType *attributeType, void *nodeContext, UA_NodeId *outNewNodeId); static UA_INLINE UA_THREADSAFE UA_StatusCode UA_Server_addVariableNode(UA_Server *server, const UA_NodeId requestedNewNodeId, const UA_NodeId parentNodeId, const UA_NodeId referenceTypeId, const UA_QualifiedName browseName, const UA_NodeId typeDefinition, const UA_VariableAttributes attr, void *nodeContext, UA_NodeId *outNewNodeId) { return __UA_Server_addNode(server, UA_NODECLASS_VARIABLE, &requestedNewNodeId, &parentNodeId, &referenceTypeId, browseName, &typeDefinition, (const UA_NodeAttributes*)&attr, &UA_TYPES[UA_TYPES_VARIABLEATTRIBUTES], nodeContext, outNewNodeId); } static UA_INLINE UA_THREADSAFE UA_StatusCode UA_Server_addVariableTypeNode(UA_Server *server, const UA_NodeId requestedNewNodeId, const UA_NodeId parentNodeId, const UA_NodeId referenceTypeId, const UA_QualifiedName browseName, const UA_NodeId typeDefinition, const UA_VariableTypeAttributes attr, void *nodeContext, UA_NodeId *outNewNodeId) { return __UA_Server_addNode(server, UA_NODECLASS_VARIABLETYPE, &requestedNewNodeId, &parentNodeId, &referenceTypeId, browseName, &typeDefinition, (const UA_NodeAttributes*)&attr, &UA_TYPES[UA_TYPES_VARIABLETYPEATTRIBUTES], nodeContext, outNewNodeId); } static UA_INLINE UA_THREADSAFE UA_StatusCode UA_Server_addObjectNode(UA_Server *server, const UA_NodeId requestedNewNodeId, const UA_NodeId parentNodeId, const UA_NodeId referenceTypeId, const UA_QualifiedName browseName, const UA_NodeId typeDefinition, const UA_ObjectAttributes attr, void *nodeContext, UA_NodeId *outNewNodeId) { return __UA_Server_addNode(server, UA_NODECLASS_OBJECT, &requestedNewNodeId, &parentNodeId, &referenceTypeId, browseName, &typeDefinition, (const UA_NodeAttributes*)&attr, &UA_TYPES[UA_TYPES_OBJECTATTRIBUTES], nodeContext, outNewNodeId); } static UA_INLINE UA_THREADSAFE UA_StatusCode UA_Server_addObjectTypeNode(UA_Server *server, const UA_NodeId requestedNewNodeId, const UA_NodeId parentNodeId, const UA_NodeId referenceTypeId, const UA_QualifiedName browseName, const UA_ObjectTypeAttributes attr, void *nodeContext, UA_NodeId *outNewNodeId) { return __UA_Server_addNode(server, UA_NODECLASS_OBJECTTYPE, &requestedNewNodeId, &parentNodeId, &referenceTypeId, browseName, &UA_NODEID_NULL, (const UA_NodeAttributes*)&attr, &UA_TYPES[UA_TYPES_OBJECTTYPEATTRIBUTES], nodeContext, outNewNodeId); } static UA_INLINE UA_THREADSAFE UA_StatusCode UA_Server_addViewNode(UA_Server *server, const UA_NodeId requestedNewNodeId, const UA_NodeId parentNodeId, const UA_NodeId referenceTypeId, const UA_QualifiedName browseName, const UA_ViewAttributes attr, void *nodeContext, UA_NodeId *outNewNodeId) { return __UA_Server_addNode(server, UA_NODECLASS_VIEW, &requestedNewNodeId, &parentNodeId, &referenceTypeId, browseName, &UA_NODEID_NULL, (const UA_NodeAttributes*)&attr, &UA_TYPES[UA_TYPES_VIEWATTRIBUTES], nodeContext, outNewNodeId); } static UA_INLINE UA_THREADSAFE UA_StatusCode UA_Server_addReferenceTypeNode(UA_Server *server, const UA_NodeId requestedNewNodeId, const UA_NodeId parentNodeId, const UA_NodeId referenceTypeId, const UA_QualifiedName browseName, const UA_ReferenceTypeAttributes attr, void *nodeContext, UA_NodeId *outNewNodeId) { return __UA_Server_addNode(server, UA_NODECLASS_REFERENCETYPE, &requestedNewNodeId, &parentNodeId, &referenceTypeId, browseName, &UA_NODEID_NULL, (const UA_NodeAttributes*)&attr, &UA_TYPES[UA_TYPES_REFERENCETYPEATTRIBUTES], nodeContext, outNewNodeId); } static UA_INLINE UA_THREADSAFE UA_StatusCode UA_Server_addDataTypeNode(UA_Server *server, const UA_NodeId requestedNewNodeId, const UA_NodeId parentNodeId, const UA_NodeId referenceTypeId, const UA_QualifiedName browseName, const UA_DataTypeAttributes attr, void *nodeContext, UA_NodeId *outNewNodeId) { return __UA_Server_addNode(server, UA_NODECLASS_DATATYPE, &requestedNewNodeId, &parentNodeId, &referenceTypeId, browseName, &UA_NODEID_NULL, (const UA_NodeAttributes*)&attr, &UA_TYPES[UA_TYPES_DATATYPEATTRIBUTES], nodeContext, outNewNodeId); } UA_StatusCode UA_THREADSAFE UA_Server_addDataSourceVariableNode(UA_Server *server, const UA_NodeId requestedNewNodeId, const UA_NodeId parentNodeId, const UA_NodeId referenceTypeId, const UA_QualifiedName browseName, const UA_NodeId typeDefinition, const UA_VariableAttributes attr, const UA_DataSource dataSource, void *nodeContext, UA_NodeId *outNewNodeId); #ifdef UA_ENABLE_METHODCALLS UA_StatusCode UA_THREADSAFE UA_Server_addMethodNodeEx(UA_Server *server, const UA_NodeId requestedNewNodeId, const UA_NodeId parentNodeId, const UA_NodeId referenceTypeId, const UA_QualifiedName browseName, const UA_MethodAttributes attr, UA_MethodCallback method, size_t inputArgumentsSize, const UA_Argument *inputArguments, const UA_NodeId inputArgumentsRequestedNewNodeId, UA_NodeId *inputArgumentsOutNewNodeId, size_t outputArgumentsSize, const UA_Argument *outputArguments, const UA_NodeId outputArgumentsRequestedNewNodeId, UA_NodeId *outputArgumentsOutNewNodeId, void *nodeContext, UA_NodeId *outNewNodeId); static UA_INLINE UA_THREADSAFE UA_StatusCode UA_Server_addMethodNode(UA_Server *server, const UA_NodeId requestedNewNodeId, const UA_NodeId parentNodeId, const UA_NodeId referenceTypeId, const UA_QualifiedName browseName, const UA_MethodAttributes attr, UA_MethodCallback method, size_t inputArgumentsSize, const UA_Argument *inputArguments, size_t outputArgumentsSize, const UA_Argument *outputArguments, void *nodeContext, UA_NodeId *outNewNodeId) { return UA_Server_addMethodNodeEx(server, requestedNewNodeId, parentNodeId, referenceTypeId, browseName, attr, method, inputArgumentsSize, inputArguments, UA_NODEID_NULL, NULL, outputArgumentsSize, outputArguments, UA_NODEID_NULL, NULL, nodeContext, outNewNodeId); } #endif
UA_Server_addNode_begin and_ The finish method divides the AddNodes service into two parts. This is useful if you want to modify the node before you complete instantiation. For example, add a child node with a specific nodeid. Otherwise, mandatory child nodes (such as ObjectType) will be added with pseudo-random unique nodeid. Existing child nodes in_ The finish part is detected by their matching BrowseName.
-
_ begin method.
Prepare the node and add it to the node to copy some unallocated attributes from the TypeDefinition node, add references to the parent node (and TypeDefinition (if applicable)) and perform type checking of variables.
If you set parentNodeId and referenceTypeId to UA_NODE_ID_NULL, you can add an object node without a parent node. Then you need to call_ Add the parent node reference and hasTypeDef reference before the finish method. This is not to say that this is only allowed for object nodes.
-
_ finish method.
If an error is encountered, the node constructor at the end deletes the node.
Special UA_ Server_ addMethodNode_ The finish method needs to be used for the method node, where you need to explicitly specify input and output parameters, which are added in the finish step (if not already).
/* The ``attr`` argument must have a type according to the NodeClass. * ``VariableAttributes`` for variables, ``ObjectAttributes`` for objects, and * so on. Missing attributes are taken from the TypeDefinition node if * applicable. */ UA_StatusCode UA_THREADSAFE UA_Server_addNode_begin(UA_Server *server, const UA_NodeClass nodeClass, const UA_NodeId requestedNewNodeId, const UA_NodeId parentNodeId, const UA_NodeId referenceTypeId, const UA_QualifiedName browseName, const UA_NodeId typeDefinition, const void *attr, const UA_DataType *attributeType, void *nodeContext, UA_NodeId *outNewNodeId); UA_StatusCode UA_THREADSAFE UA_Server_addNode_finish(UA_Server *server, const UA_NodeId nodeId); #ifdef UA_ENABLE_METHODCALLS UA_StatusCode UA_THREADSAFE UA_Server_addMethodNode_finish(UA_Server *server, const UA_NodeId nodeId, UA_MethodCallback method, size_t inputArgumentsSize, const UA_Argument* inputArguments, size_t outputArgumentsSize, const UA_Argument* outputArguments); #endif /* Deletes a node and optionally all references leading to the node. */ UA_StatusCode UA_THREADSAFE UA_Server_deleteNode(UA_Server *server, const UA_NodeId nodeId, UA_Boolean deleteReferences);
Reference Management
UA_StatusCode UA_THREADSAFE UA_Server_addReference(UA_Server *server, const UA_NodeId sourceId, const UA_NodeId refTypeId, const UA_ExpandedNodeId targetId, UA_Boolean isForward); UA_StatusCode UA_THREADSAFE UA_Server_deleteReference(UA_Server *server, const UA_NodeId sourceNodeId, const UA_NodeId referenceTypeId, UA_Boolean isForward, const UA_ExpandedNodeId targetNodeId, UA_Boolean deleteBidirectional);
event
Method UA_Server_createEvent creates an event and represents it as a node. The node receives a unique EventId, which is automatically added to the node. This method returns a NodeId to the object node, which represents the event through outNodeId. NodeId can be used to set the properties of the event. The generated NodeId is always numeric. outNodeId cannot be NULL.
Note: in order to see an event in UAExpert, the field Time must be given a value!
Method UA_ Server_ Trigger event "triggers" an event and adds it to all monitoring items of the specified original node and all its parent nodes. Any filter specified by the monitoring item is automatically applied. Using this method, you can delete the data generated by UA_ Server_ The node generated by createevent. The EventId of the new event is automatically generated and returned through outEventId. If EventId is not required, NULL can be passed. deleteEventNode specifies whether the node representation of the event should be deleted after the method is called. This can be useful if events with similar properties are often triggered. UA_TRUE will cause the node to be deleted.
#ifdef UA_ENABLE_SUBSCRIPTIONS_EVENTS /* The EventQueueOverflowEventType is defined as abstract, therefore we can not * create an instance of that type directly, but need to create a subtype. The * following is an arbitrary number which shall refer to our internal overflow * type. This is already posted on the OPC Foundation bug tracker under the * following link for clarification: * https://opcfoundation-onlineapplications.org/mantis/view.php?id=4206 */ # define UA_NS0ID_SIMPLEOVERFLOWEVENTTYPE 4035 /* Creates a node representation of an event * * @param server The server object * @param eventType The type of the event for which a node should be created * @param outNodeId The NodeId of the newly created node for the event * @return The StatusCode of the UA_Server_createEvent method */ UA_StatusCode UA_THREADSAFE UA_Server_createEvent(UA_Server *server, const UA_NodeId eventType, UA_NodeId *outNodeId); /* Triggers a node representation of an event by applying EventFilters and * adding the event to the appropriate queues. * * @param server The server object * @param eventNodeId The NodeId of the node representation of the event which should be triggered * @param outEvent the EventId of the new event * @param deleteEventNode Specifies whether the node representation of the event should be deleted * @return The StatusCode of the UA_Server_triggerEvent method */ UA_StatusCode UA_THREADSAFE UA_Server_triggerEvent(UA_Server *server, const UA_NodeId eventNodeId, const UA_NodeId originId, UA_ByteString *outEventId, const UA_Boolean deleteEventNode); #endif /* UA_ENABLE_SUBSCRIPTIONS_EVENTS */ #ifdef UA_ENABLE_SUBSCRIPTIONS_ALARMS_CONDITIONS typedef enum UA_TwoStateVariableCallbackType { UA_ENTERING_ENABLEDSTATE, UA_ENTERING_ACKEDSTATE, UA_ENTERING_CONFIRMEDSTATE, UA_ENTERING_ACTIVESTATE } UA_TwoStateVariableCallbackType; /* Callback prototype to set user specific callbacks */ typedef UA_StatusCode (*UA_TwoStateVariableChangeCallback)(UA_Server *server, const UA_NodeId *condition); /* Create condition instance. The function checks first whether the passed * conditionType is a subType of ConditionType. Then checks whether the * condition source has HasEventSource reference to its parent. If not, a * HasEventSource reference will be created between condition source and server * object. To expose the condition in address space, a hierarchical * ReferenceType should be passed to create the reference to condition source. * Otherwise, UA_NODEID_NULL should be passed to make the condition not exposed. * * @param server The server object * @param conditionId The NodeId of the requested Condition Object. When passing * UA_NODEID_NUMERIC(X,0) an unused nodeid in namespace X * will be used. E.g. passing UA_NODEID_NULL will result in a * NodeId in namespace 0. * @param conditionType The NodeId of the node representation of the ConditionType * @param conditionName The name of the condition to be created * @param conditionSource The NodeId of the Condition Source (Parent of the Condition) * @param hierarchialReferenceType The NodeId of Hierarchical ReferenceType * between Condition and its source * @param outConditionId The NodeId of the created Condition * @return The StatusCode of the UA_Server_createCondition method */ UA_StatusCode UA_Server_createCondition(UA_Server *server, const UA_NodeId conditionId, const UA_NodeId conditionType, UA_QualifiedName conditionName, const UA_NodeId conditionSource, const UA_NodeId hierarchialReferenceType, UA_NodeId *outConditionId); /* Set the value of condition field. * * @param server The server object * @param condition The NodeId of the node representation of the Condition Instance * @param value Variant Value to be written to the Field * @param fieldName Name of the Field in which the value should be written * @return The StatusCode of the UA_Server_setConditionField method*/ UA_StatusCode UA_Server_setConditionField(UA_Server *server, const UA_NodeId condition, const UA_Variant* value, const UA_QualifiedName fieldName); /* Set the value of property of condition field. * * @param server The server object * @param condition The NodeId of the node representation of the Condition Instance * @param value Variant Value to be written to the Field * @param variableFieldName Name of the Field which has a property * @param variablePropertyName Name of the Field Property in which the value should be written * @return The StatusCode of the UA_Server_setConditionVariableFieldProperty*/ UA_StatusCode UA_Server_setConditionVariableFieldProperty(UA_Server *server, const UA_NodeId condition, const UA_Variant* value, const UA_QualifiedName variableFieldName, const UA_QualifiedName variablePropertyName); /* Triggers an event only for an enabled condition. The condition list is * updated then with the last generated EventId. * * @param server The server object * @param condition The NodeId of the node representation of the Condition Instance * @param conditionSource The NodeId of the node representation of the Condition Source * @param outEventId last generated EventId * @return The StatusCode of the UA_Server_triggerConditionEvent method*/ UA_StatusCode UA_Server_triggerConditionEvent(UA_Server *server, const UA_NodeId condition, const UA_NodeId conditionSource, UA_ByteString *outEventId); /* Add an optional condition field using its name. (TODO Adding optional methods * is not implemented yet) * * @param server The server object * @param condition The NodeId of the node representation of the Condition Instance * @param conditionType The NodeId of the node representation of the Condition Type * from which the optional field comes * @param fieldName Name of the optional field * @param outOptionalVariable The NodeId of the created field (Variable Node) * @return The StatusCode of the UA_Server_addConditionOptionalField method*/ UA_StatusCode UA_Server_addConditionOptionalField(UA_Server *server, const UA_NodeId condition, const UA_NodeId conditionType, const UA_QualifiedName fieldName, UA_NodeId *outOptionalVariable); /* Function used to set a user specific callback to TwoStateVariable Fields of a * condition. The callbacks will be called before triggering the events when * transition to true State of EnabledState/Id, AckedState/Id, ConfirmedState/Id * and ActiveState/Id occurs. * * @param server The server object * @param condition The NodeId of the node representation of the Condition Instance * @param conditionSource The NodeId of the node representation of the Condition Source * @param removeBranch (Not Implemented yet) * @param callback User specific callback function * @param callbackType Callback function type, indicates where it should be called * @return The StatusCode of the UA_Server_setConditionTwoStateVariableCallback method*/ UA_StatusCode UA_Server_setConditionTwoStateVariableCallback(UA_Server *server, const UA_NodeId condition, const UA_NodeId conditionSource, UA_Boolean removeBranch, UA_TwoStateVariableChangeCallback callback, UA_TwoStateVariableCallbackType callbackType); /* Delete a condition from the address space and the internal lists. * * @param server The server object * @param condition The NodeId of the node representation of the Condition Instance * @param conditionSource The NodeId of the node representation of the Condition Source * @return UA_STATUSCODE_GOOD on success */ UA_StatusCode UA_Server_deleteCondition(UA_Server *server, const UA_NodeId condition, const UA_NodeId conditionSource); #endif /* UA_ENABLE_SUBSCRIPTIONS_ALARMS_CONDITIONS */ UA_StatusCode UA_Server_updateCertificate(UA_Server *server, const UA_ByteString *oldCertificate, const UA_ByteString *newCertificate, const UA_ByteString *newPrivateKey, UA_Boolean closeSessions, UA_Boolean closeSecureChannels);
Utility Functions
/* Lookup a datatype by its NodeId. Takes the custom types in the server * configuration into account. Return NULL if none found. */ const UA_DataType * UA_Server_findDataType(UA_Server *server, const UA_NodeId *typeId); /* Add a new namespace to the server. Returns the index of the new namespace */ UA_UInt16 UA_THREADSAFE UA_Server_addNamespace(UA_Server *server, const char* name); /* Get namespace by name from the server. */ UA_StatusCode UA_THREADSAFE UA_Server_getNamespaceByName(UA_Server *server, const UA_String namespaceUri, size_t* foundIndex);
Asynchronous operation
Some operations (such as reading out a sensor that needs to be warmed up) may take a long time. In order not to block the server in such operations, it can be "outsourced" to a worker thread.
Take call as an example. It is divided into the calling operations of each method. If the method is marked synchronous, the operation is placed in a queue and retrieved by a worker. The worker returns the results when ready. See / examples / tutorial_ server_ method_ async. Use the example in C to understand the usage.
Note that when the operation is retrieved by the worker, the operation may time out (see asyncOperationTimeout setting in server configuration).
#if UA_MULTITHREADING >= 100 /* Set the async flag in a method node */ UA_StatusCode UA_Server_setMethodNodeAsync(UA_Server *server, const UA_NodeId id, UA_Boolean isAsync); typedef enum { UA_ASYNCOPERATIONTYPE_INVALID, /* 0, the default */ UA_ASYNCOPERATIONTYPE_CALL /* UA_ASYNCOPERATIONTYPE_READ, */ /* UA_ASYNCOPERATIONTYPE_WRITE, */ } UA_AsyncOperationType; typedef union { UA_CallMethodRequest callMethodRequest; /* UA_ReadValueId readValueId; */ /* UA_WriteValue writeValue; */ } UA_AsyncOperationRequest; typedef union { UA_CallMethodResult callMethodResult; /* UA_DataValue readResult; */ /* UA_StatusCode writeResult; */ } UA_AsyncOperationResponse; /* Get the next async operation without blocking * * @param server The server object * @param type The type of the async operation * @param request Receives pointer to the operation * @param context Receives the pointer to the operation context * @param timeout The timestamp when the operation times out and can * no longer be returned to the client. The response has to * be set in UA_Server_setAsyncOperationResult in any case. * @return false if queue is empty, true else */ UA_Boolean UA_Server_getAsyncOperationNonBlocking(UA_Server *server, UA_AsyncOperationType *type, const UA_AsyncOperationRequest **request, void **context, UA_DateTime *timeout); /* UA_Boolean */ /* UA_Server_getAsyncOperationBlocking(UA_Server *server, UA_AsyncOperationType *type, */ /* const UA_AsyncOperationRequest **request, */ /* void **context, UA_DateTime *timeout); */ /* Submit an async operation result * * @param server The server object * @param response Pointer to the operation result * @param context Pointer to the operation context */ void UA_Server_setAsyncOperationResult(UA_Server *server, const UA_AsyncOperationResponse *response, void *context); /* Get the next async operation. Attention! This method is deprecated and has * been replaced by UA_Server_getAsyncOperationNonBlocking! */ UA_DEPRECATED UA_Boolean UA_Server_getAsyncOperation(UA_Server *server, UA_AsyncOperationType *type, const UA_AsyncOperationRequest **request, void **context); #endif /* !UA_MULTITHREADING >= 100 */
Statistics
The statistics counter maintains the current state of the trace stack. The counter is structured according to OPC UA communication layer.
typedef struct { UA_NetworkStatistics ns; UA_SecureChannelStatistics scs; UA_SessionStatistics ss; } UA_ServerStatistics; UA_ServerStatistics UA_Server_getStatistics(UA_Server *server);