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