refactor(client): Pull in inline definitions and better typing of async callback methods

This commit is contained in:
Julius Pfrommer 2025-02-19 20:53:54 +01:00 committed by Julius Pfrommer
parent 18b185e7e1
commit de6e63bfff
8 changed files with 466 additions and 399 deletions

View File

@ -3,6 +3,14 @@ refactorings and bug fixes are not reported here.
# Development
### Client async methods are typed
For more of the client async service calls, specialized callback types were
added. With this the callbacks receive the accurate response type instead of
void-pointers. The order of callback arguments did not change, thereby the
change is ABI stable and old code continues to work (but might get a
type-warning during compilation).
### New Realtime-PubSub model
The new Realtime-PubSub model builds upon two new public APIS: (i) The

View File

@ -52,32 +52,27 @@ subscriptionInactivityCallback (UA_Client *client, UA_UInt32 subId, void *subCon
static void
monCallback(UA_Client *client, void *userdata,
UA_UInt32 requestId, void *r) {
UA_CreateMonitoredItemsResponse *monResponse = (UA_CreateMonitoredItemsResponse *)r;
if(0 < monResponse->resultsSize && monResponse->results[0].statusCode == UA_STATUSCODE_GOOD)
{
UA_UInt32 requestId, UA_CreateMonitoredItemsResponse *r) {
if(0 < r->resultsSize && r->results[0].statusCode == UA_STATUSCODE_GOOD) {
UA_LOG_INFO(UA_Log_Stdout, UA_LOGCATEGORY_USERLAND,
"Monitoring UA_NS0ID_SERVER_SERVERSTATUS_CURRENTTIME', id %u",
monResponse->results[0].monitoredItemId);
r->results[0].monitoredItemId);
}
}
static void
createSubscriptionCallback(UA_Client *client, void *userdata, UA_UInt32 requestId, void *r)
{
UA_CreateSubscriptionResponse *response = (UA_CreateSubscriptionResponse *)r;
if (response->subscriptionId == 0)
createSubscriptionCallback(UA_Client *client, void *userdata,
UA_UInt32 requestId, UA_CreateSubscriptionResponse *r) {
if (r->subscriptionId == 0) {
UA_LOG_ERROR(UA_Log_Stdout, UA_LOGCATEGORY_USERLAND,
"response->subscriptionId == 0, %u", response->subscriptionId);
else if (response->responseHeader.serviceResult != UA_STATUSCODE_GOOD)
"response->subscriptionId == 0, %u", r->subscriptionId);
} else if (r->responseHeader.serviceResult != UA_STATUSCODE_GOOD) {
UA_LOG_INFO(UA_Log_Stdout, UA_LOGCATEGORY_USERLAND,
"Create subscription failed, serviceResult %u",
response->responseHeader.serviceResult);
else
{
"Create subscription failed, serviceResult %u",
r->responseHeader.serviceResult);
} else {
UA_LOG_INFO(UA_Log_Stdout, UA_LOGCATEGORY_USERLAND,
"Create subscription succeeded, id %u",
response->subscriptionId);
"Create subscription succeeded, id %u", r->subscriptionId);
/* Add a MonitoredItem */
UA_NodeId currentTime =
@ -88,11 +83,13 @@ createSubscriptionCallback(UA_Client *client, void *userdata, UA_UInt32 requestI
UA_MonitoredItemCreateRequest_default(currentTime);
req.itemsToCreate = &monRequest;
req.itemsToCreateSize = 1;
req.subscriptionId = response->subscriptionId;
req.subscriptionId = r->subscriptionId;
UA_Client_DataChangeNotificationCallback dataChangeNotificationCallback[1] = { handler_currentTimeChanged };
UA_StatusCode retval =
UA_Client_MonitoredItems_createDataChanges_async(client, req, NULL, dataChangeNotificationCallback, NULL, monCallback, NULL, NULL);
UA_Client_MonitoredItems_createDataChanges_async(client, req, NULL,
dataChangeNotificationCallback, NULL,
monCallback, NULL, NULL);
if (retval != UA_STATUSCODE_GOOD)
UA_LOG_ERROR(UA_Log_Stdout, UA_LOGCATEGORY_USERLAND,
"UA_Client_MonitoredItems_createDataChanges_async ", UA_StatusCode_name(retval));

View File

@ -3,7 +3,7 @@
* file, You can obtain one at http://mozilla.org/MPL/2.0/.
*
* Copyright 2018 (c) Thomas Stalder, Blue Time Concept SA
* Copyright 2018 (c) Fraunhofer IOSB (Author: Julius Pfrommer)
* Copyright 2018, 2025 (c) Fraunhofer IOSB (Author: Julius Pfrommer)
*/
#ifndef UA_CLIENT_HIGHLEVEL_ASYNC_H_
@ -23,10 +23,7 @@ _UA_BEGIN_DECLS
*
* All OPC UA services are asynchronous in nature. So several service calls can
* be made without waiting for the individual responses. Depending on the
* server's priorities responses may come in a different ordering than sent. Use
* the typed wrappers for async service requests instead of
* `__UA_Client_AsyncService` directly. However, the general mechanism of async
* service calls is explained here.
* server's priorities responses may come in a different ordering than sent.
*
* Connection and session management are performed in `UA_Client_run_iterate`,
* so to keep a connection healthy any client needs to consider how and when it
@ -34,17 +31,14 @@ _UA_BEGIN_DECLS
* renewal of a SecureChannel's SecurityToken which is designed to have a
* limited lifetime and will invalidate the connection if not renewed.
*
* We say that an async service call has been dispatched once
* __UA_Client_AsyncService returns UA_STATUSCODE_GOOD. If there is an error
* after an async service has been dispatched, the callback is called with an
* "empty" response where the StatusCode has been set accordingly. This is also
* done if the client is shutting down and the list of dispatched async services
* is emptied.
*
* The StatusCode received when the client is shutting down is
* UA_STATUSCODE_BADSHUTDOWN. The StatusCode received when the client doesn't
* receive response after the specified in config->timeout (can be overridden
* via the "timeoutHint" in the request header) is UA_STATUSCODE_BADTIMEOUT.
* If there is an error after an async service has been dispatched, the callback
* is called with an "empty" response where the StatusCode has been set
* accordingly. This is also done if the client is shutting down and the list of
* dispatched async services is emptied. The StatusCode received when the client
* is shutting down is UA_STATUSCODE_BADSHUTDOWN. The StatusCode received when
* the client doesn't receive response after the specified in config->timeout
* (can be overridden via the "timeoutHint" in the request header) is
* UA_STATUSCODE_BADTIMEOUT.
*
* The userdata and requestId arguments can be NULL. The (optional) requestId
* output can be used to cancel the service while it is still pending. The
@ -55,6 +49,9 @@ _UA_BEGIN_DECLS
* >100,000 if none is defined. Avoid these when manually setting a requetHandle
* in the requestHeader to avoid clashes. */
/* Generalized asynchronous service call. This can be used for any
* request/response datatype pair whenever no type-stable specialization is
* defined below. */
typedef void
(*UA_ClientAsyncServiceCallback)(UA_Client *client, void *userdata,
UA_UInt32 requestId, void *response);
@ -79,19 +76,6 @@ UA_EXPORT UA_THREADSAFE UA_StatusCode
UA_Client_cancelByRequestId(UA_Client *client, UA_UInt32 requestId,
UA_UInt32 *cancelCount);
/* Set new userdata and callback for an existing request.
*
* @param client Pointer to the UA_Client
* @param requestId RequestId of the request, which was returned by
* __UA_Client_AsyncService before
* @param userdata The new userdata
* @param callback The new callback
* @return UA_StatusCode UA_STATUSCODE_GOOD on success
* UA_STATUSCODE_BADNOTFOUND when no request with requestId is found. */
UA_StatusCode UA_EXPORT UA_THREADSAFE
UA_Client_modifyAsyncCallback(UA_Client *client, UA_UInt32 requestId,
void *userdata, UA_ClientAsyncServiceCallback callback);
/* Force the manual renewal of the SecureChannel. This is useful to renew the
* SecureChannel during a downtime when no time-critical operations are
* performed. This method is asynchronous. The renewal is triggered (the OPN
@ -115,62 +99,39 @@ typedef void
(*UA_ClientAsyncReadCallback)(UA_Client *client, void *userdata,
UA_UInt32 requestId, UA_ReadResponse *rr);
UA_INLINABLE( UA_THREADSAFE UA_StatusCode
UA_Client_sendAsyncReadRequest(
UA_Client *client, UA_ReadRequest *request,
UA_ClientAsyncReadCallback readCallback,
void *userdata, UA_UInt32 *reqId), {
return __UA_Client_AsyncService(
client, request, &UA_TYPES[UA_TYPES_READREQUEST],
(UA_ClientAsyncServiceCallback)readCallback,
&UA_TYPES[UA_TYPES_READRESPONSE], userdata, reqId);
})
UA_StatusCode UA_EXPORT UA_THREADSAFE
UA_Client_sendAsyncReadRequest(UA_Client *client, UA_ReadRequest *request,
UA_ClientAsyncReadCallback readCallback,
void *userdata, UA_UInt32 *reqId);
typedef void
(*UA_ClientAsyncWriteCallback)(UA_Client *client, void *userdata,
UA_UInt32 requestId, UA_WriteResponse *wr);
UA_INLINABLE( UA_THREADSAFE UA_StatusCode
UA_Client_sendAsyncWriteRequest(
UA_Client *client, UA_WriteRequest *request,
UA_ClientAsyncWriteCallback writeCallback,
void *userdata, UA_UInt32 *reqId), {
return __UA_Client_AsyncService(
client, request, &UA_TYPES[UA_TYPES_WRITEREQUEST],
(UA_ClientAsyncServiceCallback)writeCallback,
&UA_TYPES[UA_TYPES_WRITERESPONSE], userdata, reqId);
})
UA_StatusCode UA_EXPORT UA_THREADSAFE
UA_Client_sendAsyncWriteRequest(UA_Client *client, UA_WriteRequest *request,
UA_ClientAsyncWriteCallback writeCallback,
void *userdata, UA_UInt32 *reqId);
typedef void
(*UA_ClientAsyncBrowseCallback)(UA_Client *client, void *userdata,
UA_UInt32 requestId, UA_BrowseResponse *wr);
UA_INLINABLE( UA_THREADSAFE UA_StatusCode
UA_Client_sendAsyncBrowseRequest(
UA_Client *client, UA_BrowseRequest *request,
UA_ClientAsyncBrowseCallback browseCallback,
void *userdata, UA_UInt32 *reqId), {
return __UA_Client_AsyncService(
client, request, &UA_TYPES[UA_TYPES_BROWSEREQUEST],
(UA_ClientAsyncServiceCallback)browseCallback,
&UA_TYPES[UA_TYPES_BROWSERESPONSE], userdata, reqId);
})
UA_StatusCode UA_EXPORT UA_THREADSAFE
UA_Client_sendAsyncBrowseRequest(UA_Client *client, UA_BrowseRequest *request,
UA_ClientAsyncBrowseCallback browseCallback,
void *userdata, UA_UInt32 *reqId);
typedef void
(*UA_ClientAsyncBrowseNextCallback)(UA_Client *client, void *userdata,
UA_UInt32 requestId,
UA_BrowseNextResponse *wr);
UA_INLINABLE( UA_THREADSAFE UA_StatusCode
UA_StatusCode UA_EXPORT UA_THREADSAFE
UA_Client_sendAsyncBrowseNextRequest(
UA_Client *client, UA_BrowseNextRequest *request,
UA_ClientAsyncBrowseNextCallback browseNextCallback,
void *userdata, UA_UInt32 *reqId), {
return __UA_Client_AsyncService(
client, request, &UA_TYPES[UA_TYPES_BROWSENEXTREQUEST],
(UA_ClientAsyncServiceCallback)browseNextCallback,
&UA_TYPES[UA_TYPES_BROWSENEXTRESPONSE], userdata, reqId);
})
void *userdata, UA_UInt32 *reqId);
/**
* Asynchronous Operations
@ -483,243 +444,126 @@ UA_Client_readUserExecutableAttribute_async(
/**
* Write Attribute
* ^^^^^^^^^^^^^^^
*
* The methods for async writing of attributes all have a similar API::
*
* UA_StatusCode
* UA_Client_writeValueAttribute_async(
* UA_Client *client, const UA_NodeId nodeId,
* const UA_Variant *attr, UA_ClientAsyncWriteCallback callback,
* void *userdata, UA_UInt32 *reqId);
*
* We generate the methods for the different attributes with a macro. */
* The methods for async writing of attributes all have a similar API. We
* generate the method signatures with a macro. */
UA_StatusCode UA_EXPORT UA_THREADSAFE
__UA_Client_writeAttribute_async(
UA_Client *client, const UA_NodeId *nodeId,
UA_AttributeId attributeId, const void *in,
const UA_DataType *inDataType,
UA_ClientAsyncServiceCallback callback,
void *userdata, UA_UInt32 *reqId);
#define UA_CLIENT_ASYNCWRITE(NAME, ATTR_TYPE) \
UA_StatusCode UA_EXPORT UA_THREADSAFE \
NAME(UA_Client *client, const UA_NodeId nodeId, \
const ATTR_TYPE *attr, UA_ClientAsyncWriteCallback callback, \
void *userdata, UA_UInt32 *reqId);
#define UA_CLIENT_ASYNCWRITE(NAME, ATTR_ID, ATTR_TYPE, ATTR_TYPEDESC) \
UA_INLINABLE( UA_THREADSAFE UA_StatusCode NAME( \
UA_Client *client, const UA_NodeId nodeId, \
const ATTR_TYPE *attr, UA_ClientAsyncWriteCallback callback, \
void *userdata, UA_UInt32 *reqId), { \
return __UA_Client_writeAttribute_async( \
client, &nodeId, UA_ATTRIBUTEID_##ATTR_ID, attr, \
&UA_TYPES[UA_TYPES_##ATTR_TYPEDESC], \
(UA_ClientAsyncServiceCallback)callback, userdata, reqId); \
})
UA_CLIENT_ASYNCWRITE(UA_Client_writeNodeIdAttribute_async,
NODEID, UA_NodeId, NODEID)
UA_CLIENT_ASYNCWRITE(UA_Client_writeNodeClassAttribute_async,
NODECLASS, UA_NodeClass, NODECLASS)
UA_CLIENT_ASYNCWRITE(UA_Client_writeBrowseNameAttribute_async,
BROWSENAME, UA_QualifiedName, QUALIFIEDNAME)
UA_CLIENT_ASYNCWRITE(UA_Client_writeDisplayNameAttribute_async,
DISPLAYNAME, UA_LocalizedText, LOCALIZEDTEXT)
UA_CLIENT_ASYNCWRITE(UA_Client_writeDescriptionAttribute_async,
DESCRIPTION, UA_LocalizedText, LOCALIZEDTEXT)
UA_CLIENT_ASYNCWRITE(UA_Client_writeWriteMaskAttribute_async,
WRITEMASK, UA_UInt32, UINT32)
UA_CLIENT_ASYNCWRITE(UA_Client_writeIsAbstractAttribute_async,
ISABSTRACT, UA_Boolean, BOOLEAN)
UA_CLIENT_ASYNCWRITE(UA_Client_writeSymmetricAttribute_async,
SYMMETRIC, UA_Boolean, BOOLEAN)
UA_CLIENT_ASYNCWRITE(UA_Client_writeInverseNameAttribute_async,
INVERSENAME, UA_LocalizedText, LOCALIZEDTEXT)
UA_CLIENT_ASYNCWRITE(UA_Client_writeContainsNoLoopsAttribute_async,
CONTAINSNOLOOPS, UA_Boolean, BOOLEAN)
UA_CLIENT_ASYNCWRITE(UA_Client_writeEventNotifierAttribute_async,
EVENTNOTIFIER, UA_Byte, BYTE)
UA_CLIENT_ASYNCWRITE(UA_Client_writeValueAttribute_async,
VALUE, UA_Variant, VARIANT)
UA_CLIENT_ASYNCWRITE(UA_Client_writeDataTypeAttribute_async,
DATATYPE, UA_NodeId, NODEID)
UA_CLIENT_ASYNCWRITE(UA_Client_writeValueRankAttribute_async,
VALUERANK, UA_Int32, INT32)
UA_CLIENT_ASYNCWRITE(UA_Client_writeAccessLevelAttribute_async,
ACCESSLEVEL, UA_Byte, BYTE)
UA_CLIENT_ASYNCWRITE(UA_Client_writeMinimumSamplingIntervalAttribute_async,
MINIMUMSAMPLINGINTERVAL, UA_Double, DOUBLE)
UA_CLIENT_ASYNCWRITE(UA_Client_writeHistorizingAttribute_async,
HISTORIZING, UA_Boolean, BOOLEAN)
UA_CLIENT_ASYNCWRITE(UA_Client_writeExecutableAttribute_async,
EXECUTABLE, UA_Boolean, BOOLEAN)
UA_CLIENT_ASYNCWRITE(UA_Client_writeAccessLevelExAttribute_async,
ACCESSLEVELEX, UA_UInt32, UINT32)
UA_CLIENT_ASYNCWRITE(UA_Client_writeNodeIdAttribute_async, UA_NodeId)
UA_CLIENT_ASYNCWRITE(UA_Client_writeNodeClassAttribute_async, UA_NodeClass)
UA_CLIENT_ASYNCWRITE(UA_Client_writeBrowseNameAttribute_async, UA_QualifiedName)
UA_CLIENT_ASYNCWRITE(UA_Client_writeDisplayNameAttribute_async, UA_LocalizedText)
UA_CLIENT_ASYNCWRITE(UA_Client_writeDescriptionAttribute_async, UA_LocalizedText)
UA_CLIENT_ASYNCWRITE(UA_Client_writeWriteMaskAttribute_async, UA_UInt32)
UA_CLIENT_ASYNCWRITE(UA_Client_writeIsAbstractAttribute_async, UA_Boolean)
UA_CLIENT_ASYNCWRITE(UA_Client_writeSymmetricAttribute_async, UA_Boolean)
UA_CLIENT_ASYNCWRITE(UA_Client_writeInverseNameAttribute_async, UA_LocalizedText)
UA_CLIENT_ASYNCWRITE(UA_Client_writeContainsNoLoopsAttribute_async, UA_Boolean)
UA_CLIENT_ASYNCWRITE(UA_Client_writeEventNotifierAttribute_async, UA_Byte)
UA_CLIENT_ASYNCWRITE(UA_Client_writeValueAttribute_async, UA_Variant)
UA_CLIENT_ASYNCWRITE(UA_Client_writeDataTypeAttribute_async, UA_NodeId)
UA_CLIENT_ASYNCWRITE(UA_Client_writeValueRankAttribute_async, UA_Int32)
UA_CLIENT_ASYNCWRITE(UA_Client_writeAccessLevelAttribute_async, UA_Byte)
UA_CLIENT_ASYNCWRITE(UA_Client_writeMinimumSamplingIntervalAttribute_async, UA_Double)
UA_CLIENT_ASYNCWRITE(UA_Client_writeHistorizingAttribute_async, UA_Boolean)
UA_CLIENT_ASYNCWRITE(UA_Client_writeExecutableAttribute_async, UA_Boolean)
UA_CLIENT_ASYNCWRITE(UA_Client_writeAccessLevelExAttribute_async, UA_UInt32)
/**
* Method Calling
* ^^^^^^^^^^^^^^ */
UA_StatusCode UA_EXPORT UA_THREADSAFE
__UA_Client_call_async(
UA_Client *client,
const UA_NodeId objectId, const UA_NodeId methodId,
size_t inputSize, const UA_Variant *input,
UA_ClientAsyncServiceCallback callback,
void *userdata, UA_UInt32 *reqId);
typedef void
(*UA_ClientAsyncCallCallback)(
UA_Client *client, void *userdata,
UA_UInt32 requestId, UA_CallResponse *cr);
UA_INLINABLE( UA_THREADSAFE UA_StatusCode
UA_Client_call_async(
UA_Client *client, const UA_NodeId objectId,
const UA_NodeId methodId, size_t inputSize,
const UA_Variant *input, UA_ClientAsyncCallCallback callback,
void *userdata, UA_UInt32 *reqId), {
return __UA_Client_call_async(
client, objectId, methodId, inputSize, input,
(UA_ClientAsyncServiceCallback)callback, userdata, reqId);
})
UA_StatusCode UA_EXPORT UA_THREADSAFE
UA_Client_call_async(UA_Client *client, const UA_NodeId objectId,
const UA_NodeId methodId, size_t inputSize,
const UA_Variant *input,
UA_ClientAsyncCallCallback callback,
void *userdata, UA_UInt32 *reqId);
/**
* Node Management
* ^^^^^^^^^^^^^^^ */
typedef void
(*UA_ClientAsyncAddNodesCallback)(
UA_Client *client, void *userdata,
UA_UInt32 requestId, UA_AddNodesResponse *ar);
UA_StatusCode UA_EXPORT
__UA_Client_addNode_async(
UA_Client *client, 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, UA_NodeId *outNewNodeId,
UA_ClientAsyncServiceCallback callback, void *userdata,
UA_UInt32 *reqId);
UA_INLINABLE( UA_StatusCode
UA_StatusCode UA_EXPORT UA_THREADSAFE
UA_Client_addVariableNode_async(
UA_Client *client, const UA_NodeId requestedNewNodeId,
const UA_NodeId parentNodeId, const UA_NodeId referenceTypeId,
const UA_QualifiedName browseName, const UA_NodeId typeDefinition,
const UA_VariableAttributes attr, UA_NodeId *outNewNodeId,
UA_ClientAsyncAddNodesCallback callback, void *userdata,
UA_UInt32 *reqId), {
return __UA_Client_addNode_async(
client, UA_NODECLASS_VARIABLE, requestedNewNodeId,
parentNodeId, referenceTypeId, browseName,
typeDefinition, (const UA_NodeAttributes *)&attr,
&UA_TYPES[UA_TYPES_VARIABLEATTRIBUTES], outNewNodeId,
(UA_ClientAsyncServiceCallback)callback, userdata, reqId);
})
UA_UInt32 *reqId);
UA_INLINABLE( UA_StatusCode
UA_StatusCode UA_EXPORT UA_THREADSAFE
UA_Client_addVariableTypeNode_async(
UA_Client *client, const UA_NodeId requestedNewNodeId,
const UA_NodeId parentNodeId, const UA_NodeId referenceTypeId,
const UA_QualifiedName browseName, const UA_VariableTypeAttributes attr,
UA_NodeId *outNewNodeId, UA_ClientAsyncAddNodesCallback callback,
void *userdata, UA_UInt32 *reqId), {
return __UA_Client_addNode_async(
client, UA_NODECLASS_VARIABLETYPE, requestedNewNodeId, parentNodeId,
referenceTypeId, browseName, UA_NODEID_NULL,
(const UA_NodeAttributes *)&attr,
&UA_TYPES[UA_TYPES_VARIABLETYPEATTRIBUTES], outNewNodeId,
(UA_ClientAsyncServiceCallback)callback, userdata, reqId);
})
void *userdata, UA_UInt32 *reqId);
UA_INLINABLE( UA_StatusCode
UA_StatusCode UA_EXPORT UA_THREADSAFE
UA_Client_addObjectNode_async(
UA_Client *client, const UA_NodeId requestedNewNodeId,
const UA_NodeId parentNodeId, const UA_NodeId referenceTypeId,
const UA_QualifiedName browseName, const UA_NodeId typeDefinition,
const UA_ObjectAttributes attr, UA_NodeId *outNewNodeId,
UA_ClientAsyncAddNodesCallback callback, void *userdata,
UA_UInt32 *reqId), {
return __UA_Client_addNode_async(
client, UA_NODECLASS_OBJECT, requestedNewNodeId,
parentNodeId, referenceTypeId,
browseName, typeDefinition, (const UA_NodeAttributes *)&attr,
&UA_TYPES[UA_TYPES_OBJECTATTRIBUTES], outNewNodeId,
(UA_ClientAsyncServiceCallback)callback, userdata, reqId);
})
UA_UInt32 *reqId);
UA_INLINABLE( UA_StatusCode
UA_StatusCode UA_EXPORT UA_THREADSAFE
UA_Client_addObjectTypeNode_async(
UA_Client *client, const UA_NodeId requestedNewNodeId,
const UA_NodeId parentNodeId, const UA_NodeId referenceTypeId,
const UA_QualifiedName browseName, const UA_ObjectTypeAttributes attr,
UA_NodeId *outNewNodeId, UA_ClientAsyncAddNodesCallback callback,
void *userdata, UA_UInt32 *reqId), {
return __UA_Client_addNode_async(
client, UA_NODECLASS_OBJECTTYPE, requestedNewNodeId, parentNodeId,
referenceTypeId, browseName, UA_NODEID_NULL,
(const UA_NodeAttributes *)&attr,
&UA_TYPES[UA_TYPES_OBJECTTYPEATTRIBUTES], outNewNodeId,
(UA_ClientAsyncServiceCallback)callback, userdata, reqId);
})
void *userdata, UA_UInt32 *reqId);
UA_INLINABLE( UA_StatusCode
UA_StatusCode UA_EXPORT UA_THREADSAFE
UA_Client_addViewNode_async(
UA_Client *client, const UA_NodeId requestedNewNodeId,
const UA_NodeId parentNodeId, const UA_NodeId referenceTypeId,
const UA_QualifiedName browseName,
const UA_ViewAttributes attr, UA_NodeId *outNewNodeId,
UA_ClientAsyncAddNodesCallback callback, void *userdata,
UA_UInt32 *reqId), {
return __UA_Client_addNode_async(
client, UA_NODECLASS_VIEW, requestedNewNodeId,
parentNodeId, referenceTypeId,
browseName, UA_NODEID_NULL, (const UA_NodeAttributes *)&attr,
&UA_TYPES[UA_TYPES_VIEWATTRIBUTES], outNewNodeId,
(UA_ClientAsyncServiceCallback)callback, userdata, reqId);
})
UA_UInt32 *reqId);
UA_INLINABLE( UA_StatusCode
UA_StatusCode UA_EXPORT UA_THREADSAFE
UA_Client_addReferenceTypeNode_async(
UA_Client *client, const UA_NodeId requestedNewNodeId,
const UA_NodeId parentNodeId, const UA_NodeId referenceTypeId,
const UA_QualifiedName browseName, const UA_ReferenceTypeAttributes attr,
UA_NodeId *outNewNodeId, UA_ClientAsyncAddNodesCallback callback,
void *userdata, UA_UInt32 *reqId), {
return __UA_Client_addNode_async(
client, UA_NODECLASS_REFERENCETYPE, requestedNewNodeId, parentNodeId,
referenceTypeId, browseName, UA_NODEID_NULL,
(const UA_NodeAttributes *)&attr,
&UA_TYPES[UA_TYPES_REFERENCETYPEATTRIBUTES], outNewNodeId,
(UA_ClientAsyncServiceCallback)callback, userdata, reqId);
})
void *userdata, UA_UInt32 *reqId);
UA_INLINABLE( UA_StatusCode
UA_StatusCode UA_EXPORT UA_THREADSAFE
UA_Client_addDataTypeNode_async(
UA_Client *client, const UA_NodeId requestedNewNodeId,
const UA_NodeId parentNodeId, const UA_NodeId referenceTypeId,
const UA_QualifiedName browseName, const UA_DataTypeAttributes attr,
UA_NodeId *outNewNodeId, UA_ClientAsyncAddNodesCallback callback,
void *userdata, UA_UInt32 *reqId), {
return __UA_Client_addNode_async(
client, UA_NODECLASS_DATATYPE, requestedNewNodeId,
parentNodeId, referenceTypeId, browseName,
UA_NODEID_NULL, (const UA_NodeAttributes *)&attr,
&UA_TYPES[UA_TYPES_DATATYPEATTRIBUTES], outNewNodeId,
(UA_ClientAsyncServiceCallback)callback, userdata, reqId);
})
void *userdata, UA_UInt32 *reqId);
UA_INLINABLE( UA_StatusCode
UA_StatusCode UA_EXPORT UA_THREADSAFE
UA_Client_addMethodNode_async(
UA_Client *client, const UA_NodeId requestedNewNodeId,
const UA_NodeId parentNodeId, const UA_NodeId referenceTypeId,
const UA_QualifiedName browseName, const UA_MethodAttributes attr,
UA_NodeId *outNewNodeId, UA_ClientAsyncAddNodesCallback callback,
void *userdata, UA_UInt32 *reqId), {
return __UA_Client_addNode_async(
client, UA_NODECLASS_METHOD, requestedNewNodeId, parentNodeId,
referenceTypeId, browseName, UA_NODEID_NULL,
(const UA_NodeAttributes *)&attr,
&UA_TYPES[UA_TYPES_METHODATTRIBUTES], outNewNodeId,
(UA_ClientAsyncServiceCallback)callback, userdata, reqId);
})
void *userdata, UA_UInt32 *reqId);
_UA_END_DECLS

