- Main
- Tutorials
- Library
- Samples

How to build node sample for Embedded OPC UA Server

Tutorial to add a node for Embedded OPC UA Server

## Moxa Embedded OPC UA Server Introduction

MOXA Embedded OPC UA Server is constructed of multiple node operators. Each node operator has the capability to build the node hierarchy and the detail information of each node. e.g. the node name, the updated values etc....

Besides the basic operation, OPC UA server supports the data access feature. When OPC UA client would like to write the value of the node immediately, the API in the interface of node operator is actively invoked by OPC UA server to support this feature and provide the operation result.

## Node Operator Introduction

Node operator is builded as shared library and it can select which feature it supported. If it supports the specific feature, it should implement the specific interfaces and structures that OPC UA server defined like data access. OPC UA server actively invokes the API in specific interface of a node operator to achieve the corresponding behaviors.

Besides implementing the interface desgined for the node operator, OPC UA server provides the node related API to add/update nodes. To learn making a node operator by modifing sample node operator, the sample code is in `sample/mx_node_sdk/c/example/sample_node_operator.c`.

## Add a node to OPC UA server

Add a node as folder node's child.

1 MX_NODE_RESULT mx_node_operator_initialize(MX_NODE_NODE_OPERATOR_HANDLE operator_handle)
2 {
3 ...
4
5 MX_NODE_NODE_HANDLE double_handle;
6 MX_NODE_NODE var_double;
7
8 // Fill in SampleDouble's information.
9 strcpy(var_double.node_name, "SampleDouble");
10 var_double.node_type = MX_NODE_NODE_TYPE_VARIABLE;
11 strcpy(var_double.description, "SampleDouble's Description");
12 var_double.variable.access_right = MX_NODE_ACCESS_RIGHT_READWRITE;
13 var_double.variable.value.type = MX_NODE_VALUE_TYPE_DOUBLE;
14 var_double.variable.value.value.d = 0.0;
15
16 // Add SampleDouble to OPC UA server.
17 mx_node_add_node(operator_handle, &var_double, &double_handle);
18
19 // Set SampleDouble's parent to SampleFolder.
20 mx_node_set_parent_node(double_handle, folder_handle);
21
22 ...
23
24 return MX_NODE_RESULT_GOOD;
25 }
add_node

## Update a node to OPC UA server

Update the node SampleDouble.

1 void mx_node_operator_start()
2 {
3 g_state = OPERATOR_STATE_RUNNING;
4 while (g_state == OPERATOR_STATE_RUNNING)
5 {
6 ...
7
8 MX_NODE_VARIANT var_double;
9 var_double.type = MX_NODE_VALUE_TYPE_DOUBLE;
10 var_double.value.d = 5.5;
11 struct timeval timestamp = now();
12 mx_node_update_node(double_handle, &var_double, &timestamp);
13
14 sleep(3);
15 }
16 g_state = OPERATOR_STATE_STOP;
17 }
update_node

## Handle data access requests from OPC UA client

Handle a read request from OPC UA client.

1 MX_NODE_RESULT mx_node_operator_read_node(MX_NODE_NODE_HANDLE node_handle, MX_NODE_VARIANT* node_value, struct timeval* node_timestamp)
2 {
3 if (node_handle == g_my_node.node_handle)
4 {
5 ...
6 }
7 else if (node_handle == double_handle)
8 {
9 node_value->type = MX_NODE_VALUE_TYPE_DOUBLE;
10 node_value->value.d = 9.3;
11 *node_timestamp = now();
12 return MX_NODE_RESULT_GOOD;
13 }
14 return MX_NODE_RESULT_BAD;
15 }
read_node

## Build node operator

The example project path is `~/sample/mx_node_sdk/c/example/`, there are 4 files, `sample_node_operator.c`, `CMakeLists.txt`, `toolchain-native.cmake` and `toolchain-cross.cmake`. Please execute follow commands to build node operator, the output file liboperator.so is in `~/sample/mx_node_sdk/c/example`.

### Build native toolchain

1 moxa@Moxa:~/sample/mx_node_sdk/c/example$ cmake . -DCMAKE_TOOLCHAIN_FILE=toolchain-native.cmake
2 moxa@Moxa:~/sample/mx_node_sdk/c/example$ make

### Build cross toolchain

1 moxa@Moxa:~/sample/mx_node_sdk/c/example$ cmake . -DCMAKE_TOOLCHAIN_FILE=toolchain-cross.cmake
2 moxa@Moxa:~/sample/mx_node_sdk/c/example$ make

## Deploy node operator

1 moxa@Moxa:~/sample/mx_node_sdk/c/example$ mkdir /usr/local/bin/embeddedopcuaserver/OperatorLib/example
2 moxa@Moxa:~/sample/mx_node_sdk/c/example$ cp liboperator.so /usr/local/bin/embeddedopcuaserver/OperatorLib/example/

## Execute OPC UA server

1 moxa@Moxa:~$ sudo systemctl start embedded-opcua-server
2 moxa@Moxa:~$ sudo systemctl stop embedded-opcua-server
3 moxa@Moxa:~$ sudo systemctl restart embedded-opcua-server
4 moxa@Moxa:~$ sudo systemctl status embedded-opcua-server
5 moxa@Moxa:~$ sudo systemctl disable embedded-opcua-server
6 moxa@Moxa:~$ sudo systemctl enable embedded-opcua-server

## Add/Delete OPC UA server account

1 moxa@Moxa:~$ sudo opcuauser --add moxa
2 moxa@Moxa:~$ sudo opcuauser --del moxa
3
4 moxa@Moxa:~$ sudo opcuauser --help
5 Usage: opcuauser [options] username
6
7 Options:
8 -a, --add Add user account
9 -d, --del Delete user account
10 -c, --change Change user password
11 -v, --verion Show version
12 -h, --help Show help
13
14 Example:
15 opcuauser Add user account
16 opcuauser username Change user password
17 opcuauser --help Show help

Please notice that embedded-opcua-server should be reboot to take effect of user account list. Current user account list can be verify by checking `/etc/opcuauser_passwd`.