opcua 0.11 → 0.12
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.
- checksums.yaml +4 -4
- data/README.md +109 -6
- data/Rakefile +6 -5
- data/cert/cert.h +52 -52
- data/cert/cert_key.h +101 -101
- data/example/client_get_sync.rb +15 -0
- data/example/client_get_value.rb +16 -0
- data/example/client_set_value.rb +15 -0
- data/example/server.rb +15 -3
- data/ext/opcua/client/client.c +143 -17
- data/ext/opcua/client/client.h +1 -0
- data/ext/opcua/server/extconf.rb +1 -0
- data/ext/opcua/server/server.c +252 -57
- data/ext/opcua/values.h +206 -41
- data/lib/opcua/client.rb +11 -0
- data/lib/opcua/server.rb +51 -0
- data/opcua.gemspec +1 -1
- metadata +5 -2
|
@@ -0,0 +1,15 @@
|
|
|
1
|
+
#!/usr/bin/ruby
|
|
2
|
+
require_relative '../lib/opcua/client'
|
|
3
|
+
#require 'opcua/client'
|
|
4
|
+
|
|
5
|
+
### username & pass in url (e.g. siemens)
|
|
6
|
+
# client = OPCUA::Client.new("opc.tcp://OpcUaClient:SUNRISE@localhost:4840")
|
|
7
|
+
|
|
8
|
+
client = OPCUA::Client.new("opc.tcp://localhost:4840")
|
|
9
|
+
client.subscription_interval = 100 # default 500
|
|
10
|
+
|
|
11
|
+
node = client.get 2, '/KalimatC34/Tools/Tool1/ToolNumber' # get node from nodeid
|
|
12
|
+
p node.value
|
|
13
|
+
node.on_value_change do
|
|
14
|
+
puts 'now'
|
|
15
|
+
end
|
|
@@ -0,0 +1,16 @@
|
|
|
1
|
+
#!/usr/bin/ruby
|
|
2
|
+
require_relative '../lib/opcua/client'
|
|
3
|
+
#require 'opcua/client'
|
|
4
|
+
|
|
5
|
+
### username & pass in url (e.g. siemens)
|
|
6
|
+
# client = OPCUA::Client.new("opc.tcp://OpcUaClient:SUNRISE@localhost:4840")
|
|
7
|
+
|
|
8
|
+
client = OPCUA::Client.new("opc.tcp://localhost:4840")
|
|
9
|
+
client.subscription_interval = 100 # default 500
|
|
10
|
+
|
|
11
|
+
if (node = client.get 2, '/KalimatC34/Tools/Tool1/ToolNumber') # get node from nodeid
|
|
12
|
+
p node
|
|
13
|
+
p node.value
|
|
14
|
+
else
|
|
15
|
+
p 'invalid nodeid'
|
|
16
|
+
end
|
|
@@ -0,0 +1,15 @@
|
|
|
1
|
+
#!/usr/bin/ruby
|
|
2
|
+
require_relative '../lib/opcua/client'
|
|
3
|
+
#require 'opcua/client'
|
|
4
|
+
|
|
5
|
+
### username & pass in url (e.g. siemens)
|
|
6
|
+
# client = OPCUA::Client.new("opc.tcp://OpcUaClient:SUNRISE@localhost:4840")
|
|
7
|
+
|
|
8
|
+
client = OPCUA::Client.new("opc.tcp://localhost:4840")
|
|
9
|
+
client.default_ns = 2
|
|
10
|
+
|
|
11
|
+
if (node = client.get '/KalimatC34/Tools/Tool1/ToolNumber')
|
|
12
|
+
node.value = [:a, :b]
|
|
13
|
+
else
|
|
14
|
+
p 'invalid nodeid'
|
|
15
|
+
end
|
data/example/server.rb
CHANGED
|
@@ -16,9 +16,9 @@ Daemonite.new do
|
|
|
16
16
|
t.add_variable :SollWertX
|
|
17
17
|
t.add_variable :SollWertY
|
|
18
18
|
t.add_variable :SollWertZ
|
|
19
|
-
t.
|
|
19
|
+
t.add_variable_rw :ToolNumber
|
|
20
20
|
t.add_variable :DuploNumber
|
|
21
|
-
t.
|
|
21
|
+
t.add_property :testValue1
|
|
22
22
|
t.add_method :testMethod, test1: OPCUA::TYPES::STRING, test2: OPCUA::TYPES::DATETIME do |node, test1, test2|
|
|
23
23
|
ns, nid = node.id
|
|
24
24
|
puts '-' * 10
|
|
@@ -45,18 +45,30 @@ Daemonite.new do
|
|
|
45
45
|
t3 = tools.manifest(:Tool3,tt)
|
|
46
46
|
|
|
47
47
|
opts[:tn] = t1.find(:ToolNumber)
|
|
48
|
+
opts[:tn].description = 'test test'
|
|
49
|
+
opts[:tn].value = [0,1]
|
|
50
|
+
p opts[:tn].description
|
|
48
51
|
|
|
49
52
|
measurments_t1 = t1.find(:Measurements)
|
|
50
53
|
measurments_t1.manifest(:M1,mt)
|
|
51
54
|
measurments_t1.manifest(:M2,mt)
|
|
55
|
+
|
|
56
|
+
p opts['server'].namespaces
|
|
52
57
|
rescue => e
|
|
53
58
|
puts e.message
|
|
54
59
|
end
|
|
55
60
|
|
|
61
|
+
|
|
62
|
+
counter = 0
|
|
56
63
|
run do |opts|
|
|
57
64
|
GC.start
|
|
58
65
|
sleep opts['server'].run
|
|
59
|
-
|
|
66
|
+
# if counter % 100 == 0
|
|
67
|
+
# opts[:tn].value = [counter, counter]
|
|
68
|
+
# # opts[:tn].value = 1
|
|
69
|
+
# p opts[:tn].value
|
|
70
|
+
# end
|
|
71
|
+
# counter += 1
|
|
60
72
|
rescue => e
|
|
61
73
|
puts e.message
|
|
62
74
|
end
|
data/ext/opcua/client/client.c
CHANGED
|
@@ -2,6 +2,7 @@
|
|
|
2
2
|
#include "../../../cert/cert.h"
|
|
3
3
|
#include "../../../cert/cert_key.h"
|
|
4
4
|
|
|
5
|
+
|
|
5
6
|
VALUE mOPCUA = Qnil;
|
|
6
7
|
VALUE cClient = Qnil;
|
|
7
8
|
VALUE cVarNode = Qnil;
|
|
@@ -10,6 +11,11 @@ VALUE cNode = Qnil;
|
|
|
10
11
|
|
|
11
12
|
#include "../values.h"
|
|
12
13
|
|
|
14
|
+
#include <signal.h>
|
|
15
|
+
|
|
16
|
+
static volatile bool keepRunning = true;
|
|
17
|
+
void intHandler(int dummy) { keepRunning = false; }
|
|
18
|
+
|
|
13
19
|
/* -- */
|
|
14
20
|
static void node_free(node_struct *ns) { //{{{
|
|
15
21
|
if (ns != NULL) {
|
|
@@ -26,6 +32,7 @@ static node_struct * node_alloc(client_struct *client, UA_NodeId nodeid) { //{{{
|
|
|
26
32
|
ns->master = client;
|
|
27
33
|
ns->id = nodeid;
|
|
28
34
|
ns->on_change = Qnil;
|
|
35
|
+
ns->waiting = 0;
|
|
29
36
|
|
|
30
37
|
return ns;
|
|
31
38
|
} //}}}
|
|
@@ -51,6 +58,28 @@ static VALUE node_value(VALUE self) { //{{{
|
|
|
51
58
|
UA_Variant_clear(&value);
|
|
52
59
|
return rb_ary_entry(ret,0);
|
|
53
60
|
} //}}}
|
|
61
|
+
static VALUE node_value_set(VALUE self, VALUE value) { //{{{
|
|
62
|
+
node_struct *ns;
|
|
63
|
+
Data_Get_Struct(self, node_struct, ns);
|
|
64
|
+
if (!ns->master->started) rb_raise(rb_eRuntimeError, "Client disconnected.");
|
|
65
|
+
|
|
66
|
+
UA_Variant variant;
|
|
67
|
+
if (value_to_variant(value,&variant)) {
|
|
68
|
+
// printf("-----------------------------------------%ld\n",variant.arrayDimensionsSize);
|
|
69
|
+
if (variant.arrayDimensionsSize > 0) {
|
|
70
|
+
UA_Int32 ads = (UA_Int32) variant.arrayDimensionsSize;
|
|
71
|
+
UA_Client_writeValueRankAttribute(ns->master->master, ns->id, &ads);
|
|
72
|
+
UA_Client_writeArrayDimensionsAttribute(ns->master->master, ns->id, variant.arrayDimensionsSize, variant.arrayDimensions);
|
|
73
|
+
}
|
|
74
|
+
|
|
75
|
+
UA_StatusCode retval = UA_Client_writeValueAttribute(ns->master->master, ns->id, &variant);
|
|
76
|
+
if (retval != UA_STATUSCODE_GOOD) {
|
|
77
|
+
rb_raise(rb_eRuntimeError, "Can't set value: %s.", UA_StatusCode_name(retval));
|
|
78
|
+
}
|
|
79
|
+
}
|
|
80
|
+
|
|
81
|
+
return self;
|
|
82
|
+
} //}}}
|
|
54
83
|
static VALUE node_on_change(VALUE self) { //{{{
|
|
55
84
|
node_struct *ns;
|
|
56
85
|
Data_Get_Struct(self, node_struct, ns);
|
|
@@ -67,6 +96,82 @@ static VALUE node_on_change(VALUE self) { //{{{
|
|
|
67
96
|
|
|
68
97
|
return self;
|
|
69
98
|
} //}}}
|
|
99
|
+
static void node_on_value_change_handler(UA_Client *client, UA_UInt32 subId, void *subContext, UA_UInt32 monId, void *monContext, UA_DataValue *value) {
|
|
100
|
+
VALUE ins = (VALUE)monContext;
|
|
101
|
+
VALUE blk = RARRAY_AREF(ins,1);
|
|
102
|
+
|
|
103
|
+
node_struct *ns;
|
|
104
|
+
Data_Get_Struct(RARRAY_AREF(ins,0), node_struct, ns);
|
|
105
|
+
ns->waiting = ns->waiting + 1;
|
|
106
|
+
|
|
107
|
+
if (ns->waiting == 2 && (NIL_P(blk) || TYPE(blk) != T_NIL)) {
|
|
108
|
+
VALUE args = rb_ary_new2(3);
|
|
109
|
+
VALUE ret = extract_value(value->value);
|
|
110
|
+
rb_ary_store(args,0,rb_ary_entry(ret,0));
|
|
111
|
+
if (value->hasSourceTimestamp) {
|
|
112
|
+
rb_ary_store(args,1,rb_time_new(UA_DateTime_toUnixTime(value->sourceTimestamp),0));
|
|
113
|
+
} else {
|
|
114
|
+
if (value->hasServerTimestamp) {
|
|
115
|
+
rb_ary_store(args,1,rb_time_new(UA_DateTime_toUnixTime(value->serverTimestamp),0));
|
|
116
|
+
} else {
|
|
117
|
+
rb_ary_store(args,1,Qnil);
|
|
118
|
+
}
|
|
119
|
+
}
|
|
120
|
+
rb_ary_store(args,2,rb_ary_entry(ret,1));
|
|
121
|
+
rb_proc_call(blk,args);
|
|
122
|
+
}
|
|
123
|
+
}
|
|
124
|
+
static VALUE node_on_value_change(VALUE self) {
|
|
125
|
+
node_struct *ns;
|
|
126
|
+
Data_Get_Struct(self, node_struct, ns);
|
|
127
|
+
if (!ns->master->started) rb_raise(rb_eRuntimeError, "Client disconnected.");
|
|
128
|
+
|
|
129
|
+
if (!rb_block_given_p())
|
|
130
|
+
rb_raise(rb_eArgError, "you need to supply a block with #on_change");
|
|
131
|
+
|
|
132
|
+
UA_CreateSubscriptionRequest sreq; UA_CreateSubscriptionRequest_init(&sreq);
|
|
133
|
+
sreq.requestedPublishingInterval = 100;
|
|
134
|
+
sreq.requestedLifetimeCount = 10000;
|
|
135
|
+
sreq.requestedMaxKeepAliveCount = 10;
|
|
136
|
+
sreq.maxNotificationsPerPublish = 0;
|
|
137
|
+
sreq.publishingEnabled = true;
|
|
138
|
+
sreq.priority = 0;
|
|
139
|
+
|
|
140
|
+
UA_CreateSubscriptionResponse sres = UA_Client_Subscriptions_create(ns->master->master, sreq, NULL, NULL, NULL);
|
|
141
|
+
if (sres.responseHeader.serviceResult != UA_STATUSCODE_GOOD)
|
|
142
|
+
rb_raise(rb_eRuntimeError, "Subscription could not be created.");
|
|
143
|
+
|
|
144
|
+
VALUE ins = rb_ary_new2(2);
|
|
145
|
+
rb_ary_store(ins,0,self);
|
|
146
|
+
rb_ary_store(ins,1,rb_block_proc());
|
|
147
|
+
ns->waiting = 0;
|
|
148
|
+
|
|
149
|
+
UA_MonitoredItemCreateRequest monRequest = UA_MonitoredItemCreateRequest_default(ns->id);
|
|
150
|
+
UA_MonitoredItemCreateResult monResponse =
|
|
151
|
+
UA_Client_MonitoredItems_createDataChange(ns->master->master, sres.subscriptionId,
|
|
152
|
+
UA_TIMESTAMPSTORETURN_BOTH,
|
|
153
|
+
monRequest, (void *)ins, node_on_value_change_handler, NULL);
|
|
154
|
+
|
|
155
|
+
if(monResponse.statusCode != UA_STATUSCODE_GOOD) {
|
|
156
|
+
rb_raise(rb_eRuntimeError, "Monitoring item failed: %s\n", UA_StatusCode_name(monResponse.statusCode));
|
|
157
|
+
}
|
|
158
|
+
|
|
159
|
+
keepRunning = true;
|
|
160
|
+
signal(SIGINT, intHandler);
|
|
161
|
+
while (ns->waiting < 2 && keepRunning) {
|
|
162
|
+
UA_Client_run_iterate(ns->master->master, 100);
|
|
163
|
+
}
|
|
164
|
+
signal(SIGINT, SIG_DFL); // reset the disposition for SIGINT to the default
|
|
165
|
+
|
|
166
|
+
UA_MonitoredItemCreateResult_clear(&monResponse);
|
|
167
|
+
UA_MonitoredItemCreateRequest_clear(&monRequest);
|
|
168
|
+
|
|
169
|
+
UA_Client_Subscriptions_deleteSingle(ns->master->master, sres.subscriptionId);
|
|
170
|
+
UA_CreateSubscriptionResponse_clear(&sres);
|
|
171
|
+
UA_CreateSubscriptionRequest_clear(&sreq);
|
|
172
|
+
|
|
173
|
+
return self;
|
|
174
|
+
}
|
|
70
175
|
|
|
71
176
|
/* -- */
|
|
72
177
|
static void client_free(client_struct *pss) { //{{{
|
|
@@ -238,28 +343,31 @@ static VALUE client_get(int argc, VALUE* argv, VALUE self) { //{{{
|
|
|
238
343
|
if (NIL_P(ns) || TYPE(ns) != T_FIXNUM)
|
|
239
344
|
rb_raise(rb_eTypeError, "ns is not a valid (numeric) namespace id");
|
|
240
345
|
|
|
241
|
-
|
|
346
|
+
UA_NodeId it;
|
|
347
|
+
|
|
242
348
|
if (TYPE(id) == T_FIXNUM) {
|
|
243
|
-
|
|
349
|
+
it = UA_NODEID_NUMERIC(NUM2INT(ns), NUM2INT(id));
|
|
244
350
|
} else {
|
|
245
351
|
VALUE str = rb_obj_as_string(id);
|
|
246
352
|
if (NIL_P(str) || TYPE(str) != T_STRING)
|
|
247
353
|
rb_raise(rb_eTypeError, "cannot convert url to string");
|
|
248
354
|
char *nstr = (char *)StringValuePtr(str);
|
|
249
355
|
|
|
250
|
-
|
|
356
|
+
it = UA_NODEID_STRING(NUM2INT(ns), nstr);
|
|
251
357
|
}
|
|
252
358
|
|
|
253
359
|
UA_NodeClass nc;UA_NodeClass_init(&nc);
|
|
254
|
-
UA_Client_readNodeClassAttribute(pss->master,
|
|
360
|
+
UA_Client_readNodeClassAttribute(pss->master, it, &nc);
|
|
255
361
|
|
|
256
362
|
VALUE node;
|
|
257
363
|
if (nc == UA_NODECLASS_VARIABLE) {
|
|
258
|
-
node = node_wrap(cVarNode,
|
|
364
|
+
node = node_wrap(cVarNode,node_alloc(pss, it));
|
|
259
365
|
} else if (nc == UA_NODECLASS_METHOD) {
|
|
260
|
-
node = node_wrap(cMethodNode,
|
|
366
|
+
node = node_wrap(cMethodNode,node_alloc(pss, it));
|
|
367
|
+
} else if (nc == UA_NODECLASS_UNSPECIFIED) {
|
|
368
|
+
node = Qnil;
|
|
261
369
|
} else {
|
|
262
|
-
node = node_wrap(cNode,
|
|
370
|
+
node = node_wrap(cNode,node_alloc(pss, it));
|
|
263
371
|
}
|
|
264
372
|
UA_NodeClass_clear(&nc);
|
|
265
373
|
|
|
@@ -323,6 +431,25 @@ static VALUE client_debug_set(VALUE self, VALUE val) { //{{{
|
|
|
323
431
|
return self;
|
|
324
432
|
} //}}}
|
|
325
433
|
|
|
434
|
+
static VALUE client_namespaces(VALUE self) { //{{{
|
|
435
|
+
client_struct *pss;
|
|
436
|
+
Data_Get_Struct(self, client_struct, pss);
|
|
437
|
+
if (!pss->started) rb_raise(rb_eRuntimeError, "Client disconnected.");
|
|
438
|
+
|
|
439
|
+
UA_Variant value;
|
|
440
|
+
UA_Variant_init(&value);
|
|
441
|
+
UA_StatusCode retval = UA_Client_readValueAttribute(pss->master, UA_NODEID_NUMERIC(0, UA_NS0ID_SERVER_NAMESPACEARRAY), &value);
|
|
442
|
+
|
|
443
|
+
VALUE ret = Qnil;
|
|
444
|
+
if (retval == UA_STATUSCODE_GOOD) {
|
|
445
|
+
ret = extract_value(value);
|
|
446
|
+
}
|
|
447
|
+
|
|
448
|
+
UA_Variant_clear(&value);
|
|
449
|
+
RB_OBJ_FREEZE(ret);
|
|
450
|
+
return rb_ary_entry(ret,0);
|
|
451
|
+
} //}}}
|
|
452
|
+
|
|
326
453
|
static VALUE node_id(VALUE self) { //{{{
|
|
327
454
|
node_struct *ns;
|
|
328
455
|
|
|
@@ -348,7 +475,7 @@ static VALUE node_to_s(VALUE self) { //{{{
|
|
|
348
475
|
Data_Get_Struct(self, node_struct, ns);
|
|
349
476
|
|
|
350
477
|
if (ns->id.identifierType == UA_NODEIDTYPE_NUMERIC) {
|
|
351
|
-
ret = rb_sprintf("ns=%d;
|
|
478
|
+
ret = rb_sprintf("ns=%d;i=%d", ns->id.namespaceIndex, ns->id.identifier.numeric);
|
|
352
479
|
} else if(ns->id.identifierType == UA_NODEIDTYPE_STRING) {
|
|
353
480
|
ret = rb_sprintf("ns=%d;s=%.*s", ns->id.namespaceIndex, (int)ns->id.identifier.string.length, ns->id.identifier.string.data);
|
|
354
481
|
} else {
|
|
@@ -357,7 +484,7 @@ static VALUE node_to_s(VALUE self) { //{{{
|
|
|
357
484
|
return ret;
|
|
358
485
|
} //}}}
|
|
359
486
|
|
|
360
|
-
static VALUE node_call(int argc, VALUE* argv, VALUE self) {
|
|
487
|
+
static VALUE node_call(int argc, VALUE* argv, VALUE self) { //{{{
|
|
361
488
|
node_struct *ns;
|
|
362
489
|
|
|
363
490
|
VALUE splat;
|
|
@@ -389,7 +516,7 @@ static VALUE node_call(int argc, VALUE* argv, VALUE self) {
|
|
|
389
516
|
} else {
|
|
390
517
|
return Qfalse;
|
|
391
518
|
}
|
|
392
|
-
}
|
|
519
|
+
} //}}}
|
|
393
520
|
|
|
394
521
|
static void client_run_handler(UA_Client *client, UA_UInt32 subId, void *subContext, UA_UInt32 monId, void *monContext, UA_DataValue *value) { //{{{
|
|
395
522
|
VALUE val = (VALUE)monContext;
|
|
@@ -465,9 +592,9 @@ void Init_client(void) {
|
|
|
465
592
|
mOPCUA = rb_define_module("OPCUA");
|
|
466
593
|
|
|
467
594
|
cClient = rb_define_class_under(mOPCUA, "Client", rb_cObject);
|
|
468
|
-
cNode = rb_define_class_under(
|
|
469
|
-
cMethodNode = rb_define_class_under(
|
|
470
|
-
cVarNode = rb_define_class_under(
|
|
595
|
+
cNode = rb_define_class_under(cClient, "cNode", rb_cObject);
|
|
596
|
+
cMethodNode = rb_define_class_under(cClient, "cMethodNode", cNode);
|
|
597
|
+
cVarNode = rb_define_class_under(cClient, "cVarNode", cNode);
|
|
471
598
|
|
|
472
599
|
Init_types();
|
|
473
600
|
|
|
@@ -480,18 +607,17 @@ void Init_client(void) {
|
|
|
480
607
|
rb_define_method(cClient, "subscription_interval=", client_subscription_interval_set, 1);
|
|
481
608
|
rb_define_method(cClient, "default_ns", client_default_ns, 0);
|
|
482
609
|
rb_define_method(cClient, "default_ns=", client_default_ns_set, 1);
|
|
610
|
+
rb_define_method(cClient, "namespaces", client_namespaces, 0);
|
|
483
611
|
rb_define_method(cClient, "debug", client_debug, 0);
|
|
484
612
|
rb_define_method(cClient, "debug=", client_debug_set, 1);
|
|
485
613
|
|
|
486
614
|
rb_define_method(cNode, "to_s", node_to_s, 0);
|
|
487
615
|
rb_define_method(cNode, "id", node_id, 0);
|
|
488
616
|
|
|
489
|
-
rb_define_method(cMethodNode, "to_s", node_to_s, 0);
|
|
490
|
-
rb_define_method(cMethodNode, "id", node_id, 0);
|
|
491
617
|
rb_define_method(cMethodNode, "call", node_call, -1);
|
|
492
618
|
|
|
493
|
-
rb_define_method(cVarNode, "to_s", node_to_s, 0);
|
|
494
|
-
rb_define_method(cVarNode, "id", node_id, 0);
|
|
495
619
|
rb_define_method(cVarNode, "value", node_value, 0);
|
|
620
|
+
rb_define_method(cVarNode, "value=", node_value_set, 1);
|
|
496
621
|
rb_define_method(cVarNode, "on_change", node_on_change, 0);
|
|
622
|
+
rb_define_method(cVarNode, "on_value_change", node_on_value_change, 0);
|
|
497
623
|
}
|
data/ext/opcua/client/client.h
CHANGED
data/ext/opcua/server/extconf.rb
CHANGED
data/ext/opcua/server/server.c
CHANGED
|
@@ -2,9 +2,13 @@
|
|
|
2
2
|
|
|
3
3
|
VALUE mOPCUA = Qnil;
|
|
4
4
|
VALUE cServer = Qnil;
|
|
5
|
-
VALUE
|
|
6
|
-
VALUE
|
|
7
|
-
VALUE
|
|
5
|
+
VALUE cNode = Qnil;
|
|
6
|
+
VALUE cObjectNode = Qnil;
|
|
7
|
+
VALUE cTypeTopNode = Qnil;
|
|
8
|
+
VALUE cTypeSubNode = Qnil;
|
|
9
|
+
VALUE cReferenceTopNode = Qnil;
|
|
10
|
+
VALUE cReferenceSubNode = Qnil;
|
|
11
|
+
VALUE cReferenceNode = Qnil;
|
|
8
12
|
VALUE cVarNode = Qnil;
|
|
9
13
|
VALUE cMethodNode = Qnil;
|
|
10
14
|
|
|
@@ -41,7 +45,7 @@ static VALUE node_wrap(VALUE klass, node_struct *ns) { //{{{
|
|
|
41
45
|
static VALUE node_type_folder(VALUE self) { //{{{
|
|
42
46
|
node_struct *ns;
|
|
43
47
|
Data_Get_Struct(self, node_struct, ns);
|
|
44
|
-
return node_wrap(
|
|
48
|
+
return node_wrap(cTypeTopNode, node_alloc(ns->master, UA_NODEID_NUMERIC(0, UA_NS0ID_FOLDERTYPE)));
|
|
45
49
|
} //}}}
|
|
46
50
|
static VALUE node_add_object_type(VALUE self, VALUE name) { //{{{
|
|
47
51
|
node_struct *ns;
|
|
@@ -66,7 +70,34 @@ static VALUE node_add_object_type(VALUE self, VALUE name) { //{{{
|
|
|
66
70
|
NULL,
|
|
67
71
|
NULL);
|
|
68
72
|
|
|
69
|
-
return node_wrap(
|
|
73
|
+
return node_wrap(cTypeSubNode,node_alloc(ns->master,n));
|
|
74
|
+
} //}}}
|
|
75
|
+
static VALUE node_add_reference_type(VALUE self, VALUE name, VALUE type) { //{{{
|
|
76
|
+
node_struct *ns;
|
|
77
|
+
|
|
78
|
+
Data_Get_Struct(self, node_struct, ns);
|
|
79
|
+
|
|
80
|
+
VALUE str = rb_obj_as_string(name);
|
|
81
|
+
if (NIL_P(str) || TYPE(str) != T_STRING)
|
|
82
|
+
rb_raise(rb_eTypeError, "cannot convert arg 1 to string");
|
|
83
|
+
char *nstr = (char *)StringValuePtr(str);
|
|
84
|
+
if (TYPE(type) != T_FIXNUM)
|
|
85
|
+
rb_raise(rb_eTypeError, "cannot convert arg 2 to integer");
|
|
86
|
+
|
|
87
|
+
UA_NodeId n = UA_NODEID_NUMERIC(ns->master->default_ns, nodecounter++);
|
|
88
|
+
|
|
89
|
+
UA_ReferenceTypeAttributes rtAttr = UA_ReferenceTypeAttributes_default;
|
|
90
|
+
rtAttr.displayName = UA_LOCALIZEDTEXT("en-US", nstr);
|
|
91
|
+
UA_Server_addReferenceTypeNode(ns->master->master,
|
|
92
|
+
n,
|
|
93
|
+
ns->id,
|
|
94
|
+
UA_NODEID_NUMERIC(0, NUM2INT(type)),
|
|
95
|
+
UA_QUALIFIEDNAME(ns->master->default_ns, nstr),
|
|
96
|
+
rtAttr,
|
|
97
|
+
NULL,
|
|
98
|
+
NULL);
|
|
99
|
+
|
|
100
|
+
return node_wrap(cReferenceSubNode,node_alloc(ns->master,n));
|
|
70
101
|
} //}}}
|
|
71
102
|
|
|
72
103
|
static VALUE node_id(VALUE self) { //{{{
|
|
@@ -94,7 +125,7 @@ static VALUE node_to_s(VALUE self) { //{{{
|
|
|
94
125
|
Data_Get_Struct(self, node_struct, ns);
|
|
95
126
|
|
|
96
127
|
if (ns->id.identifierType == UA_NODEIDTYPE_NUMERIC) {
|
|
97
|
-
ret = rb_sprintf("ns=%d;
|
|
128
|
+
ret = rb_sprintf("ns=%d;i=%d", ns->id.namespaceIndex, ns->id.identifier.numeric);
|
|
98
129
|
} else if(ns->id.identifierType == UA_NODEIDTYPE_STRING) {
|
|
99
130
|
ret = rb_sprintf("ns=%d;s=%.*s", ns->id.namespaceIndex, (int)ns->id.identifier.string.length, ns->id.identifier.string.data);
|
|
100
131
|
} else {
|
|
@@ -102,6 +133,33 @@ static VALUE node_to_s(VALUE self) { //{{{
|
|
|
102
133
|
}
|
|
103
134
|
return ret;
|
|
104
135
|
} //}}}
|
|
136
|
+
static VALUE node_add_reference(VALUE self, VALUE to, VALUE type) { //{{{
|
|
137
|
+
node_struct *ns;
|
|
138
|
+
node_struct *tos;
|
|
139
|
+
node_struct *tys;
|
|
140
|
+
|
|
141
|
+
Data_Get_Struct(self, node_struct, ns);
|
|
142
|
+
|
|
143
|
+
if (!(rb_obj_is_kind_of(type,cReferenceSubNode) || rb_obj_is_kind_of(to,cTypeSubNode))) {
|
|
144
|
+
rb_raise(rb_eArgError, "arguments have to be NodeIDs.");
|
|
145
|
+
}
|
|
146
|
+
Data_Get_Struct(to, node_struct, tos);
|
|
147
|
+
Data_Get_Struct(type, node_struct, tys);
|
|
148
|
+
UA_NodeId n = UA_NODEID_NUMERIC(ns->master->default_ns, nodecounter++);
|
|
149
|
+
|
|
150
|
+
UA_ExpandedNodeId toNodeId;
|
|
151
|
+
toNodeId.serverIndex = 0;
|
|
152
|
+
toNodeId.namespaceUri = UA_STRING_NULL;
|
|
153
|
+
toNodeId.nodeId = tos->id;
|
|
154
|
+
|
|
155
|
+
UA_Server_addReference(ns->master->master,
|
|
156
|
+
n,
|
|
157
|
+
tys->id,
|
|
158
|
+
toNodeId,
|
|
159
|
+
true);
|
|
160
|
+
|
|
161
|
+
return node_wrap(cReferenceNode,node_alloc(ns->master,n));
|
|
162
|
+
} //}}}
|
|
105
163
|
|
|
106
164
|
static UA_StatusCode node_add_method_callback( //{{{
|
|
107
165
|
UA_Server *server,
|
|
@@ -121,7 +179,7 @@ static UA_StatusCode node_add_method_callback( //{{{
|
|
|
121
179
|
// );
|
|
122
180
|
|
|
123
181
|
VALUE args = rb_ary_new();
|
|
124
|
-
rb_ary_push(args, Data_Wrap_Struct(
|
|
182
|
+
rb_ary_push(args, Data_Wrap_Struct(cObjectNode,NULL,NULL,me));
|
|
125
183
|
for (int i = 0; i < inputSize; i++) {
|
|
126
184
|
VALUE ret = extract_value(input[i]);
|
|
127
185
|
rb_ary_push(args,rb_ary_entry(ret,0));
|
|
@@ -220,10 +278,9 @@ static VALUE node_add_method(int argc, VALUE* argv, VALUE self) { //{{{
|
|
|
220
278
|
return node_wrap(CLASS_OF(self),node_alloc(parent->master,node_add_method_ua_simple(nstr,parent,opts,blk)));
|
|
221
279
|
} //}}}
|
|
222
280
|
|
|
223
|
-
static UA_NodeId node_add_variable_ua(UA_Int32 type, UA_NodeId n, UA_LocalizedText dn, UA_QualifiedName qn, node_struct *parent,
|
|
281
|
+
static UA_NodeId node_add_variable_ua(UA_Int32 type, UA_NodeId n, UA_LocalizedText dn, UA_QualifiedName qn, node_struct *parent, UA_Byte accesslevelmask) { //{{{
|
|
224
282
|
UA_VariableAttributes vAttr = UA_VariableAttributes_default;
|
|
225
283
|
vAttr.displayName = dn;
|
|
226
|
-
|
|
227
284
|
vAttr.accessLevel = accesslevelmask;
|
|
228
285
|
|
|
229
286
|
UA_Server_addVariableNode(parent->master->master,
|
|
@@ -231,34 +288,30 @@ static UA_NodeId node_add_variable_ua(UA_Int32 type, UA_NodeId n, UA_LocalizedTe
|
|
|
231
288
|
parent->id,
|
|
232
289
|
UA_NODEID_NUMERIC(0, UA_NS0ID_HASCOMPONENT),
|
|
233
290
|
qn,
|
|
234
|
-
UA_NODEID_NUMERIC(0,
|
|
291
|
+
UA_NODEID_NUMERIC(0, type),
|
|
235
292
|
vAttr,
|
|
236
293
|
NULL,
|
|
237
294
|
NULL);
|
|
238
295
|
|
|
239
|
-
|
|
240
|
-
|
|
241
|
-
|
|
242
|
-
|
|
243
|
-
|
|
244
|
-
true);
|
|
245
|
-
}
|
|
296
|
+
UA_Server_addReference(parent->master->master,
|
|
297
|
+
n,
|
|
298
|
+
UA_NODEID_NUMERIC(0, UA_NS0ID_HASMODELLINGRULE),
|
|
299
|
+
UA_EXPANDEDNODEID_NUMERIC(0, UA_NS0ID_MODELLINGRULE_MANDATORY),
|
|
300
|
+
true);
|
|
246
301
|
|
|
247
302
|
return n;
|
|
248
|
-
|
|
249
303
|
} //}}}
|
|
250
|
-
static UA_NodeId node_add_variable_ua_simple(UA_Int32 type, char* nstr, node_struct *parent,
|
|
304
|
+
static UA_NodeId node_add_variable_ua_simple(UA_Int32 type, char* nstr, node_struct *parent, UA_Byte accesslevelmask, bool numeric) { //{{{
|
|
251
305
|
return node_add_variable_ua(
|
|
252
306
|
type,
|
|
253
307
|
numeric ? UA_NODEID_NUMERIC(parent->master->default_ns,nodecounter++) : UA_NODEID_STRING(parent->master->default_ns,nstr),
|
|
254
308
|
UA_LOCALIZEDTEXT("en-US", nstr),
|
|
255
309
|
UA_QUALIFIEDNAME(parent->master->default_ns, nstr),
|
|
256
310
|
parent,
|
|
257
|
-
ref,
|
|
258
311
|
accesslevelmask
|
|
259
312
|
);
|
|
260
313
|
} //}}}
|
|
261
|
-
static VALUE node_add_variable_wrap(int argc, VALUE* argv, VALUE self, UA_Byte accesslevelmask,bool numeric) { //{{{
|
|
314
|
+
static VALUE node_add_variable_wrap(int argc, VALUE* argv, VALUE self, UA_Byte accesslevelmask, bool numeric) { //{{{
|
|
262
315
|
node_struct *parent;
|
|
263
316
|
|
|
264
317
|
if (argc > 2 || argc == 0) { // there should only be 1 or 2 arguments
|
|
@@ -269,7 +322,7 @@ static VALUE node_add_variable_wrap(int argc, VALUE* argv, VALUE self, UA_Byte a
|
|
|
269
322
|
if (argc == 2 && argv[1] != Qnil) {
|
|
270
323
|
type = NUM2INT(argv[1]);
|
|
271
324
|
} else {
|
|
272
|
-
type =
|
|
325
|
+
type = UA_NS0ID_BASEDATAVARIABLETYPE;
|
|
273
326
|
}
|
|
274
327
|
|
|
275
328
|
Data_Get_Struct(self, node_struct, parent);
|
|
@@ -279,7 +332,7 @@ static VALUE node_add_variable_wrap(int argc, VALUE* argv, VALUE self, UA_Byte a
|
|
|
279
332
|
rb_raise(rb_eTypeError, "cannot convert obj to string");
|
|
280
333
|
char *nstr = (char *)StringValuePtr(str);
|
|
281
334
|
|
|
282
|
-
return node_wrap(cVarNode,node_alloc(parent->master,node_add_variable_ua_simple(type,nstr,parent,
|
|
335
|
+
return node_wrap(cVarNode,node_alloc(parent->master,node_add_variable_ua_simple(type,nstr,parent,accesslevelmask,numeric)));
|
|
283
336
|
} //}}}
|
|
284
337
|
static VALUE node_add_variable(int argc, VALUE* argv, VALUE self) { //{{{
|
|
285
338
|
return node_add_variable_wrap(argc,argv,self,UA_ACCESSLEVELMASK_READ,true);
|
|
@@ -364,7 +417,7 @@ static VALUE node_add_object(int argc, VALUE* argv, VALUE self) { //{{{
|
|
|
364
417
|
type = UA_NS0ID_MODELLINGRULE_MANDATORY;
|
|
365
418
|
}
|
|
366
419
|
|
|
367
|
-
if (!(rb_obj_is_kind_of(argv[1],
|
|
420
|
+
if (!(rb_obj_is_kind_of(argv[1],cTypeTopNode) || rb_obj_is_kind_of(argv[1],cTypeSubNode))) {
|
|
368
421
|
rb_raise(rb_eArgError, "argument 2 has to be a type.");
|
|
369
422
|
}
|
|
370
423
|
|
|
@@ -401,12 +454,24 @@ static bool node_get_reference(UA_Server *server, UA_NodeId parent, UA_NodeId *r
|
|
|
401
454
|
UA_BrowseDescription_init(&bDes);
|
|
402
455
|
bDes.nodeId = parent;
|
|
403
456
|
bDes.resultMask = UA_BROWSERESULTMASK_ALL;
|
|
404
|
-
UA_BrowseResult bRes = UA_Server_browse(server,
|
|
457
|
+
UA_BrowseResult bRes = UA_Server_browse(server, 999, &bDes);
|
|
405
458
|
|
|
406
459
|
if (bRes.referencesSize > 0) {
|
|
407
460
|
UA_ReferenceDescription *ref = &(bRes.references[0]);
|
|
408
461
|
|
|
409
|
-
|
|
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);
|
|
410
475
|
UA_BrowseResult_clear(&bRes);
|
|
411
476
|
return true;
|
|
412
477
|
}
|
|
@@ -480,7 +545,18 @@ static UA_StatusCode node_manifest_iter(UA_NodeId child_id, UA_Boolean is_invers
|
|
|
480
545
|
free(newparent);
|
|
481
546
|
}
|
|
482
547
|
if(nc == UA_NODECLASS_VARIABLE) {
|
|
483
|
-
|
|
548
|
+
UA_QualifiedName pqn;UA_QualifiedName_init(&pqn);
|
|
549
|
+
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);
|
|
551
|
+
|
|
552
|
+
if (property.statusCode == UA_STATUSCODE_GOOD) {
|
|
553
|
+
node_add_variable_ua(UA_NS0ID_PROPERTYTYPE,UA_NODEID_STRING(parent->master->default_ns,buffer),dn,qn,newnode,al);
|
|
554
|
+
} else {
|
|
555
|
+
node_add_variable_ua(UA_NS0ID_BASEDATAVARIABLETYPE,UA_NODEID_STRING(parent->master->default_ns,buffer),dn,qn,newnode,al);
|
|
556
|
+
}
|
|
557
|
+
|
|
558
|
+
UA_BrowsePathResult_clear(&property);
|
|
559
|
+
UA_QualifiedName_clear(&pqn);
|
|
484
560
|
}
|
|
485
561
|
if(nc == UA_NODECLASS_METHOD) {
|
|
486
562
|
UA_NodeId ttt;
|
|
@@ -512,7 +588,7 @@ static VALUE node_manifest(VALUE self, VALUE name, VALUE parent) { //{{{
|
|
|
512
588
|
node_struct *ns;
|
|
513
589
|
node_struct *ts;
|
|
514
590
|
|
|
515
|
-
if (!(rb_obj_is_kind_of(parent,
|
|
591
|
+
if (!(rb_obj_is_kind_of(parent,cTypeTopNode) || rb_obj_is_kind_of(parent,cTypeSubNode))) {
|
|
516
592
|
rb_raise(rb_eArgError, "argument 2 has to be a type.");
|
|
517
593
|
}
|
|
518
594
|
|
|
@@ -569,13 +645,64 @@ static VALUE node_find(VALUE self, VALUE qname) { //{{{
|
|
|
569
645
|
} else if (nc == UA_NODECLASS_METHOD) {
|
|
570
646
|
node = node_wrap(cMethodNode,node_alloc(ns->master,ret));
|
|
571
647
|
} else {
|
|
572
|
-
node = node_wrap(
|
|
648
|
+
node = node_wrap(cObjectNode,node_alloc(ns->master,ret));
|
|
573
649
|
}
|
|
574
650
|
UA_NodeClass_clear(&nc);
|
|
575
651
|
|
|
576
652
|
return node;
|
|
577
653
|
}
|
|
578
654
|
} //}}}
|
|
655
|
+
static VALUE server_get(int argc, VALUE* argv, VALUE self) { //{{{
|
|
656
|
+
if (argc > 2 || argc < 1) { // there should only be 1 or 2 arguments
|
|
657
|
+
rb_raise(rb_eArgError, "wrong number of arguments");
|
|
658
|
+
}
|
|
659
|
+
|
|
660
|
+
server_struct *pss;
|
|
661
|
+
Data_Get_Struct(self, server_struct, pss);
|
|
662
|
+
|
|
663
|
+
VALUE ns = UINT2NUM(pss->default_ns);
|
|
664
|
+
VALUE id;
|
|
665
|
+
|
|
666
|
+
if (argc == 1) {
|
|
667
|
+
id = argv[0];
|
|
668
|
+
} else {
|
|
669
|
+
ns = argv[0];
|
|
670
|
+
id = argv[1];
|
|
671
|
+
}
|
|
672
|
+
|
|
673
|
+
if (NIL_P(ns) || TYPE(ns) != T_FIXNUM)
|
|
674
|
+
rb_raise(rb_eTypeError, "ns is not a valid (numeric) namespace id");
|
|
675
|
+
|
|
676
|
+
UA_NodeId it;
|
|
677
|
+
|
|
678
|
+
if (TYPE(id) == T_FIXNUM) {
|
|
679
|
+
it = UA_NODEID_NUMERIC(NUM2INT(ns), NUM2INT(id));
|
|
680
|
+
} else {
|
|
681
|
+
VALUE str = rb_obj_as_string(id);
|
|
682
|
+
if (NIL_P(str) || TYPE(str) != T_STRING)
|
|
683
|
+
rb_raise(rb_eTypeError, "cannot convert url to string");
|
|
684
|
+
char *nstr = (char *)StringValuePtr(str);
|
|
685
|
+
|
|
686
|
+
it = UA_NODEID_STRING(NUM2INT(ns), nstr);
|
|
687
|
+
}
|
|
688
|
+
|
|
689
|
+
UA_NodeClass nc;UA_NodeClass_init(&nc);
|
|
690
|
+
UA_Server_readNodeClass(pss->master, it, &nc);
|
|
691
|
+
|
|
692
|
+
VALUE node;
|
|
693
|
+
if (nc == UA_NODECLASS_VARIABLE) {
|
|
694
|
+
node = node_wrap(cVarNode,node_alloc(pss, it));
|
|
695
|
+
} else if (nc == UA_NODECLASS_METHOD) {
|
|
696
|
+
node = node_wrap(cNode,node_alloc(pss, it));
|
|
697
|
+
} else if (nc == UA_NODECLASS_UNSPECIFIED) {
|
|
698
|
+
node = Qnil;
|
|
699
|
+
} else {
|
|
700
|
+
node = node_wrap(cNode,node_alloc(pss, it));
|
|
701
|
+
}
|
|
702
|
+
UA_NodeClass_clear(&nc);
|
|
703
|
+
|
|
704
|
+
return node;
|
|
705
|
+
} //}}}
|
|
579
706
|
|
|
580
707
|
static VALUE node_value_set(VALUE self, VALUE value) { //{{{
|
|
581
708
|
node_struct *ns;
|
|
@@ -583,6 +710,14 @@ static VALUE node_value_set(VALUE self, VALUE value) { //{{{
|
|
|
583
710
|
|
|
584
711
|
UA_Variant variant;
|
|
585
712
|
if (value_to_variant(value,&variant)) {
|
|
713
|
+
// printf("-----------------------------------------%ld\n",variant.arrayDimensionsSize);
|
|
714
|
+
if (variant.arrayDimensionsSize > 0) {
|
|
715
|
+
UA_Server_writeValueRank(ns->master->master, ns->id, variant.arrayDimensionsSize);
|
|
716
|
+
UA_Variant uaArrayDimensions;
|
|
717
|
+
UA_Variant_setArray(&uaArrayDimensions, variant.arrayDimensions, variant.arrayDimensionsSize, &UA_TYPES[UA_TYPES_UINT32]);
|
|
718
|
+
UA_Server_writeArrayDimensions(ns->master->master, ns->id, uaArrayDimensions);
|
|
719
|
+
}
|
|
720
|
+
|
|
586
721
|
UA_Server_writeValue(ns->master->master, ns->id, variant);
|
|
587
722
|
}
|
|
588
723
|
return self;
|
|
@@ -603,6 +738,36 @@ static VALUE node_value(VALUE self) { //{{{
|
|
|
603
738
|
}
|
|
604
739
|
|
|
605
740
|
UA_Variant_clear(&value);
|
|
741
|
+
return rb_ary_entry(ret,0);
|
|
742
|
+
} //}}}
|
|
743
|
+
static VALUE node_description_set(VALUE self, VALUE value) { //{{{
|
|
744
|
+
node_struct *ns;
|
|
745
|
+
Data_Get_Struct(self, node_struct, ns);
|
|
746
|
+
|
|
747
|
+
VALUE str = rb_obj_as_string(value);
|
|
748
|
+
if (NIL_P(str) || TYPE(str) != T_STRING)
|
|
749
|
+
rb_raise(rb_eTypeError, "cannot convert obj to string");
|
|
750
|
+
char *nstr = (char *)StringValuePtr(str);
|
|
751
|
+
UA_LocalizedText lt = UA_LOCALIZEDTEXT("en-US",nstr);
|
|
752
|
+
|
|
753
|
+
UA_Server_writeDescription(ns->master->master, ns->id, lt);
|
|
754
|
+
return self;
|
|
755
|
+
} //}}}
|
|
756
|
+
static VALUE node_description(VALUE self) { //{{{
|
|
757
|
+
node_struct *ns;
|
|
758
|
+
|
|
759
|
+
Data_Get_Struct(self, node_struct, ns);
|
|
760
|
+
|
|
761
|
+
UA_LocalizedText value;
|
|
762
|
+
UA_LocalizedText_init(&value);
|
|
763
|
+
UA_StatusCode retval = UA_Server_readDescription(ns->master->master, ns->id, &value);
|
|
764
|
+
|
|
765
|
+
VALUE ret = Qnil;
|
|
766
|
+
if (retval == UA_STATUSCODE_GOOD) {
|
|
767
|
+
ret = rb_str_export_locale(rb_str_new((char *)(value.text.data),value.text.length));
|
|
768
|
+
}
|
|
769
|
+
|
|
770
|
+
UA_LocalizedText_clear(&value);
|
|
606
771
|
return ret;
|
|
607
772
|
} //}}}
|
|
608
773
|
|
|
@@ -668,12 +833,17 @@ static VALUE server_add_namespace(VALUE self, VALUE name) { //{{{
|
|
|
668
833
|
static VALUE server_types(VALUE self) { //{{{
|
|
669
834
|
server_struct *pss;
|
|
670
835
|
Data_Get_Struct(self, server_struct, pss);
|
|
671
|
-
return node_wrap(
|
|
836
|
+
return node_wrap(cTypeTopNode, node_alloc(pss, UA_NODEID_NUMERIC(0, UA_NS0ID_BASEOBJECTTYPE)));
|
|
837
|
+
} //}}}
|
|
838
|
+
static VALUE server_references(VALUE self) { //{{{
|
|
839
|
+
server_struct *pss;
|
|
840
|
+
Data_Get_Struct(self, server_struct, pss);
|
|
841
|
+
return node_wrap(cReferenceTopNode, node_alloc(pss, UA_NODEID_NUMERIC(0, UA_NS0ID_NONHIERARCHICALREFERENCES)));
|
|
672
842
|
} //}}}
|
|
673
843
|
static VALUE server_objects(VALUE self) { //{{{
|
|
674
844
|
server_struct *pss;
|
|
675
845
|
Data_Get_Struct(self, server_struct, pss);
|
|
676
|
-
return node_wrap(
|
|
846
|
+
return node_wrap(cObjectNode, node_alloc(pss, UA_NODEID_NUMERIC(0, UA_NS0ID_OBJECTSFOLDER)));
|
|
677
847
|
} //}}}
|
|
678
848
|
static VALUE server_debug(VALUE self) { //{{{
|
|
679
849
|
server_struct *pss;
|
|
@@ -694,6 +864,23 @@ static VALUE server_debug_set(VALUE self, VALUE val) { //{{{
|
|
|
694
864
|
}
|
|
695
865
|
return self;
|
|
696
866
|
} //}}}
|
|
867
|
+
static VALUE server_namespaces(VALUE self) { //{{{
|
|
868
|
+
server_struct *pss;
|
|
869
|
+
Data_Get_Struct(self, server_struct, pss);
|
|
870
|
+
|
|
871
|
+
UA_Variant value;
|
|
872
|
+
UA_Variant_init(&value);
|
|
873
|
+
UA_StatusCode retval = UA_Server_readValue(pss->master, UA_NODEID_NUMERIC(0, UA_NS0ID_SERVER_NAMESPACEARRAY), &value);
|
|
874
|
+
|
|
875
|
+
VALUE ret = Qnil;
|
|
876
|
+
if (retval == UA_STATUSCODE_GOOD) {
|
|
877
|
+
ret = extract_value(value);
|
|
878
|
+
}
|
|
879
|
+
|
|
880
|
+
UA_Variant_clear(&value);
|
|
881
|
+
RB_OBJ_FREEZE(ret);
|
|
882
|
+
return rb_ary_entry(ret,0);
|
|
883
|
+
} //}}}
|
|
697
884
|
|
|
698
885
|
void Init_server(void) {
|
|
699
886
|
mOPCUA = rb_define_module("OPCUA");
|
|
@@ -701,45 +888,53 @@ void Init_server(void) {
|
|
|
701
888
|
rb_define_const(mOPCUA, "MANDATORYPLACEHOLDER", INT2NUM(UA_NS0ID_MODELLINGRULE_MANDATORYPLACEHOLDER));
|
|
702
889
|
rb_define_const(mOPCUA, "OPTIONAL", INT2NUM(UA_NS0ID_MODELLINGRULE_OPTIONAL));
|
|
703
890
|
rb_define_const(mOPCUA, "OPTIONALPLACEHOLDER", INT2NUM(UA_NS0ID_MODELLINGRULE_OPTIONALPLACEHOLDER));
|
|
891
|
+
rb_define_const(mOPCUA, "BASEDATAVARIABLETYPE", INT2NUM(UA_NS0ID_BASEDATAVARIABLETYPE));
|
|
892
|
+
rb_define_const(mOPCUA, "PROPERTYTYPE", INT2NUM(UA_NS0ID_PROPERTYTYPE));
|
|
704
893
|
|
|
705
894
|
Init_types();
|
|
706
895
|
|
|
707
|
-
cServer
|
|
708
|
-
|
|
709
|
-
|
|
710
|
-
|
|
711
|
-
|
|
712
|
-
|
|
896
|
+
cServer = rb_define_class_under(mOPCUA, "Server", rb_cObject);
|
|
897
|
+
cNode = rb_define_class_under(cServer, "Node", rb_cObject);
|
|
898
|
+
cObjectNode = rb_define_class_under(cServer, "ObjectNode", cNode);
|
|
899
|
+
cTypeTopNode = rb_define_class_under(cServer, "TypeTopNode", cNode);
|
|
900
|
+
cTypeSubNode = rb_define_class_under(cServer, "TypeSubNode", cNode);
|
|
901
|
+
cReferenceTopNode = rb_define_class_under(cServer, "ReferenceTopNode", cNode);
|
|
902
|
+
cReferenceSubNode = rb_define_class_under(cServer, "ReferenceSubNode", cNode);
|
|
903
|
+
cReferenceNode = rb_define_class_under(cServer, "ObjectReferenceNode", cNode);
|
|
904
|
+
cVarNode = rb_define_class_under(cServer, "ObjectVarNode", cNode);
|
|
905
|
+
cMethodNode = rb_define_class_under(cServer, "ObjectMethodNode", cNode);
|
|
713
906
|
|
|
714
907
|
rb_define_alloc_func(cServer, server_alloc);
|
|
715
908
|
rb_define_method(cServer, "initialize", server_init, 0);
|
|
716
909
|
rb_define_method(cServer, "run", server_run, 0);
|
|
717
910
|
rb_define_method(cServer, "add_namespace", server_add_namespace, 1);
|
|
718
911
|
rb_define_method(cServer, "types", server_types, 0);
|
|
912
|
+
rb_define_method(cServer, "references", server_references, 0);
|
|
719
913
|
rb_define_method(cServer, "objects", server_objects, 0);
|
|
720
914
|
rb_define_method(cServer, "debug", server_debug, 0);
|
|
721
915
|
rb_define_method(cServer, "debug=", server_debug_set, 1);
|
|
916
|
+
rb_define_method(cServer, "namespaces", server_namespaces, 0);
|
|
917
|
+
rb_define_method(cServer, "get", server_get, -1);
|
|
918
|
+
|
|
919
|
+
rb_define_method(cNode, "to_s", node_to_s, 0);
|
|
920
|
+
rb_define_method(cNode, "id", node_id, 0);
|
|
921
|
+
rb_define_method(cNode, "description", node_description, 0);
|
|
922
|
+
rb_define_method(cNode, "description=", node_description_set, 1);
|
|
923
|
+
|
|
924
|
+
rb_define_method(cTypeTopNode, "add_object_type", node_add_object_type, 1);
|
|
925
|
+
rb_define_method(cTypeTopNode, "add_reference_type", node_add_reference_type, 1);
|
|
926
|
+
rb_define_method(cTypeTopNode, "folder", node_type_folder, 0);
|
|
927
|
+
|
|
928
|
+
rb_define_method(cTypeSubNode, "add_object_type", node_add_object_type, 1);
|
|
929
|
+
rb_define_method(cTypeSubNode, "add_variable", node_add_variable, -1);
|
|
930
|
+
rb_define_method(cTypeSubNode, "add_variable_rw", node_add_variable_rw, -1);
|
|
931
|
+
rb_define_method(cTypeSubNode, "add_object", node_add_object, -1);
|
|
932
|
+
rb_define_method(cTypeSubNode, "add_method", node_add_method, -1);
|
|
933
|
+
rb_define_method(cTypeSubNode, "add_reference", node_add_reference, 2);
|
|
934
|
+
|
|
935
|
+
rb_define_method(cObjectNode, "manifest", node_manifest, 2);
|
|
936
|
+
rb_define_method(cObjectNode, "find", node_find, 1);
|
|
722
937
|
|
|
723
|
-
rb_define_method(cTypesTopNode, "add_object_type", node_add_object_type, 1);
|
|
724
|
-
rb_define_method(cTypesTopNode, "folder", node_type_folder, 0);
|
|
725
|
-
rb_define_method(cTypesSubNode, "add_object_type", node_add_object_type, 1);
|
|
726
|
-
rb_define_method(cTypesSubNode, "add_variable", node_add_variable, -1);
|
|
727
|
-
rb_define_method(cTypesSubNode, "add_variable_rw", node_add_variable_rw, -1);
|
|
728
|
-
rb_define_method(cTypesSubNode, "add_object", node_add_object, -1);
|
|
729
|
-
rb_define_method(cTypesSubNode, "add_method", node_add_method, -1);
|
|
730
|
-
rb_define_method(cTypesSubNode, "to_s", node_to_s, 0);
|
|
731
|
-
rb_define_method(cTypesSubNode, "id", node_id, 0);
|
|
732
|
-
|
|
733
|
-
rb_define_method(cObjectsNode, "manifest", node_manifest, 2);
|
|
734
|
-
rb_define_method(cObjectsNode, "find", node_find, 1);
|
|
735
|
-
rb_define_method(cObjectsNode, "to_s", node_to_s, 0);
|
|
736
|
-
rb_define_method(cObjectsNode, "id", node_id, 0);
|
|
737
|
-
|
|
738
|
-
rb_define_method(cVarNode, "to_s", node_to_s, 0);
|
|
739
|
-
rb_define_method(cVarNode, "id", node_id, 0);
|
|
740
938
|
rb_define_method(cVarNode, "value", node_value, 0);
|
|
741
939
|
rb_define_method(cVarNode, "value=", node_value_set, 1);
|
|
742
|
-
|
|
743
|
-
rb_define_method(cMethodNode, "to_s", node_to_s, 0);
|
|
744
|
-
rb_define_method(cMethodNode, "id", node_id, 0);
|
|
745
940
|
}
|