- Main
- Tutorials
- Library
- Samples

- File List
- Globals

io_node_operator.c
Go to the documentation of this file.
1 /*******************************************************************************
2 * Copyright (C) 2019 Moxa Inc. All rights reserved.
3 * SPDX-License-Identifier: Apache-2.0
4 *
5 * IO Sample for Embedded OPC UA Server
6 *
7 * Date Author Comment
8 * 2019-06-05 TJ Tai Created it.
9 ******************************************************************************/
10
26 #include <unistd.h>
27 #include <string.h>
28
29 #include <iothinx/iothinxio.h>
30
32 #include <mx_node_sdk/mx_node_interface_basic.h>
33 #include <mx_node_sdk/mx_node_interface_data_access.h>
34
35 #include "DataSet.h"
36 #include "cJSON.h"
37
38 typedef enum
39 {
40 OPERATOR_STATE_STOP,
41 OPERATOR_STATE_STOPPING,
42 OPERATOR_STATE_RUNNING,
43 } OPERATOR_STATE;
44
45 struct timeval now();
46 MX_NODE_RESULT add_io_nodes();
47
48 MX_NODE_NODE_OPERATOR_HANDLE g_operator_handle;
49 volatile OPERATOR_STATE g_state;
50
51 NODE **io_example;
52 int g_totalSlot;
53 int *g_slotNodeCountRecorder;
54
57 const char* mx_node_operator_get_version()
58 {
59 return "1.0";
60 }
61
62 long long mx_node_operator_get_supported_interfaces()
63 {
64 return INTERFACE_MX_NODE_BASIC | INTERFACE_MX_NODE_DATA_ACCESS;
65 }
66
67 MX_NODE_RESULT mx_node_operator_initialize(MX_NODE_NODE_OPERATOR_HANDLE operator_handle)
68 {
69 int rc, i, j;
70 char buffer[64];
71
72 g_operator_handle = operator_handle;
73 g_state = OPERATOR_STATE_STOP;
74
75 // initialize ioThinx I/O
76 rc = ioThinx_IO_Client_Init();
77 if (rc != IOTHINX_ERR_OK)
78 {
79 printf("ioThinx_IO_Client_Init() = %d\n", rc);
80 return MX_NODE_RESULT_BAD;
81 }
82
83 // decide load config place in the device
84 rc = parse_json_file("/usr/local/bin/embeddedopcuaserver/Config/io.conf");
85 if (rc == MX_PARSE_CONFIG_ERR){
86 printf("Load configure error, can not open config file.");
87 return MX_NODE_RESULT_BAD;
88 }
89
90 return add_io_nodes();
91 }
92
93 void mx_node_operator_uninitialize()
94 {
95 size_t i,j;
96 for (i = 0; i < g_totalSlot; ++i)
97 free(io_example[i]);
98
99 free(io_example);
100 free(g_slotNodeCountRecorder);
101 printf("Uninit finished!...\n");
102 }
103
104 void mx_node_operator_start()
105 {
106 g_state = OPERATOR_STATE_RUNNING;
107 while (g_state == OPERATOR_STATE_RUNNING)
108 {
109 for(int i=0;i<g_totalSlot;i++)
110 {
111 for(int j=0;j<g_slotNodeCountRecorder[i];j++)
112 {
113 if (io_example[i][j].access == MX_NODE_ACCESS_RIGHT_READONLY || io_example[i][j].access == MX_NODE_ACCESS_RIGHT_READWRITE) {
114 io_control_read(i, j, &io_example[i][j].data);
115 }
116
117 io_example[i][j].timestamp = Now();
118 mx_node_update_node(
119 io_example[i][j].node_handle,
120 &io_example[i][j].data,
121 &io_example[i][j].timestamp
122 );
123 }
124 }
125 sleep(1);
126 }
127 g_state = OPERATOR_STATE_STOP;
128 }
129
130 void mx_node_operator_stop()
131 {
132 if (g_state == OPERATOR_STATE_RUNNING)
133 {
134 g_state = OPERATOR_STATE_STOPPING;
135 while (g_state != OPERATOR_STATE_STOP);
136 }
137 }
139
141 MX_NODE_RESULT mx_node_operator_read_node(MX_NODE_NODE_HANDLE node_handle, MX_NODE_VARIANT* node_value, struct timeval* node_timestamp)
142 {
143 int rc, i,j;
144 FUNC_TYPE fn;
145
146 for(i=0;i<g_totalSlot;i++)
147 {
148 for(j=0;j<g_slotNodeCountRecorder[i];j++)
149 {
150 if (io_example[i][j].node_handle == node_handle) {
151 printf("io[%d,%d] ch: %d, access: %d, var_type: %d, func_type: %d, name: %s, description: %s\n",
152 i,
153 j,
154 io_example[i][j].ch,
155 io_example[i][j].access,
156 io_example[i][j].var_type,
157 io_example[i][j].func_type,
158 io_example[i][j].name,
159 io_example[i][j].description);
160
161 if (io_example[i][j].access == MX_NODE_ACCESS_RIGHT_READONLY || io_example[i][j].access == MX_NODE_ACCESS_RIGHT_READWRITE) {
162 rc = io_control_read(i, j, node_value);
163 if (rc != MX_IO_CONTROL_OK) {
164 return MX_NODE_RESULT_BAD;
165 }
166 *node_timestamp = io_example[i][j].timestamp;
167 }
168 }
169 }
170 }
171
172 return MX_NODE_RESULT_GOOD;
173 }
174
175 MX_NODE_RESULT mx_node_operator_write_node(MX_NODE_NODE_HANDLE node_handle, const MX_NODE_VARIANT* node_value)
176 {
177 int rc, i,j;
178
179 for(i=0;i<g_totalSlot;i++)
180 {
181 for(j=0;j<g_slotNodeCountRecorder[i];j++)
182 {
183 if (io_example[i][j].node_handle == node_handle) {
184 printf("io[%d,%d] ch: %d, access: %d, var_type: %d, func_type: %d, name: %s, description: %s\n",
185 i,
186 j,
187 io_example[i][j].ch,
188 io_example[i][j].access,
189 io_example[i][j].var_type,
190 io_example[i][j].func_type,
191 io_example[i][j].name,
192 io_example[i][j].description);
193
194 if (io_example[i][j].access == MX_NODE_ACCESS_RIGHT_WRITEONLY || io_example[i][j].access == MX_NODE_ACCESS_RIGHT_READWRITE) {
195 rc = io_control_write(i, j, node_value);
196 if (rc != MX_IO_CONTROL_OK) {
197 return MX_NODE_RESULT_BAD;
198 }
199 io_example[i][j].timestamp = Now();
200 }
201 }
202 }
203 }
204
205 return MX_NODE_RESULT_GOOD;
206 }
209
210 MX_NODE_RESULT add_io_nodes()
211 {
212 MX_NODE_RESULT res;
213 int rc, i,j;
214
215 // folder
216 MX_NODE_NODE folder;
217 {
218 strcpy(folder.node_name, "ioThinx-4533");
219 folder.node_type = MX_NODE_NODE_TYPE_FOLDER;
220 strcpy(folder.description, "device name");
221 }
222 MX_NODE_NODE_HANDLE folder_handle;
223 res = mx_node_add_node(g_operator_handle, &folder, &folder_handle);
224 if (res != MX_NODE_RESULT_GOOD)
225 return res;
226
227 // object
228 for(i=0;i<g_totalSlot;i++)
229 {
230 MX_NODE_NODE object;
231 {
232 sprintf(object.node_name, "Slot_%d", i);
233 object.node_type = MX_NODE_NODE_TYPE_OBJECT;
234 strcpy(object.description, "number of slot");
235 }
236 MX_NODE_NODE_HANDLE object_handle;
237 res = mx_node_add_node(g_operator_handle, &object, &object_handle);
238 if (res != MX_NODE_RESULT_GOOD)
239 return res;
240 res = mx_node_set_parent_node(object_handle, folder_handle);
241 if (res != MX_NODE_RESULT_GOOD)
242 return res;
243
244 // variable
245 for(j=0;j<g_slotNodeCountRecorder[i];j++){
246 MX_NODE_NODE variable;
247 {
248 strcpy(variable.node_name, io_example[i][j].name);
249 variable.node_type = MX_NODE_NODE_TYPE_VARIABLE;
250 strcpy(variable.description, io_example[i][j].description);
251 variable.variable.access_right = io_example[i][j].access;
252 io_example[i][j].data.type = io_example[i][j].var_type;
253 memset(&io_example[i][j].data.value, 0, sizeof(io_example[i][j].data.value));
254 variable.variable.value = io_example[i][j].data;
255 }
256 res = mx_node_add_node(g_operator_handle, &variable, &io_example[i][j].node_handle);
257 if (res != MX_NODE_RESULT_GOOD)
258 return res;
259 res = mx_node_set_parent_node(io_example[i][j].node_handle, object_handle);
260 if (res != MX_NODE_RESULT_GOOD)
261 return res;
262 }
263 }
264
265 // Config IO mode
266 uint8_t channel_count = 1;
267 uint8_t di_mode;
268 uint8_t do_mode;
269 uint8_t counter_triggers;
270 uint16_t pwm_freq = 5;
271 uint16_t pwm_duty = 50;
272 for (i = 0; i < g_totalSlot; ++i){
273 for(j = 0; j< g_slotNodeCountRecorder[i]; j++){
274 if (io_example[i][j].func_type == OPC_DO_PULSECOUNT || io_example[i][j].func_type == OPC_DO_PULSESTATUS) {
275 // set to DO_MODE PULSE
276 do_mode = DO_MODE_PWM;
277 rc = ioThinx_DO_Config_SetModes(i, io_example[i][j].ch, channel_count, &do_mode);
278 if (rc != IOTHINX_ERR_OK)
279 {
280 printf("ioThinx_DO_Config_SetModes() = %d\n", rc);
281 }
282 //set frq and duty cycle
283 rc = ioThinx_DO_Config_SetPwmConfigures(i, io_example[i][j].ch, channel_count, &pwm_freq, &pwm_duty);
284 if (rc != IOTHINX_ERR_OK)
285 {
286 printf("ioThinx_DO_Config_SetPwmConfigures() = %d\n", rc);
287 }
288 }
289 if (io_example[i][j].func_type == OPC_DI_COUNTERSTATUS || io_example[i][j].func_type == OPC_DI_COUNTERVALUE) {
290 // set to DI_MODE COUNTER
291 di_mode = DI_MODE_COUNTER;
292 counter_triggers = CNT_TRIGGER_BOTH;
293 rc = ioThinx_DI_Config_SetModes(i, io_example[i][j].ch, channel_count, &di_mode);
294 if (rc != IOTHINX_ERR_OK)
295 {
296 printf("ioThinx_DI_Config_SetModes() = %d\n", rc);
297 }
298 rc = ioThinx_DI_Config_SetCntTriggers(i, io_example[i][j].ch, channel_count, &counter_triggers);
299 if (rc != IOTHINX_ERR_OK)
300 {
301 printf("ioThinx_DI_Config_SetCntTriggers() = %d\n", rc);
302 }
303 }
304 }
305 }
306 // reload config
307 rc = ioThinx_IO_Config_Reload();
308 if (rc != IOTHINX_ERR_OK)
309 {
310 printf("ioThinx_IO_Config_Reload() = %d\n", rc);
311 }
312 return MX_NODE_RESULT_GOOD;
313 }
314
315 int parse_json_file(const char *filename)
316 {
317 FILE *f;
318 int len;
319 char *data;
320
321 f=fopen(filename,"rb");
322 if (f == NULL)
323 return MX_PARSE_CONFIG_ERR;
324 fseek(f,0,SEEK_END);
325 len=ftell(f);
326 fseek(f,0,SEEK_SET);
327 data=(char*)malloc(len+1);
328 fread(data,1,len,f);
329 fclose(f);
330
331 printf("parse file %s complete, len=%d.\n",filename,len);
332
333 cJSON_to_struct_array(data);
334
335 free(data);
336 return 0;
337 }
338
339 //parse a struct array
340 int cJSON_to_struct_array(char *text)
341 {
342 cJSON *json,*item,*object, *slotItem, *chObj;
343 int i,j;
344
345 json=cJSON_Parse(text);
346 if (!json)
347 {
348 printf("Error before: [%s]\n",cJSON_GetErrorPtr());
349 }
350 else {
351 slotItem=cJSON_GetObjectItem(json,"slot");
352 if(slotItem!=NULL)
353 {
354 g_totalSlot =cJSON_GetArraySize(slotItem);
355 //printf("cJSON_GetSlotSize: g_totalSlot=%d\n",g_totalSlot);
356 io_example = (NODE **)malloc(sizeof(NODE *)*g_totalSlot);
357 g_slotNodeCountRecorder = (int*)malloc(sizeof(int)*g_totalSlot);
358
359 for(i=0;i<g_totalSlot;i++)
360 {
361 //printf("i=%d\n",i);
362 chObj=cJSON_GetArrayItem(slotItem,i);
363 int chsize = cJSON_GetArraySize(chObj);
364 io_example[i] = (NODE *)calloc(chsize, sizeof(NODE));
365 g_slotNodeCountRecorder[i] = chsize;
366 //printf("chsize=%d\n",chsize);
367
368 for(j=0;j<chsize;j++){
369 object=cJSON_GetArrayItem(chObj,j);
370
371 item=cJSON_GetObjectItem(object,"ch");
372 if(item!=NULL)
373 {
374 //printf("cJSON_GetObjectItem: type=%d, string is %s, valueint=%d\n",item->type,item->string,item->valueint);
375 io_example[i][j].ch=item->valueint;
376 }
377 else{
378 printf("cJSON_GetObjectItem: get ch failed\n");
379 }
380
381 item=cJSON_GetObjectItem(object,"access");
382 if(item!=NULL)
383 {
384 //printf("cJSON_GetObjectItem: type=%d, string is %s, valueint=%d\n",item->type,item->string,item->valueint);
385 io_example[i][j].access=item->valueint;
386 }
387 else{
388 printf("cJSON_GetObjectItem: get access failed\n");
389 }
390 item=cJSON_GetObjectItem(object,"variant_type");
391 if(item!=NULL)
392 {
393 //printf("cJSON_GetObjectItem: type=%d, string is %s, valueint=%d\n",item->type,item->string,item->valueint);
394 io_example[i][j].var_type=item->valueint;
395 }
396 else{
397 printf("cJSON_GetObjectItem: get variable_type failed\n");
398 }
399 item=cJSON_GetObjectItem(object,"func_type");
400 if(item!=NULL)
401 {
402 //printf("cJSON_GetObjectItem: type=%d, string is %s, valueint=%d\n",item->type,item->string,item->valueint);
403 io_example[i][j].func_type=item->valueint;
404 }
405 else{
406 printf("cJSON_GetObjectItem: get func_type failed\n");
407 }
408 item=cJSON_GetObjectItem(object,"name");
409 if(item!=NULL)
410 {
411 //printf("cJSON_GetObjectItem: type=%d, string is %s\n",item->type,item->string);
412 if (i==0 && io_example[i][j].ch == -1) // slot 0 name
413 sprintf(io_example[i][j].name, "S%d_%s", i, item->valuestring);
414 else
415 sprintf(io_example[i][j].name, "S%d_C%d_%s", i, io_example[i][j].ch, item->valuestring);
416 }
417 item=cJSON_GetObjectItem(object,"description");
418 if(item!=NULL)
419 {
420 //printf("cJSON_GetObjectItem: type=%d, string is %s\n",item->type,item->string);
421 memcpy(io_example[i][j].description,item->valuestring,strlen(item->valuestring));
422 }
423 }
424 }
425 }
426
427 //for(i=0;i<g_totalSlot;i++)
428 //{
429 // for(j=0;j<g_slotNodeCountRecorder[i];j++)
430 // {
431 // printf("io[%d,%d] ch: %d, access: %d, var_type: %d, func_type: %d, name: %s, description: %s\n",
432 // i,
433 // j,
434 // io_example[i][j].ch,
435 // io_example[i][j].access,
436 // io_example[i][j].var_type,
437 // io_example[i][j].func_type,
438 // io_example[i][j].name,
439 // io_example[i][j].description);
440 // }
441 // printf("\r\n");
442 //}
443
444 cJSON_Delete(json);
445 }
446 return 0;
447 }
448
449 int io_control_read(int slot, int index, MX_NODE_VARIANT* node_value)
450 {
451 FUNC_TYPE fn;
452 int32_t rc = 0;
453 int32_t value_int;
454 uint32_t di_values = 0;
455 uint32_t do_values = 0;
456 uint32_t relay_values = 0;
457 uint32_t pwm_starts = 0;
458 uint32_t counter_starts = 0;
459 uint32_t value_uint = 0;
460 uint32_t ai_raws = 0;
461 float value_float = 0;
462 uint8_t value_uint8 = 0;
463
464 switch(io_example[slot][index].func_type){
465 case OPC_DI_MODE:
466 rc = ioThinx_DI_Config_GetModes(slot, io_example[slot][index].ch, 1, &value_uint8);
467 if (rc != IOTHINX_ERR_OK)
468 {
469 printf("ioThinx_DI_Config_GetModes() = %d\n", rc);
470 return MX_IO_CONTROL_ERR;
471 }
472 io_example[slot][index].data.value.u32 = (uint32_t)value_uint8;
473 break;
474 case OPC_DI_STATUS:
475 rc = ioThinx_DI_GetValues(slot, &di_values);
476 if (rc != IOTHINX_ERR_OK)
477 {
478 printf("ioThinx_DI_GetValues() = %d\n", rc);
479 return MX_IO_CONTROL_ERR;
480 }
481 value_int = (di_values >> io_example[slot][index].ch)& 0x1;
482 //printf("\r\n=========> MX_Read() set value = %d\r\n", value_int);
483 io_example[slot][index].data.value.i32 = value_int;
484 break;
485 case OPC_DI_COUNTERSTATUS:
486 rc = ioThinx_DI_GetCntStarts(slot, &counter_starts);
487 if (rc != IOTHINX_ERR_OK)
488 {
489 printf("\r\n ioThinx_DI_GetCntStarts() = %d\r\n", rc);
490 return MX_IO_CONTROL_ERR;
491 }
492 value_int = (counter_starts >> io_example[slot][index].ch)& 0x1;
493 io_example[slot][index].data.value.i32 = value_int;
494 break;
495 case OPC_DI_COUNTERVALUE:
496 rc = ioThinx_DI_GetCntValues(slot, io_example[slot][index].ch, 1, &value_uint);
497 if (rc != IOTHINX_ERR_OK)
498 {
499 printf("ioThinx_DI_GetCntValues() = %d\n", rc);
500 return MX_IO_CONTROL_ERR;
501 }
502 io_example[slot][index].data.value.u32 = value_uint;
503 break;
504 case OPC_DO_MODE:
505 rc = ioThinx_DO_Config_GetModes(slot, io_example[slot][index].ch, 1, &value_uint8);
506 if (rc != IOTHINX_ERR_OK)
507 {
508 printf("ioThinx_DO_Config_GetModes() = %d\n", rc);
509 }
510 io_example[slot][index].data.value.u32 = (uint32_t)value_uint8;
511 break;
512 case OPC_DO_STATUS:
513 rc = ioThinx_DO_GetValues(slot, &do_values);
514 if (rc != IOTHINX_ERR_OK)
515 {
516 printf("\r\n*** [ERR] ioThinx_DO_GetValues() = %d\r\n", rc);
517 return MX_IO_CONTROL_ERR;
518 }
519 value_int = (do_values >> io_example[slot][index].ch)& 0x1;
520 //printf("\r\n=========> MX_Read() set value = %d\r\n", value_int);
521 io_example[slot][index].data.value.i32 = value_int;
522 break;
523 case OPC_DO_PULSESTATUS:
524 rc = ioThinx_DO_GetPwmStarts(slot, &pwm_starts);
525 if (rc != IOTHINX_ERR_OK)
526 {
527 printf("\r\n ioThinx_DO_GetPwmStarts() = %d\r\n", rc);
528 return MX_IO_CONTROL_ERR;
529 }
530 value_int = (pwm_starts >> io_example[slot][index].ch)& 0x1;
531 io_example[slot][index].data.value.i32 = value_int;
532 break;
533 case OPC_DO_PULSECOUNT:
534 rc = ioThinx_DO_GetPwmCounts(slot, io_example[slot][index].ch, 1, &value_uint);
535 if (rc != IOTHINX_ERR_OK)
536 {
537 printf("ioThinx_DO_Config_GetPwmCounts() = %d\n", rc);
538 return MX_IO_CONTROL_ERR;
539 }
540 io_example[slot][index].data.value.u32 = value_uint;
541 break;
542 case OPC_RELAY_VALUE:
543 rc = ioThinx_Relay_GetValues(slot, &relay_values);
544 if (rc != IOTHINX_ERR_OK)
545 {
546 printf("ioThinx_Relay_GetValues() = %d\n", rc);
547 return MX_IO_CONTROL_ERR;
548 }
549 value_int = (relay_values >> io_example[slot][index].ch)& 0x1;
550 //printf("\r\n=========> MX_Read() set value = %d\r\n", value_int);
551 io_example[slot][index].data.value.i32 = value_int;
552 break;
553 case OPC_AI_MODE:
554 rc = ioThinx_AI_Config_GetRanges(slot, io_example[slot][index].ch, 1, &value_uint8);
555 if (rc != IOTHINX_ERR_OK)
556 {
557 printf("ioThinx_AI_GetEngs() = %d\n", rc);
558 return MX_IO_CONTROL_ERR;
559 }
560 //printf("\r\n=========> MX_Read() set value = %u\r\n", value_uint8);
561 io_example[slot][index].data.value.u8 = value_uint8;
562 break;
563 case OPC_AI_STATUS:
564 rc = ioThinx_AI_GetStatuss(slot, io_example[slot][index].ch, 1, &value_uint8);
565 if (rc != IOTHINX_ERR_OK)
566 {
567 printf("ioThinx_AI_GetEngs() = %d\n", rc);
568 return MX_IO_CONTROL_ERR;
569 }
570 //printf("\r\n=========> MX_Read() set value = %u\r\n", value_uint8);
571 io_example[slot][index].data.value.u8 = value_uint8;
572 break;
573 case OPC_AI_RAWVALUE:
574 rc = ioThinx_AI_GetRaws(slot, io_example[slot][index].ch, 1, &ai_raws);
575 if (rc != IOTHINX_ERR_OK)
576 {
577 printf("ioThinx_AI_GetEngs() = %d\n", rc);
578 return MX_IO_CONTROL_ERR;
579 }
580 //printf("\r\n=========> MX_Read() set value = %lu\r\n", ai_raws);
581 io_example[slot][index].data.value.u32 = ai_raws;
582 break;
583 case OPC_AI_MINIMUMRAWVALUE:
584 rc = ioThinx_AI_GetMinRaws(slot, io_example[slot][index].ch, 1, &ai_raws);
585 if (rc != IOTHINX_ERR_OK)
586 {
587 printf("ioThinx_AI_GetEngs() = %d\n", rc);
588 return MX_IO_CONTROL_ERR;
589 }
590 //printf("\r\n=========> MX_Read() set value = %lu\r\n", ai_raws);
591 io_example[slot][index].data.value.u32 = ai_raws;
592 break;
593 case OPC_AI_MAXIMUMRAWVALUE:
594 rc = ioThinx_AI_GetMaxRaws(slot, io_example[slot][index].ch, 1, &ai_raws);
595 if (rc != IOTHINX_ERR_OK)
596 {
597 printf("ioThinx_AI_GetEngs() = %d\n", rc);
598 return MX_IO_CONTROL_ERR;
599 }
600 //printf("\r\n=========> MX_Read() set value = %lu\r\n", ai_raws);
601 io_example[slot][index].data.value.u32 = ai_raws;
602 break;
603 case OPC_AI_SCALEDVALUE:
604 rc = ioThinx_AI_GetEngs(slot, io_example[slot][index].ch, 1, &value_float);
605 if (rc != IOTHINX_ERR_OK)
606 {
607 printf("ioThinx_AI_GetEngs() = %d\n", rc);
608 return MX_IO_CONTROL_ERR;
609 }
610 //printf("\r\n=========> MX_Read() set value = %f\r\n", value_float);
611 io_example[slot][index].data.value.f = value_float;
612 break;
613 default:
614 printf("IO function not found!\r\n");
615 return MX_IO_CONTROL_ERR;
616 }
617 *node_value = io_example[slot][index].data;
618
619 return MX_IO_CONTROL_OK;
620 }
621
622 int io_control_write(int slot, int index, const MX_NODE_VARIANT* node_value)
623 {
624 FUNC_TYPE fn;
625 int32_t value_int = 0;
626 uint32_t do_values = 0;
627 uint32_t pwm_starts = 0;
628 uint32_t counter_starts = 0;
629 uint32_t value_uint = 0;
630 uint32_t relay_values = 0;
631 int rc = 0;
632
633 switch(io_example[slot][index].func_type){
634 case OPC_DI_COUNTERSTATUS:
635 if (node_value->type == MX_NODE_VALUE_TYPE_INT32) {
636 value_int = node_value->value.i32;
637 }
638 else {
639 return MX_IO_CONTROL_ERR;
640 }
641 if (value_int != 0 && value_int != 1) {
642 return MX_IO_CONTROL_ERR;
643 }
644 rc = ioThinx_DI_GetCntStarts(slot, &counter_starts);
645 if (rc != IOTHINX_ERR_OK)
646 {
647 printf("\r\n ioThinx_DI_GetCntStarts() = %d\r\n", rc);
648 return MX_IO_CONTROL_ERR;
649 }
650 if (value_int == 1) {
651 counter_starts |= 0x1 << (io_example[slot][index].ch);
652 rc = ioThinx_DI_SetCntStarts(slot, counter_starts);
653 if (rc != IOTHINX_ERR_OK)
654 {
655 printf("ioThinx_DI_SetCntStarts() = %d\n", rc);
656 return MX_IO_CONTROL_ERR;
657 }
658 }
659 else if (value_int == 0) {
660 counter_starts |= 0x1 << (io_example[slot][index].ch);
661 rc = ioThinx_DI_SetCntStops(slot, counter_starts);
662 if (rc != IOTHINX_ERR_OK)
663 {
664 printf("ioThinx_DI_SetCntStops() = %d\n", rc);
665 return MX_IO_CONTROL_ERR;
666 }
667 }
668 else {
669 return MX_IO_CONTROL_ERR;
670 }
671 break;
672 case OPC_DI_COUNTERVALUE:
673 if (node_value->type == MX_NODE_VALUE_TYPE_UINT32) {
674 value_uint = node_value->value.u32;
675 }
676 else {
677 return MX_IO_CONTROL_ERR;
678 }
679 rc = ioThinx_DI_SetCntValues(slot, io_example[slot][index].ch, 1, &value_uint);
680 if (rc != IOTHINX_ERR_OK)
681 {
682 printf("ioThinx_DI_SetCntValues() = %d\n", rc);
683 return MX_IO_CONTROL_ERR;
684 }
685 break;
686 case OPC_DO_STATUS:
687 if (node_value->type == MX_NODE_VALUE_TYPE_INT32) {
688 value_int = node_value->value.i32;
689 }
690 else {
691 return MX_IO_CONTROL_ERR;
692 }
693 if (value_int != 0 && value_int != 1) {
694 return MX_IO_CONTROL_ERR;
695 }
696 //printf("\r\n=========> MX_Write() set value = %d\r\n", value_int);
697 rc = ioThinx_DO_GetValues(slot, &do_values);
698 if (rc != IOTHINX_ERR_OK)
699 {
700 printf("\r\nioThinx_DO_GetValues() = %d\r\n", rc);
701 return MX_IO_CONTROL_ERR;
702 }
703 do_values = do_values & ~(0x1 << io_example[slot][index].ch) | (value_int << io_example[slot][index].ch);
704 //printf("do value = %lu\n", (unsigned long)do_values);
705 rc = ioThinx_DO_SetValues(slot, do_values);
706 if (rc != IOTHINX_ERR_OK)
707 {
708 printf("ioThinx_DO_SetValues() = %d\n", rc);
709 return MX_IO_CONTROL_ERR;
710 }
711 //printf("\r\n******************* [%lu:%u] DO value = %x\r\n", do_slot, do_channel, (do_values >> do_channel) & 0x1);
712 break;
713 case OPC_DO_PULSESTATUS:
714 if (node_value->type == MX_NODE_VALUE_TYPE_INT32) {
715 value_int = node_value->value.i32;
716 }
717 else {
718 return MX_IO_CONTROL_ERR;
719 }
720 if (value_int != 0 && value_int != 1) {
721 return MX_IO_CONTROL_ERR;
722 }
723 rc = ioThinx_DO_GetPwmStarts(slot, &pwm_starts);
724 if (rc != IOTHINX_ERR_OK)
725 {
726 printf("\r\n ioThinx_DO_GetPwmStarts() = %d\r\n", rc);
727 return MX_IO_CONTROL_ERR;
728 }
729 if (value_int == 1) {
730 // start pwm
731 pwm_starts |= 0x1 << (io_example[slot][index].ch);
732 rc = ioThinx_DO_SetPwmStarts(slot, pwm_starts);
733 if (rc != IOTHINX_ERR_OK)
734 {
735 printf("ioThinx_DO_SetPwmStarts() = %d\n", rc);
736 return MX_IO_CONTROL_ERR;
737 }
738 }
739 else if (value_int == 0) {
740 // stop pwm
741 pwm_starts |= 0x1 << (io_example[slot][index].ch);
742 rc = ioThinx_DO_SetPwmStops(slot, pwm_starts);
743 if (rc != IOTHINX_ERR_OK)
744 {
745 printf("ioThinx_DO_SetPwmStops() = %d\n", rc);
746 return MX_IO_CONTROL_ERR;
747 }
748 }
749 else {
750 return MX_IO_CONTROL_ERR;
751 }
752 break;
753 case OPC_DO_PULSECOUNT:
754 if (node_value->type == MX_NODE_VALUE_TYPE_UINT32) {
755 value_uint = node_value->value.u32;
756 }
757 else {
758 return MX_IO_CONTROL_ERR;
759 }
760 rc = ioThinx_DO_SetPwmCounts(slot, io_example[slot][index].ch, 1, &value_uint);
761 if (rc != IOTHINX_ERR_OK)
762 {
763 printf("ioThinx_DO_Config_SetPwmCounts() = %d\n", rc);
764 }
765 break;
766 case OPC_RELAY_VALUE:
767 if (node_value->type == MX_NODE_VALUE_TYPE_INT32) {
768 value_int = node_value->value.i32;
769 }
770 else {
771 return MX_IO_CONTROL_ERR;
772 }
773 //printf("\r\n=========> MX_Write() set value = %d\r\n", value_int);
774 if (value_int != 0 && value_int != 1) {
775 return MX_IO_CONTROL_ERR;
776 }
777 rc = ioThinx_Relay_GetValues(slot, &relay_values);
778 if (rc != IOTHINX_ERR_OK)
779 {
780 printf("\r\nioThinx_DO_GetValues() = %d\r\n", rc);
781 return MX_IO_CONTROL_ERR;
782 }
783 relay_values = relay_values & ~(0x1 << io_example[slot][index].ch) | (value_int << io_example[slot][index].ch);
784 //printf("relay value = %lu\n", (unsigned long)relay_values);
785 rc = ioThinx_Relay_SetValues(slot, relay_values);
786 if (rc != IOTHINX_ERR_OK)
787 {
788 printf("ioThinx_DO_SetValues() = %d\n", rc);
789 return MX_IO_CONTROL_ERR;
790 }
791 //printf("\r\n******************* [%lu:%u] DO value = %x\r\n", slot, io_example[slot][index].ch, (relay_values >> io_example[slot][index].ch) & 0x1);
792 break;
793 default:
794 printf("function not found!\r\n");
795 }
796 io_example[slot][index].data = *node_value;
797 return MX_IO_CONTROL_OK;
798 }
OPERATOR_STATE_STOP
Definition: io_node_operator.c:40
_MX_NODE_VARIABLE::value
MX_NODE_VARIANT value
Definition: mx_node_node_def.h:123
_MX_NODE_VARIANT::u8
uint8_t u8
Definition: mx_node_node_def.h:107
mx_node_add_node
MX_NODE_RESULT mx_node_add_node(MX_NODE_NODE_OPERATOR_HANDLE operator_handle, MX_NODE_NODE *node, MX_NODE_NODE_HANDLE *node_handle)
Add a node to OPC UA server.
_io_node
Definition: DataSet.h:14
ioThinx_DO_SetPwmCounts
IOTHINX_ERR ioThinx_DO_SetPwmCounts(uint32_t slot, uint8_t start, uint8_t count, uint32_t buf[])
mx_node_operator_write_node
MX_NODE_RESULT mx_node_operator_write_node(MX_NODE_NODE_HANDLE node_handle, const MX_NODE_VARIANT *node_value)
Write data by handle index.
_MX_NODE_VARIANT
A variant structure is used to store different type&#39;s data.
Definition: mx_node_node_def.h:97
mx_node_operator_start
void mx_node_operator_start()
A notify to inform node operator start with non-blocking.
ioThinx_DI_SetCntStops
IOTHINX_ERR ioThinx_DI_SetCntStops(uint32_t slot, uint32_t stops)
ioThinx_AI_GetMinRaws
IOTHINX_ERR ioThinx_AI_GetMinRaws(uint32_t slot, uint8_t start, uint8_t count, uint32_t buf[])
ioThinx_DI_GetCntStarts
IOTHINX_ERR ioThinx_DI_GetCntStarts(uint32_t slot, uint32_t *p_starts)
MX_NODE_NODE_HANDLE
size_t MX_NODE_NODE_HANDLE
Handle of a node.
Definition: mx_node_node.h:42
INTERFACE_MX_NODE_BASIC
#define INTERFACE_MX_NODE_BASIC
Interface basic&#39;s flag.
Definition: mx_node_interface_basic.h:42
Now
struct timeval Now()
Definition: DataSet.h:50
OPC_DI_COUNTERSTATUS
Definition: DataSet.h:30
g_slotNodeCountRecorder
int * g_slotNodeCountRecorder
Definition: io_node_operator.c:53
OPC_AI_STATUS
Definition: DataSet.h:37
MX_NODE_ACCESS_RIGHT_READWRITE
Definition: mx_node_node_def.h:90
MX_PARSE_CONFIG_ERR
#define MX_PARSE_CONFIG_ERR
Definition: DataSet.h:10
MX_NODE_NODE_TYPE_VARIABLE
Definition: mx_node_node_def.h:44
cJSON::valueint
int valueint
Definition: cJSON.h:117
_io_node::access
int access
Definition: DataSet.h:20
_MX_NODE_NODE::variable
MX_NODE_VARIABLE variable
Definition: mx_node_node_def.h:148
MX_NODE_RESULT
enum _MX_NODE_RESULT MX_NODE_RESULT
A result enumeration represents success or not.
g_state
volatile OPERATOR_STATE g_state
Definition: io_node_operator.c:49
ioThinx_DI_SetCntStarts
IOTHINX_ERR ioThinx_DI_SetCntStarts(uint32_t slot, uint32_t starts)
MX_NODE_ACCESS_RIGHT_READONLY
Definition: mx_node_node_def.h:88
_io_node::ch
int ch
Definition: DataSet.h:16
OPC_AI_MAXIMUMRAWVALUE
Definition: DataSet.h:40
ioThinx_DO_SetPwmStops
IOTHINX_ERR ioThinx_DO_SetPwmStops(uint32_t slot, uint32_t stops)
ioThinx_DO_GetPwmCounts
IOTHINX_ERR ioThinx_DO_GetPwmCounts(uint32_t slot, uint8_t start, uint8_t count, uint32_t buf[])
ioThinx_Relay_GetValues
IOTHINX_ERR ioThinx_Relay_GetValues(uint32_t slot, uint32_t *p_values)
ioThinx_DO_SetValues
IOTHINX_ERR ioThinx_DO_SetValues(uint32_t slot, uint32_t values)
_io_node::timestamp
struct timeval timestamp
Definition: DataSet.h:24
MX_NODE_ACCESS_RIGHT_WRITEONLY
Definition: mx_node_node_def.h:89
mx_node_operator_stop
void mx_node_operator_stop()
A notify to inform node operator stopping.
OPERATOR_STATE_RUNNING
Definition: io_node_operator.c:42
_MX_NODE_NODE
A node&#39;s sturcture contain name, description, node type and attribute.
Definition: mx_node_node_def.h:139
ioThinx_DI_Config_SetModes
IOTHINX_ERR ioThinx_DI_Config_SetModes(uint32_t slot, uint8_t start, uint8_t count, uint8_t buf[])
index
int index
Definition: cJSON.h:168
mx_node_set_parent_node
MX_NODE_RESULT mx_node_set_parent_node(MX_NODE_NODE_HANDLE node_handle, MX_NODE_NODE_HANDLE parent_node_handle)
Set a node&#39;s parent.
ioThinx_DO_GetPwmStarts
IOTHINX_ERR ioThinx_DO_GetPwmStarts(uint32_t slot, uint32_t *p_starts)
INTERFACE_MX_NODE_DATA_ACCESS
#define INTERFACE_MX_NODE_DATA_ACCESS
Interface data access&#39;s flag.
Definition: mx_node_interface_basic.h:48
DO_MODE_PWM
#define DO_MODE_PWM
Definition: iothinxio.h:292
ioThinx_DI_GetCntValues
IOTHINX_ERR ioThinx_DI_GetCntValues(uint32_t slot, uint8_t start, uint8_t count, uint32_t buf[])
mx_node_operator_get_version
const char * mx_node_operator_get_version()
Get node operator&#39;s version.
mx_node_operator_read_node
MX_NODE_RESULT mx_node_operator_read_node(MX_NODE_NODE_HANDLE node_handle, MX_NODE_VARIANT *node_value, struct timeval *node_timestamp)
Read a node&#39;s data and timestamp.
_MX_NODE_VARIANT::i32
int32_t i32
Definition: mx_node_node_def.h:105
mx_node_operator_get_supported_interfaces
long long mx_node_operator_get_supported_interfaces()
Get supported interfaces.
name
const char *const name
Definition: cJSON.h:258
_MX_NODE_VARIANT::u32
uint32_t u32
Definition: mx_node_node_def.h:109
ioThinx_AI_GetMaxRaws
IOTHINX_ERR ioThinx_AI_GetMaxRaws(uint32_t slot, uint8_t start, uint8_t count, uint32_t buf[])
IOTHINX_ERR_OK
#define IOTHINX_ERR_OK
Definition: iothinxio.h:35
io_example
NODE ** io_example
Definition: io_node_operator.c:51
io_control_write
int io_control_write(int slot, int index, const MX_NODE_VARIANT *node_value)
Definition: io_node_operator.c:622
OPC_RELAY_VALUE
Definition: DataSet.h:42
_MX_NODE_VARIABLE::access_right
MX_NODE_ACCESS_RIGHT access_right
Definition: mx_node_node_def.h:124
OPC_DO_PULSECOUNT
Definition: DataSet.h:35
g_totalSlot
int g_totalSlot
Definition: io_node_operator.c:52
CNT_TRIGGER_BOTH
#define CNT_TRIGGER_BOTH
Definition: iothinxio.h:99
ioThinx_Relay_SetValues
IOTHINX_ERR ioThinx_Relay_SetValues(uint32_t slot, uint32_t values)
ioThinx_DO_Config_SetModes
IOTHINX_ERR ioThinx_DO_Config_SetModes(uint32_t slot, uint8_t start, uint8_t count, uint8_t buf[])
ioThinx_AI_GetRaws
IOTHINX_ERR ioThinx_AI_GetRaws(uint32_t slot, uint8_t start, uint8_t count, uint32_t buf[])
MX_NODE_RESULT_GOOD
Definition: mx_node_node_def.h:158
MX_NODE_NODE_TYPE_OBJECT
Definition: mx_node_node_def.h:43
parse_json_file
int parse_json_file(const char *filename)
Definition: io_node_operator.c:315
DI_MODE_COUNTER
#define DI_MODE_COUNTER
Definition: iothinxio.h:89
cJSON_to_struct_array
int cJSON_to_struct_array(char *text)
Definition: io_node_operator.c:340
MX_NODE_VALUE_TYPE_INT32
Definition: mx_node_node_def.h:71
OPC_AI_MODE
Definition: DataSet.h:36
ioThinx_DI_Config_GetModes
IOTHINX_ERR ioThinx_DI_Config_GetModes(uint32_t slot, uint8_t start, uint8_t count, uint8_t buf[])
buffer
char * buffer
Definition: cJSON.h:161
cJSON.h
OPC_DI_MODE
Definition: DataSet.h:28
MX_IO_CONTROL_ERR
#define MX_IO_CONTROL_ERR
Definition: DataSet.h:12
add_io_nodes
MX_NODE_RESULT add_io_nodes()
Definition: io_node_operator.c:210
now
struct timeval now()
custom function
Definition: demo_node_operator.c:303
ioThinx_AI_GetEngs
IOTHINX_ERR ioThinx_AI_GetEngs(uint32_t slot, uint8_t start, uint8_t count, float buf[])
ioThinx_AI_Config_GetRanges
IOTHINX_ERR ioThinx_AI_Config_GetRanges(uint32_t slot, uint8_t start, uint8_t count, uint8_t buf[])
FUNC_TYPE
FUNC_TYPE
Definition: DataSet.h:27
OPC_DO_STATUS
Definition: DataSet.h:33
item
cJSON * item
Definition: cJSON.h:218
OPC_AI_MINIMUMRAWVALUE
Definition: DataSet.h:39
ioThinx_IO_Config_Reload
IOTHINX_ERR ioThinx_IO_Config_Reload(void)
ioThinx_DI_Config_SetCntTriggers
IOTHINX_ERR ioThinx_DI_Config_SetCntTriggers(uint32_t slot, uint8_t start, uint8_t count, uint8_t buf[])
OPC_DI_STATUS
Definition: DataSet.h:29
_io_node::func_type
int func_type
Definition: DataSet.h:19
io_control_read
int io_control_read(int slot, int index, MX_NODE_VARIANT *node_value)
Definition: io_node_operator.c:449
_MX_NODE_NODE::node_name
char node_name[MAX_NODE_NAME_LEN]
Definition: mx_node_node_def.h:141
MX_NODE_VALUE_TYPE_UINT32
Definition: mx_node_node_def.h:75
ioThinx_DO_Config_SetPwmConfigures
IOTHINX_ERR ioThinx_DO_Config_SetPwmConfigures(uint32_t slot, uint8_t start, uint8_t count, uint16_t frequencies[], uint16_t duty_cycles[])
g_operator_handle
MX_NODE_NODE_OPERATOR_HANDLE g_operator_handle
Definition: io_node_operator.c:48
ioThinx_DI_SetCntValues
IOTHINX_ERR ioThinx_DI_SetCntValues(uint32_t slot, uint8_t start, uint8_t count, uint32_t buf[])
ioThinx_DI_GetValues
IOTHINX_ERR ioThinx_DI_GetValues(uint32_t slot, uint32_t *p_values)
OPERATOR_STATE
OPERATOR_STATE
include interfaces
Definition: io_node_operator.c:38
_MX_NODE_NODE::description
char description[MAX_NODE_DESC_LEN]
Definition: mx_node_node_def.h:142
_MX_NODE_VARIANT::type
MX_NODE_VALUE_TYPE type
Definition: mx_node_node_def.h:99
DataSet.h
mx_node_operator_uninitialize
void mx_node_operator_uninitialize()
Do node operator&#39;s uninitialize.
OPERATOR_STATE_STOPPING
Definition: io_node_operator.c:41
MX_IO_CONTROL_OK
#define MX_IO_CONTROL_OK
Definition: DataSet.h:11
MX_NODE_NODE_TYPE_FOLDER
Definition: mx_node_node_def.h:42
_io_node::name
char name[64]
Definition: DataSet.h:17
OPC_AI_SCALEDVALUE
Definition: DataSet.h:41
_MX_NODE_VARIANT::f
float f
Definition: mx_node_node_def.h:111
ioThinx_DO_Config_GetModes
IOTHINX_ERR ioThinx_DO_Config_GetModes(uint32_t slot, uint8_t start, uint8_t count, uint8_t buf[])
OPC_AI_RAWVALUE
Definition: DataSet.h:38
MX_NODE_RESULT_BAD
Definition: mx_node_node_def.h:159
_io_node::var_type
int var_type
Definition: DataSet.h:18
_MX_NODE_VARIANT::value
union _MX_NODE_VARIANT::@0 value
ioThinx_IO_Client_Init
IOTHINX_ERR ioThinx_IO_Client_Init(void)
ioThinx_DO_GetValues
IOTHINX_ERR ioThinx_DO_GetValues(uint32_t slot, uint32_t *p_values)
ioThinx_DO_SetPwmStarts
IOTHINX_ERR ioThinx_DO_SetPwmStarts(uint32_t slot, uint32_t starts)
ioThinx_AI_GetStatuss
IOTHINX_ERR ioThinx_AI_GetStatuss(uint32_t slot, uint8_t start, uint8_t count, uint8_t buf[])
cJSON
Definition: cJSON.h:103
_io_node::data
MX_NODE_VARIANT data
Definition: DataSet.h:23
OPC_DO_MODE
Definition: DataSet.h:32
cJSON::valuestring
char * valuestring
Definition: cJSON.h:115
_io_node::description
char description[64]
Definition: DataSet.h:21
_MX_NODE_NODE::node_type
MX_NODE_NODE_TYPE node_type
Definition: mx_node_node_def.h:143
mx_node_operator_initialize
MX_NODE_RESULT mx_node_operator_initialize(MX_NODE_NODE_OPERATOR_HANDLE operator_handle)
Do node operator&#39;s initialize, like create nodes.
OPC_DI_COUNTERVALUE
Definition: DataSet.h:31
mx_node_update_node
MX_NODE_RESULT mx_node_update_node(MX_NODE_NODE_HANDLE node_handle, MX_NODE_VARIANT *value, struct timeval *timestamp)
Update a node&#39;s data and timestamp.
OPC_DO_PULSESTATUS
Definition: DataSet.h:34
MX_NODE_NODE_OPERATOR_HANDLE
size_t MX_NODE_NODE_OPERATOR_HANDLE
Handle of a node operator.
Definition: mx_node_node.h:37
OPERATOR_STATE
OPERATOR_STATE
custom define
Definition: demo_node_operator.c:35