2 How to build node sample for Embedded OPC UA Server {#opcuaserver-sample}
4 @brief Tutorial to add a node for Embedded OPC UA Server
6 ## Moxa Embedded OPC UA Server Introduction
8 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....
10 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.
12 ## Node Operator Introduction
14 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.
16 Besides implementing the interface desgined for the node operator, OPC UA server provides the node related API to add/update nodes.
17 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```.
19 ## Add a node to OPC UA server
21 Add a node as folder node's child.
23 MX_NODE_RESULT mx_node_operator_initialize(MX_NODE_NODE_OPERATOR_HANDLE operator_handle)
27 MX_NODE_NODE_HANDLE double_handle;
28 MX_NODE_NODE var_double;
30 // Fill in SampleDouble's information.
31 strcpy(var_double.node_name, "SampleDouble");
32 var_double.node_type = MX_NODE_NODE_TYPE_VARIABLE;
33 strcpy(var_double.description, "SampleDouble's Description");
34 var_double.variable.access_right = MX_NODE_ACCESS_RIGHT_READWRITE;
35 var_double.variable.value.type = MX_NODE_VALUE_TYPE_DOUBLE;
36 var_double.variable.value.value.d = 0.0;
38 // Add SampleDouble to OPC UA server.
39 mx_node_add_node(operator_handle, &var_double, &double_handle);
41 // Set SampleDouble's parent to SampleFolder.
42 mx_node_set_parent_node(double_handle, folder_handle);
46 return MX_NODE_RESULT_GOOD;
51 ## Update a node to OPC UA server
53 Update the node SampleDouble.
55 void mx_node_operator_start()
57 g_state = OPERATOR_STATE_RUNNING;
58 while (g_state == OPERATOR_STATE_RUNNING)
62 MX_NODE_VARIANT var_double;
63 var_double.type = MX_NODE_VALUE_TYPE_DOUBLE;
64 var_double.value.d = 5.5;
65 struct timeval timestamp = now();
66 mx_node_update_node(double_handle, &var_double, ×tamp);
70 g_state = OPERATOR_STATE_STOP;
73 ![update_node][update_node]
75 ## Handle data access requests from OPC UA client
77 Handle a read request from OPC UA client.
79 MX_NODE_RESULT mx_node_operator_read_node(MX_NODE_NODE_HANDLE node_handle, MX_NODE_VARIANT* node_value, struct timeval* node_timestamp)
81 if (node_handle == g_my_node.node_handle)
85 else if (node_handle == double_handle)
87 node_value->type = MX_NODE_VALUE_TYPE_DOUBLE;
88 node_value->value.d = 9.3;
89 *node_timestamp = now();
90 return MX_NODE_RESULT_GOOD;
92 return MX_NODE_RESULT_BAD;
95 ![read_node][read_node]
97 ## Build node operator
99 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```.
100 Please execute follow commands to build node operator, the output file **liboperator.so** is in ```~/sample/mx_node_sdk/c/example```.
102 ### Build native toolchain
105 moxa@Moxa:~/sample/mx_node_sdk/c/example$ cmake . -DCMAKE_TOOLCHAIN_FILE=toolchain-native.cmake
106 moxa@Moxa:~/sample/mx_node_sdk/c/example$ make
109 ### Build cross toolchain
112 moxa@Moxa:~/sample/mx_node_sdk/c/example$ cmake . -DCMAKE_TOOLCHAIN_FILE=toolchain-cross.cmake
113 moxa@Moxa:~/sample/mx_node_sdk/c/example$ make
116 ## Deploy node operator
119 moxa@Moxa:~/sample/mx_node_sdk/c/example$ mkdir /usr/local/bin/embeddedopcuaserver/OperatorLib/example
120 moxa@Moxa:~/sample/mx_node_sdk/c/example$ cp liboperator.so /usr/local/bin/embeddedopcuaserver/OperatorLib/example/
123 ## Location for OPC UA client certificate
125 Put OPC UA client certificate to ```/usr/local/bin/embeddedopcuaserver/mxopcserver/certificationstores/trusted/certs/```
127 ## Execute OPC UA server
130 moxa@Moxa:~$ sudo systemctl start embedded-opcua-server
131 moxa@Moxa:~$ sudo systemctl stop embedded-opcua-server
132 moxa@Moxa:~$ sudo systemctl restart embedded-opcua-server
133 moxa@Moxa:~$ sudo systemctl status embedded-opcua-server
134 moxa@Moxa:~$ sudo systemctl disable embedded-opcua-server
135 moxa@Moxa:~$ sudo systemctl enable embedded-opcua-server
138 ## Security policy for OPC UA server
141 * Basic128Rsa15 - Sign
142 * Basic128Rsa15 - Sign & Encrypt
144 * Basic256 - Sign & Encrypt
145 * Basic256Sha256 - Sign
146 * Basic256Sha256 - Sign & Encrypt
148 ## Add/Delete OPC UA server account
151 moxa@Moxa:~$ sudo opcuauser --add moxa
152 moxa@Moxa:~$ sudo opcuauser --del moxa
154 moxa@Moxa:~$ sudo opcuauser --help
155 Usage: opcuauser [options] username
158 -a, --add Add user account
159 -d, --del Delete user account
160 -c, --change Change user password
161 -v, --verion Show version
165 opcuauser Add user account
166 opcuauser username Change user password
167 opcuauser --help Show help
170 Please notice that embedded-opcua-server should be reboot to take effect of user account list.
171 Current user account list can be verify by checking ```/etc/opcuauser_passwd```.
173 [comment]: # (Images)
174 [add_node]: images/add_node.png
175 [update_node]: images/update_node.png
176 [read_node]: images/read_node.png