tutorial/opcua/node/README.md
Go to the documentation of this file.
1 
2 How to build node sample for Embedded OPC UA Server {#opcuaserver-sample}
3 ----
4 @brief Tutorial to add a node for Embedded OPC UA Server
5 
6 ## Moxa Embedded OPC UA Server Introduction
7 
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....
9 
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.
11 
12 ## Node Operator Introduction
13 
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.
15 
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```.
18 
19 ## Add a node to OPC UA server
20 
21 Add a node as folder node's child.
22 ``` c
23 MX_NODE_RESULT mx_node_operator_initialize(MX_NODE_NODE_OPERATOR_HANDLE operator_handle)
24 {
25  ...
26 
27  MX_NODE_NODE_HANDLE double_handle;
28  MX_NODE_NODE var_double;
29 
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;
37 
38  // Add SampleDouble to OPC UA server.
39  mx_node_add_node(operator_handle, &var_double, &double_handle);
40 
41  // Set SampleDouble's parent to SampleFolder.
42  mx_node_set_parent_node(double_handle, folder_handle);
43 
44  ...
45 
46  return MX_NODE_RESULT_GOOD;
47 }
48 ```
49 ![add_node][add_node]
50 
51 ## Update a node to OPC UA server
52 
53 Update the node SampleDouble.
54 ``` c
55 void mx_node_operator_start()
56 {
57  g_state = OPERATOR_STATE_RUNNING;
58  while (g_state == OPERATOR_STATE_RUNNING)
59  {
60  ...
61 
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, &timestamp);
67 
68  sleep(3);
69  }
70  g_state = OPERATOR_STATE_STOP;
71 }
72 ```
73 ![update_node][update_node]
74 
75 ## Handle data access requests from OPC UA client
76 
77 Handle a read request from OPC UA client.
78 ``` c
79 MX_NODE_RESULT mx_node_operator_read_node(MX_NODE_NODE_HANDLE node_handle, MX_NODE_VARIANT* node_value, struct timeval* node_timestamp)
80 {
81  if (node_handle == g_my_node.node_handle)
82  {
83  ...
84  }
85  else if (node_handle == double_handle)
86  {
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;
91  }
92  return MX_NODE_RESULT_BAD;
93 }
94 ```
95 ![read_node][read_node]
96 
97 ## Build node operator
98 
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```.
101 
102 ### Build native toolchain
103 
104 ```
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
107 ```
108 
109 ### Build cross toolchain
110 
111 ```
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
114 ```
115 
116 ## Deploy node operator
117 
118 ```
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/
121 ```
122 
123 ## Execute OPC UA server
124 
125 ```
126 moxa@Moxa:~$ sudo systemctl start embedded-opcua-server
127 moxa@Moxa:~$ sudo systemctl stop embedded-opcua-server
128 moxa@Moxa:~$ sudo systemctl restart embedded-opcua-server
129 moxa@Moxa:~$ sudo systemctl status embedded-opcua-server
130 moxa@Moxa:~$ sudo systemctl disable embedded-opcua-server
131 moxa@Moxa:~$ sudo systemctl enable embedded-opcua-server
132 ```
133 
134 ## Add/Delete OPC UA server account
135 
136 ```
137 moxa@Moxa:~$ sudo opcuauser --add moxa
138 moxa@Moxa:~$ sudo opcuauser --del moxa
139 
140 moxa@Moxa:~$ sudo opcuauser --help
141 Usage: opcuauser [options] username
142 
143 Options:
144  -a, --add Add user account
145  -d, --del Delete user account
146  -c, --change Change user password
147  -v, --verion Show version
148  -h, --help Show help
149 
150 Example:
151  opcuauser Add user account
152  opcuauser username Change user password
153  opcuauser --help Show help
154 ```
155 
156 Please notice that embedded-opcua-server should be reboot to take effect of user account list.
157 Current user account list can be verify by checking ```/etc/opcuauser_passwd```.
158 
159 [comment]: # (Images)
160 [add_node]: images/add_node.png
161 [update_node]: images/update_node.png
162 [read_node]: images/read_node.png