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 {
44 
45 struct timeval now();
47 
50 
54 
57 const char* mx_node_operator_get_version()
58 {
59  return "1.0";
60 }
61 
63 {
65 }
66 
68 {
69  int rc, i, j;
70  char buffer[64];
71 
72  g_operator_handle = operator_handle;
74 
75  // initialize ioThinx I/O
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 
94 {
95  size_t i,j;
96  for (i = 0; i < g_totalSlot; ++i)
97  free(io_example[i]);
98 
99  free(io_example);
101  printf("Uninit finished!...\n");
102 }
103 
105 {
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();
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  }
128 }
129 
131 {
133  {
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 
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 
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");
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);
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
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;
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;
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;
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){
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 }
MX_NODE_VARIANT value
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.
IOTHINX_ERR ioThinx_DO_SetPwmCounts(uint32_t slot, uint8_t start, uint8_t count, uint32_t buf[])
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.
A variant structure is used to store different type&#39;s data.
void mx_node_operator_start()
A notify to inform node operator start with non-blocking.
IOTHINX_ERR ioThinx_DI_SetCntStops(uint32_t slot, uint32_t stops)
IOTHINX_ERR ioThinx_AI_GetMinRaws(uint32_t slot, uint8_t start, uint8_t count, uint32_t buf[])
IOTHINX_ERR ioThinx_DI_GetCntStarts(uint32_t slot, uint32_t *p_starts)
size_t MX_NODE_NODE_HANDLE
Handle of a node.
Definition: mx_node_node.h:42
#define INTERFACE_MX_NODE_BASIC
Interface basic&#39;s flag.
struct timeval Now()
Definition: DataSet.h:50
int * g_slotNodeCountRecorder
#define MX_PARSE_CONFIG_ERR
Definition: DataSet.h:10
int valueint
Definition: cJSON.h:117
int access
Definition: DataSet.h:20
MX_NODE_VARIABLE variable
enum _MX_NODE_RESULT MX_NODE_RESULT
A result enumeration represents success or not.
volatile OPERATOR_STATE g_state
IOTHINX_ERR ioThinx_DI_SetCntStarts(uint32_t slot, uint32_t starts)
int ch
Definition: DataSet.h:16
IOTHINX_ERR ioThinx_DO_SetPwmStops(uint32_t slot, uint32_t stops)
IOTHINX_ERR ioThinx_DO_GetPwmCounts(uint32_t slot, uint8_t start, uint8_t count, uint32_t buf[])
IOTHINX_ERR ioThinx_Relay_GetValues(uint32_t slot, uint32_t *p_values)
IOTHINX_ERR ioThinx_DO_SetValues(uint32_t slot, uint32_t values)
struct timeval timestamp
Definition: DataSet.h:24
void mx_node_operator_stop()
A notify to inform node operator stopping.
A node&#39;s sturcture contain name, description, node type and attribute.
IOTHINX_ERR ioThinx_DI_Config_SetModes(uint32_t slot, uint8_t start, uint8_t count, uint8_t buf[])
int index
Definition: cJSON.h:168
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_ERR ioThinx_DO_GetPwmStarts(uint32_t slot, uint32_t *p_starts)
#define INTERFACE_MX_NODE_DATA_ACCESS
Interface data access&#39;s flag.
#define DO_MODE_PWM
Definition: iothinxio.h:291
IOTHINX_ERR ioThinx_DI_GetCntValues(uint32_t slot, uint8_t start, uint8_t count, uint32_t buf[])
const char * mx_node_operator_get_version()
Get node operator&#39;s version.
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.
long long mx_node_operator_get_supported_interfaces()
Get supported interfaces.
const char *const name
Definition: cJSON.h:258
IOTHINX_ERR ioThinx_AI_GetMaxRaws(uint32_t slot, uint8_t start, uint8_t count, uint32_t buf[])
#define IOTHINX_ERR_OK
Definition: iothinxio.h:35
NODE ** io_example
int io_control_write(int slot, int index, const MX_NODE_VARIANT *node_value)
MX_NODE_ACCESS_RIGHT access_right
int g_totalSlot
#define CNT_TRIGGER_BOTH
Definition: iothinxio.h:98
IOTHINX_ERR ioThinx_Relay_SetValues(uint32_t slot, uint32_t values)
IOTHINX_ERR ioThinx_DO_Config_SetModes(uint32_t slot, uint8_t start, uint8_t count, uint8_t buf[])
IOTHINX_ERR ioThinx_AI_GetRaws(uint32_t slot, uint8_t start, uint8_t count, uint32_t buf[])
int parse_json_file(const char *filename)
#define DI_MODE_COUNTER
Definition: iothinxio.h:88
int cJSON_to_struct_array(char *text)
IOTHINX_ERR ioThinx_DI_Config_GetModes(uint32_t slot, uint8_t start, uint8_t count, uint8_t buf[])
char * buffer
Definition: cJSON.h:161
#define MX_IO_CONTROL_ERR
Definition: DataSet.h:12
MX_NODE_RESULT add_io_nodes()
struct timeval now()
custom function
IOTHINX_ERR ioThinx_AI_GetEngs(uint32_t slot, uint8_t start, uint8_t count, float buf[])
IOTHINX_ERR ioThinx_AI_Config_GetRanges(uint32_t slot, uint8_t start, uint8_t count, uint8_t buf[])
FUNC_TYPE
Definition: DataSet.h:27
cJSON * item
Definition: cJSON.h:218
IOTHINX_ERR ioThinx_IO_Config_Reload(void)
IOTHINX_ERR ioThinx_DI_Config_SetCntTriggers(uint32_t slot, uint8_t start, uint8_t count, uint8_t buf[])
int func_type
Definition: DataSet.h:19
int io_control_read(int slot, int index, MX_NODE_VARIANT *node_value)
char node_name[MAX_NODE_NAME_LEN]
IOTHINX_ERR ioThinx_DO_Config_SetPwmConfigures(uint32_t slot, uint8_t start, uint8_t count, uint16_t frequencies[], uint16_t duty_cycles[])
MX_NODE_NODE_OPERATOR_HANDLE g_operator_handle
IOTHINX_ERR ioThinx_DI_SetCntValues(uint32_t slot, uint8_t start, uint8_t count, uint32_t buf[])
IOTHINX_ERR ioThinx_DI_GetValues(uint32_t slot, uint32_t *p_values)
OPERATOR_STATE
include interfaces
char description[MAX_NODE_DESC_LEN]
MX_NODE_VALUE_TYPE type
void mx_node_operator_uninitialize()
Do node operator&#39;s uninitialize.
#define MX_IO_CONTROL_OK
Definition: DataSet.h:11
char name[64]
Definition: DataSet.h:17
IOTHINX_ERR ioThinx_DO_Config_GetModes(uint32_t slot, uint8_t start, uint8_t count, uint8_t buf[])
int var_type
Definition: DataSet.h:18
union _MX_NODE_VARIANT::@0 value
IOTHINX_ERR ioThinx_IO_Client_Init(void)
IOTHINX_ERR ioThinx_DO_GetValues(uint32_t slot, uint32_t *p_values)
IOTHINX_ERR ioThinx_DO_SetPwmStarts(uint32_t slot, uint32_t starts)
IOTHINX_ERR ioThinx_AI_GetStatuss(uint32_t slot, uint8_t start, uint8_t count, uint8_t buf[])
Definition: cJSON.h:103
MX_NODE_VARIANT data
Definition: DataSet.h:23
char * valuestring
Definition: cJSON.h:115
char description[64]
Definition: DataSet.h:21
MX_NODE_NODE_TYPE node_type
MX_NODE_RESULT mx_node_operator_initialize(MX_NODE_NODE_OPERATOR_HANDLE operator_handle)
Do node operator&#39;s initialize, like create nodes.
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.
size_t MX_NODE_NODE_OPERATOR_HANDLE
Handle of a node operator.
Definition: mx_node_node.h:37
OPERATOR_STATE
custom define