opcua 0.12 → 0.13

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (41) hide show
  1. checksums.yaml +4 -4
  2. data/README.md +71 -4
  3. data/cert/cert.h +52 -52
  4. data/cert/cert_key.h +101 -101
  5. data/example/array/Makefile +3 -0
  6. data/example/array/clienttest.c +168 -0
  7. data/example/array/open62541.h +27464 -0
  8. data/example/array/servertest.c +142 -0
  9. data/example/bug5.rb +22 -0
  10. data/example/client_method.rb +7 -3
  11. data/example/server.rb +3 -3
  12. data/ext/opcua/client/client.c +38 -13
  13. data/ext/opcua/client/client.h +2 -1
  14. data/ext/opcua/client/finders.c +1 -0
  15. data/ext/opcua/client/finders.h +1 -0
  16. data/ext/opcua/client/log_none.c +1 -0
  17. data/ext/opcua/client/log_none.h +1 -0
  18. data/ext/opcua/client/strnautocat.c +1 -0
  19. data/ext/opcua/client/strnautocat.h +1 -0
  20. data/ext/opcua/client/values.c +1 -0
  21. data/ext/opcua/client/values.h +1 -0
  22. data/ext/opcua/helpers/finders.c +142 -0
  23. data/ext/opcua/helpers/finders.h +13 -0
  24. data/ext/opcua/{log_none.h → helpers/log_none.c} +2 -0
  25. data/ext/opcua/helpers/log_none.h +12 -0
  26. data/ext/opcua/{strnautocat.h → helpers/strnautocat.c} +2 -0
  27. data/ext/opcua/helpers/strnautocat.h +8 -0
  28. data/ext/opcua/{values.h → helpers/values.c} +64 -25
  29. data/ext/opcua/helpers/values.h +12 -0
  30. data/ext/opcua/server/finders.c +1 -0
  31. data/ext/opcua/server/finders.h +1 -0
  32. data/ext/opcua/server/log_none.c +1 -0
  33. data/ext/opcua/server/log_none.h +1 -0
  34. data/ext/opcua/server/server.c +70 -57
  35. data/ext/opcua/server/server.h +4 -2
  36. data/ext/opcua/server/strnautocat.c +1 -0
  37. data/ext/opcua/server/strnautocat.h +1 -0
  38. data/ext/opcua/server/values.c +1 -0
  39. data/ext/opcua/server/values.h +1 -0
  40. data/opcua.gemspec +1 -1
  41. metadata +32 -6
@@ -0,0 +1,13 @@
1
+ #ifndef __OPCUA_SMART_FINDERS_H__
2
+ #define __OPCUA_SMART_FINDERS_H__
3
+
4
+ #include <open62541.h>
5
+ #include <ruby.h>
6
+
7
+ RUBY_EXTERN UA_BrowsePathResult node_browse_path(UA_Server *server, UA_NodeId relative, UA_NodeId ref, UA_QualifiedName mqn, bool inverse);
8
+ RUBY_EXTERN bool server_node_get_reference(UA_Server *server, UA_NodeId parent, UA_NodeId *result, bool inverse);
9
+ RUBY_EXTERN bool client_node_get_reference_by_name(UA_Client *client, UA_NodeId parent, UA_QualifiedName name, UA_NodeId *result, bool inverse);
10
+ RUBY_EXTERN bool client_node_get_reference_by_type(UA_Client *client, UA_NodeId parent, UA_NodeId type, UA_NodeId *result, bool inverse);
11
+ RUBY_EXTERN bool client_node_list_references(UA_Client *client, UA_NodeId parent, bool inverse);
12
+
13
+ #endif
@@ -1,3 +1,5 @@
1
+ #include "log_none.h"
2
+
1
3
  void UA_Log_None_log(void *_, UA_LogLevel level, UA_LogCategory category, const char *msg, va_list args) { }
2
4
  void UA_Log_None_clear(void *logContext) { }
3
5
  const UA_Logger UA_Log_None_ = {UA_Log_None_log, NULL, UA_Log_None_clear};