View File

@ -73,33 +73,48 @@ UA_Client_Subscriptions_create(UA_Client *client,
UA_Client_StatusChangeNotificationCallback statusChangeCallback,
UA_Client_DeleteSubscriptionCallback deleteCallback);
typedef void
(*UA_ClientAsyncCreateSubscriptionCallback)(
UA_Client *client, void *userdata, UA_UInt32 requestId,
UA_CreateSubscriptionResponse *response);
UA_StatusCode UA_EXPORT UA_THREADSAFE
UA_Client_Subscriptions_create_async(UA_Client *client,
const UA_CreateSubscriptionRequest request,
void *subscriptionContext,
UA_Client_StatusChangeNotificationCallback statusChangeCallback,
UA_Client_DeleteSubscriptionCallback deleteCallback,
UA_ClientAsyncServiceCallback callback,
UA_ClientAsyncCreateSubscriptionCallback callback,
void *userdata, UA_UInt32 *requestId);
UA_ModifySubscriptionResponse UA_EXPORT UA_THREADSAFE
UA_Client_Subscriptions_modify(UA_Client *client,
const UA_ModifySubscriptionRequest request);
typedef void
(*UA_ClientAsyncModifySubscriptionCallback)(
UA_Client *client, void *userdata, UA_UInt32 requestId,
UA_ModifySubscriptionResponse *response);
UA_StatusCode UA_EXPORT UA_THREADSAFE
UA_Client_Subscriptions_modify_async(UA_Client *client,
const UA_ModifySubscriptionRequest request,
UA_ClientAsyncServiceCallback callback,
UA_ClientAsyncModifySubscriptionCallback callback,
void *userdata, UA_UInt32 *requestId);
UA_DeleteSubscriptionsResponse UA_EXPORT UA_THREADSAFE
UA_Client_Subscriptions_delete(UA_Client *client,
const UA_DeleteSubscriptionsRequest request);
typedef void
(*UA_ClientAsyncDeleteSubscriptionsCallback)(
UA_Client *client, void *userdata, UA_UInt32 requestId,
UA_DeleteSubscriptionsResponse *response);
UA_StatusCode UA_EXPORT UA_THREADSAFE
UA_Client_Subscriptions_delete_async(UA_Client *client,
const UA_DeleteSubscriptionsRequest request,
UA_ClientAsyncServiceCallback callback,
UA_ClientAsyncDeleteSubscriptionsCallback callback,
void *userdata, UA_UInt32 *requestId);
/* Delete a single subscription */
@ -176,12 +191,17 @@ UA_Client_MonitoredItems_createDataChanges(UA_Client *client,
UA_Client_DataChangeNotificationCallback *callbacks,
UA_Client_DeleteMonitoredItemCallback *deleteCallbacks);
typedef void
(*UA_ClientAsyncCreateMonitoredItemsCallback)(
UA_Client *client, void *userdata, UA_UInt32 requestId,
UA_CreateMonitoredItemsResponse *response);
UA_StatusCode UA_EXPORT UA_THREADSAFE
UA_Client_MonitoredItems_createDataChanges_async(UA_Client *client,
const UA_CreateMonitoredItemsRequest request, void **contexts,
UA_Client_DataChangeNotificationCallback *callbacks,
UA_Client_DeleteMonitoredItemCallback *deleteCallbacks,
UA_ClientAsyncServiceCallback createCallback,
UA_ClientAsyncCreateMonitoredItemsCallback createCallback,
void *userdata, UA_UInt32 *requestId);
UA_MonitoredItemCreateResult UA_EXPORT UA_THREADSAFE
@ -205,7 +225,7 @@ UA_Client_MonitoredItems_createEvents_async(UA_Client *client,
const UA_CreateMonitoredItemsRequest request, void **contexts,
UA_Client_EventNotificationCallback *callbacks,
UA_Client_DeleteMonitoredItemCallback *deleteCallbacks,
UA_ClientAsyncServiceCallback createCallback,
UA_ClientAsyncCreateMonitoredItemsCallback createCallback,
void *userdata, UA_UInt32 *requestId);
UA_MonitoredItemCreateResult UA_EXPORT UA_THREADSAFE
@ -220,10 +240,15 @@ UA_DeleteMonitoredItemsResponse UA_EXPORT UA_THREADSAFE
UA_Client_MonitoredItems_delete(UA_Client *client,
const UA_DeleteMonitoredItemsRequest);
typedef void
(*UA_ClientAsyncDeleteMonitoredItemsCallback)(
UA_Client *client, void *userdata, UA_UInt32 requestId,
UA_DeleteMonitoredItemsResponse *response);
UA_StatusCode UA_EXPORT UA_THREADSAFE
UA_Client_MonitoredItems_delete_async(UA_Client *client,
const UA_DeleteMonitoredItemsRequest request,
UA_ClientAsyncServiceCallback callback,
UA_ClientAsyncDeleteMonitoredItemsCallback callback,
void *userdata, UA_UInt32 *requestId);
UA_StatusCode UA_EXPORT UA_THREADSAFE
@ -238,31 +263,46 @@ UA_ModifyMonitoredItemsResponse UA_EXPORT UA_THREADSAFE
UA_Client_MonitoredItems_modify(UA_Client *client,
const UA_ModifyMonitoredItemsRequest request);
typedef void
(*UA_ClientAsyncModifyMonitoredItemsCallback)(
UA_Client *client, void *userdata, UA_UInt32 requestId,
UA_DeleteMonitoredItemsResponse *response);
UA_StatusCode UA_EXPORT UA_THREADSAFE
UA_Client_MonitoredItems_modify_async(UA_Client *client,
const UA_ModifyMonitoredItemsRequest request,
UA_ClientAsyncServiceCallback callback,
UA_ClientAsyncModifyMonitoredItemsCallback callback,
void *userdata, UA_UInt32 *requestId);
UA_SetMonitoringModeResponse UA_EXPORT UA_THREADSAFE
UA_Client_MonitoredItems_setMonitoringMode(
UA_Client *client, const UA_SetMonitoringModeRequest request);
typedef void
(*UA_ClientAsyncSetMonitoringModeCallback)(
UA_Client *client, void *userdata, UA_UInt32 requestId,
UA_SetMonitoringModeResponse *response);
UA_StatusCode UA_EXPORT UA_THREADSAFE
UA_Client_MonitoredItems_setMonitoringMode_async(
UA_Client *client, const UA_SetMonitoringModeRequest request,
UA_ClientAsyncServiceCallback callback, void *userdata,
UA_UInt32 *requestId);
UA_ClientAsyncSetMonitoringModeCallback callback,
void *userdata, UA_UInt32 *requestId);
UA_SetTriggeringResponse UA_EXPORT UA_THREADSAFE
UA_Client_MonitoredItems_setTriggering(
UA_Client *client, const UA_SetTriggeringRequest request);
typedef void
(*UA_ClientAsyncSetTriggeringCallback)(
UA_Client *client, void *userdata, UA_UInt32 requestId,
UA_SetTriggeringResponse *response);
UA_StatusCode UA_EXPORT UA_THREADSAFE
UA_Client_MonitoredItems_setTriggering_async(
UA_Client *client, const UA_SetTriggeringRequest request,
UA_ClientAsyncServiceCallback callback, void *userdata,
UA_UInt32 *requestId);
UA_ClientAsyncSetTriggeringCallback callback,
void *userdata, UA_UInt32 *requestId);
/* Retrieve or change the user supplied MonitoredItem context */
UA_StatusCode UA_EXPORT UA_THREADSAFE

