Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

add import nodeset files #7

Open
wants to merge 86 commits into
base: master
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
86 commits
Select commit Hold shift + click to select a range
34975b7
update README.md Installation and Development section
ttrau Jun 17, 2019
ada11ba
add server.namespaces and support for string arrays
ttrau Jun 17, 2019
5c7754b
add opcua classes and dynamic class creation from nodeset
ttrau Jun 17, 2019
bb56f6b
add nodeset import, test nodesets and possible modeling example
ttrau Jun 17, 2019
651d315
begin add nodeset import support
ttrau Jun 17, 2019
1b29b1a
simplified names
ttrau Jun 17, 2019
4ccd551
exit server after automatically
ttrau Jun 17, 2019
c6acd4e
clean up
ttrau Jun 17, 2019
b30dc2d
ignore .so and *cert
ttrau Jun 17, 2019
127e711
ignore .so and *cert
ttrau Jun 17, 2019
d03b366
clean up
ttrau Jun 17, 2019
0b87480
clean up
ttrau Jun 17, 2019
fea1705
clean up
ttrau Jun 17, 2019
f9edb7a
simplify with BaseNode.from_xml method
ttrau Jun 17, 2019
3952a6e
add example
ttrau Jun 17, 2019
37df213
remove nodeset - LICENSE MISSING
ttrau Jun 20, 2019
c730baf
add new nodeset with License
ttrau Jun 20, 2019
917b56e
change add nodeset; BaseNode to only meta
ttrau Jun 20, 2019
ba57c91
extract BaseNode; clean up
ttrau Jun 20, 2019
8daa30c
change modeling style
ttrau Jun 20, 2019
dd2a3be
simplify BaseNode
ttrau Jun 20, 2019
08c2e94
enhance parse nodeset
ttrau Jun 20, 2019
9e2fe4a
fix wrong ns error
ttrau Jun 20, 2019
400c3a4
accept changes
ttrau Jun 20, 2019
8005ca3
add UA namespace
ttrau Jun 20, 2019
0882d52
add server.find method
ttrau Jun 21, 2019
8af474f
implement server find(nodeid) -> get node/check if node exists
ttrau Jun 21, 2019
f4108e5
clean up server.rb
ttrau Jun 21, 2019
17bfa31
add c nodeid_from_str, rb server.add_type
ttrau Jun 22, 2019
cc9f2fd
c add_type
ttrau Jun 23, 2019
476b13e
implement add ObjectTypes and ReferenceTypes from nodeset
ttrau Jun 23, 2019
4d8dab0
found error @nodeid_from_str
ttrau Jun 23, 2019
13effd2
error at nodeid_from_str
ttrau Jun 23, 2019
ebd08e9
fixed nodeid_from_str error
ttrau Jun 23, 2019
9962ddf
import sample
ttrau Jun 23, 2019
4e5c397
implement add datatype
ttrau Jun 23, 2019
f6478b8
clean up; implementing node.abstract=
ttrau Jun 24, 2019
dacb685
implement get/set abstract
ttrau Jun 24, 2019
20cb7df
split server_add_type to single methods
ttrau Jun 25, 2019
1598b84
update TODO, sample
ttrau Jun 25, 2019
0ec190c
clean up
ttrau Jul 1, 2019
c92d064
constants use nodes instead of nodeids
ttrau Jul 7, 2019
23f6ce7
reset before merge; add Importer
ttrau Jul 13, 2019
b8e7946
add from basenode; clean up
ttrau Jul 13, 2019
9c9d32d
get references
ttrau Jul 13, 2019
01b2d7b
find parent node
ttrau Jul 13, 2019
6681b0e
use correct reference_node
ttrau Jul 13, 2019
137de7d
raise namespace indices missing
ttrau Jul 13, 2019
840b59e
add objects,but no check for hierarchical ref
ttrau Jul 13, 2019
d4f57cd
node inversename, symmetric, follow_reference
ttrau Jul 13, 2019
d5f6b44
fix follow return array
ttrau Jul 13, 2019
b1b93db
add object with correct reference to parent
ttrau Jul 13, 2019
2f96be9
add event notifier
ttrau Jul 13, 2019
a7d39e6
variabletype add datatype
ttrau Jul 13, 2019
76acc5e
add default types
ttrau Jul 13, 2019
ce39fa3
clean up; make tests raise exceptions
ttrau Jul 13, 2019
82958be
add set datatype
ttrau Jul 14, 2019
43f1d40
test set array dimensions
ttrau Jul 14, 2019
1fd6fa4
clean up tests; add variables by type
ttrau Jul 14, 2019
0b1cc37
merge with opcua-smart
ttrau Jul 15, 2019
5fb9866
server_add_namespace returns index; fix node_dimension
ttrau Jul 15, 2019
ac13e89
node_dimension to node_dimensions
ttrau Jul 15, 2019
b1242ff
fix variable_type rank and dimensions
ttrau Jul 15, 2019
7a57ac4
correct sample matrices
ttrau Jul 16, 2019
1af611e
finish implement matrices
ttrau Jul 16, 2019
44f4e91
add import opcua full or tiny
ttrau Jul 16, 2019
74d168b
add install instructions from blank fedora
ttrau Jul 19, 2019
543d37a
server add method simple
ttrau Jul 19, 2019
b0138a8
add matrix example
ttrau Jul 19, 2019
cd11ce8
Variable get Value
ttrau Jul 19, 2019
04daef5
clean regex
ttrau Jul 20, 2019
a85b338
find extension objects and values
ttrau Jul 20, 2019
74667bd
xpath name() to local-name()
ttrau Jul 20, 2019
1afc328
xpath name() to local-name()
ttrau Jul 20, 2019
3f8489a
value_set unless proposals where set before
ttrau Jul 20, 2019
b3dab41
add bytestring support
ttrau Jul 20, 2019
7ac3b62
clean up
ttrau Jul 20, 2019
9e93642
add support LocalizedText; Array values
ttrau Jul 20, 2019
d91d93c
reset 2 before adding values and extensionobjects
ttrau Jul 21, 2019
f785a3b
clean up
ttrau Jul 22, 2019
93d4d44
fix matrices and arrays
ttrau Jul 22, 2019
dece4bd
clean up
ttrau Jul 22, 2019
b1b06d3
add node_server; fix node_follow and free
ttrau Dec 31, 2019
047a519
add client.types .objects .references
ttrau Jan 3, 2020
7f0afd4
merge upstream
ttrau Jan 3, 2020
ca0cb3b
clean up
ttrau Jan 7, 2020
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
3 changes: 3 additions & 0 deletions .gitignore
Original file line number Diff line number Diff line change
@@ -1,2 +1,5 @@
tmp
pkg
cert/cert*
*.so
.vscode
29 changes: 29 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -63,6 +63,35 @@ sudo ldconfig # update libs
sudo ldconfig -p | grep libopen62541 # check if its there
```

or on 64-bit systems:

```sh
sudo echo "/usr/local/lib64" > /etc/ld.so.conf.d/local.conf # add to libs path
sudo ldconfig # update libs
sudo ldconfig -p | grep libopen62541 # check if its there
```

## Development

Use rake to build c bindings:

```sh
rake
```

Run server with verbose:

```sh
ruby example/server_import_nodeset.rb -v restart
```

Use relative paths to ruby libraries:

```rb
#require 'opcua/server'
require_relative '../lib/opcua/server'
```

## EXAMPLES

### Server
Expand Down
2 changes: 1 addition & 1 deletion example/bug5.rb → example/client/bug5.rb
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
#!/usr/bin/ruby
require_relative '../lib/opcua/server'
require_relative '../../lib/opcua/server'

Daemonite.new do
server = OPCUA::Server.new
Expand Down
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
#!/usr/bin/ruby
require_relative '../lib/opcua/client'
require_relative '../../lib/opcua/client'
#require 'opcua/client'

### username & pass in url (e.g. siemens)
Expand Down
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
#!/usr/bin/ruby
require_relative '../lib/opcua/client'
require_relative '../../lib/opcua/client'
#require 'opcua/client'

### username & pass in url (e.g. siemens)
Expand Down
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
#!/usr/bin/ruby
require_relative '../lib/opcua/client'
require_relative '../../lib/opcua/client'
#require 'opcua/client'

### username & pass in url (e.g. siemens)
Expand Down
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
#!/usr/bin/ruby
require_relative '../lib/opcua/client'
require_relative '../../lib/opcua/client'
#require 'opcua/client'

### username & pass in url (e.g. siemens)
Expand Down
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
#!/usr/bin/ruby
require_relative '../lib/opcua/client'
require_relative '../../lib/opcua/client'
#require 'opcua/client'

### username & pass in url (e.g. siemens)
Expand Down
3,667 changes: 3,667 additions & 0 deletions example/nodeset/nodesets/Example.Reference.1.0.NodeSet2.xml

Large diffs are not rendered by default.

5,137 changes: 5,137 additions & 0 deletions example/nodeset/nodesets/Opc.Ua.AutoID.1.0.NodeSet2.xml

Large diffs are not rendered by default.

2,545 changes: 2,545 additions & 0 deletions example/nodeset/nodesets/Opc.Ua.Di.1.2.NodeSet2.xml

Large diffs are not rendered by default.

139 changes: 139 additions & 0 deletions example/nodeset/server_import_nodeset.rb
Original file line number Diff line number Diff line change
@@ -0,0 +1,139 @@
#!/usr/bin/ruby
# require 'opcua/server'
require_relative '../../lib/opcua/server'

Daemonite.new do
on startup do |opts|
srv = opts['server'] = OPCUA::Server.new

def err(message)
puts "\e[31m#{message}\e[0m"
end
def highlight(message)
puts "\e[36m#{message}\e[0m"
end

srv.import_ua # import small nodeset --> faster and contains most necessary stuff
#srv.import_ua_full # import full nodeset

highlight "Imported OPC UA Nodeset"

# Tests:
err "UA::HasSubtype not found" unless UA::HasSubtype.to_s == "ns=0;i=45"
err "UA::LocalizedText not found" unless UA::LocalizedText.to_s == "ns=0;i=21"

srv.add_nodeset File.read('Opc.Ua.Di.1.2.NodeSet2.xml'), :DI # https://opcfoundation.org/UA/schemas/DI/1.2/Opc.Ua.Di.NodeSet2.xml
highlight "Imported DI Nodeset"
srv.add_nodeset File.read('Opc.Ua.AutoID.1.0.NodeSet2.xml'), :AutoId, :DI # https://opcfoundation.org/UA/schemas/AutoID/1.0/Opc.Ua.AutoID.NodeSet2.xml
highlight "Imported AutoID Nodeset"
srv.add_nodeset File.read('Example.Reference.1.0.NodeSet2.xml'), :Testing, :DI, :Robotics # Really weird local testing nodeset with references to DI and Robotics
highlight "Imported Testing Nodeset"
ex = srv.add_namespace 'http://example.org/'

# Tests:
err "Server known Nodes: #{srv.nodes.length} changed?" unless srv.nodes.length == 597 || srv.nodes.length == 218 # depends on UA full or tiny
err "add_object_type Error" unless srv.add_object_type("TestType","ns=#{ex};i=77777", UA::BaseObjectType, UA::HasSubtype).to_s == "ns=#{ex};i=77777"
err "add_data_type Error" unless srv.add_data_type("TestDataType","ns=#{ex};i=77778", UA::Structure, UA::HasSubtype).to_s == "ns=#{ex};i=77778"
err "add_object Error" unless srv.add_object("TestDevice", "ns=#{ex};i=31243", srv.objects, UA::Organizes, AutoId::OpticalReaderDeviceType).to_s == "ns=#{ex};i=31243"

tt = srv.add_object_type(:TestComponentType, "ns=#{ex};i=77900", DI::ComponentType, UA::HasSubtype).tap{ |t|
t.add_variable :Matrix_2x2
t.add_variable :Matrix_2x3x2
t.add_variable :Array
# ERROR almost always: (Error should have something to do with server_add_object_type)
#t.add_method :Puts, input1: OPCUA::TYPES::STRING do |node, input1|
# highlight input1
#end
}

# ERROR sometimes:
#tt.add_method :Puts, input1: OPCUA::TYPES::STRING do |node, input1|
# highlight input1
#end

srv.objects.manifest(:MatrixTest, tt)

v0 = srv.get "ns=#{ex};s=/MatrixTest/Matrix_2x2"
v1 = srv.get "ns=#{ex};s=/MatrixTest/Matrix_2x3x2"
v2 = srv.get "ns=#{ex};s=/MatrixTest/Array"

v0.datatype = UA::Double
v0.rank = 2 # just as example, will be automatically set when defining a matrix
v0.dimensions = [2, 2] # 2x2 Matrix
v0.value = [
11, 12,
21, 22
]
v1.datatype = UA::Double
v1.rank = 2
v1.dimensions = [2, 3, 2] # 2x3x2 Matrix
v1.value = [
0, 1, 10, 11, 20, 21,
100, 101, 110, 111, 120, 121
] # filling upward from low to high
#v2.datatype = UA::Double
#v2.rank = 1
#v2.dimensions = [4] # don't set this stuff, because it is already defined in the array:
v2.value = [1, 2, 3, 4]

err "v0 false DataType" unless v0.datatype.name == "Double"
err "v0 false ValueRank" unless v0.rank == 2
err "v0 false Dimensions" unless v0.dimensions == [2, 2]
err "v0 false Value" unless v0.value[0] == [11, 12, 21, 22]
err "v1 false ValueRank" unless v1.rank == 3
err "v1 false Dimensions" unless v1.dimensions == [2, 3, 2]
err "v1 false Value" unless v1.value[0] == [0, 1, 10, 11, 20, 21, 100, 101, 110, 111, 120, 121]
err "v2 false DataType at the node itself is not automatically set: #{v2.datatype.name}" unless v2.datatype.name == "Double"
err "v2 false ValueRank" unless v2.rank == 1
err "v2 false Dimensions" unless v2.dimensions == [4]
err "v2 false Value" unless v2.value[0] == [1, 2, 3, 4]
v2.value = [1, 2, 3, 4, 5, 6, 7, 8, 9]
err "v2 false Value when changing array size" unless v2.value[0] == [1, 2, 3, 4, 5, 6, 7, 8, 9]


err "DI import Error @TopologyElement->ComponentType" unless DI::ComponentType.follow_inverse(UA::HasSubtype).first.name == "TopologyElementType"
err "DI DeviceType not found" unless DI::ComponentType.follow(UA::HasSubtype).select{ |n| n.name == "DeviceType" }.length == 1
err "UA HasChild references missing or new added" unless UA::HasChild.follow_all(UA::HasSubtype).select{ |n| n.name == "Aggregates" || n.name == "HasSubtype" }.length == 2

node = UA::HasComponent
path = ""
until node.nil?
path += "->#{node.name}"
node = node.follow_inverse(UA::HasSubtype).first
end
err "Parents of UA::HasComponent false: #{path}" unless path == "->HasComponent->Aggregates->HasChild->HierarchicalReferences->References"









puts "\e[32mFinished\e[0m"

rescue => e
puts "=====================ERROR====================="
puts e.message
puts e.backtrace
puts "======================END======================"
end

counter = 0
run do |opts|
GC.start
sleep opts['server'].run
if counter % 40 == 0
#raise "exit"
end
counter += 1
rescue => e
if e.message == "exit"
puts "\n\n\-->exit"
break
end
end
end.loop!

exit
34 changes: 34 additions & 0 deletions example/nodeset/small_nodeset.rb
Original file line number Diff line number Diff line change
@@ -0,0 +1,34 @@
require 'nokogiri'

def is_necessary(node)
necessary = [
"StateMachineType"
]
find_follow(node)
false
end

def find_follow(node)
follow = [
"HasComponent",
"HasSubtype"
]
node.xpath('xmlns:References/xmlns:Reference').each do |ref|
node.xpath("parent::*/*[@NodeId='#{ref.content}']").each do |fnode|
puts "lol"
end if follow.include? ref['ReferenceType']
end
false
end

nodeset = Nokogiri::XML(File.read(File.join(File.dirname(__FILE__), "../../lib/opcua/Opc.Ua.1.04.NodeSet2.xml")))

nodeset.xpath("/*/*").each do |node|
unless node.name == 'UAReferenceType'
if node['NodeId'] =~ /i=(.*)/ && $1.to_i > 1000
node.remove unless is_necessary node
end
end
end

File.write(File.join(File.dirname(__FILE__), "../../lib/opcua/Opc.Ua.thin.NodeSet2.xml"), nodeset.to_xml)
File renamed without changes.
2 changes: 1 addition & 1 deletion example/server.rb → example/server/server.rb
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
#!/usr/bin/ruby
require_relative '../lib/opcua/server'
require_relative '../../lib/opcua/server'
#require 'opcua/server'

Daemonite.new do
Expand Down
3 changes: 2 additions & 1 deletion example/server_deep.rb → example/server/server_deep.rb
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
#!/usr/bin/ruby
require_relative '../lib/opcua/server'
require_relative '../../lib/opcua/server'
# require 'opcua/server'

Daemonite.new do
server = OPCUA::Server.new
Expand Down
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
#!/usr/bin/ruby
require_relative '../lib/opcua/server'
require_relative '../../lib/opcua/server'
#require 'opcua/server'

Daemonite.new do
Expand Down
File renamed without changes.
55 changes: 39 additions & 16 deletions ext/opcua/client/client.c
Original file line number Diff line number Diff line change
Expand Up @@ -329,6 +329,29 @@ static VALUE client_init(VALUE self,VALUE url,VALUE user,VALUE pass) { //{{{

return self;
} //}}}
static VALUE client_get_node(VALUE self, UA_NodeId nodeid)
{ //{{{
client_struct *pss;
Data_Get_Struct(self, client_struct, pss);
if (!pss->started) rb_raise(rb_eRuntimeError, "Client disconnected.");

UA_NodeClass nc;UA_NodeClass_init(&nc);
UA_Client_readNodeClassAttribute(pss->master, nodeid, &nc);

VALUE node;
if (nc == UA_NODECLASS_VARIABLE) {
node = node_wrap(cVarNode,node_alloc(pss, nodeid));
} else if (nc == UA_NODECLASS_METHOD) {
node = node_wrap(cMethodNode,node_alloc(pss, nodeid));
} else if (nc == UA_NODECLASS_UNSPECIFIED) {
node = Qnil;
} else {
node = node_wrap(cNode,node_alloc(pss, nodeid));
}
UA_NodeClass_clear(&nc);

return node;
} //}}}
static VALUE client_get(int argc, VALUE* argv, VALUE self) { //{{{
if (argc > 2 || argc < 1) { // there should only be 1 or 2 arguments
rb_raise(rb_eArgError, "wrong number of arguments");
Expand Down Expand Up @@ -364,22 +387,19 @@ static VALUE client_get(int argc, VALUE* argv, VALUE self) { //{{{
it = UA_NODEID_STRING(NUM2INT(ns), nstr);
}

UA_NodeClass nc;UA_NodeClass_init(&nc);
UA_Client_readNodeClassAttribute(pss->master, it, &nc);

VALUE node;
if (nc == UA_NODECLASS_VARIABLE) {
node = node_wrap(cVarNode,node_alloc(pss, it));
} else if (nc == UA_NODECLASS_METHOD) {
node = node_wrap(cMethodNode,node_alloc(pss, it));
} else if (nc == UA_NODECLASS_UNSPECIFIED) {
node = Qnil;
} else {
node = node_wrap(cNode,node_alloc(pss, it));
}
UA_NodeClass_clear(&nc);

return node;
return client_get_node(self, it);
} //}}}
static VALUE client_types(VALUE self)
{ //{{{
return client_get_node(self, UA_NODEID_NUMERIC(0, UA_NS0ID_BASEOBJECTTYPE));
} //}}}
static VALUE client_references(VALUE self)
{ //{{{
return client_get_node(self, UA_NODEID_NUMERIC(0, UA_NS0ID_NONHIERARCHICALREFERENCES));
} //}}}
static VALUE client_objects(VALUE self)
{ //{{{
return client_get_node(self, UA_NODEID_NUMERIC(0, UA_NS0ID_OBJECTSFOLDER));
} //}}}
static VALUE client_subscription_interval(VALUE self) { //{{{
client_struct *pss;
Expand Down Expand Up @@ -643,6 +663,9 @@ void Init_client(void) {
rb_define_method(cClient, "default_ns", client_default_ns, 0);
rb_define_method(cClient, "default_ns=", client_default_ns_set, 1);
rb_define_method(cClient, "namespaces", client_namespaces, 0);
rb_define_method(cClient, "types", client_types, 0);
rb_define_method(cClient, "references", client_references, 0);
rb_define_method(cClient, "objects", client_objects, 0);
rb_define_method(cClient, "debug", client_debug, 0);
rb_define_method(cClient, "debug=", client_debug_set, 1);

Expand Down
Loading