@@ -0,0 +1,12 @@
1
+ #ifndef __OPCUA_SMART_LOG_NONE_H__
2
+ #define __OPCUA_SMART_LOG_NONE_H__
3
+
4
+ #include <open62541.h>
5
+ #include <ruby.h>
6
+
7
+ RUBY_EXTERN void UA_Log_None_log(void *_, UA_LogLevel level, UA_LogCategory category, const char *msg, va_list args);
8
+ RUBY_EXTERN void UA_Log_None_clear(void *logContext);
9
+ RUBY_EXTERN const UA_Logger UA_Log_None_;
10
+ RUBY_EXTERN const UA_Logger *UA_Log_None;
11
+
12
+ #endif
@@ -1,3 +1,5 @@
1
+ #include "strnautocat.h"
2
+
1
3
  char *strnautocat(char *str, char *s2, size_t num) {
2
4
  int len = 0;
3
5
  char *s;
@@ -0,0 +1,8 @@
1
+ #ifndef __OPCUA_SMART_STRNAUTOCAT_H__
2
+ #define __OPCUA_SMART_STRNAUTOCAT_H__
3
+
4
+ #include <ruby.h>
5
+
6
+ RUBY_EXTERN char *strnautocat(char *str, char *s2, size_t num);
7
+
8
+ #endif
@@ -1,12 +1,13 @@
1
- /* -- */
2
- VALUE mTYPES = Qnil;
1
+ #include "values.h"
2
+
3
+ VALUE mOPCUA;
3
4
 
4
5
  /* -- */
5
- static void variant_set_one_dimension(UA_Variant *variant,UA_UInt32 len) {
6
+ static void variant_set_one_dimension(UA_Variant *variant,UA_UInt32 len) { //{{{
6
7
  variant->arrayDimensions = (UA_UInt32 *)UA_Array_new(1, &UA_TYPES[UA_TYPES_UINT32]);
7
8
  variant->arrayDimensions[0] = len;
8
9
  variant->arrayDimensionsSize = 1;
9
- }
10
+ } //}}}
10
11
  static bool value_to_array(VALUE value, UA_Variant *variant) {/*{{{*/
11
12
  int done = false;
12
13
 
@@ -92,7 +93,8 @@ static bool value_to_array(VALUE value, UA_Variant *variant) {/*{{{*/
92
93
  }
93
94
  return done;
94
95
  }/*}}}*/
95
- static bool value_to_variant(VALUE value, UA_Variant *variant) { //{{{
96
+
97
+ bool value_to_variant(VALUE value, UA_Variant *variant, UA_UInt32 proposal) { //{{{
96
98
  bool done = false;
97
99
  if (rb_obj_is_kind_of(value,rb_cTime)) {
98
100
  UA_DateTime tmp = UA_DateTime_fromUnixTime(rb_time_timeval(value).tv_sec);
@@ -115,13 +117,39 @@ static bool value_to_variant(VALUE value, UA_Variant *variant) { //{{{
115
117
  break;
116
118
  }
117
119
  case T_FLOAT:
118
- case T_FIXNUM:
119
120
  {
120
121
  UA_Double tmp = NUM2DBL(value);
121
122
  UA_Variant_setScalarCopy(variant, &tmp, &UA_TYPES[UA_TYPES_DOUBLE]);
122
123
  done = true;
123
124
  break;
124
125
  }
126
+ case T_FIXNUM:
127
+ {
128
+ if (proposal == UA_TYPES_SBYTE) {
129
+ UA_SByte tmp = (UA_SByte)NUM2CHR(value);
130
+ UA_Variant_setScalarCopy(variant, &tmp, &UA_TYPES[UA_TYPES_SBYTE]);
131
+ } else if (proposal == UA_TYPES_BYTE) {
132
+ UA_SByte tmp = (UA_Byte)NUM2CHR(value);
133
+ UA_Variant_setScalarCopy(variant, &tmp, &UA_TYPES[UA_TYPES_BYTE]);
134
+ } else if (proposal == UA_TYPES_INT16) {
135
+ UA_Int16 tmp = NUM2INT(value);
136
+ UA_Variant_setScalarCopy(variant, &tmp, &UA_TYPES[UA_TYPES_INT16]);
137
+ } else if (proposal == UA_TYPES_UINT16) {
138
+ UA_UInt16 tmp = NUM2INT(value);
139
+ UA_Variant_setScalarCopy(variant, &tmp, &UA_TYPES[UA_TYPES_UINT16]);
140
+ } else if (proposal == UA_TYPES_INT32) {
141
+ UA_Int32 tmp = NUM2LONG(value);
142
+ UA_Variant_setScalarCopy(variant, &tmp, &UA_TYPES[UA_TYPES_INT32]);
143
+ } else if (proposal == UA_TYPES_UINT32) {
144
+ UA_UInt32 tmp = NUM2ULONG(value);
145
+ UA_Variant_setScalarCopy(variant, &tmp, &UA_TYPES[UA_TYPES_UINT32]);
146
+ } else {
147
+ UA_Int32 tmp = NUM2LONG(value);
148
+ UA_Variant_setScalarCopy(variant, &tmp, &UA_TYPES[UA_TYPES_INT32]);
149
+ }
150
+ done = true;
151
+ break;
152
+ }
125
153
  case T_STRING:
126
154
  case T_SYMBOL:
127
155
  {
@@ -142,9 +170,8 @@ static bool value_to_variant(VALUE value, UA_Variant *variant) { //{{{
142
170
  }
143
171
  return done;
144
172
  } //}}}
145
- /* ++ */
146
173
 
147
- static void Init_types() {/*{{{*/
174
+ void Init_types() {/*{{{*/
148
175
  mTYPES = rb_define_module_under(mOPCUA,"TYPES");
149
176
  rb_define_const(mTYPES, "DATETIME", INT2NUM(UA_TYPES_DATETIME ));
150
177
  rb_define_const(mTYPES, "BOOLEAN", INT2NUM(UA_TYPES_BOOLEAN ));
@@ -156,32 +183,38 @@ static void Init_types() {/*{{{*/
156
183
  rb_define_const(mTYPES, "STRING", INT2NUM(UA_TYPES_STRING ));
157
184
  }/*}}}*/
158
185
 
159
- static VALUE UA_TYPES_DATETIME_to_value(UA_DateTime data) {
186
+ static VALUE UA_TYPES_DATETIME_to_value(UA_DateTime data) { //{{{
160
187
  return rb_time_new(UA_DateTime_toUnixTime(data),0);
161
- }
162
- static VALUE UA_TYPES_BOOLEAN_to_value(UA_Boolean data) {
188
+ } //}}}
189
+ static VALUE UA_TYPES_BOOLEAN_to_value(UA_Boolean data) { //{{{
163
190
  return data ? Qtrue : Qfalse;
164
- }
165
- static VALUE UA_TYPES_DOUBLE_to_value(UA_Double data) {
191
+ } //}}}
192
+ static VALUE UA_TYPES_DOUBLE_to_value(UA_Double data) { //{{{
166
193
  return DBL2NUM(data);
167
- }
168
- static VALUE UA_TYPES_INT32_to_value(UA_Int32 data) {
194
+ } //}}}
195
+ static VALUE UA_TYPES_SBYTE_to_value(UA_SByte data) { //{{{
196
+ return CHR2FIX((signed char)data);
197
+ } //}}}
198
+ static VALUE UA_TYPES_INT32_to_value(UA_Int32 data) { //{{{
169
199
  return INT2NUM(data);
170
- }
171
- static VALUE UA_TYPES_INT16_to_value(UA_Int16 data) {
200
+ } //}}}
201
+ static VALUE UA_TYPES_INT16_to_value(UA_Int16 data) { //{{{
172
202
  return INT2NUM(data);
173
- }
174
- static VALUE UA_TYPES_UINT32_to_value(UA_UInt32 data) {
203
+ } //}}}
204
+ static VALUE UA_TYPES_BYTE_to_value(UA_Byte data) { //{{{
205
+ return CHR2FIX((unsigned char)data);
206
+ } //}}}
207
+ static VALUE UA_TYPES_UINT32_to_value(UA_UInt32 data) { //{{{
175
208
  return UINT2NUM(data);
176
- }
177
- static VALUE UA_TYPES_UINT16_to_value(UA_UInt16 data) {
209
+ } //}}}
210
+ static VALUE UA_TYPES_UINT16_to_value(UA_UInt16 data) { //{{{
178
211
  return UINT2NUM(data);
179
- }
180
- static VALUE UA_TYPES_STRING_to_value(UA_String data) {
212
+ } //}}}
213
+ static VALUE UA_TYPES_STRING_to_value(UA_String data) { //{{{
181
214
  return rb_str_export_locale(rb_str_new((char *)(data.data),data.length));
182
- }
215
+ } //}}}
183
216
 
184
- static VALUE extract_value(UA_Variant value) { //{{{
217
+ VALUE extract_value(UA_Variant value) { //{{{
185
218
  VALUE ret = rb_ary_new2(2);
186
219
  rb_ary_store(ret,0,Qnil);
187
220
  rb_ary_store(ret,1,Qnil);
@@ -210,6 +243,12 @@ static VALUE extract_value(UA_Variant value) { //{{{
210
243
  } else if (UA_Variant_hasScalarType(&value, &UA_TYPES[UA_TYPES_UINT16])) {
211
244
  rb_ary_store(ret,0,UA_TYPES_UINT16_to_value(*(UA_UInt16 *)value.data));
212
245
  rb_ary_store(ret,1,ID2SYM(rb_intern("VariantType.UInt16")));
246
+ } else if (UA_Variant_hasScalarType(&value, &UA_TYPES[UA_TYPES_SBYTE])) {
247
+ rb_ary_store(ret,0,UA_TYPES_SBYTE_to_value(*(UA_SByte *)value.data));
248
+ rb_ary_store(ret,1,ID2SYM(rb_intern("VariantType.SByte")));
249
+ } else if (UA_Variant_hasScalarType(&value, &UA_TYPES[UA_TYPES_BYTE])) {
250
+ rb_ary_store(ret,0,UA_TYPES_BYTE_to_value(*(UA_Byte *)value.data));
251
+ rb_ary_store(ret,1,ID2SYM(rb_intern("VariantType.Byte")));
213
252
  } else if (UA_Variant_hasScalarType(&value, &UA_TYPES[UA_TYPES_STRING])) {
214
253
  rb_ary_store(ret,0,UA_TYPES_STRING_to_value(*(UA_String *)value.data));
215
254
  rb_ary_store(ret,1,ID2SYM(rb_intern("VariantType.String")));
@@ -0,0 +1,12 @@
1
+ #ifndef __OPCUA_SMART_VALUES_H__
2
+ #define __OPCUA_SMART_VALUES_H__
3
+
4
+ #include <open62541.h>
5
+ #include <ruby.h>
6
+
7
+ VALUE mTYPES;
8
+ RUBY_EXTERN bool value_to_variant(VALUE value, UA_Variant *variant, UA_UInt32 proposal);
9
+ RUBY_EXTERN void Init_types();
10
+ RUBY_EXTERN VALUE extract_value(UA_Variant value);
11
+
12
+ #endif
@@ -0,0 +1 @@
1
+ ../helpers/finders.c
@@ -0,0 +1 @@
1
+ ../helpers/finders.h
@@ -0,0 +1 @@
1
+ ../helpers/log_none.c
@@ -0,0 +1 @@
1
+ ../helpers/log_none.h
@@ -12,7 +12,7 @@ VALUE cReferenceNode = Qnil;
12
12
  VALUE cVarNode = Qnil;
13
13
  VALUE cMethodNode = Qnil;
14
14
 
15
- #include "../values.h"
15
+ #include "values.h"
16
16
 
17
17
  int nodecounter = 2000;
18
18
 
@@ -24,7 +24,7 @@ static void node_free(node_struct *ns) { //{{{
24
24
  }
25
25
  free(ns);
26
26
  }
27
- } //}}}
27
+ } // }}}
28
28
  static node_struct * node_alloc(server_struct *server, UA_NodeId nodeid) { //{{{
29
29
  node_struct *ns;
30
30
  ns = (node_struct *)malloc(sizeof(node_struct));
@@ -34,6 +34,7 @@ static node_struct * node_alloc(server_struct *server, UA_NodeId nodeid) { //{{{
34
34
  ns->master = server;
35
35
  ns->id = nodeid;
36
36
  ns->method = Qnil;
37
+ ns->exists = true;
37
38
 
38
39
  return ns;
39
40
  } //}}}
@@ -45,12 +46,14 @@ static VALUE node_wrap(VALUE klass, node_struct *ns) { //{{{
45
46
  static VALUE node_type_folder(VALUE self) { //{{{
46
47
  node_struct *ns;
47
48
  Data_Get_Struct(self, node_struct, ns);
49
+ if (!ns->exists) rb_raise(rb_eRuntimeError, "Node does not exist anymore.");
48
50
  return node_wrap(cTypeTopNode, node_alloc(ns->master, UA_NODEID_NUMERIC(0, UA_NS0ID_FOLDERTYPE)));
49
51
  } //}}}
50
52
  static VALUE node_add_object_type(VALUE self, VALUE name) { //{{{
51
53
  node_struct *ns;
52
54
 
53
55
  Data_Get_Struct(self, node_struct, ns);
56
+ if (!ns->exists) rb_raise(rb_eRuntimeError, "Node does not exist anymore.");
54
57
 
55
58
  VALUE str = rb_obj_as_string(name);
56
59
  if (NIL_P(str) || TYPE(str) != T_STRING)
@@ -76,6 +79,7 @@ static VALUE node_add_reference_type(VALUE self, VALUE name, VALUE type) { //{{{
76
79
  node_struct *ns;
77
80
 
78
81
  Data_Get_Struct(self, node_struct, ns);
82
+ if (!ns->exists) rb_raise(rb_eRuntimeError, "Node does not exist anymore.");
79
83
 
80
84
  VALUE str = rb_obj_as_string(name);
81
85
  if (NIL_P(str) || TYPE(str) != T_STRING)
@@ -104,6 +108,7 @@ static VALUE node_id(VALUE self) { //{{{
104
108
  node_struct *ns;
105
109
 
106
110
  Data_Get_Struct(self, node_struct, ns);
111
+ if (!ns->exists) rb_raise(rb_eRuntimeError, "Node does not exist anymore.");
107
112
 
108
113
  VALUE ret = rb_ary_new();
109
114
 
@@ -118,11 +123,23 @@ static VALUE node_id(VALUE self) { //{{{
118
123
  }
119
124
  return ret;
120
125
  } //}}}
126
+ static VALUE node_name(VALUE self) { //{{{
127
+ node_struct *ns;
128
+
129
+ Data_Get_Struct(self, node_struct, ns);
130
+ if (!ns->exists) rb_raise(rb_eRuntimeError, "Node does not exist anymore.");
131
+
132
+ UA_QualifiedName qn; UA_QualifiedName_init(&qn);
133
+ UA_Server_readBrowseName(ns->master->master, ns->id, &qn);
134
+
135
+ return rb_sprintf("%.*s", (int)qn.name.length, qn.name.data);
136
+ } //}}}
121
137
  static VALUE node_to_s(VALUE self) { //{{{
122
138
  node_struct *ns;
123
139
  VALUE ret;
124
140
 
125
141
  Data_Get_Struct(self, node_struct, ns);
142
+ if (!ns->exists) rb_raise(rb_eRuntimeError, "Node does not exist anymore.");
126
143
 
127
144
  if (ns->id.identifierType == UA_NODEIDTYPE_NUMERIC) {
128
145
  ret = rb_sprintf("ns=%d;i=%d", ns->id.namespaceIndex, ns->id.identifier.numeric);
@@ -139,12 +156,15 @@ static VALUE node_add_reference(VALUE self, VALUE to, VALUE type) { //{{{
139
156
  node_struct *tys;
140
157
 
141
158
  Data_Get_Struct(self, node_struct, ns);
159
+ if (!ns->exists) rb_raise(rb_eRuntimeError, "Node does not exist anymore.");
142
160
 
143
161
  if (!(rb_obj_is_kind_of(type,cReferenceSubNode) || rb_obj_is_kind_of(to,cTypeSubNode))) {
144
162
  rb_raise(rb_eArgError, "arguments have to be NodeIDs.");
145
163
  }
146
164
  Data_Get_Struct(to, node_struct, tos);
165
+ if (!tos->exists) rb_raise(rb_eRuntimeError, "To (arg 1) node does not exist anymore.");
147
166
  Data_Get_Struct(type, node_struct, tys);
167
+ if (!tys->exists) rb_raise(rb_eRuntimeError, "Type (arg 2) node does not exist anymore.");
148
168
  UA_NodeId n = UA_NODEID_NUMERIC(ns->master->default_ns, nodecounter++);
149
169
 
150
170
  UA_ExpandedNodeId toNodeId;
@@ -269,6 +289,7 @@ static VALUE node_add_method(int argc, VALUE* argv, VALUE self) { //{{{
269
289
  if (NIL_P(opts)) opts = rb_hash_new();
270
290
 
271
291
  Data_Get_Struct(self, node_struct, parent);
292
+ if (!parent->exists) rb_raise(rb_eRuntimeError, "Node does not exist anymore.");
272
293
 
273
294
  VALUE str = rb_obj_as_string(name);
274
295
  if (NIL_P(str) || TYPE(str) != T_STRING)
@@ -326,6 +347,7 @@ static VALUE node_add_variable_wrap(int argc, VALUE* argv, VALUE self, UA_Byte a
326
347
  }
327
348
 
328
349
  Data_Get_Struct(self, node_struct, parent);
350
+ if (!parent->exists) rb_raise(rb_eRuntimeError, "Node does not exist anymore.");
329
351
 
330
352
  VALUE str = rb_obj_as_string(argv[0]);
331
353
  if (NIL_P(str) || TYPE(str) != T_STRING)
@@ -422,7 +444,9 @@ static VALUE node_add_object(int argc, VALUE* argv, VALUE self) { //{{{
422
444
  }
423
445
 
424
446
  Data_Get_Struct(self, node_struct, parent);
447
+ if (!parent->exists) rb_raise(rb_eRuntimeError, "Parent node does not exist anymore.");
425
448
  Data_Get_Struct(argv[1], node_struct, datatype);
449
+ if (!datatype->exists) rb_raise(rb_eRuntimeError, "Datatype node does not exist anymore.");
426
450
 
427
451
  VALUE str = rb_obj_as_string(argv[0]);
428
452
  if (NIL_P(str) || TYPE(str) != T_STRING)
@@ -432,52 +456,6 @@ static VALUE node_add_object(int argc, VALUE* argv, VALUE self) { //{{{
432
456
  return node_wrap(CLASS_OF(self),node_alloc(parent->master,node_add_object_ua_simple(type,nstr,parent,datatype,argv[2])));
433
457
  } //}}}
434
458
 
435
- static UA_BrowsePathResult node_browse_path(UA_Server *server, UA_NodeId relative, UA_NodeId ref, UA_QualifiedName mqn) { //{{{
436
- UA_RelativePathElement rpe;
437
- UA_RelativePathElement_init(&rpe);
438
- rpe.referenceTypeId = ref;
439
- rpe.isInverse = false;
440
- rpe.includeSubtypes = false;
441
- rpe.targetName = mqn;
442
-
443
- UA_BrowsePath bp;
444
- UA_BrowsePath_init(&bp);
445
- bp.startingNode = relative;
446
- bp.relativePath.elementsSize = 1;
447
- bp.relativePath.elements = &rpe;
448
-
449
- return UA_Server_translateBrowsePathToNodeIds(server, &bp);
450
- } //}}}
451
-
452
- static bool node_get_reference(UA_Server *server, UA_NodeId parent, UA_NodeId *result) { //{{{
453
- UA_BrowseDescription bDes;
454
- UA_BrowseDescription_init(&bDes);
455
- bDes.nodeId = parent;
456
- bDes.resultMask = UA_BROWSERESULTMASK_ALL;
457
- UA_BrowseResult bRes = UA_Server_browse(server, 999, &bDes);
458
-
459
- if (bRes.referencesSize > 0) {
460
- UA_ReferenceDescription *ref = &(bRes.references[0]);
461
-
462
- UA_NodeId_copy(&ref->nodeId.nodeId,result);
463
-
464
- UA_QualifiedName qn; UA_QualifiedName_init(&qn);
465
- UA_Server_readBrowseName(server, ref->nodeId.nodeId, &qn);
466
-
467
- // printf("NS: %d ---> NodeId %u; %-16.*s\n",
468
- // ref->nodeId.nodeId.namespaceIndex,
469
- // ref->nodeId.nodeId.identifier.numeric,
470
- // (int)qn.name.length,
471
- // qn.name.data
472
- // );
473
-
474
- UA_BrowseResult_deleteMembers(&bRes);
475
- UA_BrowseResult_clear(&bRes);
476
- return true;
477
- }
478
- return false;
479
- } //}}}
480
-
481
459
  static UA_StatusCode node_manifest_iter(UA_NodeId child_id, UA_Boolean is_inverse, UA_NodeId reference_type_id, void *handle) { //{{{
482
460
  if (is_inverse) return UA_STATUSCODE_GOOD;
483
461
 
@@ -516,8 +494,8 @@ static UA_StatusCode node_manifest_iter(UA_NodeId child_id, UA_Boolean is_invers
516
494
  if (child_id.namespaceIndex == parent->master->default_ns) {
517
495
  UA_QualifiedName mqn;UA_QualifiedName_init(&mqn);
518
496
  UA_Server_readBrowseName(parent->master->master, UA_NODEID_NUMERIC(0, UA_NS0ID_MODELLINGRULE_MANDATORY), &mqn);
519
-
520
- UA_BrowsePathResult mandatory = node_browse_path(parent->master->master, child_id, UA_NODEID_NUMERIC(0, UA_NS0ID_HASMODELLINGRULE), mqn);
497
+ UA_BrowsePathResult mandatory = node_browse_path(parent->master->master, child_id, UA_NODEID_NUMERIC(0, UA_NS0ID_HASMODELLINGRULE), mqn, false);
498
+ UA_QualifiedName_clear(&mqn);
521
499
 
522
500
  if (mandatory.statusCode == UA_STATUSCODE_GOOD && (nc == UA_NODECLASS_OBJECT || nc == UA_NODECLASS_VARIABLE || nc == UA_NODECLASS_METHOD)) {
523
501
  char * buffer = strnautocat(NULL,"",0);
@@ -529,7 +507,7 @@ static UA_StatusCode node_manifest_iter(UA_NodeId child_id, UA_Boolean is_invers
529
507
  buffer = strnautocat(buffer,(char *)qn.name.data,qn.name.length);
530
508
  if(nc == UA_NODECLASS_OBJECT) {
531
509
  UA_NodeId typeid;
532
- node_get_reference(parent->master->master, child_id, &typeid);
510
+ server_node_get_reference(parent->master->master, child_id, &typeid, false);
533
511
 
534
512
  node_struct *thetype = node_alloc(parent->master,typeid);
535
513
 
@@ -547,7 +525,8 @@ static UA_StatusCode node_manifest_iter(UA_NodeId child_id, UA_Boolean is_invers
547
525
  if(nc == UA_NODECLASS_VARIABLE) {
548
526
  UA_QualifiedName pqn;UA_QualifiedName_init(&pqn);
549
527
  UA_Server_readBrowseName(parent->master->master, UA_NODEID_NUMERIC(0, UA_NS0ID_PROPERTYTYPE), &pqn);
550
- UA_BrowsePathResult property = node_browse_path(parent->master->master, child_id, UA_NODEID_NUMERIC(0, UA_NS0ID_HASTYPEDEFINITION), pqn);
528
+ UA_BrowsePathResult property = node_browse_path(parent->master->master, child_id, UA_NODEID_NUMERIC(0, UA_NS0ID_HASTYPEDEFINITION), pqn, false);
529
+ UA_QualifiedName_clear(&pqn);
551
530
 
552
531
  if (property.statusCode == UA_STATUSCODE_GOOD) {
553
532
  node_add_variable_ua(UA_NS0ID_PROPERTYTYPE,UA_NODEID_STRING(parent->master->default_ns,buffer),dn,qn,newnode,al);
@@ -556,12 +535,11 @@ static UA_StatusCode node_manifest_iter(UA_NodeId child_id, UA_Boolean is_invers
556
535
  }
557
536
 
558
537
  UA_BrowsePathResult_clear(&property);
559
- UA_QualifiedName_clear(&pqn);
560
538
  }
561
539
  if(nc == UA_NODECLASS_METHOD) {
562
540
  UA_NodeId ttt;
563
541
  VALUE blk = rb_hash_aref(parent->master->methods,INT2NUM(child_id.identifier.numeric));
564
- if (node_get_reference(parent->master->master, child_id, &ttt)) {
542
+ if (server_node_get_reference(parent->master->master, child_id, &ttt, false)) {
565
543
  UA_Variant arv; UA_Variant_init(&arv);
566
544
  UA_Server_readValue(parent->master->master, ttt, &arv);
567
545
 
@@ -573,7 +551,6 @@ static UA_StatusCode node_manifest_iter(UA_NodeId child_id, UA_Boolean is_invers
573
551
  }
574
552
  }
575
553
  UA_BrowsePathResult_clear(&mandatory);
576
- UA_QualifiedName_clear(&mqn);
577
554
  }
578
555
 
579
556
  UA_NodeClass_clear(&nc);
@@ -593,7 +570,9 @@ static VALUE node_manifest(VALUE self, VALUE name, VALUE parent) { //{{{
593
570
  }
594
571
 
595
572
  Data_Get_Struct(self, node_struct, ns);
573
+ if (!ns->exists) rb_raise(rb_eRuntimeError, "Node does not exist anymore.");
596
574
  Data_Get_Struct(parent, node_struct, ts);
575
+ if (!ns->exists) rb_raise(rb_eRuntimeError, "Target node does not exist anymore.");
597
576
 
598
577
  VALUE str = rb_obj_as_string(name);
599
578
  if (NIL_P(str) || TYPE(str) != T_STRING)
@@ -620,13 +599,14 @@ static VALUE node_find(VALUE self, VALUE qname) { //{{{
620
599
  node_struct *ns;
621
600
 
622
601
  Data_Get_Struct(self, node_struct, ns);
602
+ if (!ns->exists) rb_raise(rb_eRuntimeError, "Node does not exist anymore.");
623
603
 
624
604
  VALUE str = rb_obj_as_string(qname);
625
605
  if (NIL_P(str) || TYPE(str) != T_STRING)
626
606
  rb_raise(rb_eTypeError, "cannot convert obj to string");
627
607
  char *nstr = (char *)StringValuePtr(str);
628
608
 
629
- UA_BrowsePathResult bpr = node_browse_path(ns->master->master, ns->id, UA_NODEID_NUMERIC(0, UA_NS0ID_HASCOMPONENT), UA_QUALIFIEDNAME(ns->master->default_ns, nstr));
609
+ UA_BrowsePathResult bpr = node_browse_path(ns->master->master, ns->id, UA_NODEID_NUMERIC(0, UA_NS0ID_HASCOMPONENT), UA_QUALIFIEDNAME(ns->master->default_ns, nstr), false);
630
610
 
631
611
  if(bpr.statusCode != UA_STATUSCODE_GOOD || bpr.targetsSize < 1) {
632
612
  return Qnil;
@@ -707,9 +687,10 @@ static VALUE server_get(int argc, VALUE* argv, VALUE self) { //{{{
707
687
  static VALUE node_value_set(VALUE self, VALUE value) { //{{{
708
688
  node_struct *ns;
709
689
  Data_Get_Struct(self, node_struct, ns);
690
+ if (!ns->exists) rb_raise(rb_eRuntimeError, "Node does not exist anymore.");
710
691
 
711
692
  UA_Variant variant;
712
- if (value_to_variant(value,&variant)) {
693
+ if (value_to_variant(value,&variant,-1)) {
713
694
  // printf("-----------------------------------------%ld\n",variant.arrayDimensionsSize);
714
695
  if (variant.arrayDimensionsSize > 0) {
715
696
  UA_Server_writeValueRank(ns->master->master, ns->id, variant.arrayDimensionsSize);
@@ -726,6 +707,7 @@ static VALUE node_value(VALUE self) { //{{{
726
707
  node_struct *ns;
727
708
 
728
709
  Data_Get_Struct(self, node_struct, ns);
710
+ if (!ns->exists) rb_raise(rb_eRuntimeError, "Node does not exist anymore.");
729
711
 
730
712
  UA_Variant value;
731
713
  UA_Variant_init(&value);
@@ -740,9 +722,34 @@ static VALUE node_value(VALUE self) { //{{{
740
722
  UA_Variant_clear(&value);
741
723
  return rb_ary_entry(ret,0);
742
724
  } //}}}
725
+ static VALUE node_delete(VALUE self) { //{{{
726
+ node_struct *ns;
727
+
728
+ Data_Get_Struct(self, node_struct, ns);
729
+ if (!ns->exists) rb_raise(rb_eRuntimeError, "Node does not exist anymore.");
730
+
731
+ UA_StatusCode retval = UA_Server_deleteNode(ns->master->master, ns->id, true);
732
+
733
+ if (retval == UA_STATUSCODE_GOOD) {
734
+ ns->exists = false;
735
+ return Qtrue;
736
+ }
737
+
738
+ return Qfalse;
739
+ } //}}}
740
+ static VALUE node_exists(VALUE self) { //{{{
741
+ node_struct *ns;
742
+
743
+ Data_Get_Struct(self, node_struct, ns);
744
+ if (ns->exists)
745
+ return Qtrue;
746
+ else
747
+ return Qfalse;
748
+ } //}}}
743
749
  static VALUE node_description_set(VALUE self, VALUE value) { //{{{
744
750
  node_struct *ns;
745
751
  Data_Get_Struct(self, node_struct, ns);
752
+ if (!ns->exists) rb_raise(rb_eRuntimeError, "Node does not exist anymore.");
746
753
 
747
754
  VALUE str = rb_obj_as_string(value);
748
755
  if (NIL_P(str) || TYPE(str) != T_STRING)
@@ -757,6 +764,7 @@ static VALUE node_description(VALUE self) { //{{{
757
764
  node_struct *ns;
758
765
 
759
766
  Data_Get_Struct(self, node_struct, ns);
767
+ if (!ns->exists) rb_raise(rb_eRuntimeError, "Node does not exist anymore.");
760
768
 
761
769
  UA_LocalizedText value;
762
770
  UA_LocalizedText_init(&value);
@@ -918,8 +926,10 @@ void Init_server(void) {
918
926
 
919
927
  rb_define_method(cNode, "to_s", node_to_s, 0);
920
928
  rb_define_method(cNode, "id", node_id, 0);
929
+ rb_define_method(cNode, "name", node_name, 0);
921
930
  rb_define_method(cNode, "description", node_description, 0);
922
931
  rb_define_method(cNode, "description=", node_description_set, 1);
932
+ rb_define_method(cNode, "exists?", node_exists, 0);
923
933
 
924
934
  rb_define_method(cTypeTopNode, "add_object_type", node_add_object_type, 1);
925
935
  rb_define_method(cTypeTopNode, "add_reference_type", node_add_reference_type, 1);
@@ -931,10 +941,13 @@ void Init_server(void) {
931
941
  rb_define_method(cTypeSubNode, "add_object", node_add_object, -1);
932
942
  rb_define_method(cTypeSubNode, "add_method", node_add_method, -1);
933
943
  rb_define_method(cTypeSubNode, "add_reference", node_add_reference, 2);
944
+ rb_define_method(cTypeSubNode, "delete!", node_delete, 0);
934
945
 
935
946
  rb_define_method(cObjectNode, "manifest", node_manifest, 2);
936
947
  rb_define_method(cObjectNode, "find", node_find, 1);
948
+ rb_define_method(cObjectNode, "delete!", node_delete, 0);
937
949
 
938
950
  rb_define_method(cVarNode, "value", node_value, 0);
939
951
  rb_define_method(cVarNode, "value=", node_value_set, 1);
952
+ rb_define_method(cVarNode, "delete!", node_delete, 0);
940
953
  }