Coverage Report

Created: 2026-08-14 07:31

next uncovered line (L), next uncovered region (R), next uncovered branch (B)
/src/open62541_15/src/client/ua_client_highlevel.c
Line
Count
Source
1
/* This Source Code Form is subject to the terms of the Mozilla Public
2
 * License, v. 2.0. If a copy of the MPL was not distributed with this
3
 * file, You can obtain one at http://mozilla.org/MPL/2.0/.
4
 *
5
 *    Copyright 2015-2021 (c) Fraunhofer IOSB (Author: Julius Pfrommer)
6
 *    Copyright 2015 (c) Oleksiy Vasylyev
7
 *    Copyright 2017 (c) Florian Palm
8
 *    Copyright 2016 (c) Chris Iatrou
9
 *    Copyright 2017 (c) Stefan Profanter, fortiss GmbH
10
 *    Copyright 2018 (c) Fabian Arndt
11
 *    Copyright 2018 (c) Peter Rustler, basyskom GmbH
12
 */
13
14
#include "ua_client_internal.h"
15
16
UA_StatusCode
17
UA_Client_NamespaceGetIndex(UA_Client *client, UA_String *namespaceUri,
18
0
                            UA_UInt16 *namespaceIndex) {
19
0
    UA_ReadRequest request;
20
0
    UA_ReadRequest_init(&request);
21
0
    UA_ReadValueId id;
22
0
    UA_ReadValueId_init(&id);
23
0
    id.attributeId = UA_ATTRIBUTEID_VALUE;
24
0
    id.nodeId = UA_NS0ID(SERVER_NAMESPACEARRAY);
25
0
    request.nodesToRead = &id;
26
0
    request.nodesToReadSize = 1;
27
28
0
    UA_ReadResponse response = UA_Client_Service_read(client, request);
29
30
0
    UA_StatusCode retval = UA_STATUSCODE_GOOD;
31
0
    if(response.responseHeader.serviceResult != UA_STATUSCODE_GOOD)
32
0
        retval = response.responseHeader.serviceResult;
33
0
    else if(response.resultsSize != 1 || !response.results[0].hasValue)
34
0
        retval = UA_STATUSCODE_BADNODEATTRIBUTESINVALID;
35
0
    else if(response.results[0].value.type != &UA_TYPES[UA_TYPES_STRING])
36
0
        retval = UA_STATUSCODE_BADTYPEMISMATCH;
37
38
0
    if(retval != UA_STATUSCODE_GOOD) {
39
0
        UA_ReadResponse_clear(&response);
40
0
        return retval;
41
0
    }
42
43
0
    retval = UA_STATUSCODE_BADNOTFOUND;
44
0
    UA_String *ns = (UA_String *)response.results[0].value.data;
45
0
    for(size_t i = 0; i < response.results[0].value.arrayLength; ++i) {
46
0
        if(UA_String_equal(namespaceUri, &ns[i])) {
47
0
            *namespaceIndex = (UA_UInt16)i;
48
0
            retval = UA_STATUSCODE_GOOD;
49
0
            break;
50
0
        }
51
0
    }
52
53
0
    UA_ReadResponse_clear(&response);
54
0
    return retval;
55
0
}
56
57
UA_StatusCode
58
UA_Client_forEachChildNodeCall(UA_Client *client, UA_NodeId parentNodeId,
59
0
                               UA_NodeIteratorCallback callback, void *handle) {
60
0
    UA_BrowseRequest bReq;
61
0
    UA_BrowseRequest_init(&bReq);
62
0
    bReq.requestedMaxReferencesPerNode = 0;
63
0
    bReq.nodesToBrowse = UA_BrowseDescription_new();
64
0
    if(!bReq.nodesToBrowse)
65
0
        return UA_STATUSCODE_BADOUTOFMEMORY;
66
0
    bReq.nodesToBrowseSize = 1;
67
0
    UA_NodeId_copy(&parentNodeId, &bReq.nodesToBrowse[0].nodeId);
68
0
    bReq.nodesToBrowse[0].resultMask = UA_BROWSERESULTMASK_ALL; //return everything
69
0
    bReq.nodesToBrowse[0].browseDirection = UA_BROWSEDIRECTION_BOTH;
70
71
0
    UA_BrowseResponse bResp = UA_Client_Service_browse(client, bReq);
72
73
0
    UA_StatusCode retval = bResp.responseHeader.serviceResult;
74
0
    if(retval == UA_STATUSCODE_GOOD) {
75
0
        for(size_t i = 0; i < bResp.resultsSize; ++i) {
76
0
            for(size_t j = 0; j < bResp.results[i].referencesSize; ++j) {
77
0
                UA_ReferenceDescription *ref = &bResp.results[i].references[j];
78
0
                retval |= callback(ref->nodeId.nodeId, !ref->isForward,
79
0
                                   ref->referenceTypeId, handle);
80
0
            }
81
0
        }
82
0
    }
83
84
0
    UA_BrowseRequest_clear(&bReq);
85
0
    UA_BrowseResponse_clear(&bResp);
86
0
    return retval;
87
0
}
88
89
/*******************/
90
/* Node Management */
91
/*******************/
92
93
UA_StatusCode
94
UA_Client_addReference(UA_Client *client, const UA_NodeId sourceNodeId,
95
                       const UA_NodeId referenceTypeId, UA_Boolean isForward,
96
                       const UA_String targetServerUri,
97
                       const UA_ExpandedNodeId targetNodeId,
98
0
                       UA_NodeClass targetNodeClass) {
99
0
    UA_AddReferencesItem item;
100
0
    UA_AddReferencesItem_init(&item);
101
0
    item.sourceNodeId = sourceNodeId;
102
0
    item.referenceTypeId = referenceTypeId;
103
0
    item.isForward = isForward;
104
0
    item.targetServerUri = targetServerUri;
105
0
    item.targetNodeId = targetNodeId;
106
0
    item.targetNodeClass = targetNodeClass;
107
0
    UA_AddReferencesRequest request;
108
0
    UA_AddReferencesRequest_init(&request);
109
0
    request.referencesToAdd = &item;
110
0
    request.referencesToAddSize = 1;
111
0
    UA_AddReferencesResponse response = UA_Client_Service_addReferences(client, request);
112
0
    UA_StatusCode retval = response.responseHeader.serviceResult;
113
0
    if(retval != UA_STATUSCODE_GOOD) {
114
0
        UA_AddReferencesResponse_clear(&response);
115
0
        return retval;
116
0
    }
117
0
    if(response.resultsSize != 1) {
118
0
        UA_AddReferencesResponse_clear(&response);
119
0
        return UA_STATUSCODE_BADUNEXPECTEDERROR;
120
0
    }
121
0
    retval = response.results[0];
122
0
    UA_AddReferencesResponse_clear(&response);
123
0
    return retval;
124
0
}
125
126
UA_StatusCode
127
UA_Client_deleteReference(UA_Client *client, const UA_NodeId sourceNodeId,
128
                          const UA_NodeId referenceTypeId, UA_Boolean isForward,
129
                          const UA_ExpandedNodeId targetNodeId,
130
0
                          UA_Boolean deleteBidirectional) {
131
0
    UA_DeleteReferencesItem item;
132
0
    UA_DeleteReferencesItem_init(&item);
133
0
    item.sourceNodeId = sourceNodeId;
134
0
    item.referenceTypeId = referenceTypeId;
135
0
    item.isForward = isForward;
136
0
    item.targetNodeId = targetNodeId;
137
0
    item.deleteBidirectional = deleteBidirectional;
138
0
    UA_DeleteReferencesRequest request;
139
0
    UA_DeleteReferencesRequest_init(&request);
140
0
    request.referencesToDelete = &item;
141
0
    request.referencesToDeleteSize = 1;
142
0
    UA_DeleteReferencesResponse response = UA_Client_Service_deleteReferences(client, request);
143
0
    UA_StatusCode retval = response.responseHeader.serviceResult;
144
0
    if(retval != UA_STATUSCODE_GOOD) {
145
0
        UA_DeleteReferencesResponse_clear(&response);
146
0
        return retval;
147
0
    }
148
0
    if(response.resultsSize != 1) {
149
0
        UA_DeleteReferencesResponse_clear(&response);
150
0
        return UA_STATUSCODE_BADUNEXPECTEDERROR;
151
0
    }
152
0
    retval = response.results[0];
153
0
    UA_DeleteReferencesResponse_clear(&response);
154
0
    return retval;
155
0
}
156
157
UA_StatusCode
158
UA_Client_deleteNode(UA_Client *client, const UA_NodeId nodeId,
159
0
                     UA_Boolean deleteTargetReferences) {
160
0
    UA_DeleteNodesItem item;
161
0
    UA_DeleteNodesItem_init(&item);
162
0
    item.nodeId = nodeId;
163
0
    item.deleteTargetReferences = deleteTargetReferences;
164
0
    UA_DeleteNodesRequest request;
165
0
    UA_DeleteNodesRequest_init(&request);
166
0
    request.nodesToDelete = &item;
167
0
    request.nodesToDeleteSize = 1;
168
0
    UA_DeleteNodesResponse response = UA_Client_Service_deleteNodes(client, request);
169
0
    UA_StatusCode retval = response.responseHeader.serviceResult;
170
0
    if(retval != UA_STATUSCODE_GOOD) {
171
0
        UA_DeleteNodesResponse_clear(&response);
172
0
        return retval;
173
0
    }
174
0
    if(response.resultsSize != 1) {
175
0
        UA_DeleteNodesResponse_clear(&response);
176
0
        return UA_STATUSCODE_BADUNEXPECTEDERROR;
177
0
    }
178
0
    retval = response.results[0];
179
0
    UA_DeleteNodesResponse_clear(&response);
180
0
    return retval;
181
0
}
182
183
static UA_StatusCode
184
__Client_addNode(UA_Client *client, const UA_NodeClass nodeClass,
185
                 const UA_NodeId requestedNewNodeId, const UA_NodeId parentNodeId,
186
                 const UA_NodeId referenceTypeId, const UA_QualifiedName browseName,
187
                 const UA_NodeId typeDefinition, const UA_NodeAttributes *attr,
188
0
                 const UA_DataType *attributeType, UA_NodeId *outNewNodeId) {
189
0
    UA_AddNodesRequest request;
190
0
    UA_AddNodesRequest_init(&request);
191
0
    UA_AddNodesItem item;
192
0
    UA_AddNodesItem_init(&item);
193
0
    item.parentNodeId.nodeId = parentNodeId;
194
0
    item.referenceTypeId = referenceTypeId;
195
0
    item.requestedNewNodeId.nodeId = requestedNewNodeId;
196
0
    item.browseName = browseName;
197
0
    item.nodeClass = nodeClass;
198
0
    item.typeDefinition.nodeId = typeDefinition;
199
0
    item.nodeAttributes.encoding = UA_EXTENSIONOBJECT_DECODED_NODELETE;
200
0
    item.nodeAttributes.content.decoded.type = attributeType;
201
0
    item.nodeAttributes.content.decoded.data = (void*)(uintptr_t)attr; // hack. is not written into.
202
0
    request.nodesToAdd = &item;
203
0
    request.nodesToAddSize = 1;
204
0
    UA_AddNodesResponse response = UA_Client_Service_addNodes(client, request);
205
206
0
    UA_StatusCode retval = response.responseHeader.serviceResult;
207
0
    if(retval != UA_STATUSCODE_GOOD) {
208
0
        UA_AddNodesResponse_clear(&response);
209
0
        return retval;
210
0
    }
211
212
0
    if(response.resultsSize != 1) {
213
0
        UA_AddNodesResponse_clear(&response);
214
0
        return UA_STATUSCODE_BADUNEXPECTEDERROR;
215
0
    }
216
217
    /* Move the id of the created node */
218
0
    retval = response.results[0].statusCode;
219
0
    if(retval == UA_STATUSCODE_GOOD && outNewNodeId) {
220
0
        *outNewNodeId = response.results[0].addedNodeId;
221
0
        UA_NodeId_init(&response.results[0].addedNodeId);
222
0
    }
223
224
0
    UA_AddNodesResponse_clear(&response);
225
0
    return retval;
226
0
}
227
228
UA_StatusCode
229
UA_Client_addVariableNode(UA_Client *client, const UA_NodeId requestedNewNodeId,
230
                          const UA_NodeId parentNodeId,
231
                          const UA_NodeId referenceTypeId,
232
                          const UA_QualifiedName browseName,
233
                          const UA_NodeId typeDefinition,
234
                          const UA_VariableAttributes attr,
235
0
                          UA_NodeId *outNewNodeId) {
236
0
    return __Client_addNode(client, UA_NODECLASS_VARIABLE, requestedNewNodeId,
237
0
                            parentNodeId, referenceTypeId, browseName,
238
0
                            typeDefinition, (const UA_NodeAttributes*)&attr,
239
0
                            &UA_TYPES[UA_TYPES_VARIABLEATTRIBUTES], outNewNodeId);
240
0
}
241
242
UA_StatusCode
243
UA_Client_addVariableTypeNode(UA_Client *client,
244
                              const UA_NodeId requestedNewNodeId,
245
                              const UA_NodeId parentNodeId,
246
                              const UA_NodeId referenceTypeId,
247
                              const UA_QualifiedName browseName,
248
                              const UA_VariableTypeAttributes attr,
249
0
                              UA_NodeId *outNewNodeId) {
250
0
    return __Client_addNode(client, UA_NODECLASS_VARIABLETYPE, requestedNewNodeId,
251
0
                            parentNodeId, referenceTypeId, browseName,
252
0
                            UA_NODEID_NULL, (const UA_NodeAttributes*)&attr,
253
0
                            &UA_TYPES[UA_TYPES_VARIABLETYPEATTRIBUTES], outNewNodeId);
254
0
}
255
256
UA_StatusCode
257
UA_Client_addObjectNode(UA_Client *client, const UA_NodeId requestedNewNodeId,
258
                        const UA_NodeId parentNodeId,
259
                        const UA_NodeId referenceTypeId,
260
                        const UA_QualifiedName browseName,
261
                        const UA_NodeId typeDefinition,
262
0
                        const UA_ObjectAttributes attr, UA_NodeId *outNewNodeId) {
263
0
    return __Client_addNode(client, UA_NODECLASS_OBJECT, requestedNewNodeId,
264
0
                            parentNodeId, referenceTypeId, browseName,
265
0
                            typeDefinition, (const UA_NodeAttributes*)&attr,
266
0
                            &UA_TYPES[UA_TYPES_OBJECTATTRIBUTES], outNewNodeId);
267
0
}
268
269
UA_StatusCode
270
UA_Client_addObjectTypeNode(UA_Client *client, const UA_NodeId requestedNewNodeId,
271
                            const UA_NodeId parentNodeId,
272
                            const UA_NodeId referenceTypeId,
273
                            const UA_QualifiedName browseName,
274
                            const UA_ObjectTypeAttributes attr,
275
0
                            UA_NodeId *outNewNodeId) {
276
0
    return __Client_addNode(client, UA_NODECLASS_OBJECTTYPE, requestedNewNodeId,
277
0
                            parentNodeId, referenceTypeId, browseName,
278
0
                            UA_NODEID_NULL, (const UA_NodeAttributes*)&attr,
279
0
                            &UA_TYPES[UA_TYPES_OBJECTTYPEATTRIBUTES], outNewNodeId);
280
0
}
281
282
UA_StatusCode
283
UA_Client_addViewNode(UA_Client *client, const UA_NodeId requestedNewNodeId,
284
                      const UA_NodeId parentNodeId,
285
                      const UA_NodeId referenceTypeId,
286
                      const UA_QualifiedName browseName,
287
                      const UA_ViewAttributes attr,
288
0
                      UA_NodeId *outNewNodeId) {
289
0
    return __Client_addNode(client, UA_NODECLASS_VIEW, requestedNewNodeId,
290
0
                            parentNodeId, referenceTypeId, browseName,
291
0
                            UA_NODEID_NULL, (const UA_NodeAttributes*)&attr,
292
0
                            &UA_TYPES[UA_TYPES_VIEWATTRIBUTES], outNewNodeId);
293
0
}
294
295
UA_StatusCode
296
UA_Client_addReferenceTypeNode(UA_Client *client,
297
                               const UA_NodeId requestedNewNodeId,
298
                               const UA_NodeId parentNodeId,
299
                               const UA_NodeId referenceTypeId,
300
                               const UA_QualifiedName browseName,
301
                               const UA_ReferenceTypeAttributes attr,
302
0
                               UA_NodeId *outNewNodeId) {
303
0
    return __Client_addNode(client, UA_NODECLASS_REFERENCETYPE, requestedNewNodeId,
304
0
                            parentNodeId, referenceTypeId, browseName,
305
0
                            UA_NODEID_NULL, (const UA_NodeAttributes*)&attr,
306
0
                            &UA_TYPES[UA_TYPES_REFERENCETYPEATTRIBUTES], outNewNodeId);
307
0
}
308
309
UA_StatusCode
310
UA_Client_addDataTypeNode(UA_Client *client, const UA_NodeId requestedNewNodeId,
311
                          const UA_NodeId parentNodeId,
312
                          const UA_NodeId referenceTypeId,
313
                          const UA_QualifiedName browseName,
314
                          const UA_DataTypeAttributes attr,
315
0
                          UA_NodeId *outNewNodeId) {
316
0
    return __Client_addNode(client, UA_NODECLASS_DATATYPE, requestedNewNodeId,
317
0
                            parentNodeId, referenceTypeId, browseName,
318
0
                            UA_NODEID_NULL, (const UA_NodeAttributes*)&attr,
319
0
                            &UA_TYPES[UA_TYPES_DATATYPEATTRIBUTES], outNewNodeId);
320
0
}
321
322
UA_StatusCode
323
UA_Client_addMethodNode(UA_Client *client, const UA_NodeId requestedNewNodeId,
324
                        const UA_NodeId parentNodeId,
325
                        const UA_NodeId referenceTypeId,
326
                        const UA_QualifiedName browseName,
327
                        const UA_MethodAttributes attr,
328
0
                        UA_NodeId *outNewNodeId) {
329
0
    return __Client_addNode(client, UA_NODECLASS_METHOD, requestedNewNodeId,
330
0
                            parentNodeId, referenceTypeId, browseName,
331
0
                            UA_NODEID_NULL, (const UA_NodeAttributes*)&attr,
332
0
                            &UA_TYPES[UA_TYPES_METHODATTRIBUTES], outNewNodeId);
333
0
}
334
335
/********/
336
/* Call */
337
/********/
338
339
UA_StatusCode
340
UA_Client_call(UA_Client *client, const UA_NodeId objectId,
341
               const UA_NodeId methodId, size_t inputSize,
342
               const UA_Variant *input, size_t *outputSize,
343
0
               UA_Variant **output) {
344
    /* Set up the request */
345
0
    UA_CallRequest request;
346
0
    UA_CallRequest_init(&request);
347
0
    UA_CallMethodRequest item;
348
0
    UA_CallMethodRequest_init(&item);
349
0
    item.methodId = methodId;
350
0
    item.objectId = objectId;
351
0
    item.inputArguments = (UA_Variant *)(void*)(uintptr_t)input; // cast const...
352
0
    item.inputArgumentsSize = inputSize;
353
0
    request.methodsToCall = &item;
354
0
    request.methodsToCallSize = 1;
355
356
    /* Call the service */
357
0
    UA_CallResponse response = UA_Client_Service_call(client, request);
358
0
    UA_StatusCode retval = response.responseHeader.serviceResult;
359
0
    if(retval == UA_STATUSCODE_GOOD) {
360
0
        if(response.resultsSize == 1)
361
0
            retval = response.results[0].statusCode;
362
0
        else
363
0
            retval = UA_STATUSCODE_BADUNEXPECTEDERROR;
364
0
    }
365
0
    if(UA_StatusCode_isBad(retval)) {
366
0
        UA_CallResponse_clear(&response);
367
0
        return retval;
368
0
    }
369
370
    /* Move the output arguments */
371
0
    if(output != NULL && outputSize != NULL) {
372
0
        *output = response.results[0].outputArguments;
373
0
        *outputSize = response.results[0].outputArgumentsSize;
374
0
        response.results[0].outputArguments = NULL;
375
0
        response.results[0].outputArgumentsSize = 0;
376
0
    }
377
0
    UA_CallResponse_clear(&response);
378
0
    return retval;
379
0
}
380
381
/**********/
382
/* Browse */
383
/**********/
384
385
UA_BrowseResult
386
UA_Client_browse(UA_Client *client, const UA_ViewDescription *view,
387
                 UA_UInt32 requestedMaxReferencesPerNode,
388
0
                 const UA_BrowseDescription *nodesToBrowse) {
389
0
    UA_BrowseResult res;
390
0
    UA_BrowseRequest request;
391
0
    UA_BrowseResponse response;
392
0
    UA_BrowseResponse_init(&response);
393
0
    UA_StatusCode retval = UA_STATUSCODE_GOOD;
394
0
    if(!nodesToBrowse) {
395
0
        retval = UA_STATUSCODE_BADINTERNALERROR;
396
0
        goto error;
397
0
    }
398
399
    /* Set up the request */
400
0
    UA_BrowseRequest_init(&request);
401
0
    if(view)
402
0
        request.view = *view;
403
0
    request.requestedMaxReferencesPerNode = requestedMaxReferencesPerNode;
404
0
    request.nodesToBrowse = (UA_BrowseDescription*)(uintptr_t)nodesToBrowse;
405
0
    request.nodesToBrowseSize = 1;
406
407
    /* Call the service */
408
0
    response = UA_Client_Service_browse(client, request);
409
0
    retval = response.responseHeader.serviceResult;
410
0
    if(retval == UA_STATUSCODE_GOOD && response.resultsSize != 1)
411
0
        retval = UA_STATUSCODE_BADUNEXPECTEDERROR;
412
0
    if(UA_StatusCode_isBad(retval))
413
0
        goto error;
414
415
    /* Return the result */
416
0
    res = response.results[0];
417
0
    response.resultsSize = 0;
418
0
    UA_BrowseResponse_clear(&response);
419
0
    return res;
420
421
0
 error:
422
0
    UA_BrowseResponse_clear(&response);
423
0
    UA_BrowseResult_init(&res);
424
0
    res.statusCode = retval;
425
0
    return res;
426
0
}
427
428
UA_BrowseResult
429
UA_Client_browseNext(UA_Client *client, UA_Boolean releaseContinuationPoint,
430
0
                     UA_ByteString continuationPoint) {
431
    /* Set up the request */
432
0
    UA_BrowseNextRequest request;
433
0
    UA_BrowseNextRequest_init(&request);
434
0
    request.releaseContinuationPoints = releaseContinuationPoint;
435
0
    request.continuationPoints = &continuationPoint;
436
0
    request.continuationPointsSize = 1;
437
438
    /* Call the service */
439
0
    UA_BrowseResult res;
440
0
    UA_BrowseNextResponse response = UA_Client_Service_browseNext(client, request);
441
0
    UA_StatusCode retval = response.responseHeader.serviceResult;
442
0
    if(retval == UA_STATUSCODE_GOOD && response.resultsSize != 1)
443
0
        retval = UA_STATUSCODE_BADUNEXPECTEDERROR;
444
0
    if(UA_StatusCode_isBad(retval)) {
445
0
        UA_BrowseNextResponse_clear(&response);
446
0
        UA_BrowseResult_init(&res);
447
0
        res.statusCode = retval;
448
0
        return res;
449
0
    }
450
451
    /* Return the result */
452
0
    res = response.results[0];
453
0
    response.resultsSize = 0;
454
0
    UA_BrowseNextResponse_clear(&response);
455
0
    return res;
456
0
}
457
458
UA_BrowsePathResult
459
UA_Client_translateBrowsePathToNodeIds(UA_Client *client,
460
0
                                       const UA_BrowsePath *browsePath) {
461
0
    UA_BrowsePathResult res;
462
0
    UA_TranslateBrowsePathsToNodeIdsRequest request;
463
0
    UA_TranslateBrowsePathsToNodeIdsResponse response;
464
0
    UA_TranslateBrowsePathsToNodeIdsResponse_init(&response);
465
0
    UA_StatusCode retval = UA_STATUSCODE_GOOD;
466
0
    if(!browsePath) {
467
0
        retval = UA_STATUSCODE_BADINTERNALERROR;
468
0
        goto error;
469
0
    }
470
471
    /* Set up the request */
472
0
    UA_TranslateBrowsePathsToNodeIdsRequest_init(&request);
473
0
    request.browsePaths = (UA_BrowsePath*)(uintptr_t)browsePath;
474
0
    request.browsePathsSize = 1;
475
476
    /* Call the service */
477
0
    response = UA_Client_Service_translateBrowsePathsToNodeIds(client, request);
478
0
    retval = response.responseHeader.serviceResult;
479
0
    if(retval == UA_STATUSCODE_GOOD && response.resultsSize != 1)
480
0
        retval = UA_STATUSCODE_BADUNEXPECTEDERROR;
481
0
    if(UA_StatusCode_isBad(retval))
482
0
        goto error;
483
484
    /* Return the result */
485
0
    res = response.results[0];
486
0
    response.resultsSize = 0;
487
0
    UA_TranslateBrowsePathsToNodeIdsResponse_clear(&response);
488
0
    return res;
489
490
0
 error:
491
0
    UA_TranslateBrowsePathsToNodeIdsResponse_clear(&response);
492
0
    UA_BrowsePathResult_init(&res);
493
0
    res.statusCode = retval;
494
0
    return res;
495
0
}
496
497
/********************/
498
/* Write Attributes */
499
/********************/
500
501
UA_StatusCode UA_EXPORT UA_THREADSAFE
502
0
UA_Client_write(UA_Client *client, const UA_WriteValue *wv) {
503
0
    if(!wv)
504
0
        return UA_STATUSCODE_BADINTERNALERROR;
505
506
    /* Set up the request */
507
0
    UA_WriteRequest request;
508
0
    UA_WriteRequest_init(&request);
509
0
    request.nodesToWrite = (UA_WriteValue*)(uintptr_t)wv;
510
0
    request.nodesToWriteSize = 1;
511
512
    /* Call the service */
513
0
    UA_StatusCode retval = UA_STATUSCODE_GOOD;
514
0
    UA_WriteResponse response = UA_Client_Service_write(client, request);
515
0
    retval = response.responseHeader.serviceResult;
516
0
    if(retval == UA_STATUSCODE_GOOD && response.resultsSize != 1)
517
0
        retval = UA_STATUSCODE_BADUNEXPECTEDERROR;
518
0
    if(UA_StatusCode_isBad(retval)) {
519
0
        UA_WriteResponse_clear(&response);
520
0
        return retval;
521
0
    }
522
523
    /* Return the result */
524
0
    retval = response.results[0];
525
0
    UA_WriteResponse_clear(&response);
526
0
    return retval;
527
0
}
528
529
static UA_StatusCode
530
__Client_writeAttribute(UA_Client *client, const UA_NodeId *nodeId,
531
                        UA_AttributeId attributeId, const void *in,
532
0
                        const UA_DataType *inDataType) {
533
0
    if(!in || !inDataType)
534
0
      return UA_STATUSCODE_BADTYPEMISMATCH;
535
536
0
    UA_WriteValue wValue;
537
0
    UA_WriteValue_init(&wValue);
538
0
    wValue.nodeId = *nodeId;
539
0
    wValue.attributeId = attributeId;
540
0
    if(attributeId == UA_ATTRIBUTEID_VALUE &&
541
0
       inDataType == &UA_TYPES[UA_TYPES_VARIANT]) {
542
0
        wValue.value.value = *(const UA_Variant*)in;
543
0
        wValue.value.hasValue = true;
544
0
    } else if(attributeId == UA_ATTRIBUTEID_VALUE &&
545
0
              inDataType == &UA_TYPES[UA_TYPES_DATAVALUE]) {
546
0
        wValue.value = *(const UA_DataValue*)in;
547
0
    } else {
548
        /* Hack to get rid of the const annotation.
549
         * The value is never written into. */
550
0
        UA_Variant_setScalar(&wValue.value.value, (void*)(uintptr_t)in, inDataType);
551
0
        wValue.value.hasValue = true;
552
0
    }
553
0
    UA_WriteRequest wReq;
554
0
    UA_WriteRequest_init(&wReq);
555
0
    wReq.nodesToWrite = &wValue;
556
0
    wReq.nodesToWriteSize = 1;
557
558
0
    UA_WriteResponse wResp = UA_Client_Service_write(client, wReq);
559
560
0
    UA_StatusCode retval = wResp.responseHeader.serviceResult;
561
0
    if(retval == UA_STATUSCODE_GOOD) {
562
0
        if(wResp.resultsSize == 1)
563
0
            retval = wResp.results[0];
564
0
        else
565
0
            retval = UA_STATUSCODE_BADUNEXPECTEDERROR;
566
0
    }
567
568
0
    UA_WriteResponse_clear(&wResp);
569
0
    return retval;
570
0
}
571
572
UA_StatusCode
573
UA_Client_writeNodeIdAttribute(UA_Client *client, const UA_NodeId nodeId,
574
0
                               const UA_NodeId *newNodeId) {
575
0
    return __Client_writeAttribute(client, &nodeId, UA_ATTRIBUTEID_NODEID,
576
0
                                   newNodeId, &UA_TYPES[UA_TYPES_NODEID]);
577
0
}
578
579
UA_StatusCode
580
UA_Client_writeNodeClassAttribute(UA_Client *client, const UA_NodeId nodeId,
581
0
                                  const UA_NodeClass *newNodeClass) {
582
0
    return __Client_writeAttribute(client, &nodeId, UA_ATTRIBUTEID_NODECLASS,
583
0
                                   newNodeClass, &UA_TYPES[UA_TYPES_NODECLASS]);
584
0
}
585
586
UA_StatusCode
587
UA_Client_writeBrowseNameAttribute(UA_Client *client, const UA_NodeId nodeId,
588
0
                                   const UA_QualifiedName *newBrowseName) {
589
0
    return __Client_writeAttribute(client, &nodeId, UA_ATTRIBUTEID_BROWSENAME,
590
0
                                   newBrowseName, &UA_TYPES[UA_TYPES_QUALIFIEDNAME]);
591
0
}
592
593
UA_StatusCode
594
UA_Client_writeDisplayNameAttribute(UA_Client *client, const UA_NodeId nodeId,
595
0
                                    const UA_LocalizedText *newDisplayName) {
596
0
    return __Client_writeAttribute(client, &nodeId, UA_ATTRIBUTEID_DISPLAYNAME,
597
0
                                   newDisplayName, &UA_TYPES[UA_TYPES_LOCALIZEDTEXT]);
598
0
}
599
600
UA_StatusCode
601
UA_Client_writeDescriptionAttribute(UA_Client *client, const UA_NodeId nodeId,
602
0
                                    const UA_LocalizedText *newDescription) {
603
0
    return __Client_writeAttribute(client, &nodeId, UA_ATTRIBUTEID_DESCRIPTION,
604
0
                                   newDescription, &UA_TYPES[UA_TYPES_LOCALIZEDTEXT]);
605
0
}
606
607
UA_StatusCode
608
UA_Client_writeWriteMaskAttribute(UA_Client *client, const UA_NodeId nodeId,
609
0
                                  const UA_UInt32 *newWriteMask) {
610
0
    return __Client_writeAttribute(client, &nodeId, UA_ATTRIBUTEID_WRITEMASK,
611
0
                                   newWriteMask, &UA_TYPES[UA_TYPES_UINT32]);
612
0
}
613
614
UA_StatusCode
615
UA_Client_writeUserWriteMaskAttribute(UA_Client *client, const UA_NodeId nodeId,
616
0
                                      const UA_UInt32 *newUserWriteMask) {
617
0
    return __Client_writeAttribute(client, &nodeId, UA_ATTRIBUTEID_USERWRITEMASK,
618
0
                                   newUserWriteMask, &UA_TYPES[UA_TYPES_UINT32]);
619
0
}
620
621
UA_StatusCode
622
UA_Client_writeIsAbstractAttribute(UA_Client *client, const UA_NodeId nodeId,
623
0
                                   const UA_Boolean *newIsAbstract) {
624
0
    return __Client_writeAttribute(client, &nodeId, UA_ATTRIBUTEID_ISABSTRACT,
625
0
                                   newIsAbstract, &UA_TYPES[UA_TYPES_BOOLEAN]);
626
0
}
627
628
UA_StatusCode
629
UA_Client_writeSymmetricAttribute(UA_Client *client, const UA_NodeId nodeId,
630
0
                                  const UA_Boolean *newSymmetric) {
631
0
    return __Client_writeAttribute(client, &nodeId, UA_ATTRIBUTEID_SYMMETRIC,
632
0
                                   newSymmetric, &UA_TYPES[UA_TYPES_BOOLEAN]);
633
0
}
634
635
UA_StatusCode
636
UA_Client_writeInverseNameAttribute(UA_Client *client, const UA_NodeId nodeId,
637
0
                                    const UA_LocalizedText *newInverseName) {
638
0
    return __Client_writeAttribute(client, &nodeId, UA_ATTRIBUTEID_INVERSENAME,
639
0
                                   newInverseName, &UA_TYPES[UA_TYPES_LOCALIZEDTEXT]);
640
0
}
641
642
UA_StatusCode
643
UA_Client_writeContainsNoLoopsAttribute(UA_Client *client, const UA_NodeId nodeId,
644
0
                                        const UA_Boolean *newContainsNoLoops) {
645
0
    return __Client_writeAttribute(client, &nodeId, UA_ATTRIBUTEID_CONTAINSNOLOOPS,
646
0
                                   newContainsNoLoops, &UA_TYPES[UA_TYPES_BOOLEAN]);
647
0
}
648
649
UA_StatusCode
650
UA_Client_writeEventNotifierAttribute(UA_Client *client, const UA_NodeId nodeId,
651
0
                                      const UA_Byte *newEventNotifier) {
652
0
    return __Client_writeAttribute(client, &nodeId, UA_ATTRIBUTEID_EVENTNOTIFIER,
653
0
                                   newEventNotifier, &UA_TYPES[UA_TYPES_BYTE]);
654
0
}
655
656
UA_StatusCode
657
UA_Client_writeValueAttribute(UA_Client *client, const UA_NodeId nodeId,
658
0
                              const UA_Variant *newValue) {
659
0
    return __Client_writeAttribute(client, &nodeId, UA_ATTRIBUTEID_VALUE,
660
0
                                   newValue, &UA_TYPES[UA_TYPES_VARIANT]);
661
0
}
662
663
UA_StatusCode
664
UA_Client_writeValueAttribute_scalar(UA_Client *client, const UA_NodeId nodeId,
665
                                     const void *newValue,
666
0
                                     const UA_DataType *valueType) {
667
0
    return __Client_writeAttribute(client, &nodeId, UA_ATTRIBUTEID_VALUE,
668
0
                                   newValue, valueType);
669
0
}
670
671
UA_StatusCode
672
UA_Client_writeValueAttributeEx(UA_Client *client, const UA_NodeId nodeId,
673
0
                                const UA_DataValue *newValue) {
674
0
    return __Client_writeAttribute(client, &nodeId, UA_ATTRIBUTEID_VALUE,
675
0
                                   newValue, &UA_TYPES[UA_TYPES_DATAVALUE]);
676
0
}
677
678
UA_StatusCode
679
UA_Client_writeDataTypeAttribute(UA_Client *client, const UA_NodeId nodeId,
680
0
                                 const UA_NodeId *newDataType) {
681
0
    return __Client_writeAttribute(client, &nodeId, UA_ATTRIBUTEID_DATATYPE,
682
0
                                   newDataType, &UA_TYPES[UA_TYPES_NODEID]);
683
0
}
684
685
UA_StatusCode
686
UA_Client_writeValueRankAttribute(UA_Client *client, const UA_NodeId nodeId,
687
0
                                  const UA_Int32 *newValueRank) {
688
0
    return __Client_writeAttribute(client, &nodeId, UA_ATTRIBUTEID_VALUERANK,
689
0
                                   newValueRank, &UA_TYPES[UA_TYPES_INT32]);
690
0
}
691
692
UA_StatusCode
693
UA_Client_writeAccessLevelAttribute(UA_Client *client, const UA_NodeId nodeId,
694
0
                                    const UA_Byte *newAccessLevel) {
695
0
    return __Client_writeAttribute(client, &nodeId, UA_ATTRIBUTEID_ACCESSLEVEL,
696
0
                                   newAccessLevel, &UA_TYPES[UA_TYPES_BYTE]);
697
0
}
698
699
UA_StatusCode
700
UA_Client_writeAccessLevelExAttribute(UA_Client *client, const UA_NodeId nodeId,
701
0
                                      UA_UInt32 *newAccessLevelEx) {
702
0
    return __Client_writeAttribute(client, &nodeId, UA_ATTRIBUTEID_ACCESSLEVELEX,
703
0
                                   newAccessLevelEx, &UA_TYPES[UA_TYPES_UINT32]);
704
0
}
705
706
UA_StatusCode
707
UA_Client_writeUserAccessLevelAttribute(UA_Client *client, const UA_NodeId nodeId,
708
0
                                        const UA_Byte *newUserAccessLevel) {
709
0
    return __Client_writeAttribute(client, &nodeId, UA_ATTRIBUTEID_USERACCESSLEVEL,
710
0
                                   newUserAccessLevel, &UA_TYPES[UA_TYPES_BYTE]);
711
0
}
712
713
UA_StatusCode
714
UA_Client_writeMinimumSamplingIntervalAttribute(UA_Client *client,
715
                                                const UA_NodeId nodeId,
716
0
                                                const UA_Double *newMinInterval) {
717
0
    return __Client_writeAttribute(client, &nodeId, UA_ATTRIBUTEID_MINIMUMSAMPLINGINTERVAL,
718
0
                                   newMinInterval, &UA_TYPES[UA_TYPES_DOUBLE]);
719
0
}
720
721
UA_StatusCode
722
UA_Client_writeHistorizingAttribute(UA_Client *client, const UA_NodeId nodeId,
723
0
                                    const UA_Boolean *newHistorizing) {
724
0
    return __Client_writeAttribute(client, &nodeId, UA_ATTRIBUTEID_HISTORIZING,
725
0
                                   newHistorizing, &UA_TYPES[UA_TYPES_BOOLEAN]);
726
0
}
727
728
UA_StatusCode
729
UA_Client_writeExecutableAttribute(UA_Client *client, const UA_NodeId nodeId,
730
0
                                   const UA_Boolean *newExecutable) {
731
0
    return __Client_writeAttribute(client, &nodeId, UA_ATTRIBUTEID_EXECUTABLE,
732
0
                                   newExecutable, &UA_TYPES[UA_TYPES_BOOLEAN]);
733
0
}
734
735
UA_StatusCode
736
UA_Client_writeUserExecutableAttribute(UA_Client *client, const UA_NodeId nodeId,
737
0
                                       const UA_Boolean *newUserExecutable) {
738
0
    return __Client_writeAttribute(client, &nodeId, UA_ATTRIBUTEID_USEREXECUTABLE,
739
0
                                   newUserExecutable, &UA_TYPES[UA_TYPES_BOOLEAN]);
740
0
}
741
742
UA_StatusCode
743
UA_Client_writeArrayDimensionsAttribute(UA_Client *client, const UA_NodeId nodeId,
744
                                        size_t newArrayDimensionsSize,
745
0
                                        const UA_UInt32 *newArrayDimensions) {
746
0
    if(!newArrayDimensions)
747
0
      return UA_STATUSCODE_BADTYPEMISMATCH;
748
749
0
    UA_WriteValue wValue;
750
0
    UA_WriteValue_init(&wValue);
751
0
    wValue.nodeId = nodeId;
752
0
    wValue.attributeId = UA_ATTRIBUTEID_ARRAYDIMENSIONS;
753
0
    UA_Variant_setArray(&wValue.value.value, (void*)(uintptr_t)newArrayDimensions,
754
0
                        newArrayDimensionsSize, &UA_TYPES[UA_TYPES_UINT32]);
755
0
    wValue.value.hasValue = true;
756
0
    UA_WriteRequest wReq;
757
0
    UA_WriteRequest_init(&wReq);
758
0
    wReq.nodesToWrite = &wValue;
759
0
    wReq.nodesToWriteSize = 1;
760
761
0
    UA_WriteResponse wResp = UA_Client_Service_write(client, wReq);
762
763
0
    UA_StatusCode retval = wResp.responseHeader.serviceResult;
764
0
    if(retval == UA_STATUSCODE_GOOD) {
765
0
        if(wResp.resultsSize == 1)
766
0
            retval = wResp.results[0];
767
0
        else
768
0
            retval = UA_STATUSCODE_BADUNEXPECTEDERROR;
769
0
    }
770
0
    UA_WriteResponse_clear(&wResp);
771
0
    return retval;
772
0
}
773
774
/*******************/
775
/* Read Attributes */
776
/*******************/
777
778
UA_DataValue
779
0
UA_Client_read(UA_Client *client, const UA_ReadValueId *rvi) {
780
    /* Set up the request */
781
0
    UA_ReadRequest request;
782
0
    UA_ReadRequest_init(&request);
783
0
    request.timestampsToReturn = UA_TIMESTAMPSTORETURN_BOTH;
784
0
    request.nodesToRead = (UA_ReadValueId*)(uintptr_t)rvi;
785
0
    request.nodesToReadSize = 1;
786
787
    /* Call the service */
788
0
    UA_DataValue res;
789
0
    UA_ReadResponse response = UA_Client_Service_read(client, request);
790
0
    UA_StatusCode retval = response.responseHeader.serviceResult;
791
0
    if(retval == UA_STATUSCODE_GOOD && response.resultsSize != 1)
792
0
        retval = UA_STATUSCODE_BADUNEXPECTEDERROR;
793
0
    if(UA_StatusCode_isBad(retval)) {
794
0
        UA_ReadResponse_clear(&response);
795
0
        UA_DataValue_init(&res);
796
0
        res.status = retval;
797
0
        res.hasStatus = true;
798
0
        return res;
799
0
    }
800
801
    /* Return the result */
802
0
    res = response.results[0];
803
0
    response.resultsSize = 0;
804
0
    UA_ReadResponse_clear(&response);
805
0
    return res;
806
0
}
807
808
static UA_StatusCode
809
__Client_readAttribute(UA_Client *client, const UA_NodeId *nodeId,
810
                       UA_AttributeId attributeId, void *out,
811
0
                       const UA_DataType *outDataType) {
812
0
    UA_ReadValueId item;
813
0
    UA_ReadValueId_init(&item);
814
0
    item.nodeId = *nodeId;
815
0
    item.attributeId = attributeId;
816
0
    UA_ReadRequest request;
817
0
    UA_ReadRequest_init(&request);
818
0
    request.nodesToRead = &item;
819
0
    request.nodesToReadSize = 1;
820
0
    UA_ReadResponse response = UA_Client_Service_read(client, request);
821
0
    UA_StatusCode retval = response.responseHeader.serviceResult;
822
0
    if(retval == UA_STATUSCODE_GOOD) {
823
0
        if(response.resultsSize == 1)
824
0
            retval = response.results[0].status;
825
0
        else
826
0
            retval = UA_STATUSCODE_BADUNEXPECTEDERROR;
827
0
    }
828
0
    if(!UA_StatusCode_isEqualTop(retval,UA_STATUSCODE_GOOD)) {
829
0
        UA_ReadResponse_clear(&response);
830
0
        return retval;
831
0
    }
832
833
    /* Set the StatusCode */
834
0
    UA_DataValue *res = response.results;
835
0
    if(res->hasStatus)
836
0
        retval = res->status;
837
838
    /* Return early of no value is given */
839
0
    if(!res->hasValue) {
840
0
        retval = UA_STATUSCODE_BADUNEXPECTEDERROR;
841
0
        UA_ReadResponse_clear(&response);
842
0
        return retval;
843
0
    }
844
845
    /* Copy value into out */
846
0
    if(attributeId == UA_ATTRIBUTEID_VALUE) {
847
0
        memcpy(out, &res->value, sizeof(UA_Variant));
848
0
        UA_Variant_init(&res->value);
849
0
    } else if(attributeId == UA_ATTRIBUTEID_NODECLASS) {
850
0
        memcpy(out, (UA_NodeClass*)res->value.data, sizeof(UA_NodeClass));
851
0
    } else if(UA_Variant_isScalar(&res->value) &&
852
0
              res->value.type == outDataType) {
853
0
        memcpy(out, res->value.data, res->value.type->memSize);
854
0
        UA_free(res->value.data);
855
0
        res->value.data = NULL;
856
0
    } else {
857
0
        retval = UA_STATUSCODE_BADUNEXPECTEDERROR;
858
0
    }
859
860
0
    UA_ReadResponse_clear(&response);
861
0
    return retval;
862
0
}
863
864
UA_StatusCode
865
UA_Client_readNodeIdAttribute(UA_Client *client, const UA_NodeId nodeId,
866
0
                              UA_NodeId *out) {
867
0
    return __Client_readAttribute(client, &nodeId, UA_ATTRIBUTEID_NODEID,
868
0
                                  out, &UA_TYPES[UA_TYPES_NODEID]);
869
0
}
870
871
UA_StatusCode
872
UA_Client_readNodeClassAttribute(UA_Client *client, const UA_NodeId nodeId,
873
0
                                 UA_NodeClass *out) {
874
0
    return __Client_readAttribute(client, &nodeId, UA_ATTRIBUTEID_NODECLASS,
875
0
                                  out, &UA_TYPES[UA_TYPES_NODECLASS]);
876
0
}
877
878
UA_StatusCode
879
UA_Client_readBrowseNameAttribute(UA_Client *client, const UA_NodeId nodeId,
880
0
                                  UA_QualifiedName *out) {
881
0
    return __Client_readAttribute(client, &nodeId, UA_ATTRIBUTEID_BROWSENAME,
882
0
                                  out, &UA_TYPES[UA_TYPES_QUALIFIEDNAME]);
883
0
}
884
885
UA_StatusCode
886
UA_Client_readDisplayNameAttribute(UA_Client *client, const UA_NodeId nodeId,
887
0
                                   UA_LocalizedText *out) {
888
0
    return __Client_readAttribute(client, &nodeId, UA_ATTRIBUTEID_DISPLAYNAME,
889
0
                                  out, &UA_TYPES[UA_TYPES_LOCALIZEDTEXT]);
890
0
}
891
892
UA_StatusCode
893
UA_Client_readDescriptionAttribute(UA_Client *client, const UA_NodeId nodeId,
894
0
                                   UA_LocalizedText *out) {
895
0
    return __Client_readAttribute(client, &nodeId, UA_ATTRIBUTEID_DESCRIPTION,
896
0
                                  out, &UA_TYPES[UA_TYPES_LOCALIZEDTEXT]);
897
0
}
898
899
UA_StatusCode
900
UA_Client_readWriteMaskAttribute(UA_Client *client, const UA_NodeId nodeId,
901
0
                                 UA_UInt32 *out) {
902
0
    return __Client_readAttribute(client, &nodeId, UA_ATTRIBUTEID_WRITEMASK,
903
0
                                  out, &UA_TYPES[UA_TYPES_UINT32]);
904
0
}
905
906
UA_StatusCode
907
UA_Client_readUserWriteMaskAttribute(UA_Client *client, const UA_NodeId nodeId,
908
0
                                     UA_UInt32 *out) {
909
0
    return __Client_readAttribute(client, &nodeId, UA_ATTRIBUTEID_USERWRITEMASK,
910
0
                                  out, &UA_TYPES[UA_TYPES_UINT32]);
911
0
}
912
913
UA_StatusCode
914
UA_Client_readIsAbstractAttribute(UA_Client *client, const UA_NodeId nodeId,
915
0
                                  UA_Boolean *out) {
916
0
    return __Client_readAttribute(client, &nodeId, UA_ATTRIBUTEID_ISABSTRACT,
917
0
                                  out, &UA_TYPES[UA_TYPES_BOOLEAN]);
918
0
}
919
920
UA_StatusCode
921
UA_Client_readSymmetricAttribute(UA_Client *client, const UA_NodeId nodeId,
922
0
                                 UA_Boolean *out) {
923
0
    return __Client_readAttribute(client, &nodeId, UA_ATTRIBUTEID_SYMMETRIC,
924
0
                                  out, &UA_TYPES[UA_TYPES_BOOLEAN]);
925
0
}
926
927
UA_StatusCode
928
UA_Client_readInverseNameAttribute(UA_Client *client, const UA_NodeId nodeId,
929
0
                                   UA_LocalizedText *out) {
930
0
    return __Client_readAttribute(client, &nodeId, UA_ATTRIBUTEID_INVERSENAME,
931
0
                                  out, &UA_TYPES[UA_TYPES_LOCALIZEDTEXT]);
932
0
}
933
934
UA_StatusCode
935
UA_Client_readContainsNoLoopsAttribute(UA_Client *client, const UA_NodeId nodeId,
936
0
                                       UA_Boolean *outContainsNoLoops) {
937
0
    return __Client_readAttribute(client, &nodeId, UA_ATTRIBUTEID_CONTAINSNOLOOPS,
938
0
                                     outContainsNoLoops, &UA_TYPES[UA_TYPES_BOOLEAN]);
939
0
}
940
941
UA_StatusCode
942
UA_Client_readEventNotifierAttribute(UA_Client *client, const UA_NodeId nodeId,
943
0
                                     UA_Byte *out) {
944
0
    return __Client_readAttribute(client, &nodeId, UA_ATTRIBUTEID_EVENTNOTIFIER,
945
0
                                  out, &UA_TYPES[UA_TYPES_BYTE]);
946
0
}
947
948
UA_StatusCode
949
UA_Client_readValueAttribute(UA_Client *client, const UA_NodeId nodeId,
950
0
                             UA_Variant *out) {
951
0
    return __Client_readAttribute(client, &nodeId, UA_ATTRIBUTEID_VALUE,
952
0
                                  out, &UA_TYPES[UA_TYPES_VARIANT]);
953
0
}
954
955
UA_StatusCode
956
UA_Client_readDataTypeAttribute(UA_Client *client, const UA_NodeId nodeId,
957
0
                                UA_NodeId *out) {
958
0
    return __Client_readAttribute(client, &nodeId, UA_ATTRIBUTEID_DATATYPE,
959
0
                                  out, &UA_TYPES[UA_TYPES_NODEID]);
960
0
}
961
962
UA_StatusCode
963
UA_Client_readValueRankAttribute(UA_Client *client, const UA_NodeId nodeId,
964
0
                                 UA_Int32 *out) {
965
0
    return __Client_readAttribute(client, &nodeId, UA_ATTRIBUTEID_VALUERANK,
966
0
                                  out, &UA_TYPES[UA_TYPES_INT32]);
967
0
}
968
969
UA_StatusCode
970
UA_Client_readAccessLevelAttribute(UA_Client *client, const UA_NodeId nodeId,
971
0
                                   UA_Byte *out) {
972
0
    return __Client_readAttribute(client, &nodeId, UA_ATTRIBUTEID_ACCESSLEVEL,
973
0
                                  out, &UA_TYPES[UA_TYPES_BYTE]);
974
0
}
975
976
UA_StatusCode
977
UA_Client_readAccessLevelExAttribute(UA_Client *client, const UA_NodeId nodeId,
978
0
                                     UA_UInt32 *out) {
979
0
    return __Client_readAttribute(client, &nodeId, UA_ATTRIBUTEID_ACCESSLEVELEX,
980
0
                                  out, &UA_TYPES[UA_TYPES_UINT32]);
981
0
}
982
983
UA_StatusCode
984
UA_Client_readUserAccessLevelAttribute(UA_Client *client, const UA_NodeId nodeId,
985
0
                                       UA_Byte *out) {
986
0
    return __Client_readAttribute(client, &nodeId, UA_ATTRIBUTEID_USERACCESSLEVEL,
987
0
                                  out, &UA_TYPES[UA_TYPES_BYTE]);
988
0
}
989
990
UA_StatusCode
991
UA_Client_readMinimumSamplingIntervalAttribute(UA_Client *client, const UA_NodeId nodeId,
992
0
                                               UA_Double *out) {
993
0
    return __Client_readAttribute(client, &nodeId, UA_ATTRIBUTEID_MINIMUMSAMPLINGINTERVAL,
994
0
                                  out, &UA_TYPES[UA_TYPES_DOUBLE]);
995
0
}
996
997
UA_StatusCode
998
UA_Client_readHistorizingAttribute(UA_Client *client, const UA_NodeId nodeId,
999
0
                                   UA_Boolean *out) {
1000
0
    return __Client_readAttribute(client, &nodeId, UA_ATTRIBUTEID_HISTORIZING,
1001
0
                                  out, &UA_TYPES[UA_TYPES_BOOLEAN]);
1002
0
}
1003
1004
UA_StatusCode
1005
UA_Client_readExecutableAttribute(UA_Client *client, const UA_NodeId nodeId,
1006
0
                                  UA_Boolean *out) {
1007
0
    return __Client_readAttribute(client, &nodeId, UA_ATTRIBUTEID_EXECUTABLE,
1008
0
                                  out, &UA_TYPES[UA_TYPES_BOOLEAN]);
1009
0
}
1010
1011
UA_StatusCode
1012
UA_Client_readUserExecutableAttribute(UA_Client *client, const UA_NodeId nodeId,
1013
0
                                      UA_Boolean *out) {
1014
0
    return __Client_readAttribute(client, &nodeId, UA_ATTRIBUTEID_USEREXECUTABLE,
1015
0
                                  out, &UA_TYPES[UA_TYPES_BOOLEAN]);
1016
0
}
1017
1018
UA_StatusCode
1019
UA_Client_readDatatypeDefinitionAttribute(UA_Client* client, const UA_NodeId nodeId,
1020
0
                                          UA_StructureDefinition *out) {
1021
0
    return __Client_readAttribute(client, &nodeId, UA_ATTRIBUTEID_DATATYPEDEFINITION,
1022
0
                                  out, &UA_TYPES[UA_TYPES_STRUCTUREDEFINITION]);
1023
0
}
1024
1025
static UA_StatusCode
1026
processReadArrayDimensionsResult(UA_ReadResponse *response,
1027
                                 UA_UInt32 **outArrayDimensions,
1028
0
                                 size_t *outArrayDimensionsSize) {
1029
0
    UA_StatusCode retval = response->responseHeader.serviceResult;
1030
0
    if(retval != UA_STATUSCODE_GOOD)
1031
0
        return retval;
1032
1033
0
    if(response->resultsSize != 1)
1034
0
        return UA_STATUSCODE_BADUNEXPECTEDERROR;
1035
1036
0
    retval = response->results[0].status;
1037
0
    if(!UA_StatusCode_isEqualTop(retval,UA_STATUSCODE_GOOD))
1038
0
        return retval;
1039
1040
0
    UA_DataValue *res = &response->results[0];
1041
0
    if(!res->hasValue ||
1042
0
       UA_Variant_isScalar(&res->value) ||
1043
0
       res->value.type != &UA_TYPES[UA_TYPES_UINT32])
1044
0
        return UA_STATUSCODE_BADUNEXPECTEDERROR;
1045
1046
    /* Move results */
1047
0
    *outArrayDimensions = (UA_UInt32*)res->value.data;
1048
0
    *outArrayDimensionsSize = res->value.arrayLength;
1049
0
    res->value.data = NULL;
1050
0
    res->value.arrayLength = 0;
1051
0
    return UA_STATUSCODE_GOOD;
1052
0
}
1053
1054
UA_StatusCode
1055
UA_Client_readArrayDimensionsAttribute(UA_Client *client, const UA_NodeId nodeId,
1056
                                       size_t *outArrayDimensionsSize,
1057
0
                                       UA_UInt32 **outArrayDimensions) {
1058
0
    UA_ReadValueId item;
1059
0
    UA_ReadValueId_init(&item);
1060
0
    item.nodeId = nodeId;
1061
0
    item.attributeId = UA_ATTRIBUTEID_ARRAYDIMENSIONS;
1062
0
    UA_ReadRequest request;
1063
0
    UA_ReadRequest_init(&request);
1064
0
    request.nodesToRead = &item;
1065
0
    request.nodesToReadSize = 1;
1066
1067
0
    UA_ReadResponse response = UA_Client_Service_read(client, request);
1068
0
    UA_StatusCode retval = processReadArrayDimensionsResult(&response, outArrayDimensions,
1069
0
                                                            outArrayDimensionsSize);
1070
0
    UA_ReadResponse_clear(&response);
1071
0
    return retval;
1072
0
}
1073
1074
/*********************/
1075
/* Historical Access */
1076
/*********************/
1077
#ifdef UA_ENABLE_HISTORIZING
1078
1079
static UA_HistoryReadResponse
1080
__UA_Client_HistoryRead(UA_Client *client, const UA_NodeId *nodeId,
1081
                        UA_ExtensionObject* details, UA_String indexRange,
1082
                        UA_TimestampsToReturn timestampsToReturn,
1083
0
                        UA_ByteString continuationPoint, UA_Boolean releaseConti) {
1084
1085
0
    UA_HistoryReadValueId item;
1086
0
    UA_HistoryReadValueId_init(&item);
1087
1088
0
    item.nodeId = *nodeId;
1089
0
    item.indexRange = indexRange;
1090
0
    item.continuationPoint = continuationPoint;
1091
0
    item.dataEncoding = UA_QUALIFIEDNAME(0, NULL);
1092
1093
0
    UA_HistoryReadRequest request;
1094
0
    UA_HistoryReadRequest_init(&request);
1095
1096
0
    request.nodesToRead = &item;
1097
0
    request.nodesToReadSize = 1;
1098
0
    request.timestampsToReturn = timestampsToReturn; // Defaults to Source
1099
0
    request.releaseContinuationPoints = releaseConti; // No values are returned, if true
1100
1101
    /* Build ReadDetails */
1102
0
    request.historyReadDetails = *details;
1103
1104
0
    return UA_Client_Service_historyRead(client, request);
1105
0
}
1106
1107
static UA_StatusCode
1108
__UA_Client_HistoryRead_service(UA_Client *client, const UA_NodeId *nodeId,
1109
                                   const UA_HistoricalIteratorCallback callback,
1110
                                   UA_ExtensionObject *details, UA_String indexRange,
1111
                                   UA_TimestampsToReturn timestampsToReturn,
1112
0
                                   void *callbackContext) {
1113
1114
0
    UA_ByteString continuationPoint = UA_BYTESTRING_NULL;
1115
0
    UA_Boolean continuationAvail = false;
1116
0
    UA_Boolean fetchMore = false;
1117
0
    UA_StatusCode retval = UA_STATUSCODE_GOOD;
1118
1119
0
    do {
1120
        /* We release the continuation point, if no more data is requested by the user */
1121
0
        UA_Boolean cleanup = !fetchMore && continuationAvail;
1122
0
        UA_HistoryReadResponse response =
1123
0
            __UA_Client_HistoryRead(client, nodeId, details, indexRange, timestampsToReturn, continuationPoint, cleanup);
1124
1125
0
        if(cleanup) {
1126
0
            retval = response.responseHeader.serviceResult;
1127
0
cleanup:    UA_HistoryReadResponse_clear(&response);
1128
0
            UA_ByteString_clear(&continuationPoint);
1129
0
            return retval;
1130
0
        }
1131
1132
0
        retval = response.responseHeader.serviceResult;
1133
0
        if(retval == UA_STATUSCODE_GOOD) {
1134
0
            if(response.resultsSize == 1)
1135
0
                retval = response.results[0].statusCode;
1136
0
            else
1137
0
                retval = UA_STATUSCODE_BADUNEXPECTEDERROR;
1138
0
        }
1139
0
        if(!UA_StatusCode_isEqualTop(retval,UA_STATUSCODE_GOOD))
1140
0
            goto cleanup;
1141
1142
0
        UA_HistoryReadResult *res = response.results;
1143
1144
        /* Clear old and check / store new continuation point */
1145
0
        UA_ByteString_clear(&continuationPoint);
1146
0
        UA_ByteString_copy(&res->continuationPoint, &continuationPoint);
1147
0
        continuationAvail = !UA_ByteString_equal(&continuationPoint, &UA_BYTESTRING_NULL);
1148
1149
        /* Client callback with possibility to request further values */
1150
0
        fetchMore = callback(client, nodeId, continuationAvail, &res->historyData, callbackContext);
1151
1152
        /* Regular cleanup */
1153
0
        UA_HistoryReadResponse_clear(&response);
1154
0
    } while(continuationAvail);
1155
1156
0
    return retval;
1157
0
}
1158
1159
UA_StatusCode
1160
UA_Client_HistoryRead_events(UA_Client *client, const UA_NodeId *nodeId,
1161
                                const UA_HistoricalIteratorCallback callback,
1162
                                UA_DateTime startTime, UA_DateTime endTime,
1163
                                UA_String indexRange, const UA_EventFilter filter, UA_UInt32 numValuesPerNode,
1164
0
                                UA_TimestampsToReturn timestampsToReturn, void *callbackContext) {
1165
1166
0
    UA_ReadEventDetails details;
1167
0
    UA_ReadEventDetails_init(&details);
1168
0
    details.filter = filter;
1169
1170
    // At least two of the following parameters must be set
1171
0
    details.numValuesPerNode = numValuesPerNode; // 0 = return all / max server is capable of
1172
0
    details.startTime = startTime;
1173
0
    details.endTime = endTime;
1174
1175
0
    UA_ExtensionObject detailsExtensionObject;
1176
0
    UA_ExtensionObject_init(&detailsExtensionObject);
1177
0
    detailsExtensionObject.content.decoded.type = &UA_TYPES[UA_TYPES_READEVENTDETAILS];
1178
0
    detailsExtensionObject.content.decoded.data = &details;
1179
0
    detailsExtensionObject.encoding = UA_EXTENSIONOBJECT_DECODED;
1180
1181
0
    return __UA_Client_HistoryRead_service(client, nodeId, callback, &detailsExtensionObject,
1182
0
                                              indexRange, timestampsToReturn, callbackContext);
1183
0
}
1184
1185
static UA_StatusCode
1186
__UA_Client_HistoryRead_service_rawMod(UA_Client *client, const UA_NodeId *nodeId,
1187
                                          const UA_HistoricalIteratorCallback callback,
1188
                                          UA_DateTime startTime,UA_DateTime endTime,
1189
                                          UA_String indexRange, UA_Boolean returnBounds, UA_UInt32 numValuesPerNode,
1190
                                          UA_Boolean readModified, UA_TimestampsToReturn timestampsToReturn,
1191
0
                                          void *callbackContext) {
1192
1193
0
    UA_ReadRawModifiedDetails details;
1194
0
    UA_ReadRawModifiedDetails_init(&details);
1195
0
    details.isReadModified = readModified; // Return only modified values
1196
0
    details.returnBounds = returnBounds;   // Return values pre / post given range
1197
1198
    // At least two of the following parameters must be set
1199
0
    details.numValuesPerNode = numValuesPerNode;   // 0 = return all / max server is capable of
1200
0
    details.startTime = startTime;
1201
0
    details.endTime = endTime;
1202
1203
0
    UA_ExtensionObject detailsExtensionObject;
1204
0
    UA_ExtensionObject_init(&detailsExtensionObject);
1205
0
    detailsExtensionObject.content.decoded.type = &UA_TYPES[UA_TYPES_READRAWMODIFIEDDETAILS];
1206
0
    detailsExtensionObject.content.decoded.data = &details;
1207
0
    detailsExtensionObject.encoding = UA_EXTENSIONOBJECT_DECODED;
1208
1209
0
    return __UA_Client_HistoryRead_service(client, nodeId, callback,
1210
0
                                              &detailsExtensionObject, indexRange,
1211
0
                                              timestampsToReturn, callbackContext);
1212
0
}
1213
1214
UA_StatusCode
1215
UA_Client_HistoryRead_raw(UA_Client *client, const UA_NodeId *nodeId,
1216
                             const UA_HistoricalIteratorCallback callback,
1217
                             UA_DateTime startTime, UA_DateTime endTime,
1218
                             UA_String indexRange, UA_Boolean returnBounds, UA_UInt32 numValuesPerNode,
1219
0
                             UA_TimestampsToReturn timestampsToReturn, void *callbackContext) {
1220
1221
0
    return __UA_Client_HistoryRead_service_rawMod(client, nodeId, callback, startTime, endTime, indexRange, returnBounds,
1222
0
                                                     numValuesPerNode, false, timestampsToReturn, callbackContext);
1223
0
}
1224
1225
UA_StatusCode
1226
UA_Client_HistoryRead_modified(UA_Client *client, const UA_NodeId *nodeId,
1227
                                  const UA_HistoricalIteratorCallback callback,
1228
                                  UA_DateTime startTime, UA_DateTime endTime,
1229
                                  UA_String indexRange, UA_Boolean returnBounds, UA_UInt32 maxItems,
1230
0
                                  UA_TimestampsToReturn timestampsToReturn, void *callbackContext) {
1231
0
    return __UA_Client_HistoryRead_service_rawMod(client, nodeId, callback, startTime,
1232
0
                                                  endTime, indexRange, returnBounds, maxItems,
1233
0
                                                  true, timestampsToReturn, callbackContext);
1234
0
}
1235
1236
static UA_HistoryUpdateResponse
1237
0
__UA_Client_HistoryUpdate(UA_Client *client, void *details, size_t typeId) {
1238
0
    UA_HistoryUpdateRequest request;
1239
0
    UA_HistoryUpdateRequest_init(&request);
1240
1241
0
    UA_ExtensionObject extension;
1242
0
    UA_ExtensionObject_init(&extension);
1243
0
    request.historyUpdateDetailsSize = 1;
1244
0
    request.historyUpdateDetails = &extension;
1245
1246
0
    extension.encoding = UA_EXTENSIONOBJECT_DECODED;
1247
0
    extension.content.decoded.type = &UA_TYPES[typeId];
1248
0
    extension.content.decoded.data = details;
1249
1250
0
    UA_HistoryUpdateResponse response;
1251
0
    response = UA_Client_Service_historyUpdate(client, request);
1252
0
    return response;
1253
0
}
1254
1255
static UA_StatusCode
1256
__UA_Client_HistoryUpdate_updateData(UA_Client *client, const UA_NodeId *nodeId,
1257
0
                                     UA_PerformUpdateType type, UA_DataValue *value) {
1258
0
    UA_StatusCode ret = UA_STATUSCODE_GOOD;
1259
0
    UA_UpdateDataDetails details;
1260
0
    UA_UpdateDataDetails_init(&details);
1261
1262
0
    details.performInsertReplace = type;
1263
0
    details.updateValuesSize = 1;
1264
0
    details.updateValues = value;
1265
0
    UA_NodeId_copy(nodeId, &details.nodeId);
1266
1267
0
    UA_HistoryUpdateResponse response;
1268
0
    response = __UA_Client_HistoryUpdate(client, &details, UA_TYPES_UPDATEDATADETAILS);
1269
0
    if(response.responseHeader.serviceResult != UA_STATUSCODE_GOOD) {
1270
0
        ret = response.responseHeader.serviceResult;
1271
0
        goto cleanup;
1272
0
    }
1273
0
    if(response.resultsSize != 1 || response.results[0].operationResultsSize != 1) {
1274
0
        ret = UA_STATUSCODE_BADUNEXPECTEDERROR;
1275
0
        goto cleanup;
1276
0
    }
1277
0
    if(response.results[0].statusCode != UA_STATUSCODE_GOOD) {
1278
0
        ret = response.results[0].statusCode;
1279
0
        goto cleanup;
1280
0
    }
1281
0
    ret = response.results[0].operationResults[0];
1282
0
cleanup:
1283
0
    UA_HistoryUpdateResponse_clear(&response);
1284
0
    UA_NodeId_clear(&details.nodeId);
1285
0
    return ret;
1286
0
}
1287
1288
UA_StatusCode
1289
UA_Client_HistoryUpdate_insert(UA_Client *client, const UA_NodeId *nodeId,
1290
0
                               UA_DataValue *value) {
1291
0
    return __UA_Client_HistoryUpdate_updateData(client, nodeId,
1292
0
                                                UA_PERFORMUPDATETYPE_INSERT,
1293
0
                                                value);
1294
0
}
1295
1296
UA_StatusCode
1297
UA_Client_HistoryUpdate_replace(UA_Client *client, const UA_NodeId *nodeId,
1298
0
                                UA_DataValue *value) {
1299
0
    return __UA_Client_HistoryUpdate_updateData(client, nodeId,
1300
0
                                                UA_PERFORMUPDATETYPE_REPLACE,
1301
0
                                                value);
1302
0
}
1303
1304
UA_StatusCode
1305
UA_Client_HistoryUpdate_update(UA_Client *client, const UA_NodeId *nodeId,
1306
0
                               UA_DataValue *value) {
1307
0
    return __UA_Client_HistoryUpdate_updateData(client, nodeId,
1308
0
                                                UA_PERFORMUPDATETYPE_UPDATE,
1309
0
                                                value);
1310
0
}
1311
1312
UA_StatusCode
1313
UA_Client_HistoryUpdate_deleteRaw(UA_Client *client, const UA_NodeId *nodeId,
1314
0
                                  UA_DateTime startTimestamp, UA_DateTime endTimestamp) {
1315
0
    UA_DeleteRawModifiedDetails details;
1316
0
    UA_DeleteRawModifiedDetails_init(&details);
1317
0
    details.isDeleteModified = false;
1318
0
    details.startTime = startTimestamp;
1319
0
    details.endTime = endTimestamp;
1320
0
    UA_NodeId_copy(nodeId, &details.nodeId);
1321
1322
0
    UA_StatusCode ret = UA_STATUSCODE_GOOD;
1323
0
    UA_HistoryUpdateResponse response;
1324
0
    response = __UA_Client_HistoryUpdate(client, &details, UA_TYPES_DELETERAWMODIFIEDDETAILS);
1325
0
    if(response.responseHeader.serviceResult != UA_STATUSCODE_GOOD) {
1326
0
        ret = response.responseHeader.serviceResult;
1327
0
        goto cleanup;
1328
0
    }
1329
0
    if(response.resultsSize != 1) {
1330
0
        ret = UA_STATUSCODE_BADUNEXPECTEDERROR;
1331
0
        goto cleanup;
1332
0
    }
1333
1334
0
    ret = response.results[0].statusCode;
1335
1336
0
cleanup:
1337
0
    UA_HistoryUpdateResponse_clear(&response);
1338
0
    UA_NodeId_clear(&details.nodeId);
1339
0
    return ret;
1340
0
}
1341
1342
#endif
1343
1344
/*******************/
1345
/* Async Functions */
1346
/*******************/
1347
1348
static UA_StatusCode
1349
__UA_Client_writeAttribute_async(UA_Client *client, const UA_NodeId *nodeId,
1350
                                 UA_AttributeId attributeId, const void *in,
1351
                                 const UA_DataType *inDataType,
1352
                                 UA_ClientAsyncServiceCallback callback,
1353
0
                                 void *userdata, UA_UInt32 *reqId) {
1354
0
    if(!in)
1355
0
        return UA_STATUSCODE_BADTYPEMISMATCH;
1356
1357
0
    UA_WriteValue wValue;
1358
0
    UA_WriteValue_init(&wValue);
1359
0
    wValue.nodeId = *nodeId;
1360
0
    wValue.attributeId = attributeId;
1361
0
    if(attributeId == UA_ATTRIBUTEID_VALUE)
1362
0
        wValue.value.value = *(const UA_Variant*) in;
1363
0
    else
1364
        /* hack. is never written into. */
1365
0
        UA_Variant_setScalar(&wValue.value.value, (void*) (uintptr_t) in,
1366
0
                inDataType);
1367
0
    wValue.value.hasValue = true;
1368
0
    UA_WriteRequest wReq;
1369
0
    UA_WriteRequest_init(&wReq);
1370
0
    wReq.nodesToWrite = &wValue;
1371
0
    wReq.nodesToWriteSize = 1;
1372
1373
0
    return __UA_Client_AsyncService(client, &wReq,
1374
0
                                    &UA_TYPES[UA_TYPES_WRITEREQUEST], callback,
1375
0
                                    &UA_TYPES[UA_TYPES_WRITERESPONSE], userdata, reqId);
1376
0
}
1377
1378
UA_StatusCode
1379
UA_Client_call_async(UA_Client *client, const UA_NodeId objectId,
1380
                     const UA_NodeId methodId, size_t inputSize,
1381
                     const UA_Variant *input,
1382
                     UA_ClientAsyncCallCallback callback,
1383
0
                     void *userdata, UA_UInt32 *reqId) {
1384
0
    UA_CallRequest request;
1385
0
    UA_CallRequest_init(&request);
1386
0
    UA_CallMethodRequest item;
1387
0
    UA_CallMethodRequest_init(&item);
1388
0
    item.objectId = objectId;
1389
0
    item.methodId = methodId;
1390
0
    item.inputArguments = (UA_Variant *)(uintptr_t)input; /* cast const */
1391
0
    item.inputArgumentsSize = inputSize;
1392
0
    request.methodsToCall = &item;
1393
0
    request.methodsToCallSize = 1;
1394
0
    return __UA_Client_AsyncService(client, &request,
1395
0
            &UA_TYPES[UA_TYPES_CALLREQUEST], (UA_ClientAsyncServiceCallback)callback,
1396
0
            &UA_TYPES[UA_TYPES_CALLRESPONSE], userdata, reqId);
1397
0
}
1398
1399
/*************************/
1400
/* Read Single Attribute */
1401
/*************************/
1402
1403
typedef struct {
1404
    UA_ClientAsyncOperationCallback userCallback;
1405
    void *userContext;
1406
    const UA_DataType *resultType; /* DataValue -> Value attribute,
1407
                                    * Variant -> ArrayDimensions attribute */
1408
} UA_AttributeReadContext;
1409
1410
static void
1411
AttributeReadCallback(UA_Client *client, void *userdata,
1412
0
                      UA_UInt32 requestId, UA_ReadResponse *rr) {
1413
0
    UA_AttributeReadContext *ctx = (UA_AttributeReadContext*)userdata;
1414
0
    UA_LOG_DEBUG(UA_Client_getConfig(client)->logging, UA_LOGCATEGORY_CLIENT,
1415
0
                "Async read response for request %" PRIu32, requestId);
1416
1417
0
    UA_DataValue *dv = NULL;
1418
1419
    /* Check the ServiceResult */
1420
0
    UA_StatusCode res = rr->responseHeader.serviceResult;
1421
0
    if(res != UA_STATUSCODE_GOOD)
1422
0
        goto finish;
1423
1424
    /* Check result array size */
1425
0
    if(rr->resultsSize != 1) {
1426
0
        res = UA_STATUSCODE_BADINTERNALERROR;
1427
0
        goto finish;
1428
0
    }
1429
1430
    /* A Value attribute */
1431
0
    dv = &rr->results[0];
1432
0
    if(ctx->resultType == &UA_TYPES[UA_TYPES_DATAVALUE]) {
1433
0
        ctx->userCallback(client, ctx->userContext, requestId,
1434
0
                          UA_STATUSCODE_GOOD, dv);
1435
0
        goto finish;
1436
0
    }
1437
1438
    /* An ArrayDimensions attribute. Has to be an array of UInt32. */
1439
0
    if(ctx->resultType == &UA_TYPES[UA_TYPES_VARIANT]) {
1440
0
        if(dv->hasValue &&
1441
0
           UA_Variant_hasArrayType(&dv->value, &UA_TYPES[UA_TYPES_UINT32])) {
1442
0
            ctx->userCallback(client, ctx->userContext, requestId,
1443
0
                              UA_STATUSCODE_GOOD, &dv->value);
1444
0
        } else {
1445
0
            res = UA_STATUSCODE_BADINTERNALERROR;
1446
0
        }
1447
0
        goto finish;
1448
0
    }
1449
1450
    /* Check we have a value */
1451
0
    if(!dv->hasValue) {
1452
0
        res = UA_STATUSCODE_BADINTERNALERROR;
1453
0
        goto finish;
1454
0
    }
1455
1456
    /* Check the type. Try to adjust "in situ" if no match. */
1457
0
    if(!UA_Variant_hasScalarType(&dv->value, ctx->resultType)) {
1458
        /* Remember the old pointer, adjustType can "unwrap" a type but won't
1459
         * free the wrapper. Because the server code still keeps the wrapper. */
1460
0
        void *oldVal = dv->value.data;
1461
0
        adjustType(&dv->value, ctx->resultType);
1462
0
        if(dv->value.data != oldVal)
1463
0
            UA_free(oldVal);
1464
0
        if(!UA_Variant_hasScalarType(&dv->value, ctx->resultType)) {
1465
0
            res = UA_STATUSCODE_BADINTERNALERROR;
1466
0
            goto finish;
1467
0
        }
1468
0
    }
1469
1470
    /* Callback into userland */
1471
0
    ctx->userCallback(client, ctx->userContext, requestId,
1472
0
                      UA_STATUSCODE_GOOD, dv->value.data);
1473
1474
0
 finish:
1475
0
    if(res != UA_STATUSCODE_GOOD)
1476
0
        ctx->userCallback(client, ctx->userContext, requestId, res, NULL);
1477
0
    UA_free(ctx);
1478
0
}
1479
1480
static UA_StatusCode
1481
readAttribute_async(UA_Client *client, const UA_ReadValueId *rvi,
1482
                    UA_TimestampsToReturn timestampsToReturn,
1483
                    const UA_DataType *resultType, /* For the specialized reads */
1484
                    UA_ClientAsyncOperationCallback callback,
1485
0
                    void *userdata, UA_UInt32 *requestId) {
1486
0
    UA_AttributeReadContext *ctx = (UA_AttributeReadContext*)
1487
0
        UA_malloc(sizeof(UA_AttributeReadContext));
1488
0
    if(!ctx)
1489
0
        return UA_STATUSCODE_BADOUTOFMEMORY;
1490
1491
0
    ctx->userCallback = callback;
1492
0
    ctx->userContext = userdata;
1493
0
    ctx->resultType = resultType;
1494
1495
0
    UA_ReadRequest request;
1496
0
    UA_ReadRequest_init(&request);
1497
0
    request.nodesToRead = (UA_ReadValueId*)(uintptr_t)rvi; /* hack, treated as const */
1498
0
    request.nodesToReadSize = 1;
1499
0
    request.timestampsToReturn = timestampsToReturn;
1500
1501
0
    UA_StatusCode res =
1502
0
        __UA_Client_AsyncService(client, &request, &UA_TYPES[UA_TYPES_READREQUEST],
1503
0
                                 (UA_ClientAsyncServiceCallback)AttributeReadCallback,
1504
0
                                 &UA_TYPES[UA_TYPES_READRESPONSE], ctx, requestId);
1505
0
    if(res != UA_STATUSCODE_GOOD)
1506
0
        UA_free(ctx);
1507
0
    return res;
1508
0
}
1509
1510
UA_StatusCode
1511
UA_Client_readAttribute_async(UA_Client *client, const UA_ReadValueId *rvi,
1512
                              UA_TimestampsToReturn timestampsToReturn,
1513
                              UA_ClientAsyncReadAttributeCallback callback,
1514
0
                              void *userdata, UA_UInt32 *requestId) {
1515
0
    return readAttribute_async(client, rvi, timestampsToReturn,
1516
0
                               &UA_TYPES[UA_TYPES_DATAVALUE], /* special handling */
1517
0
                               (UA_ClientAsyncOperationCallback)callback,
1518
0
                               userdata, requestId);
1519
0
}
1520
1521
/* Helper to keep the code short */
1522
static UA_StatusCode
1523
readAttribute_simpleAsync(UA_Client *client, const UA_NodeId *nodeId,
1524
                          UA_AttributeId attributeId, const UA_DataType *resultType,
1525
                          UA_ClientAsyncOperationCallback callback,
1526
0
                          void *userdata, UA_UInt32 *requestId) {
1527
0
    UA_ReadValueId rvi;
1528
0
    UA_ReadValueId_init(&rvi);
1529
0
    rvi.nodeId = *nodeId;
1530
0
    rvi.attributeId = attributeId;
1531
0
    return readAttribute_async(client, &rvi, UA_TIMESTAMPSTORETURN_NEITHER,
1532
0
                               resultType, callback, userdata, requestId);
1533
0
}
1534
1535
UA_StatusCode
1536
UA_Client_readValueAttribute_async(UA_Client *client, const UA_NodeId nodeId,
1537
                                   UA_ClientAsyncReadValueAttributeCallback callback,
1538
0
                                   void *userdata, UA_UInt32 *requestId) {
1539
0
    return readAttribute_simpleAsync(client, &nodeId, UA_ATTRIBUTEID_VALUE,
1540
0
                                     &UA_TYPES[UA_TYPES_DATAVALUE], /* special hndling */
1541
0
                                     (UA_ClientAsyncOperationCallback)callback,
1542
0
                                     userdata, requestId);
1543
0
}
1544
1545
UA_StatusCode
1546
UA_Client_readDataTypeAttribute_async(UA_Client *client, const UA_NodeId nodeId,
1547
                                      UA_ClientAsyncReadDataTypeAttributeCallback callback,
1548
0
                                      void *userdata, UA_UInt32 *requestId) {
1549
0
    return readAttribute_simpleAsync(client, &nodeId, UA_ATTRIBUTEID_DATATYPE,
1550
0
                                     &UA_TYPES[UA_TYPES_NODEID],
1551
0
                                     (UA_ClientAsyncOperationCallback)callback,
1552
0
                                     userdata, requestId);
1553
0
}
1554
1555
UA_StatusCode
1556
UA_Client_readArrayDimensionsAttribute_async(UA_Client *client, const UA_NodeId nodeId,
1557
                                             UA_ClientReadArrayDimensionsAttributeCallback callback,
1558
0
                                             void *userdata, UA_UInt32 *requestId) {
1559
0
    return readAttribute_simpleAsync(client, &nodeId, UA_ATTRIBUTEID_ARRAYDIMENSIONS,
1560
0
                                     &UA_TYPES[UA_TYPES_VARIANT], /* special handling */
1561
0
                                     (UA_ClientAsyncOperationCallback)callback,
1562
0
                                     userdata, requestId);
1563
0
}
1564
1565
UA_StatusCode
1566
UA_Client_readNodeClassAttribute_async(UA_Client *client, const UA_NodeId nodeId,
1567
                                       UA_ClientAsyncReadNodeClassAttributeCallback callback,
1568
0
                                       void *userdata, UA_UInt32 *requestId) {
1569
0
    return readAttribute_simpleAsync(client, &nodeId, UA_ATTRIBUTEID_NODECLASS,
1570
0
                                     &UA_TYPES[UA_TYPES_NODECLASS],
1571
0
                                     (UA_ClientAsyncOperationCallback)callback,
1572
0
                                     userdata, requestId);
1573
0
}
1574
1575
UA_StatusCode
1576
UA_Client_readBrowseNameAttribute_async(UA_Client *client, const UA_NodeId nodeId,
1577
                                        UA_ClientAsyncReadBrowseNameAttributeCallback callback,
1578
0
                                        void *userdata, UA_UInt32 *requestId) {
1579
0
    return readAttribute_simpleAsync(client, &nodeId, UA_ATTRIBUTEID_BROWSENAME,
1580
0
                                     &UA_TYPES[UA_TYPES_QUALIFIEDNAME],
1581
0
                                     (UA_ClientAsyncOperationCallback)callback,
1582
0
                                     userdata, requestId);
1583
0
}
1584
1585
UA_StatusCode
1586
UA_Client_readDisplayNameAttribute_async(UA_Client *client, const UA_NodeId nodeId,
1587
                                         UA_ClientAsyncReadDisplayNameAttributeCallback callback,
1588
0
                                         void *userdata, UA_UInt32 *requestId) {
1589
0
    return readAttribute_simpleAsync(client, &nodeId, UA_ATTRIBUTEID_DISPLAYNAME,
1590
0
                                     &UA_TYPES[UA_TYPES_LOCALIZEDTEXT],
1591
0
                                     (UA_ClientAsyncOperationCallback)callback,
1592
0
                                     userdata, requestId);
1593
0
}
1594
1595
UA_StatusCode
1596
UA_Client_readDescriptionAttribute_async(UA_Client *client, const UA_NodeId nodeId,
1597
                                         UA_ClientAsyncReadDescriptionAttributeCallback callback,
1598
0
                                         void *userdata, UA_UInt32 *requestId) {
1599
0
    return readAttribute_simpleAsync(client, &nodeId, UA_ATTRIBUTEID_DESCRIPTION,
1600
0
                                     &UA_TYPES[UA_TYPES_LOCALIZEDTEXT],
1601
0
                                     (UA_ClientAsyncOperationCallback)callback,
1602
0
                                     userdata, requestId);
1603
0
}
1604
1605
UA_StatusCode
1606
UA_Client_readWriteMaskAttribute_async(UA_Client *client, const UA_NodeId nodeId,
1607
                                       UA_ClientAsyncReadWriteMaskAttributeCallback callback,
1608
0
                                       void *userdata, UA_UInt32 *requestId) {
1609
0
    return readAttribute_simpleAsync(client, &nodeId, UA_ATTRIBUTEID_WRITEMASK,
1610
0
                                     &UA_TYPES[UA_TYPES_UINT32],
1611
0
                                     (UA_ClientAsyncOperationCallback)callback,
1612
0
                                     userdata, requestId);
1613
0
}
1614
1615
UA_StatusCode UA_EXPORT
1616
UA_Client_readUserWriteMaskAttribute_async(UA_Client *client, const UA_NodeId nodeId,
1617
                                           UA_ClientAsyncReadUserWriteMaskAttributeCallback callback,
1618
0
                                           void *userdata, UA_UInt32 *requestId) {
1619
0
    return readAttribute_simpleAsync(client, &nodeId, UA_ATTRIBUTEID_USERWRITEMASK,
1620
0
                                     &UA_TYPES[UA_TYPES_UINT32],
1621
0
                                     (UA_ClientAsyncOperationCallback)callback,
1622
0
                                     userdata, requestId);
1623
0
}
1624
1625
UA_StatusCode
1626
UA_Client_readIsAbstractAttribute_async(UA_Client *client, const UA_NodeId nodeId,
1627
                                        UA_ClientAsyncReadIsAbstractAttributeCallback callback,
1628
0
                                        void *userdata, UA_UInt32 *requestId) {
1629
0
    return readAttribute_simpleAsync(client, &nodeId, UA_ATTRIBUTEID_ISABSTRACT,
1630
0
                                     &UA_TYPES[UA_TYPES_BOOLEAN],
1631
0
                                     (UA_ClientAsyncOperationCallback)callback,
1632
0
                                     userdata, requestId);
1633
0
}
1634
1635
UA_StatusCode
1636
UA_Client_readSymmetricAttribute_async(UA_Client *client, const UA_NodeId nodeId,
1637
                                       UA_ClientAsyncReadSymmetricAttributeCallback callback,
1638
0
                                       void *userdata, UA_UInt32 *requestId) {
1639
0
    return readAttribute_simpleAsync(client, &nodeId, UA_ATTRIBUTEID_SYMMETRIC,
1640
0
                                     &UA_TYPES[UA_TYPES_BOOLEAN],
1641
0
                                     (UA_ClientAsyncOperationCallback)callback,
1642
0
                                     userdata, requestId);
1643
0
}
1644
1645
UA_StatusCode
1646
UA_Client_readInverseNameAttribute_async(UA_Client *client, const UA_NodeId nodeId,
1647
                                         UA_ClientAsyncReadInverseNameAttributeCallback callback,
1648
0
                                         void *userdata, UA_UInt32 *requestId) {
1649
0
    return readAttribute_simpleAsync(client, &nodeId, UA_ATTRIBUTEID_INVERSENAME,
1650
0
                                     &UA_TYPES[UA_TYPES_LOCALIZEDTEXT],
1651
0
                                     (UA_ClientAsyncOperationCallback)callback,
1652
0
                                     userdata, requestId);
1653
0
}
1654
1655
UA_StatusCode
1656
UA_Client_readContainsNoLoopsAttribute_async(UA_Client *client, const UA_NodeId nodeId,
1657
                                             UA_ClientAsyncReadContainsNoLoopsAttributeCallback callback,
1658
0
                                             void *userdata, UA_UInt32 *requestId) {
1659
0
    return readAttribute_simpleAsync(client, &nodeId, UA_ATTRIBUTEID_CONTAINSNOLOOPS,
1660
0
                                     &UA_TYPES[UA_TYPES_BOOLEAN],
1661
0
                                     (UA_ClientAsyncOperationCallback)callback,
1662
0
                                     userdata, requestId);
1663
0
}
1664
1665
UA_StatusCode
1666
UA_Client_readEventNotifierAttribute_async(UA_Client *client, const UA_NodeId nodeId,
1667
                                           UA_ClientAsyncReadEventNotifierAttributeCallback callback,
1668
0
                                           void *userdata, UA_UInt32 *requestId) {
1669
0
    return readAttribute_simpleAsync(client, &nodeId, UA_ATTRIBUTEID_EVENTNOTIFIER,
1670
0
                                     &UA_TYPES[UA_TYPES_BYTE],
1671
0
                                     (UA_ClientAsyncOperationCallback)callback,
1672
0
                                     userdata, requestId);
1673
0
}
1674
1675
UA_StatusCode
1676
UA_Client_readValueRankAttribute_async(UA_Client *client, const UA_NodeId nodeId,
1677
                                       UA_ClientAsyncReadValueRankAttributeCallback callback,
1678
0
                                       void *userdata, UA_UInt32 *requestId) {
1679
0
    return readAttribute_simpleAsync(client, &nodeId, UA_ATTRIBUTEID_VALUERANK,
1680
0
                                     &UA_TYPES[UA_TYPES_INT32],
1681
0
                                     (UA_ClientAsyncOperationCallback)callback,
1682
0
                                     userdata, requestId);
1683
0
}
1684
1685
UA_StatusCode
1686
UA_Client_readAccessLevelAttribute_async(UA_Client *client, const UA_NodeId nodeId,
1687
                                         UA_ClientAsyncReadAccessLevelAttributeCallback callback,
1688
0
                                         void *userdata, UA_UInt32 *requestId) {
1689
0
    return readAttribute_simpleAsync(client, &nodeId, UA_ATTRIBUTEID_ACCESSLEVEL,
1690
0
                                     &UA_TYPES[UA_TYPES_BYTE],
1691
0
                                     (UA_ClientAsyncOperationCallback)callback,
1692
0
                                     userdata, requestId);
1693
0
}
1694
1695
UA_StatusCode
1696
UA_Client_readAccessLevelExAttribute_async(UA_Client *client, const UA_NodeId nodeId,
1697
                                           UA_ClientAsyncReadAccessLevelExAttributeCallback callback,
1698
0
                                           void *userdata, UA_UInt32 *requestId) {
1699
0
    return readAttribute_simpleAsync(client, &nodeId, UA_ATTRIBUTEID_ACCESSLEVELEX,
1700
0
                                     &UA_TYPES[UA_TYPES_UINT32],
1701
0
                                     (UA_ClientAsyncOperationCallback)callback,
1702
0
                                     userdata, requestId);
1703
0
}
1704
1705
UA_StatusCode
1706
UA_Client_readUserAccessLevelAttribute_async(UA_Client *client, const UA_NodeId nodeId,
1707
                                             UA_ClientAsyncReadUserAccessLevelAttributeCallback callback,
1708
0
                                             void *userdata, UA_UInt32 *requestId) {
1709
0
    return readAttribute_simpleAsync(client, &nodeId, UA_ATTRIBUTEID_USERACCESSLEVEL,
1710
0
                                     &UA_TYPES[UA_TYPES_BYTE],
1711
0
                                     (UA_ClientAsyncOperationCallback)callback,
1712
0
                                     userdata, requestId);
1713
0
}
1714
1715
UA_StatusCode
1716
UA_Client_readMinimumSamplingIntervalAttribute_async(UA_Client *client, const UA_NodeId nodeId,
1717
                                                     UA_ClientAsyncReadMinimumSamplingIntervalAttributeCallback callback,
1718
0
                                                     void *userdata, UA_UInt32 *requestId) {
1719
0
    return readAttribute_simpleAsync(client, &nodeId, UA_ATTRIBUTEID_MINIMUMSAMPLINGINTERVAL,
1720
0
                                     &UA_TYPES[UA_TYPES_DOUBLE],
1721
0
                                     (UA_ClientAsyncOperationCallback)callback,
1722
0
                                     userdata, requestId);
1723
0
}
1724
1725
UA_StatusCode
1726
UA_Client_readHistorizingAttribute_async(UA_Client *client, const UA_NodeId nodeId,
1727
                                         UA_ClientAsyncReadHistorizingAttributeCallback callback,
1728
0
                                         void *userdata, UA_UInt32 *requestId) {
1729
0
    return readAttribute_simpleAsync(client, &nodeId, UA_ATTRIBUTEID_HISTORIZING,
1730
0
                                     &UA_TYPES[UA_TYPES_BOOLEAN],
1731
0
                                     (UA_ClientAsyncOperationCallback)callback,
1732
0
                                     userdata, requestId);
1733
0
}
1734
1735
UA_StatusCode
1736
UA_Client_readExecutableAttribute_async(UA_Client *client, const UA_NodeId nodeId,
1737
                                        UA_ClientAsyncReadExecutableAttributeCallback callback,
1738
0
                                        void *userdata, UA_UInt32 *requestId) {
1739
0
    return readAttribute_simpleAsync(client, &nodeId, UA_ATTRIBUTEID_EXECUTABLE,
1740
0
                                     &UA_TYPES[UA_TYPES_BOOLEAN],
1741
0
                                     (UA_ClientAsyncOperationCallback)callback,
1742
0
                                     userdata, requestId);
1743
0
}
1744
1745
UA_StatusCode
1746
UA_Client_readUserExecutableAttribute_async(UA_Client *client, const UA_NodeId nodeId,
1747
                                            UA_ClientAsyncReadUserExecutableAttributeCallback callback,
1748
0
                                            void *userdata, UA_UInt32 *requestId) {
1749
0
    return readAttribute_simpleAsync(client, &nodeId, UA_ATTRIBUTEID_USEREXECUTABLE,
1750
0
                                     &UA_TYPES[UA_TYPES_BOOLEAN],
1751
0
                                     (UA_ClientAsyncOperationCallback)callback,
1752
0
                                     userdata, requestId);
1753
0
}
1754
1755
static UA_StatusCode
1756
__UA_Client_addNode_async(UA_Client *client, const UA_NodeClass nodeClass,
1757
                          const UA_NodeId requestedNewNodeId, const UA_NodeId parentNodeId,
1758
                          const UA_NodeId referenceTypeId, const UA_QualifiedName browseName,
1759
                          const UA_NodeId typeDefinition, const UA_NodeAttributes *attr,
1760
                          const UA_DataType *attributeType, UA_NodeId *outNewNodeId,
1761
                          UA_ClientAsyncServiceCallback callback, void *userdata,
1762
0
                          UA_UInt32 *reqId) {
1763
0
    UA_AddNodesRequest request;
1764
0
    UA_AddNodesRequest_init(&request);
1765
0
    UA_AddNodesItem item;
1766
0
    UA_AddNodesItem_init(&item);
1767
0
    item.parentNodeId.nodeId = parentNodeId;
1768
0
    item.referenceTypeId = referenceTypeId;
1769
0
    item.requestedNewNodeId.nodeId = requestedNewNodeId;
1770
0
    item.browseName = browseName;
1771
0
    item.nodeClass = nodeClass;
1772
0
    item.typeDefinition.nodeId = typeDefinition;
1773
0
    item.nodeAttributes.encoding = UA_EXTENSIONOBJECT_DECODED_NODELETE;
1774
0
    item.nodeAttributes.content.decoded.type = attributeType;
1775
0
    item.nodeAttributes.content.decoded.data = (void*) (uintptr_t) attr; // hack. is not written into.
1776
0
    request.nodesToAdd = &item;
1777
0
    request.nodesToAddSize = 1;
1778
1779
0
    return __UA_Client_AsyncService(client, &request,
1780
0
            &UA_TYPES[UA_TYPES_ADDNODESREQUEST], callback,
1781
0
            &UA_TYPES[UA_TYPES_ADDNODESRESPONSE], userdata, reqId);
1782
1783
0
}
1784
1785
UA_StatusCode
1786
UA_Client_addVariableNode_async(UA_Client *client, const UA_NodeId requestedNewNodeId,
1787
                                const UA_NodeId parentNodeId, const UA_NodeId referenceTypeId,
1788
                                const UA_QualifiedName browseName, const UA_NodeId typeDefinition,
1789
                                const UA_VariableAttributes attr, UA_NodeId *outNewNodeId,
1790
                                UA_ClientAsyncAddNodesCallback callback, void *userdata,
1791
0
                                UA_UInt32 *reqId) {
1792
0
    return __UA_Client_addNode_async(client, UA_NODECLASS_VARIABLE, requestedNewNodeId, parentNodeId,
1793
0
                                     referenceTypeId, browseName, typeDefinition, (const UA_NodeAttributes *)&attr,
1794
0
                                     &UA_TYPES[UA_TYPES_VARIABLEATTRIBUTES], outNewNodeId,
1795
0
                                     (UA_ClientAsyncServiceCallback)callback, userdata, reqId);
1796
0
}
1797
1798
UA_StatusCode
1799
UA_Client_addVariableTypeNode_async(UA_Client *client, const UA_NodeId requestedNewNodeId,
1800
                                    const UA_NodeId parentNodeId, const UA_NodeId referenceTypeId,
1801
                                    const UA_QualifiedName browseName, const UA_VariableTypeAttributes attr,
1802
                                    UA_NodeId *outNewNodeId, UA_ClientAsyncAddNodesCallback callback,
1803
0
                                    void *userdata, UA_UInt32 *reqId) {
1804
0
    return __UA_Client_addNode_async(client, UA_NODECLASS_VARIABLETYPE, requestedNewNodeId, parentNodeId,
1805
0
                                     referenceTypeId, browseName, UA_NODEID_NULL, (const UA_NodeAttributes *)&attr,
1806
0
                                     &UA_TYPES[UA_TYPES_VARIABLETYPEATTRIBUTES], outNewNodeId,
1807
0
                                     (UA_ClientAsyncServiceCallback)callback, userdata, reqId);
1808
0
}
1809
1810
UA_StatusCode
1811
UA_Client_addObjectNode_async(UA_Client *client, const UA_NodeId requestedNewNodeId,
1812
                              const UA_NodeId parentNodeId, const UA_NodeId referenceTypeId,
1813
                              const UA_QualifiedName browseName, const UA_NodeId typeDefinition,
1814
                              const UA_ObjectAttributes attr, UA_NodeId *outNewNodeId,
1815
                              UA_ClientAsyncAddNodesCallback callback, void *userdata,
1816
0
                              UA_UInt32 *reqId) {
1817
0
    return __UA_Client_addNode_async(client, UA_NODECLASS_OBJECT, requestedNewNodeId, parentNodeId,
1818
0
                                     referenceTypeId, browseName, typeDefinition, (const UA_NodeAttributes *)&attr,
1819
0
                                     &UA_TYPES[UA_TYPES_OBJECTATTRIBUTES], outNewNodeId,
1820
0
                                     (UA_ClientAsyncServiceCallback)callback, userdata, reqId);
1821
0
}
1822
1823
UA_StatusCode
1824
UA_Client_addObjectTypeNode_async(UA_Client *client, const UA_NodeId requestedNewNodeId,
1825
                                  const UA_NodeId parentNodeId, const UA_NodeId referenceTypeId,
1826
                                  const UA_QualifiedName browseName, const UA_ObjectTypeAttributes attr,
1827
                                  UA_NodeId *outNewNodeId, UA_ClientAsyncAddNodesCallback callback,
1828
0
                                  void *userdata, UA_UInt32 *reqId) {
1829
0
    return __UA_Client_addNode_async(client, UA_NODECLASS_OBJECTTYPE, requestedNewNodeId, parentNodeId,
1830
0
                                     referenceTypeId, browseName, UA_NODEID_NULL, (const UA_NodeAttributes *)&attr,
1831
0
                                     &UA_TYPES[UA_TYPES_OBJECTTYPEATTRIBUTES], outNewNodeId,
1832
0
                                     (UA_ClientAsyncServiceCallback)callback, userdata, reqId);
1833
0
}
1834
1835
UA_StatusCode
1836
UA_Client_addViewNode_async(UA_Client *client, const UA_NodeId requestedNewNodeId,
1837
                            const UA_NodeId parentNodeId, const UA_NodeId referenceTypeId,
1838
                            const UA_QualifiedName browseName, const UA_ViewAttributes attr,
1839
                            UA_NodeId *outNewNodeId, UA_ClientAsyncAddNodesCallback callback,
1840
0
                            void *userdata, UA_UInt32 *reqId) {
1841
0
    return __UA_Client_addNode_async(client, UA_NODECLASS_VIEW, requestedNewNodeId, parentNodeId,
1842
0
                                     referenceTypeId, browseName, UA_NODEID_NULL, (const UA_NodeAttributes *)&attr,
1843
0
                                     &UA_TYPES[UA_TYPES_VIEWATTRIBUTES], outNewNodeId,
1844
0
                                     (UA_ClientAsyncServiceCallback)callback, userdata, reqId);
1845
0
}
1846
1847
UA_StatusCode
1848
UA_Client_addReferenceTypeNode_async(UA_Client *client, const UA_NodeId requestedNewNodeId,
1849
                                     const UA_NodeId parentNodeId, const UA_NodeId referenceTypeId,
1850
                                     const UA_QualifiedName browseName, const UA_ReferenceTypeAttributes attr,
1851
                                     UA_NodeId *outNewNodeId, UA_ClientAsyncAddNodesCallback callback,
1852
0
                                     void *userdata, UA_UInt32 *reqId) {
1853
0
    return __UA_Client_addNode_async(client, UA_NODECLASS_REFERENCETYPE, requestedNewNodeId, parentNodeId,
1854
0
                                     referenceTypeId, browseName, UA_NODEID_NULL,
1855
0
                                     (const UA_NodeAttributes *)&attr,
1856
0
                                     &UA_TYPES[UA_TYPES_REFERENCETYPEATTRIBUTES], outNewNodeId,
1857
0
                                     (UA_ClientAsyncServiceCallback)callback, userdata, reqId);
1858
0
}
1859
1860
UA_StatusCode
1861
UA_Client_addDataTypeNode_async(UA_Client *client, const UA_NodeId requestedNewNodeId,
1862
                                const UA_NodeId parentNodeId, const UA_NodeId referenceTypeId,
1863
                                const UA_QualifiedName browseName, const UA_DataTypeAttributes attr,
1864
                                UA_NodeId *outNewNodeId, UA_ClientAsyncAddNodesCallback callback,
1865
0
                                void *userdata, UA_UInt32 *reqId) {
1866
0
    return __UA_Client_addNode_async(client, UA_NODECLASS_DATATYPE, requestedNewNodeId, parentNodeId,
1867
0
                                     referenceTypeId, browseName, UA_NODEID_NULL, (const UA_NodeAttributes *)&attr,
1868
0
                                     &UA_TYPES[UA_TYPES_DATATYPEATTRIBUTES], outNewNodeId,
1869
0
                                     (UA_ClientAsyncServiceCallback)callback, userdata, reqId);
1870
0
}
1871
1872
UA_StatusCode
1873
UA_Client_addMethodNode_async(UA_Client *client, const UA_NodeId requestedNewNodeId,
1874
                              const UA_NodeId parentNodeId, const UA_NodeId referenceTypeId,
1875
                              const UA_QualifiedName browseName, const UA_MethodAttributes attr,
1876
                              UA_NodeId *outNewNodeId, UA_ClientAsyncAddNodesCallback callback,
1877
0
                              void *userdata, UA_UInt32 *reqId) {
1878
0
    return __UA_Client_addNode_async(client, UA_NODECLASS_METHOD, requestedNewNodeId, parentNodeId,
1879
0
                                     referenceTypeId, browseName, UA_NODEID_NULL, (const UA_NodeAttributes *)&attr,
1880
0
                                     &UA_TYPES[UA_TYPES_METHODATTRIBUTES], outNewNodeId,
1881
0
                                     (UA_ClientAsyncServiceCallback)callback, userdata, reqId);
1882
0
}
1883
1884
#define UA_CLIENT_ASYNCWRITE_IMPL(NAME, ATTR_ID, ATTR_TYPE, ATTR_TYPEDESC)                               \
1885
    UA_StatusCode NAME(UA_Client *client, const UA_NodeId nodeId,                                        \
1886
                       const ATTR_TYPE *attr, UA_ClientAsyncWriteCallback callback,                      \
1887
0
                       void *userdata, UA_UInt32 *reqId) {                                               \
1888
0
        return __UA_Client_writeAttribute_async(client, &nodeId, UA_ATTRIBUTEID_##ATTR_ID, attr,           \
1889
0
                                                &UA_TYPES[UA_TYPES_##ATTR_TYPEDESC], \
1890
0
                                                (UA_ClientAsyncServiceCallback)callback, userdata, reqId); \
1891
0
}
Unexecuted instantiation: UA_Client_writeNodeIdAttribute_async
Unexecuted instantiation: UA_Client_writeNodeClassAttribute_async
Unexecuted instantiation: UA_Client_writeBrowseNameAttribute_async
Unexecuted instantiation: UA_Client_writeDisplayNameAttribute_async
Unexecuted instantiation: UA_Client_writeDescriptionAttribute_async
Unexecuted instantiation: UA_Client_writeWriteMaskAttribute_async
Unexecuted instantiation: UA_Client_writeIsAbstractAttribute_async
Unexecuted instantiation: UA_Client_writeSymmetricAttribute_async
Unexecuted instantiation: UA_Client_writeInverseNameAttribute_async
Unexecuted instantiation: UA_Client_writeContainsNoLoopsAttribute_async
Unexecuted instantiation: UA_Client_writeEventNotifierAttribute_async
Unexecuted instantiation: UA_Client_writeValueAttribute_async
Unexecuted instantiation: UA_Client_writeDataTypeAttribute_async
Unexecuted instantiation: UA_Client_writeValueRankAttribute_async
Unexecuted instantiation: UA_Client_writeAccessLevelAttribute_async
Unexecuted instantiation: UA_Client_writeMinimumSamplingIntervalAttribute_async
Unexecuted instantiation: UA_Client_writeHistorizingAttribute_async
Unexecuted instantiation: UA_Client_writeExecutableAttribute_async
Unexecuted instantiation: UA_Client_writeAccessLevelExAttribute_async
1892
1893
UA_CLIENT_ASYNCWRITE_IMPL(UA_Client_writeNodeIdAttribute_async, NODEID, UA_NodeId, NODEID)
1894
UA_CLIENT_ASYNCWRITE_IMPL(UA_Client_writeNodeClassAttribute_async, NODECLASS, UA_NodeClass, NODECLASS)
1895
UA_CLIENT_ASYNCWRITE_IMPL(UA_Client_writeBrowseNameAttribute_async, BROWSENAME, UA_QualifiedName, QUALIFIEDNAME)
1896
UA_CLIENT_ASYNCWRITE_IMPL(UA_Client_writeDisplayNameAttribute_async, DISPLAYNAME, UA_LocalizedText, LOCALIZEDTEXT)
1897
UA_CLIENT_ASYNCWRITE_IMPL(UA_Client_writeDescriptionAttribute_async, DESCRIPTION, UA_LocalizedText, LOCALIZEDTEXT)
1898
UA_CLIENT_ASYNCWRITE_IMPL(UA_Client_writeWriteMaskAttribute_async, WRITEMASK, UA_UInt32, UINT32)
1899
UA_CLIENT_ASYNCWRITE_IMPL(UA_Client_writeIsAbstractAttribute_async, ISABSTRACT, UA_Boolean, BOOLEAN)
1900
UA_CLIENT_ASYNCWRITE_IMPL(UA_Client_writeSymmetricAttribute_async, SYMMETRIC, UA_Boolean, BOOLEAN)
1901
UA_CLIENT_ASYNCWRITE_IMPL(UA_Client_writeInverseNameAttribute_async, INVERSENAME, UA_LocalizedText, LOCALIZEDTEXT)
1902
UA_CLIENT_ASYNCWRITE_IMPL(UA_Client_writeContainsNoLoopsAttribute_async, CONTAINSNOLOOPS, UA_Boolean, BOOLEAN)
1903
UA_CLIENT_ASYNCWRITE_IMPL(UA_Client_writeEventNotifierAttribute_async, EVENTNOTIFIER, UA_Byte, BYTE)
1904
UA_CLIENT_ASYNCWRITE_IMPL(UA_Client_writeValueAttribute_async, VALUE, UA_Variant, VARIANT)
1905
UA_CLIENT_ASYNCWRITE_IMPL(UA_Client_writeDataTypeAttribute_async, DATATYPE, UA_NodeId, NODEID)
1906
UA_CLIENT_ASYNCWRITE_IMPL(UA_Client_writeValueRankAttribute_async, VALUERANK, UA_Int32, INT32)
1907
UA_CLIENT_ASYNCWRITE_IMPL(UA_Client_writeAccessLevelAttribute_async, ACCESSLEVEL, UA_Byte, BYTE)
1908
UA_CLIENT_ASYNCWRITE_IMPL(UA_Client_writeMinimumSamplingIntervalAttribute_async, MINIMUMSAMPLINGINTERVAL, UA_Double, DOUBLE)
1909
UA_CLIENT_ASYNCWRITE_IMPL(UA_Client_writeHistorizingAttribute_async, HISTORIZING, UA_Boolean, BOOLEAN)
1910
UA_CLIENT_ASYNCWRITE_IMPL(UA_Client_writeExecutableAttribute_async, EXECUTABLE, UA_Boolean, BOOLEAN)
1911
UA_CLIENT_ASYNCWRITE_IMPL(UA_Client_writeAccessLevelExAttribute_async, ACCESSLEVELEX, UA_UInt32, UINT32)