forked from open62541/open62541
-
Notifications
You must be signed in to change notification settings - Fork 0
/
client_async.c
205 lines (174 loc) · 7.57 KB
/
client_async.c
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
/* This work is licensed under a Creative Commons CCZero 1.0 Universal License.
* See http://creativecommons.org/publicdomain/zero/1.0/ for more information. */
#include <open62541/client_config_default.h>
#include <open62541/client_highlevel_async.h>
#include <open62541/client_subscriptions.h>
#include <open62541/plugin/log_stdout.h>
#include <open62541/server_config_default.h>
#include <stdlib.h>
#define NODES_EXIST
/* async connection callback, it only gets called after the completion of the whole
* connection process*/
static void
onConnect(UA_Client *client, void *userdata, UA_UInt32 requestId,
void *status) {
printf("Async connect returned with status code %s\n",
UA_StatusCode_name(*(UA_StatusCode *) status));
}
static
void
fileBrowsed(UA_Client *client, void *userdata, UA_UInt32 requestId,
UA_BrowseResponse *response) {
printf("%-50s%i\n", "Received BrowseResponse for request ", requestId);
UA_String us = *(UA_String *) userdata;
printf("---%.*s passed safely \n", (int) us.length, us.data);
}
/*high-level function callbacks*/
static
void
readValueAttributeCallback(UA_Client *client, void *userdata,
UA_UInt32 requestId, UA_Variant *var) {
printf("%-50s%i\n", "Read value attribute for request", requestId);
if(UA_Variant_hasScalarType(var, &UA_TYPES[UA_TYPES_INT32])) {
UA_Int32 int_val = *(UA_Int32*) var->data;
printf("---%-40s%-8i\n",
"Reading the value of node (1, \"the.answer\"):", int_val);
}
/*more type distinctions possible*/
return;
}
static
void
attrWritten(UA_Client *client, void *userdata, UA_UInt32 requestId,
UA_WriteResponse *response) {
/*assuming no data to be retrieved by writing attributes*/
printf("%-50s%i\n", "Wrote value attribute for request ", requestId);
UA_WriteResponse_clear(response);
}
#ifdef NODES_EXIST
#ifdef UA_ENABLE_METHODCALLS
static void
methodCalled(UA_Client *client, void *userdata, UA_UInt32 requestId,
UA_CallResponse *response) {
printf("%-50s%i\n", "Called method for request ", requestId);
size_t outputSize;
UA_Variant *output;
UA_StatusCode retval = response->responseHeader.serviceResult;
if(retval == UA_STATUSCODE_GOOD) {
if(response->resultsSize == 1)
retval = response->results[0].statusCode;
else
retval = UA_STATUSCODE_BADUNEXPECTEDERROR;
}
if(retval != UA_STATUSCODE_GOOD) {
UA_CallResponse_clear(response);
}
/* Move the output arguments */
output = response->results[0].outputArguments;
outputSize = response->results[0].outputArgumentsSize;
response->results[0].outputArguments = NULL;
response->results[0].outputArgumentsSize = 0;
if(retval == UA_STATUSCODE_GOOD) {
printf("---Method call was successful, returned %lu values.\n",
(unsigned long) outputSize);
UA_Array_delete(output, outputSize, &UA_TYPES[UA_TYPES_VARIANT]);
} else {
printf("---Method call was unsuccessful, returned %x values.\n",
retval);
}
UA_CallResponse_clear(response);
}
static void
translateCalled(UA_Client *client, void *userdata, UA_UInt32 requestId,
UA_TranslateBrowsePathsToNodeIdsResponse *response) {
printf("%-50s%i\n", "Translated path for request ", requestId);
if(response->results[0].targetsSize == 1)
return;
UA_TranslateBrowsePathsToNodeIdsResponse_clear(response);
}
#endif /* UA_ENABLE_METHODCALLS */
#endif
int
main(int argc, char *argv[]) {
UA_Client *client = UA_Client_new();
UA_ClientConfig_setDefault(UA_Client_getConfig(client));
UA_UInt32 reqId = 0;
UA_String userdata = UA_STRING("userdata");
UA_BrowseRequest bReq;
UA_BrowseRequest_init(&bReq);
bReq.requestedMaxReferencesPerNode = 0;
bReq.nodesToBrowse = UA_BrowseDescription_new();
bReq.nodesToBrowseSize = 1;
bReq.nodesToBrowse[0].nodeId = UA_NODEID_NUMERIC(0, UA_NS0ID_OBJECTSFOLDER);
bReq.nodesToBrowse[0].resultMask = UA_BROWSERESULTMASK_ALL; /* return everything */
UA_Client_connect_async(client, "opc.tcp://localhost:4840", onConnect, NULL);
/*Windows needs time to response*/
UA_sleep_ms(100);
/* What happens if client tries to send request before connected? */
UA_Client_sendAsyncBrowseRequest(client, &bReq, fileBrowsed, &userdata, &reqId);
UA_DateTime startTime = UA_DateTime_nowMonotonic();
do {
/*TODO: fix memory-related bugs if condition not checked*/
if(UA_Client_getState(client) == UA_CLIENTSTATE_SESSION) {
/* If not connected requests are not sent */
UA_Client_sendAsyncBrowseRequest(client, &bReq, fileBrowsed, &userdata, &reqId);
}
/* Requests are processed */
UA_BrowseRequest_clear(&bReq);
UA_Client_run_iterate(client, 0);
UA_sleep_ms(100);
/* Break loop if server cannot be connected within 2s -- prevents build timeout */
if(UA_DateTime_nowMonotonic() - startTime > 2000 * UA_DATETIME_MSEC)
break;
} while(reqId < 10);
/* Demo: high-level functions */
UA_Int32 value = 0;
UA_Variant myVariant;
UA_Variant_init(&myVariant);
UA_Variant input;
UA_Variant_init(&input);
for(UA_UInt16 i = 0; i < 5; i++) {
if(UA_Client_getState(client) == UA_CLIENTSTATE_SESSION) {
/* writing and reading value 1 to 5 */
UA_Variant_setScalarCopy(&myVariant, &value, &UA_TYPES[UA_TYPES_INT32]);
value++;
UA_Client_writeValueAttribute_async(client,
UA_NODEID_STRING(1, "the.answer"),
&myVariant, attrWritten, NULL,
&reqId);
UA_Variant_clear(&myVariant);
UA_Client_readValueAttribute_async(client,
UA_NODEID_STRING(1, "the.answer"),
readValueAttributeCallback, NULL,
&reqId);
//TODO: check the existance of the nodes inside these functions (otherwise seg faults)
#ifdef NODES_EXIST
#ifdef UA_ENABLE_METHODCALLS
UA_String stringValue = UA_String_fromChars("World");
UA_Variant_setScalar(&input, &stringValue, &UA_TYPES[UA_TYPES_STRING]);
UA_Client_call_async(client,
UA_NODEID_NUMERIC(0, UA_NS0ID_OBJECTSFOLDER),
UA_NODEID_NUMERIC(1, 62541), 1, &input,
methodCalled, NULL, &reqId);
UA_String_clear(&stringValue);
#define pathSize 3
char *paths[pathSize] = { "Server", "ServerStatus", "State" };
UA_UInt32 ids[pathSize] = { UA_NS0ID_ORGANIZES,
UA_NS0ID_HASCOMPONENT, UA_NS0ID_HASCOMPONENT };
UA_Cient_translateBrowsePathsToNodeIds_async(client, paths, ids, pathSize,
translateCalled, NULL, &reqId);
#endif /* UA_ENABLE_METHODCALLS */
#endif
/* How often UA_Client_run_iterate is called depends on the number of request sent */
UA_Client_run_iterate(client, 0);
UA_Client_run_iterate(client, 0);
}
}
UA_Client_run_iterate(client, 0);
/* Async disconnect kills unprocessed requests */
// UA_Client_disconnect_async (client, &reqId); //can only be used when connected = true
// UA_Client_run_iterate (client, &timedOut);
UA_Client_disconnect(client);
UA_Client_delete(client);
return EXIT_SUCCESS;
}