- Main
- Tutorials
- Library
- Samples

- File List
- Globals

tutorial/opcua/io/README.md
Go to the documentation of this file.
1 How to build IO sample for Embedded OPC UA Server {#opcuaserver-io}
2 ---
3 @brief Tutorial to add IO nodes for Embedded OPC UA Server that represents ioThinx-4533 device IO modules status.
4
5 ## Table of Contents
6
7 * Beginners Guide
8 * User Scenario 1
9 * User Scenario 2
10 * User Scenario 3
11 * Compile Guide
12 * Appendix and FAQ
13
14 ## Beginners Guide
15
16 If you are a total beginner to this, start here!
17
18 1. make sure your firmware version is above or equal to V1.1
19 ```
20 kversion
21 ```
22 2. download embeddedopcuaserver-plugin-dev_<version>_armhf.deb to 4533
23 * [embeddedopcuaserver-plugin-dev_1.0.0_armhf.deb](embeddedopcuaserver-plugin-dev_1.0.0_armhf.deb)
24
25 3. install embeddedopcuaserver-plugin-dev_<version>_armhf.deb
26 ```
27 dpkg -i embeddedopcuaserver-plugin-dev_<version>_armhf.deb
28 ```
29
30 4. Check io.conf under `/usr/local/bin/embeddedopcuaserver/Config` fits your ioThinx-4533 IO modules layout
31 5. Execute `systemctl start embedded-opcua-server` to run up server
32 6. Start using OPC UA client to browse IO data
33
34
35 ## User Scenario
36
37 ### User Scenario 1: Add an diStatus node(config only)
38
39 Add Slot 1/Channel 4 diStatus to OPC UA Server, just modify io.conf under `/usr/local/bin/embeddedopcuaserver/Config` to
40
41 ```
42 {
43 "slot": [
44 null,
45 [
46 {"ch": 0, "access": 1, "variant_type": 3, "func_type": 10, "name": "diMode", "description": "di mode"},
47 {"ch": 0, "access": 1, "variant_type": 3, "func_type": 11, "name": "diStatus", "description": "di status"},
48 {"ch": 1, "access": 1, "variant_type": 3, "func_type": 11, "name": "diStatus", "description": "di status"},
49 {"ch": 2, "access": 1, "variant_type": 3, "func_type": 11, "name": "diStatus", "description": "di status"},
50 {"ch": 3, "access": 3, "variant_type": 3, "func_type": 12, "name": "diCounterStatus", "description": "di counter status"},
51 {"ch": 3, "access": 3, "variant_type": 7, "func_type": 13, "name": "diCounterValue", "description": "di counter value"},
52 {"ch": 4, "access": 1, "variant_type": 3, "func_type": 11, "name": "diStatus", "description": "di status"}
53 ]
54 ]
55 }
56 ```
57
58 Please notice:
59 - slot 1 must be 45MR-1600/45MR-1601/45MR-2606
60 - follow json format to add your own node
61
62
63 ### User Scenario 2: Change module slot order(config only)
64
65 Adjust io.config to follow ioThinx-4533 real hardware modules order.
66 Now slot 1 is 45MR-1600 and slot 2 is 45MR-2600 which the io.conf may looks like below.
67
68 ```
69 {
70 "slot": [
71 null,
72 [
73 {"ch": 0, "access": 1, "variant_type": 3, "func_type": 10, "name": "diMode", "description": "di mode"},
74 {"ch": 0, "access": 1, "variant_type": 3, "func_type": 11, "name": "diStatus", "description": "di status"},
75 {"ch": 1, "access": 1, "variant_type": 3, "func_type": 11, "name": "diStatus", "description": "di status"},
76 {"ch": 2, "access": 1, "variant_type": 3, "func_type": 11, "name": "diStatus", "description": "di status"},
77 {"ch": 3, "access": 3, "variant_type": 3, "func_type": 12, "name": "diCounterStatus", "description": "di counter status"},
78 {"ch": 3, "access": 3, "variant_type": 7, "func_type": 13, "name": "diCounterValue", "description": "di counter value"},
79 {"ch": 4, "access": 1, "variant_type": 3, "func_type": 11, "name": "diStatus", "description": "di status"}
80 ],
81 [
82 {"ch": 0, "access": 1, "variant_type": 3, "func_type": 20, "name": "doMode", "description": "do mode"},
83 {"ch": 0, "access": 3, "variant_type": 3, "func_type": 21, "name": "doStatus", "description": "do status"},
84 {"ch": 1, "access": 3, "variant_type": 3, "func_type": 21, "name": "doStatus", "description": "do status"},
85 {"ch": 2, "access": 3, "variant_type": 3, "func_type": 22, "name": "doPulseStatus", "description": "do pluse status"},
86 {"ch": 2, "access": 3, "variant_type": 7, "func_type": 23, "name": "doPulseCount", "description": "do pluse count"},
87 {"ch": 3, "access": 3, "variant_type": 3, "func_type": 22, "name": "doPulseStatus", "description": "do pluse status"},
88 {"ch": 3, "access": 3, "variant_type": 7, "func_type": 23, "name": "doPulseCount", "description": "do pluse count"}
89 ]
90 ]
91 }
92 ```
93
94 Now switch slot 1 and slot 2 and insert an 45MR-2404 in between which make ioThinx-4533 hardware modules order into
95 slot 1: 45MR-2600, slot 2: 45MR-2404, slot 3: 45MR-1600 and if we don't want to monitor 45MR-2404, the io.conf may replace like below.
96
97 ```
98 {
99 "slot": [
100 null,
101 [
102 {"ch": 0, "access": 1, "variant_type": 3, "func_type": 20, "name": "doMode", "description": "do mode"},
103 {"ch": 0, "access": 3, "variant_type": 3, "func_type": 21, "name": "doStatus", "description": "do status"},
104 {"ch": 1, "access": 3, "variant_type": 3, "func_type": 21, "name": "doStatus", "description": "do status"},
105 {"ch": 2, "access": 3, "variant_type": 3, "func_type": 22, "name": "doPulseStatus", "description": "do pluse status"},
106 {"ch": 2, "access": 3, "variant_type": 7, "func_type": 23, "name": "doPulseCount", "description": "do pluse count"},
107 {"ch": 3, "access": 3, "variant_type": 3, "func_type": 22, "name": "doPulseStatus", "description": "do pluse status"},
108 {"ch": 3, "access": 3, "variant_type": 7, "func_type": 23, "name": "doPulseCount", "description": "do pluse count"}
109 ],
110 null,
111 [
112 {"ch": 0, "access": 1, "variant_type": 3, "func_type": 10, "name": "diMode", "description": "di mode"},
113 {"ch": 0, "access": 1, "variant_type": 3, "func_type": 11, "name": "diStatus", "description": "di status"},
114 {"ch": 1, "access": 1, "variant_type": 3, "func_type": 11, "name": "diStatus", "description": "di status"},
115 {"ch": 2, "access": 1, "variant_type": 3, "func_type": 11, "name": "diStatus", "description": "di status"},
116 {"ch": 3, "access": 3, "variant_type": 3, "func_type": 12, "name": "diCounterStatus", "description": "di counter status"},
117 {"ch": 3, "access": 3, "variant_type": 7, "func_type": 13, "name": "diCounterValue", "description": "di counter value"},
118 {"ch": 4, "access": 1, "variant_type": 3, "func_type": 11, "name": "diStatus", "description": "di status"}
119 ]
120 ]
121 }
122 ```
123
124 Please notice:
125 - slot order is start from 0 and slot 0 means the node from CPU head
126 - if this io module is no need to be monitor by OPC UA Server, then give an null in the io.conf
127
128 ### User Scenario 3: Add new IO func_type (coding & config)
129
130 Define new FUNC_TYPE in `DataSet.h` and add read/write function case in `io_control_read()` and `io_control_write()` of `io_node_operator.c`.
131 If this io data need to be configured first during the initialization, then configure function should be add in `add_io_nodes()`.
132
133 Modify `io.conf` to load __hello do__ info and add new func_type 99 as below.
134
135 ```
136 {
137 "slot": [
138 null,
139 [
140 {"ch": 0, "access": 1, "variant_type": 3, "func_type": 20, "name": "doMode", "description": "do mode"},
141 {"ch": 3, "access": 1, "variant_type": 3, "func_type": 99, "name": "helloDO", "description": "hello do"}
142 ]
143 ]
144 }
145 ```
146
147 ## Compile Guide
148
149 ### Using native toolchain
150
151 1. Copy sample.tar.gz contained in the programing guide from your PC to ioThinx:\n
152 For example, if the IP address of the ioThinx is "192.168.127.254", use the following command:
153 ```
154 user@Linux:~$ scp sample.tar.gz moxa@192.168.127.254:~
155 ```
156 2. Extract the sample code
157 ```
158 moxa@Moxa:~$ tar zxvf sample.tar.gz
159 ```
160 3. Build IO sample code
161 ```
162 moxa@Moxa:~$ cd sample/mx_node_sdk/c/io
163 ```
164 Build via cmake & make
165 ```
166 moxa@Moxa:~/sample/mx_node_sdk/c/io$ cmake .
167 moxa@Moxa:~/sample/mx_node_sdk/c/io$ make
168 ```
169 4. Move `liboperator.so` to `OperatorLib`
170 ```
171 moxa@Moxa:~/sample/mx_node_sdk/c/io$ cp liboperator.so /usr/local/bin/embeddedopcuaserver/OperatorLib/IOProtocol/
172 ```
173 5. Restart server via systemd
174 ```
175 moxa@Moxa:~/sample/mx_node_sdk/c/io$ sudo systemctl restart embedded-opcua-server
176 ```
177
178 ### Using cross toolchain
179
180 1. Copy sample.tar.gz contained in the programing guide to your PC
181 2. Extract the sample code
182 ```
183 user@Linux:~$ tar zxvf sample.tar.gz
184 ```
185 3. Build IO sample code
186 ```
187 user@Linux:~$ cd sample/mx_node_sdk/c/io
188 ```
189 Build via cmake & make
190 ```
191 user@Linux:~/sample/mx_node_sdk/c/io$ cmake . -DCMAKE_TOOLCHAIN_FILE=toolchain-cross.cmake
192 user@Linux:~/sample/mx_node_sdk/c/io$ make
193 ```
194 4. Copy the sample program to ioThinx:\n
195 For example, if the IP address of the ioThinx is "192.168.127.254", use the following command:
196 ```
197 user@Linux:~/sample/mx_node_sdk/c/io$ scp liboperator.so moxa@192.168.127.254:~
198 ```
199 5. Move `liboperator.so` to `OperatorLib`
200 ```
201 moxa@Moxa:~$ cp liboperator.so /usr/local/bin/embeddedopcuaserver/OperatorLib/IOProtocol/
202 ```
203 6. Restart server via systemd
204 ```
205 moxa@Moxa:~$ sudo systemctl restart embedded-opcua-server
206 ```
207
208 ## Appendix and FAQ
209
210 ### Programming Source Code
211
212 * example
213 - quick example to show 2 data nodes onto OPC UA Server
214 * demo
215 - demo sample shows all data types nodes onto OPC UA Server
216 * io
217 - io sample shows io data nodes onto OPC UA Server
218
219 ```
220 mx_node_sdk
221 c
222 ├── demo
223 │ ├── CMakeLists.txt
224 │ ├── demo_node_operator.c
225 │ ├── toolchain-cross.cmake
226 │ └── toolchain-native.cmake
227 ├── example
228 │ ├── CMakeLists.txt
229 │ ├── sample_node_operator.c
230 │ ├── toolchain-cross.cmake
231 │ └── toolchain-native.cmake
232 └── io
233 ├── cJSON.c
234 ├── cJSON.h
235 ├── CMakeLists.txt
236 ├── DataSet.h
237 ├── io_node_operator.c
238 ├── toolchain-cross.cmake
239 └── toolchain-native.cmake
240 ```
241
242 ### IO Config Format
243 Explain how to use io.conf to fit your usage
244
245 * slot
246 - follow array index to represent which slot
247 * access
248 - Node's access right. Please reference MX_NODE_ACCESS_RIGHT
249 * variant_type
250 - MX_Variant's data type. please reference MX_NODE_VALUE_TYPE
251 * func_type
252 - function type which is define in DataSet.h
253
254 ### Execute OPC UA server
255
256 ```
257 moxa@Moxa:~$ sudo systemctl start embedded-opcua-server
258 moxa@Moxa:~$ sudo systemctl stop embedded-opcua-server
259 moxa@Moxa:~$ sudo systemctl restart embedded-opcua-server
260 moxa@Moxa:~$ sudo systemctl status embedded-opcua-server
261 moxa@Moxa:~$ sudo systemctl disable embedded-opcua-server
262 moxa@Moxa:~$ sudo systemctl enable embedded-opcua-server
263 ```
264
265 ### Add/Delete OPC UA server account
266
267 ```
268 moxa@Moxa:~$ sudo opcuauser --add moxa
269 moxa@Moxa:~$ sudo opcuauser --del moxa
270
271 moxa@Moxa:~$ sudo opcuauser --help
272 Usage: opcuauser [options] username
273
274 Options:
275 -a, --add Add user account
276 -d, --del Delete user account
277 -c, --change Change user password
278 -v, --verion Show version
279 -h, --help Show help
280
281 Example:
282 opcuauser Add user account
283 opcuauser username Change user password
284 opcuauser --help Show help
285 ```
286
287 Please notice that embedded-opcua-server should be reboot to take effect of user account list.
288 Current user account list can be verify by checking ```/etc/opcuauser_passwd```.
289
290 ### Anonymous user account setting
291
292 Default Anonymous user account is enable, use `opcuauser` command to add or delete anonymous user will not change anything.
293 If OPC UA Server want to delete anonymous user account, please move to file `/usr/local/bin/embeddedopcuaserver/OPCUAServerData/Config/OPCUA.json`
294
295 ```
296 ...
297 "SupportAnonymous":1,
298 ...
299 ```
300 Modify setting to disable,
301 ```
302 ...
303 "SupportAnonymous":0,
304 ...
305 ```
306
307 ### Debug
308
309 log: Systemd service syslog must be active(running)
310 - if non-active
311 - check `systemctl status embedded-opcua-server`.
312 - if active
313 - check `/var/log/syslog` to see all debug info during server enable.
314
315 ### Limitation
316
317 1. This OPC UA Server can only be executed on ioThinx-4533-LX.
318 2. Please backup `/usr/local/bin/embeddedopcuaserver/OPCUAServerData/Config` before FWR upgrade.
319 3. Use Lan1 internet setting as default connection setting.