- Main
- Tutorials
- Library
- Samples

- File List
- Globals

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