View File

@ -697,15 +697,6 @@ __Client_Service(UA_Client *client, const void *request,
respHeader->serviceResult = retval;
}
void
__UA_Client_Service(UA_Client *client, const void *request,
const UA_DataType *requestType, void *response,
const UA_DataType *responseType) {
lockClient(client);
__Client_Service(client, request, requestType, response, responseType);
unlockClient(client);
}
/***********************************/
/* Handling of Async Service Calls */
/***********************************/
@ -753,24 +744,6 @@ __Client_AsyncService_removeAll(UA_Client *client, UA_StatusCode statusCode) {
}
}
UA_StatusCode
UA_Client_modifyAsyncCallback(UA_Client *client, UA_UInt32 requestId,
void *userdata, UA_ClientAsyncServiceCallback callback) {
lockClient(client);
AsyncServiceCall *ac;
UA_StatusCode res = UA_STATUSCODE_BADNOTFOUND;
LIST_FOREACH(ac, &client->asyncServiceCalls, pointers) {
if(ac->requestId == requestId) {
ac->callback = callback;
ac->userdata = userdata;
res = UA_STATUSCODE_GOOD;
break;
}
}
unlockClient(client);
return res;
}
UA_StatusCode
__Client_AsyncService(UA_Client *client, const void *request,
const UA_DataType *requestType,
@ -828,20 +801,6 @@ __Client_AsyncService(UA_Client *client, const void *request,
return UA_STATUSCODE_GOOD;
}
UA_StatusCode
__UA_Client_AsyncService(UA_Client *client, const void *request,
const UA_DataType *requestType,
UA_ClientAsyncServiceCallback callback,
const UA_DataType *responseType,
void *userdata, UA_UInt32 *requestId) {
lockClient(client);
UA_StatusCode res =
__Client_AsyncService(client, request, requestType, callback, responseType,
userdata, requestId);
unlockClient(client);
return res;
}
static UA_StatusCode
cancelByRequestHandle(UA_Client *client, UA_UInt32 requestHandle, UA_UInt32 *cancelCount) {
UA_CancelRequest creq;
@ -1303,6 +1262,15 @@ UA_Client_connectUsername(UA_Client *client, const char *endpointUrl,
/* Service Shorthands */
/**********************/
void
__UA_Client_Service(UA_Client *client, const void *request,
const UA_DataType *requestType, void *response,
const UA_DataType *responseType) {
lockClient(client);
__Client_Service(client, request, requestType, response, responseType);
unlockClient(client);
}
UA_ReadResponse
UA_Client_Service_read(UA_Client *client, const UA_ReadRequest request) {
UA_ReadResponse response;
@ -1447,3 +1415,58 @@ UA_Client_Service_queryNext(UA_Client *client, const UA_QueryNextRequest request
}
#endif
/********************/
/* Async Shorthands */
/********************/
UA_StatusCode
__UA_Client_AsyncService(UA_Client *client, const void *request,
const UA_DataType *requestType,
UA_ClientAsyncServiceCallback callback,
const UA_DataType *responseType,
void *userdata, UA_UInt32 *requestId) {
lockClient(client);
UA_StatusCode res =
__Client_AsyncService(client, request, requestType, callback, responseType,
userdata, requestId);
unlockClient(client);
return res;
}
UA_StatusCode
UA_Client_sendAsyncReadRequest(UA_Client *client, UA_ReadRequest *request,
UA_ClientAsyncReadCallback readCallback,
void *userdata, UA_UInt32 *reqId) {
return __UA_Client_AsyncService(client, request, &UA_TYPES[UA_TYPES_READREQUEST],
(UA_ClientAsyncServiceCallback)readCallback,
&UA_TYPES[UA_TYPES_READRESPONSE], userdata, reqId);
}
UA_StatusCode
UA_Client_sendAsyncWriteRequest(UA_Client *client, UA_WriteRequest *request,
UA_ClientAsyncWriteCallback writeCallback,
void *userdata, UA_UInt32 *reqId) {
return __UA_Client_AsyncService(client, request, &UA_TYPES[UA_TYPES_WRITEREQUEST],
(UA_ClientAsyncServiceCallback)writeCallback,
&UA_TYPES[UA_TYPES_WRITERESPONSE], userdata, reqId);
}
UA_StatusCode
UA_Client_sendAsyncBrowseRequest(UA_Client *client, UA_BrowseRequest *request,
UA_ClientAsyncBrowseCallback browseCallback,
void *userdata, UA_UInt32 *reqId) {
return __UA_Client_AsyncService(client, request, &UA_TYPES[UA_TYPES_BROWSEREQUEST],
(UA_ClientAsyncServiceCallback)browseCallback,
&UA_TYPES[UA_TYPES_BROWSERESPONSE], userdata, reqId);
}
UA_StatusCode
UA_Client_sendAsyncBrowseNextRequest(UA_Client *client,
UA_BrowseNextRequest *request,
UA_ClientAsyncBrowseNextCallback browseNextCallback,
void *userdata, UA_UInt32 *reqId) {
return __UA_Client_AsyncService(client, request, &UA_TYPES[UA_TYPES_BROWSENEXTREQUEST],
(UA_ClientAsyncServiceCallback)browseNextCallback,
&UA_TYPES[UA_TYPES_BROWSENEXTRESPONSE], userdata, reqId);
}

View File

@ -11,12 +11,7 @@
* Copyright 2018 (c) Peter Rustler, basyskom GmbH
*/
#include <open62541/client_highlevel.h>
#include <open62541/client_highlevel_async.h>
#include "../util/ua_util_internal.h"
/* The highlevel client API is an "outer onion layer". This file does not
* include ua_client_internal.h on purpose. */
#include "ua_client_internal.h"
UA_StatusCode
UA_Client_NamespaceGetIndex(UA_Client *client, UA_String *namespaceUri,
@ -907,10 +902,11 @@ cleanup:
/* Async Functions */
/*******************/
UA_StatusCode
static UA_StatusCode
__UA_Client_writeAttribute_async(UA_Client *client, const UA_NodeId *nodeId,
UA_AttributeId attributeId, const void *in,
const UA_DataType *inDataType, UA_ClientAsyncServiceCallback callback,
const UA_DataType *inDataType,
UA_ClientAsyncServiceCallback callback,
void *userdata, UA_UInt32 *reqId) {
if(!in)
return UA_STATUSCODE_BADTYPEMISMATCH;
@ -932,69 +928,31 @@ __UA_Client_writeAttribute_async(UA_Client *client, const UA_NodeId *nodeId,
wReq.nodesToWriteSize = 1;
return __UA_Client_AsyncService(client, &wReq,
&UA_TYPES[UA_TYPES_WRITEREQUEST], callback,
&UA_TYPES[UA_TYPES_WRITERESPONSE], userdata, reqId);
&UA_TYPES[UA_TYPES_WRITEREQUEST], callback,
&UA_TYPES[UA_TYPES_WRITERESPONSE], userdata, reqId);
}
UA_StatusCode
__UA_Client_addNode_async(UA_Client *client, 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, UA_NodeId *outNewNodeId,
UA_ClientAsyncServiceCallback callback, void *userdata,
UA_UInt32 *reqId) {
UA_AddNodesRequest request;
UA_AddNodesRequest_init(&request);
UA_AddNodesItem item;
UA_AddNodesItem_init(&item);
item.parentNodeId.nodeId = parentNodeId;
item.referenceTypeId = referenceTypeId;
item.requestedNewNodeId.nodeId = requestedNewNodeId;
item.browseName = browseName;
item.nodeClass = nodeClass;
item.typeDefinition.nodeId = typeDefinition;
item.nodeAttributes.encoding = UA_EXTENSIONOBJECT_DECODED_NODELETE;
item.nodeAttributes.content.decoded.type = attributeType;
item.nodeAttributes.content.decoded.data = (void*) (uintptr_t) attr; // hack. is not written into.
request.nodesToAdd = &item;
request.nodesToAddSize = 1;
return __UA_Client_AsyncService(client, &request,
&UA_TYPES[UA_TYPES_ADDNODESREQUEST], callback,
&UA_TYPES[UA_TYPES_ADDNODESRESPONSE], userdata, reqId);
}
UA_StatusCode
__UA_Client_call_async(UA_Client *client, const UA_NodeId objectId,
const UA_NodeId methodId, size_t inputSize,
const UA_Variant *input, UA_ClientAsyncServiceCallback callback,
void *userdata, UA_UInt32 *reqId) {
UA_Client_call_async(UA_Client *client, const UA_NodeId objectId,
const UA_NodeId methodId, size_t inputSize,
const UA_Variant *input,
UA_ClientAsyncCallCallback callback,
void *userdata, UA_UInt32 *reqId) {
UA_CallRequest request;
UA_CallRequest_init(&request);
UA_CallMethodRequest item;
UA_CallMethodRequest_init(&item);
item.methodId = methodId;
item.objectId = objectId;
item.inputArguments = (UA_Variant *) (void*) (uintptr_t) input; // cast const...
item.methodId = methodId;
item.inputArguments = (UA_Variant *)(uintptr_t)input; /* cast const */
item.inputArgumentsSize = inputSize;
request.methodsToCall = &item;
request.methodsToCallSize = 1;
return __UA_Client_AsyncService(client, &request,
&UA_TYPES[UA_TYPES_CALLREQUEST], callback,
&UA_TYPES[UA_TYPES_CALLREQUEST], (UA_ClientAsyncServiceCallback)callback,
&UA_TYPES[UA_TYPES_CALLRESPONSE], userdata, reqId);
}
/* UA_StatusCode */
/* UA_Cient_translateBrowsePathsToNodeIds_async(UA_Client *client, char **paths, */
/* UA_UInt32 *ids, size_t pathSize, */
/* UA_ClientAsyncTranslateCallback callback, */
/* void *userdata, UA_UInt32 *reqId) { */
/* return UA_STATUSCODE_BADNOTIMPLEMENTED; */
/* } */
/*************************/
/* Read Single Attribute */
/*************************/
@ -1350,3 +1308,161 @@ UA_Client_readUserExecutableAttribute_async(UA_Client *client, const UA_NodeId n
(UA_ClientAsyncOperationCallback)callback,
userdata, requestId);
}
static UA_StatusCode
__UA_Client_addNode_async(UA_Client *client, 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, UA_NodeId *outNewNodeId,
UA_ClientAsyncServiceCallback callback, void *userdata,
UA_UInt32 *reqId) {
UA_AddNodesRequest request;
UA_AddNodesRequest_init(&request);
UA_AddNodesItem item;
UA_AddNodesItem_init(&item);
item.parentNodeId.nodeId = parentNodeId;
item.referenceTypeId = referenceTypeId;
item.requestedNewNodeId.nodeId = requestedNewNodeId;
item.browseName = browseName;
item.nodeClass = nodeClass;
item.typeDefinition.nodeId = typeDefinition;
item.nodeAttributes.encoding = UA_EXTENSIONOBJECT_DECODED_NODELETE;
item.nodeAttributes.content.decoded.type = attributeType;
item.nodeAttributes.content.decoded.data = (void*) (uintptr_t) attr; // hack. is not written into.
request.nodesToAdd = &item;
request.nodesToAddSize = 1;
return __UA_Client_AsyncService(client, &request,
&UA_TYPES[UA_TYPES_ADDNODESREQUEST], callback,
&UA_TYPES[UA_TYPES_ADDNODESRESPONSE], userdata, reqId);
}
UA_StatusCode
UA_Client_addVariableNode_async(UA_Client *client, const UA_NodeId requestedNewNodeId,
const UA_NodeId parentNodeId, const UA_NodeId referenceTypeId,
const UA_QualifiedName browseName, const UA_NodeId typeDefinition,
const UA_VariableAttributes attr, UA_NodeId *outNewNodeId,
UA_ClientAsyncAddNodesCallback callback, void *userdata,
UA_UInt32 *reqId) {
return __UA_Client_addNode_async(client, UA_NODECLASS_VARIABLE, requestedNewNodeId, parentNodeId,
referenceTypeId, browseName, typeDefinition, (const UA_NodeAttributes *)&attr,
&UA_TYPES[UA_TYPES_VARIABLEATTRIBUTES], outNewNodeId,
(UA_ClientAsyncServiceCallback)callback, userdata, reqId);
}
UA_StatusCode
UA_Client_addVariableTypeNode_async(UA_Client *client, const UA_NodeId requestedNewNodeId,
const UA_NodeId parentNodeId, const UA_NodeId referenceTypeId,
const UA_QualifiedName browseName, const UA_VariableTypeAttributes attr,
UA_NodeId *outNewNodeId, UA_ClientAsyncAddNodesCallback callback,
void *userdata, UA_UInt32 *reqId) {
return __UA_Client_addNode_async(client, UA_NODECLASS_VARIABLETYPE, requestedNewNodeId, parentNodeId,
referenceTypeId, browseName, UA_NODEID_NULL, (const UA_NodeAttributes *)&attr,
&UA_TYPES[UA_TYPES_VARIABLETYPEATTRIBUTES], outNewNodeId,
(UA_ClientAsyncServiceCallback)callback, userdata, reqId);
}
UA_StatusCode
UA_Client_addObjectNode_async(UA_Client *client, const UA_NodeId requestedNewNodeId,
const UA_NodeId parentNodeId, const UA_NodeId referenceTypeId,
const UA_QualifiedName browseName, const UA_NodeId typeDefinition,
const UA_ObjectAttributes attr, UA_NodeId *outNewNodeId,
UA_ClientAsyncAddNodesCallback callback, void *userdata,
UA_UInt32 *reqId) {
return __UA_Client_addNode_async(client, UA_NODECLASS_OBJECT, requestedNewNodeId, parentNodeId,
referenceTypeId, browseName, typeDefinition, (const UA_NodeAttributes *)&attr,
&UA_TYPES[UA_TYPES_OBJECTATTRIBUTES], outNewNodeId,
(UA_ClientAsyncServiceCallback)callback, userdata, reqId);
}
UA_StatusCode
UA_Client_addObjectTypeNode_async(UA_Client *client, const UA_NodeId requestedNewNodeId,
const UA_NodeId parentNodeId, const UA_NodeId referenceTypeId,
const UA_QualifiedName browseName, const UA_ObjectTypeAttributes attr,
UA_NodeId *outNewNodeId, UA_ClientAsyncAddNodesCallback callback,
void *userdata, UA_UInt32 *reqId) {
return __UA_Client_addNode_async(client, UA_NODECLASS_OBJECTTYPE, requestedNewNodeId, parentNodeId,
referenceTypeId, browseName, UA_NODEID_NULL, (const UA_NodeAttributes *)&attr,
&UA_TYPES[UA_TYPES_OBJECTTYPEATTRIBUTES], outNewNodeId,
(UA_ClientAsyncServiceCallback)callback, userdata, reqId);
}
UA_StatusCode
UA_Client_addViewNode_async(UA_Client *client, const UA_NodeId requestedNewNodeId,
const UA_NodeId parentNodeId, const UA_NodeId referenceTypeId,
const UA_QualifiedName browseName, const UA_ViewAttributes attr,
UA_NodeId *outNewNodeId, UA_ClientAsyncAddNodesCallback callback,
void *userdata, UA_UInt32 *reqId) {
return __UA_Client_addNode_async(client, UA_NODECLASS_VIEW, requestedNewNodeId, parentNodeId,
referenceTypeId, browseName, UA_NODEID_NULL, (const UA_NodeAttributes *)&attr,
&UA_TYPES[UA_TYPES_VIEWATTRIBUTES], outNewNodeId,
(UA_ClientAsyncServiceCallback)callback, userdata, reqId);
}
UA_StatusCode
UA_Client_addReferenceTypeNode_async(UA_Client *client, const UA_NodeId requestedNewNodeId,
const UA_NodeId parentNodeId, const UA_NodeId referenceTypeId,
const UA_QualifiedName browseName, const UA_ReferenceTypeAttributes attr,
UA_NodeId *outNewNodeId, UA_ClientAsyncAddNodesCallback callback,
void *userdata, UA_UInt32 *reqId) {
return __UA_Client_addNode_async(client, UA_NODECLASS_REFERENCETYPE, requestedNewNodeId, parentNodeId,
referenceTypeId, browseName, UA_NODEID_NULL,
(const UA_NodeAttributes *)&attr,
&UA_TYPES[UA_TYPES_REFERENCETYPEATTRIBUTES], outNewNodeId,
(UA_ClientAsyncServiceCallback)callback, userdata, reqId);
}
UA_StatusCode
UA_Client_addDataTypeNode_async(UA_Client *client, const UA_NodeId requestedNewNodeId,
const UA_NodeId parentNodeId, const UA_NodeId referenceTypeId,
const UA_QualifiedName browseName, const UA_DataTypeAttributes attr,
UA_NodeId *outNewNodeId, UA_ClientAsyncAddNodesCallback callback,
void *userdata, UA_UInt32 *reqId) {
return __UA_Client_addNode_async(client, UA_NODECLASS_DATATYPE, requestedNewNodeId, parentNodeId,
referenceTypeId, browseName, UA_NODEID_NULL, (const UA_NodeAttributes *)&attr,
&UA_TYPES[UA_TYPES_DATATYPEATTRIBUTES], outNewNodeId,
(UA_ClientAsyncServiceCallback)callback, userdata, reqId);
}
UA_StatusCode
UA_Client_addMethodNode_async(UA_Client *client, const UA_NodeId requestedNewNodeId,
const UA_NodeId parentNodeId, const UA_NodeId referenceTypeId,
const UA_QualifiedName browseName, const UA_MethodAttributes attr,
UA_NodeId *outNewNodeId, UA_ClientAsyncAddNodesCallback callback,
void *userdata, UA_UInt32 *reqId) {
return __UA_Client_addNode_async(client, UA_NODECLASS_METHOD, requestedNewNodeId, parentNodeId,
referenceTypeId, browseName, UA_NODEID_NULL, (const UA_NodeAttributes *)&attr,
&UA_TYPES[UA_TYPES_METHODATTRIBUTES], outNewNodeId,
(UA_ClientAsyncServiceCallback)callback, userdata, reqId);
}
#define UA_CLIENT_ASYNCWRITE_IMPL(NAME, ATTR_ID, ATTR_TYPE, ATTR_TYPEDESC) \
UA_StatusCode NAME(UA_Client *client, const UA_NodeId nodeId, \
const ATTR_TYPE *attr, UA_ClientAsyncWriteCallback callback, \
void *userdata, UA_UInt32 *reqId) { \
return __UA_Client_writeAttribute_async(client, &nodeId, UA_ATTRIBUTEID_##ATTR_ID, attr, \
&UA_TYPES[UA_TYPES_##ATTR_TYPEDESC], \
(UA_ClientAsyncServiceCallback)callback, userdata, reqId); \
}
UA_CLIENT_ASYNCWRITE_IMPL(UA_Client_writeNodeIdAttribute_async, NODEID, UA_NodeId, NODEID)
UA_CLIENT_ASYNCWRITE_IMPL(UA_Client_writeNodeClassAttribute_async, NODECLASS, UA_NodeClass, NODECLASS)
UA_CLIENT_ASYNCWRITE_IMPL(UA_Client_writeBrowseNameAttribute_async, BROWSENAME, UA_QualifiedName, QUALIFIEDNAME)
UA_CLIENT_ASYNCWRITE_IMPL(UA_Client_writeDisplayNameAttribute_async, DISPLAYNAME, UA_LocalizedText, LOCALIZEDTEXT)
UA_CLIENT_ASYNCWRITE_IMPL(UA_Client_writeDescriptionAttribute_async, DESCRIPTION, UA_LocalizedText, LOCALIZEDTEXT)
UA_CLIENT_ASYNCWRITE_IMPL(UA_Client_writeWriteMaskAttribute_async, WRITEMASK, UA_UInt32, UINT32)
UA_CLIENT_ASYNCWRITE_IMPL(UA_Client_writeIsAbstractAttribute_async, ISABSTRACT, UA_Boolean, BOOLEAN)
UA_CLIENT_ASYNCWRITE_IMPL(UA_Client_writeSymmetricAttribute_async, SYMMETRIC, UA_Boolean, BOOLEAN)
UA_CLIENT_ASYNCWRITE_IMPL(UA_Client_writeInverseNameAttribute_async, INVERSENAME, UA_LocalizedText, LOCALIZEDTEXT)
UA_CLIENT_ASYNCWRITE_IMPL(UA_Client_writeContainsNoLoopsAttribute_async, CONTAINSNOLOOPS, UA_Boolean, BOOLEAN)
UA_CLIENT_ASYNCWRITE_IMPL(UA_Client_writeEventNotifierAttribute_async, EVENTNOTIFIER, UA_Byte, BYTE)
UA_CLIENT_ASYNCWRITE_IMPL(UA_Client_writeValueAttribute_async, VALUE, UA_Variant, VARIANT)
UA_CLIENT_ASYNCWRITE_IMPL(UA_Client_writeDataTypeAttribute_async, DATATYPE, UA_NodeId, NODEID)
UA_CLIENT_ASYNCWRITE_IMPL(UA_Client_writeValueRankAttribute_async, VALUERANK, UA_Int32, INT32)
UA_CLIENT_ASYNCWRITE_IMPL(UA_Client_writeAccessLevelAttribute_async, ACCESSLEVEL, UA_Byte, BYTE)
UA_CLIENT_ASYNCWRITE_IMPL(UA_Client_writeMinimumSamplingIntervalAttribute_async, MINIMUMSAMPLINGINTERVAL, UA_Double, DOUBLE)
UA_CLIENT_ASYNCWRITE_IMPL(UA_Client_writeHistorizingAttribute_async, HISTORIZING, UA_Boolean, BOOLEAN)
UA_CLIENT_ASYNCWRITE_IMPL(UA_Client_writeExecutableAttribute_async, EXECUTABLE, UA_Boolean, BOOLEAN)
UA_CLIENT_ASYNCWRITE_IMPL(UA_Client_writeAccessLevelExAttribute_async, ACCESSLEVELEX, UA_UInt32, UINT32)

View File

@ -129,14 +129,12 @@ UA_Client_Subscriptions_create(UA_Client *client,
}
UA_StatusCode
UA_Client_Subscriptions_create_async(UA_Client *client,
const UA_CreateSubscriptionRequest request,
UA_Client_Subscriptions_create_async(UA_Client *client, const UA_CreateSubscriptionRequest request,
void *subscriptionContext,
UA_Client_StatusChangeNotificationCallback statusChangeCallback,
UA_Client_DeleteSubscriptionCallback deleteCallback,
UA_ClientAsyncServiceCallback createCallback,
void *userdata,
UA_UInt32 *requestId) {
UA_ClientAsyncCreateSubscriptionCallback createCallback,
void *userdata, UA_UInt32 *requestId) {
CustomCallback *cc = (CustomCallback *)UA_calloc(1, sizeof(CustomCallback));
if(!cc)
return UA_STATUSCODE_BADOUTOFMEMORY;
@ -151,7 +149,7 @@ UA_Client_Subscriptions_create_async(UA_Client *client,
sub->statusChangeCallback = statusChangeCallback;
sub->deleteCallback = deleteCallback;
cc->userCallback = createCallback;
cc->userCallback = (UA_ClientAsyncServiceCallback)createCallback;
cc->userData = userdata;
cc->clientData = sub;
@ -271,7 +269,7 @@ UA_Client_Subscriptions_modify(UA_Client *client,
UA_StatusCode
UA_Client_Subscriptions_modify_async(UA_Client *client,
const UA_ModifySubscriptionRequest request,
UA_ClientAsyncServiceCallback callback,
UA_ClientAsyncModifySubscriptionCallback callback,
void *userdata, UA_UInt32 *requestId) {
lockClient(client);
@ -289,11 +287,12 @@ UA_Client_Subscriptions_modify_async(UA_Client *client,
cc->clientData = (void *)(uintptr_t)request.subscriptionId;
cc->userData = userdata;
cc->userCallback = callback;
cc->userCallback = (UA_ClientAsyncServiceCallback)callback;
UA_StatusCode res =
__Client_AsyncService(client, &request, &UA_TYPES[UA_TYPES_MODIFYSUBSCRIPTIONREQUEST],
ua_Subscriptions_modify_handler, &UA_TYPES[UA_TYPES_MODIFYSUBSCRIPTIONRESPONSE],
ua_Subscriptions_modify_handler,
&UA_TYPES[UA_TYPES_MODIFYSUBSCRIPTIONRESPONSE],
cc, requestId);
unlockClient(client);
@ -400,14 +399,14 @@ ua_Subscriptions_delete_handler(UA_Client *client, void *data,
UA_StatusCode
UA_Client_Subscriptions_delete_async(UA_Client *client,
const UA_DeleteSubscriptionsRequest request,
UA_ClientAsyncServiceCallback callback,
UA_ClientAsyncDeleteSubscriptionsCallback callback,
void *userdata, UA_UInt32 *requestId) {
/* Make a copy of the request that persists into the async callback */
DeleteSubscriptionCallback *dsc = (DeleteSubscriptionCallback*)
UA_malloc(sizeof(DeleteSubscriptionCallback));
if(!dsc)
return UA_STATUSCODE_BADOUTOFMEMORY;
dsc->userCallback = callback;
dsc->userCallback = (UA_ClientAsyncServiceCallback)callback;
dsc->userData = userdata;
UA_StatusCode res = UA_DeleteSubscriptionsRequest_copy(&request, &dsc->request);
if(res != UA_STATUSCODE_GOOD) {
@ -680,7 +679,8 @@ static UA_StatusCode
createDataChanges_async(UA_Client *client, const UA_CreateMonitoredItemsRequest request,
void **contexts, void **callbacks,
UA_Client_DeleteMonitoredItemCallback *deleteCallbacks,
UA_ClientAsyncServiceCallback createCallback, void *userdata,
UA_ClientAsyncServiceCallback createCallback,
void *userdata,
UA_UInt32 *requestId) {
UA_LOCK_ASSERT(&client->clientMutex);
@ -731,12 +731,13 @@ UA_Client_MonitoredItems_createDataChanges_async(UA_Client *client,
void **contexts,
UA_Client_DataChangeNotificationCallback *callbacks,
UA_Client_DeleteMonitoredItemCallback *deleteCallbacks,
UA_ClientAsyncServiceCallback createCallback,
UA_ClientAsyncCreateMonitoredItemsCallback createCallback,
void *userdata, UA_UInt32 *requestId) {
lockClient(client);
UA_StatusCode res =
createDataChanges_async(client, request, contexts, (void **)callbacks,
deleteCallbacks, createCallback, userdata, requestId);
createDataChanges_async(client, request, contexts, (void **)callbacks, deleteCallbacks,
(UA_ClientAsyncServiceCallback)createCallback,
userdata, requestId);
unlockClient(client);
return res;
}
@ -793,12 +794,12 @@ UA_Client_MonitoredItems_createEvents_async(UA_Client *client,
void **contexts,
UA_Client_EventNotificationCallback *callbacks,
UA_Client_DeleteMonitoredItemCallback *deleteCallbacks,
UA_ClientAsyncServiceCallback createCallback,
UA_ClientAsyncCreateMonitoredItemsCallback createCallback,
void *userdata, UA_UInt32 *requestId) {
lockClient(client);
UA_StatusCode res =
createDataChanges_async(client, request, contexts, (void **)callbacks, deleteCallbacks,
createCallback, userdata, requestId);
(UA_ClientAsyncServiceCallback)createCallback, userdata, requestId);
unlockClient(client);
return res;
}
@ -925,7 +926,7 @@ UA_Client_MonitoredItems_delete(UA_Client *client,
UA_StatusCode
UA_Client_MonitoredItems_delete_async(UA_Client *client,
const UA_DeleteMonitoredItemsRequest request,
UA_ClientAsyncServiceCallback callback,
UA_ClientAsyncDeleteMonitoredItemsCallback callback,
void *userdata, UA_UInt32 *requestId) {
/* Send the request */
CustomCallback *cc = (CustomCallback *)UA_calloc(1, sizeof(CustomCallback));
@ -940,7 +941,7 @@ UA_Client_MonitoredItems_delete_async(UA_Client *client,
UA_DeleteMonitoredItemsRequest_copy(&request, req_copy);
cc->clientData = req_copy;
cc->userCallback = callback;
cc->userCallback = (UA_ClientAsyncServiceCallback)callback;
cc->userData = userdata;
return __UA_Client_AsyncService(client, &request, &UA_TYPES[UA_TYPES_DELETEMONITOREDITEMSREQUEST],
@ -1026,7 +1027,7 @@ UA_Client_MonitoredItems_modify(UA_Client *client,
UA_StatusCode
UA_Client_MonitoredItems_modify_async(UA_Client *client,
const UA_ModifyMonitoredItemsRequest request,
UA_ClientAsyncServiceCallback callback,
UA_ClientAsyncModifyMonitoredItemsCallback callback,
void *userdata, UA_UInt32 *requestId) {
lockClient(client);
@ -1042,7 +1043,8 @@ UA_Client_MonitoredItems_modify_async(UA_Client *client,
UA_StatusCode statusCode = __Client_AsyncService(
client, &modifiedRequest, &UA_TYPES[UA_TYPES_MODIFYMONITOREDITEMSREQUEST],
callback, &UA_TYPES[UA_TYPES_MODIFYMONITOREDITEMSRESPONSE], userdata, requestId);
(UA_ClientAsyncServiceCallback)callback,
&UA_TYPES[UA_TYPES_MODIFYMONITOREDITEMSRESPONSE], userdata, requestId);
unlockClient(client);
UA_ModifyMonitoredItemsRequest_clear(&modifiedRequest);
@ -1517,3 +1519,45 @@ UA_Client_Subscriptions_setPublishingMode(UA_Client *client,
&response, &UA_TYPES[UA_TYPES_SETPUBLISHINGMODERESPONSE]);
return response;
}
UA_SetMonitoringModeResponse
UA_Client_MonitoredItems_setMonitoringMode(UA_Client *client,
const UA_SetMonitoringModeRequest request) {
UA_SetMonitoringModeResponse response;
__UA_Client_Service(client, &request, &UA_TYPES[UA_TYPES_SETMONITORINGMODEREQUEST],
&response, &UA_TYPES[UA_TYPES_SETMONITORINGMODERESPONSE]);
return response;
}
UA_StatusCode
UA_Client_MonitoredItems_setMonitoringMode_async(UA_Client *client,
const UA_SetMonitoringModeRequest request,
UA_ClientAsyncSetMonitoringModeCallback callback,
void *userdata, UA_UInt32 *requestId) {
return __UA_Client_AsyncService(client, &request,
&UA_TYPES[UA_TYPES_SETMONITORINGMODEREQUEST],
(UA_ClientAsyncServiceCallback)callback,
&UA_TYPES[UA_TYPES_SETMONITORINGMODERESPONSE],
userdata, requestId);
}
UA_SetTriggeringResponse
UA_Client_MonitoredItems_setTriggering(UA_Client *client,
const UA_SetTriggeringRequest request) {
UA_SetTriggeringResponse response;
__UA_Client_Service(client, &request, &UA_TYPES[UA_TYPES_SETTRIGGERINGREQUEST],
&response, &UA_TYPES[UA_TYPES_SETTRIGGERINGRESPONSE]);
return response;
}
UA_StatusCode
UA_Client_MonitoredItems_setTriggering_async(UA_Client *client,
const UA_SetTriggeringRequest request,
UA_ClientAsyncSetTriggeringCallback callback,
void *userdata, UA_UInt32 *requestId) {
return __UA_Client_AsyncService(client, &request,
&UA_TYPES[UA_TYPES_SETTRIGGERINGREQUEST],
(UA_ClientAsyncServiceCallback)callback,
&UA_TYPES[UA_TYPES_SETTRIGGERINGRESPONSE],
userdata, requestId);
}

View File

@ -74,37 +74,32 @@ dataChangeHandler(UA_Client *client, UA_UInt32 subId, void *subContext,
static void
createSubscriptionCallback(UA_Client *client, void *userdata, UA_UInt32 requestId,
void *r) {
UA_CreateSubscriptionResponse_copy((const UA_CreateSubscriptionResponse *)r,
(UA_CreateSubscriptionResponse *)userdata);
UA_CreateSubscriptionResponse *r) {
UA_CreateSubscriptionResponse_copy(r, (UA_CreateSubscriptionResponse *)userdata);
}
static void
modifySubscriptionCallback(UA_Client *client, void *userdata, UA_UInt32 requestId,
void *r) {
UA_ModifySubscriptionResponse_copy((const UA_ModifySubscriptionResponse *)r,
(UA_ModifySubscriptionResponse *)userdata);
UA_ModifySubscriptionResponse *r) {
UA_ModifySubscriptionResponse_copy(r, (UA_ModifySubscriptionResponse *)userdata);
}
static void
createDataChangesCallback(UA_Client *client, void *userdata, UA_UInt32 requestId,
void *r) {
UA_CreateMonitoredItemsResponse_copy((const UA_CreateMonitoredItemsResponse *)r,
(UA_CreateMonitoredItemsResponse *)userdata);
UA_CreateMonitoredItemsResponse *r) {
UA_CreateMonitoredItemsResponse_copy(r, (UA_CreateMonitoredItemsResponse *)userdata);
}
static void
deleteMonitoredItemsCallback(UA_Client *client, void *userdata, UA_UInt32 requestId,
void *r) {
UA_DeleteMonitoredItemsResponse_copy((const UA_DeleteMonitoredItemsResponse *)r,
(UA_DeleteMonitoredItemsResponse *)userdata);
UA_DeleteMonitoredItemsResponse *r) {
UA_DeleteMonitoredItemsResponse_copy(r, (UA_DeleteMonitoredItemsResponse *)userdata);
}
static void
deleteSubscriptionsCallback(UA_Client *client, void *userdata, UA_UInt32 requestId,
void *r) {
UA_DeleteSubscriptionsResponse_copy((const UA_DeleteSubscriptionsResponse *)r,
(UA_DeleteSubscriptionsResponse *)userdata);
UA_DeleteSubscriptionsResponse *r) {
UA_DeleteSubscriptionsResponse_copy(r, (UA_DeleteSubscriptionsResponse *)userdata);
}
START_TEST(Client_subscription) {
@ -1257,14 +1252,14 @@ static UA_SessionState sessState;
static UA_Boolean hasMon;
static void
monCallback(UA_Client *client, void *userdata,
UA_UInt32 requestId, void *r) {
monCallback(UA_Client *client, void *userdata, UA_UInt32 requestId,
UA_CreateMonitoredItemsResponse *r) {
hasMon = true;
}
static void
createSubscriptionCallback2(UA_Client *client, void *userdata,
UA_UInt32 requestId, void *r) {
createSubscriptionCallback2(UA_Client *client, void *userdata, UA_UInt32 requestId,
UA_CreateSubscriptionResponse *r) {
UA_CreateSubscriptionResponse *rr = (UA_CreateSubscriptionResponse*)r;
ck_assert_uint_ne(rr->subscriptionId, 0);