WIP. Note from vdbijl. There are not many options to interact with OPC UA servers in Ruby. This is one of them. The other is opcua-smart, but I have some trouble getting it to work. I am trying to see if it's worthwile to extend this client with more functionality.
My wishlist:
- support for reading and writing all, or the mostly used, data types
- support for detection of objects on the server
Incomplete OPC-UA client library for Ruby. Wraps open62541: https://open62541.org.
Add it to your Gemfile:
gem 'opcua_client'Use start helper to automatically close connections:
require 'opcua_client'
OPCUAClient.start("opc.tcp://127.0.0.1:4840") do |client|
# write to ns=2;s=1
client.write_int16(2, "1", 888)
puts client.read_int16(2, "1")
endOr handle connections manually:
require 'opcua_client'
client = OPCUAClient::Client.new
begin
client.connect("opc.tcp://127.0.0.1:4840")
# write to ns=2;s=1
client.write_int16(2, "1", 888)
puts client.read_int16(2, "1")
client.multi_write_int16(2, (1..10).map{|x| "action_#{x}"}, (1..10).map{|x| x * 10}) # 10x writes
client.multi_write_int32(2, (1..10).map{|x| "amount_#{x}"}, (1..10).map{|x| x * 10 + 1}) # 10x writes
ensure
client.disconnect
endclient.connect(String url)- raises OPCUAClient::Error if unsuccessfulclient.disconnect => Fixnum- returns status
All methods raise OPCUAClient::Error if unsuccessful.
client.read_int16(Fixnum ns, String name) => Fixnumclient.read_uint16(Fixnum ns, String name) => Fixnumclient.read_int32(Fixnum ns, String name) => Fixnumclient.read_uint32(Fixnum ns, String name) => Fixnumclient.read_float(Fixnum ns, String name) => Floatclient.read_boolean(Fixnum ns, String name) => true/falseclient.write_int16(Fixnum ns, String name, Fixnum value)client.write_uint16(Fixnum ns, String name, Fixnum value)client.write_int32(Fixnum ns, String name, Fixnum value)client.write_uint32(Fixnum ns, String name, Fixnum value)client.write_float(Fixnum ns, String name, Float value)client.write_boolean(Fixnum ns, String name, bool value)client.multi_write_int16(Fixnum ns, Array[String] names, Array[Fixnum] values)client.multi_write_uint16(Fixnum ns, Array[String] names, Array[Fixnum] values)client.multi_write_int32(Fixnum ns, Array[String] names, Array[Fixnum] values)client.multi_write_uint32(Fixnum ns, Array[String] names, Array[Fixnum] values)client.multi_write_float(Fixnum ns, Array[String] names, Array[Float] values)client.multi_write_boolean(Fixnum ns, Array[String] names, Array[bool] values)
client.state => Fixnum- client internal stateclient.human_state => String- human readable client internal stateOPCUAClient::Client.human_status_code(Fixnum status) => String- returns human status for status
cli = OPCUAClient::Client.new
cli.after_session_created do |cli|
subscription_id = cli.create_subscription
ns_index = 1
node_name = "the.answer"
cli.add_monitored_item(subscription_id, ns_index, node_name)
end
cli.after_data_changed do |subscription_id, monitor_id, server_time, source_time, new_value|
puts("data changed: " + [subscription_id, monitor_id, server_time, source_time, new_value].inspect)
end
cli.connect("opc.tcp://127.0.0.1:4840")
loop do
cli.connect("opc.tcp://127.0.0.1:4840") # no-op if connected
cli.run_mon_cycle
sleep(0.2)
endclient.create_subscription => Fixnum- nil if errorclient.add_monitored_item(Fixnum subscription, Fixnum ns, String name) => Fixnum- nil if errorclient.run_mon_cycle- returns statusclient.run_mon_cycle!- raises OPCUAClient::Error if unsuccessful
after_session_createdafter_data_changed
bundlemake -C tools/server/ clean all # clean+all
tools/server/server # run$ bin/rake compile
$ bin/console
pry> client = OPCUAClient::Client.new
pry> client.connect("opc.tcp://127.0.0.1:4840")
pry> client.read_uint32(5, "uint32b")
pry> client.read_uint16(5, "uint16b")
pry> client.read_bool(5, "true_var")$ bin/rake compile
$ bin/rake spec