#include <uaclient/uaclient.h>
#include <uaclient/uaclient_services.h>
#include <uaclient/uaclient_simple_browse.h>
#include <uabase/nodeid.h>
#include <trace/trace.h>
#include <memory/memory.h>
#include <common/errors.h>
#include <uabase/identifiers.h>
#include <uabase/datavalue.h>
#include <uabase/variant.h>
#include <uabase/structure/browseresultmask.h>
#include <uabase/structure/nodeclass.h>
#include <uabase/attributeid.h>
#include "sampleclient.h"
static int sample_client_browse_cb(
int client_result,
void *cb_data)
{
struct sample_client *ctx = cb_data;
int32_t i,j;
int ret;
UA_UNUSED(client);
if (client_result != 0) {
ctx->result = client_result;
ctx->cur_state = SAMPLE_CLIENT_STATE_DISCONNECT;
return 0;
} else if (service_result != 0) {
ctx->result = UA_EBADSERVICERESPONSE;
ctx->cur_state = SAMPLE_CLIENT_STATE_DISCONNECT;
return 0;
}
ret = ua_nodeid_to_string(&req->
nodes[i].
node_id, &result_string);
if (ret == 0) {
printf("Browse result [%i](Source nodeid: %s, num_references: %i):\n",
i,
} else {
printf("Browse result [%i](Source nodeid: %s, num_references: %i):\n",
i,
"<convert failed>",
}
printf(" Reference [%i]:\n", j);
ret = ua_nodeid_to_string(&ref->
node_id.
id, &result_string);
if (ret == 0) {
} else {
printf(" Target nodeid: <convert failed>\n");
}
printf(
" Nodeclass: %s\n", ua_nodeclass_to_string(ref->
node_class));
}
}
ctx->cur_state = SAMPLE_CLIENT_STATE_DISCONNECT;
return 0;
}
static void sample_client_browse(struct sample_client *ctx)
{
int ret;
if (ret != 0) goto error;
| UA_BROWSERESULTMASK_DISPLAYNAME
| UA_BROWSERESULTMASK_NODECLASS;
| UA_BROWSERESULTMASK_DISPLAYNAME
| UA_BROWSERESULTMASK_NODECLASS;
ret = ua_client_begin_simple_browse(&ctx->client,
NULL,
&req,
sample_client_browse_cb,
ctx);
if (ret != 0) goto error;
ctx->cur_state = SAMPLE_CLIENT_STATE_BROWSING;
return;
error:
ctx->result = ret;
ctx->cur_state = SAMPLE_CLIENT_STATE_BROWSE_DONE;
return;
}
static int sample_client_read_cb(
int client_result,
void *cb_data)
{
struct sample_client *ctx = cb_data;
int ret;
int32_t i;
UA_UNUSED(client);
UA_UNUSED(req);
if (client_result != 0) {
ctx->result = client_result;
ctx->cur_state = SAMPLE_CLIENT_STATE_DISCONNECT;
return 0;
ctx->result = UA_EBADSERVICERESPONSE;
ctx->cur_state = SAMPLE_CLIENT_STATE_DISCONNECT;
return 0;
ctx->result = UA_EBADINTERNALERROR;
ctx->cur_state = SAMPLE_CLIENT_STATE_DISCONNECT;
return 0;
}
printf("Read result [%i]:\n", i);
printf(
" Bad statuscode=0x%08X\n", result->
status);
continue;
}
ret = ua_variant_to_string(&result->
value, &result_string);
if (ret != 0) {
printf(" Could not be converted with 'ua_variant_to_string'\n");
continue;
}
}
ctx->cur_state = SAMPLE_CLIENT_STATE_READ_DONE;
return 0;
}
static void sample_client_read(struct sample_client *ctx)
{
int ret;
if (ret != 0) goto error;
ret = ua_client_begin_read(
&ctx->client,
NULL,
&req,
sample_client_read_cb,
ctx);
if (ret != 0) goto error;
ctx->cur_state = SAMPLE_CLIENT_STATE_READING;
return;
error:
ctx->result = ret;
ctx->cur_state = SAMPLE_CLIENT_STATE_DISCONNECT;
return;
}
static void sample_client_connection_status_changed_cb(
struct ua_client *client,
enum ua_client_connection_status status)
{
const char *status_str = ua_client_connection_status_to_string(status);
UA_UNUSED(client);
printf("Connection Status Changed: %s\n", status_str);
}
static bool sample_client_connection_error_cb(
struct ua_client *client,
enum ua_client_state state,
int client_error,
{
struct sample_client *ctx = ua_client_get_userdata(client);
UA_UNUSED(state);
if (client_error != 0) {
printf("\nClient error: %i\n", client_error);
ctx->cur_state = SAMPLE_CLIENT_STATE_FINISHED;
ctx->result = -1;
}
if (statuscode != 0) {
printf("\nServer error: 0x%08X\n", statuscode);
ctx->cur_state = SAMPLE_CLIENT_STATE_FINISHED;
ctx->result = -1;
}
return false;
}
static void sample_client_disconnect_cb(
struct ua_client *client,
void *cb_data,
int result,
ua_statuscode statuscode)
{
struct sample_client *ctx = cb_data;
UA_UNUSED(client);
if (result != 0) {
ctx->result = result;
} else if (statuscode != 0) {
ctx->result = UA_EBADSERVICERESPONSE;
}
ctx->cur_state = SAMPLE_CLIENT_STATE_FINISHED;
}
static void sample_client_disconnect(struct sample_client *ctx)
{
int ret;
ret = ua_client_begin_disconnect(&ctx->client, sample_client_disconnect_cb, ctx);
if (ret != 0) {
if (ctx->result != 0) ctx->result = ret;
ctx->cur_state = SAMPLE_CLIENT_STATE_FINISHED;
} else {
ctx->cur_state = SAMPLE_CLIENT_STATE_DISCONNECTING;
}
}
static void sample_client_connect_cb(
struct ua_client *client,
void *cb_data,
int result,
ua_statuscode statuscode)
{
struct sample_client *ctx = cb_data;
UA_UNUSED(client);
if (result != 0) {
ctx->result = result;
ctx->cur_state = SAMPLE_CLIENT_STATE_FINISHED;
} else if (statuscode != 0) {
ctx->result = UA_EBADSERVICERESPONSE;
ctx->cur_state = SAMPLE_CLIENT_STATE_FINISHED;
} else {
ctx->cur_state = SAMPLE_CLIENT_STATE_CONNECTED;
}
}
static void sample_client_connect(struct sample_client *ctx)
{
int ret;
ret = ua_client_begin_connect(&ctx->client, ctx->url, sample_client_connect_cb, ctx);
if (ret != 0) {
ctx->result = ret;
ctx->cur_state = SAMPLE_CLIENT_STATE_FINISHED;
} else {
ctx->cur_state = SAMPLE_CLIENT_STATE_CONNECTING;
}
}
int sample_client_get_result(struct sample_client *ctx)
{
return ctx->result;
}
void sample_client_cleanup(struct sample_client *ctx)
{
ua_client_cleanup(&ctx->client);
}
int sample_client_init(struct sample_client *ctx, const char *url)
{
int ret;
ret = ua_client_init(&ctx->client);
if (ret != 0) {
return ret;
}
callbacks.status_changed_cb = sample_client_connection_status_changed_cb;
callbacks.error_cb = sample_client_connection_error_cb;
ua_client_set_callbacks(&ctx->client, &callbacks);
ua_client_set_userdata(&ctx->client, ctx);
ctx->cur_state = SAMPLE_CLIENT_STATE_INITIAL;
ctx->url = url;
ctx->result = 0;
return 0;
}
bool sample_client_check_state(struct sample_client *ctx)
{
switch (ctx->cur_state) {
case SAMPLE_CLIENT_STATE_INITIAL:
sample_client_connect(ctx);
break;
case SAMPLE_CLIENT_STATE_CONNECTED:
sample_client_read(ctx);
break;
case SAMPLE_CLIENT_STATE_READ_DONE:
sample_client_browse(ctx);
break;
case SAMPLE_CLIENT_STATE_BROWSE_DONE:
ctx->cur_state = SAMPLE_CLIENT_STATE_DISCONNECT;
break;
case SAMPLE_CLIENT_STATE_DISCONNECT:
sample_client_disconnect(ctx);
break;
case SAMPLE_CLIENT_STATE_FINISHED:
return false;
default:
break;;
}
return true;
}