opcua 0.12 → 0.13

Sign up to get free protection for your applications and to get access to all the features.
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
  }