OPC UA
opcua
module implements communication over OPC UA protocol.
OPC UA client is available since Gateway version 2.0.2.
opcua.client()
-- @param url string OPC UA connection string
-- @return table OPC UA client
function opcua.client(url)
end
Creates a new OPC UA client
instance with the given connection string.
The underlying TCP connection is established on-demand when the first request is initiated, so this method does not return any error.
Example
local client = opcua.client('opc.tcp://opcuademo.sterfive.com:26543')
Advanced client configuration
Since Gateway version 2.1.1 OPC UA client supports additional settings.
-- @param url string OPC UA connection string
-- @param cfg table connection settings
-- @return table, string OPC UA client and error string
function opcua.client(url, cfg)
end
Authentication methods
OPC UA client supports authentication either with a username or with a certificate. Only one authentication method can be used at a time.
Authentication with username
Authentication with a username requires username
and password
.
Example
local cfg = {
auth = {
username='user',
password='123456',
}
}
Authentication with certificate
Authentication with a certificate requires cert
and key
.
Example
local cfg = {
auth = {
cert='certificate',
key='private key',
}
}
Security
OPC UA client supports a configuration of a secure connection. It should either set mode
and policy
, set none for both or leave them empty. If mode
and policy
are set to not none, cert
and key
are required.
If Authentication with certificate
is configured, the Security configuration should use the same cert
/key
pair.
mode
supports next variables:
opcua.security_mode_none
opcua.security_mode_sign
opcua.security_mode_sign_and_encrypt
policy
supports next variables:
opcua.security_policy_none
opcua.security_policy_basic128_rsa15
opcua.security_policy_basic256
opcua.security_policy_basic256_sha256
opcua.security_policy_aes128_sha256rsa_oaep
opcua.security_policy_aes256_sha256rsa_pss
Example
local cfg = {
security = {
mode=opcua.security_mode_sign,
policy=opcua.security_policy_basic256,
cert='certificate',
key='private key',
},
}
client
Object
client:read()
-- @param request table Read request object
-- @return table, string Response object and error string
function client:read(request)
end
Performs a read request initiated with opcua.read_request()
method. Returns two values: results
and error
. When the performed request failed (e.g. network timeout) error
will contain non-nil string. If any response is obtained, error
will be nil.
results
is a list with results for every requested value. The number of results is equal to the number of values in the read request. Every result contain an error
and value
fields. error
is nil
if read succeeded or contains a string with error if it failed.
OPC UA types will be automatically converted to appropriate Lua types like number
, string
or table
.
Example
-- Initiate request object that will read two values
local request = opcua.read_request({ 'ns=1;i=1678', 'ns=1;i=1348' })
-- Send request
local results, err = client:read(request)
if err then
enapter.log('read failed: '..err, 'error')
else
for i, r in ipairs(results) do
if r.error then
enapter.log('failed: '..r.error, 'error')
else
enapter.log('value #'..i..': '..tostring(r.value))
end
end
end
client:write()
-- @param request table Write request object
-- @return table, string Response object and error string
function client:write(request)
end
Performs a write request initiated with opcua.write_request()
method. Returns two values: results
and error
. When the performed request failed (e.g. network timeout) error
will contain non-nil string. If any response is obtained, error
will be nil.
results
is a list with results for every written value. The number of results is equal to the number of values in the write request. Every result contain an error
field. error
is nil
if write succeeded or contains a string with error if it failed.
Example
-- Initiate request object that will write three values of different types
local request = opcua.write_request({
{node_id = 'ns=2;s=Some.Double', value = 12.5},
{node_id = 'ns=2;s=Some.String', value = 'test'},
{node_id = 'ns=2;s=Some.Number', value = 59},
})
-- Send request
local results, err = client:write(request)
if err then
enapter.log('write failed: '..err, 'error')
else
for i, r in ipairs(results) do
if r.error then
enapter.log('failed: '..r.error, 'error')
else
enapter.log('write #'..i..' succeeded')
end
end
end
client:call_method()
-- @param request table Method request object
-- @return table, string Return values and error string
function client:call_method(request)
end
Performs a method call request initiated with opcua.method_request()
method. Returns two values: values
(an array of values returned by method call) and error
. When the performed request failed (e.g. network timeout) error
will contain non-nil string. If any response is obtained, error
will be nil.
Methods in OPC UA may return several values, thus returned values
is always an array (even of one element). Since the method call may return a nil
values, it's advisable to access return values using positional array access (e.g. values[1]
) due to Lua specifics in working with nil
values (iteration using ipairs
will stop on the first nil
value and will ignore the rest).
Example
-- Initiate request object object node, method node, and method arguments
local request = opcua.method_request(
'ns=2;s=Some',
'ns=2;s=Some.Multiply',
{2, 2}
)
local values, err = client:call_method(request)
if err then
enapter.log('method failed: '..err, 'error')
else
enapter.log('result: '..tostring(values[1]))
end
client:subscribe()
This function is available since Gateway version 2.1.1.
-- @param node_id string Node ID of node which value we want to subscribe to
-- @param interval integer defines how frequently the client sends update via callback
-- @param callback function call when update incoming
-- @return integer, string Return subscription id and error string
function client:subscribe(node_id, interval, callback)
end
Creates a subscription to get value updates for a specified node. Returns two values: subscription id
(used for canceling subscription with client:unsubscribe()
method) and error
. When the subscribe command fails (e.g. network timeout), error
will contain a non-nil string. If the subscribe command succeeds, error
will be nil.
Example
local node_id = "ns=2;s=Write.String"
local interval = 1000
local sub_id, err = client:subscribe(node_id, interval, function(value)
enapter.log("Subscription callback value: "..tostring(value))
end)
if err then
enapter.log("Subscribe error: "..err, "error")
else
enapter.log("Subscribe success")
end
client:unsubscribe()
This function is available since Gateway version 2.1.1.
-- @param sub_id integer subscription id
-- @return string Return error string
function client:unsubscribe(sub_id)
end
Cancels subscription to node value updates. Function returns error
. When the unsubscribe command fails (e.g. network timeout), error
will contain a non-nil string. If the unsubscribe command succeeds, error
will be nil.
Example
sub_id, _ = client:subscribe(node_id_1, interval, function(value) end)
err = client:unsubscribe(sub_id)
if err then
enapter.log("Unsubscribe error: "..err, "error")
else
enapter.log("Unsubscribe success")
end
client:node_attributes()
-- @param node_id string OPC UA node id
-- @return table, string Return object and error string
function client:node_attributes(node_id)
end
Performs getting node attributes initiated with node identifier string (e.g. ns=2;s=Read.StatusCode
). Returns two values: node data
and error
. When the performed request failed (e.g. network timeout) error
will contain non-nil string. If any response is obtained, error
will be nil.
node data
is a table of attributes for the node. Client supports next attributes returning:
OPC UA Attribute | Lua Table Field Name | Lua Table Field Type |
---|---|---|
NodeID | node_id | string |
NodeClass | node_class | string |
BrowseName | browse_name | string |
DisplayName | display_name | string |
Description | description | string |
DataType | data_type | string |
A list of available attributes in node data
depends on a node type.
data_type
takes one of the following values:
- Double
- GUID
- NodeID
- Number
- StatusCode
- String
- Argument
Or node identifier string (e.g. i=293
) for unsupported types.
Example
local node_data, err = client:node_attributes("ns=2;s=Read.String")
if err then
enapter.log("Error get node attributes: "..err, "error")
else
enapter.log(
"String attributes\n"
.."node_class: "..node_data.node_class.."\n"
.."browse_name: "..node_data.browse_name.."\n"
.."display_name: "..node_data.display_name.."\n"
.."description: "..node_data.description.."\n"
.."data_type: "..node_data.data_type.."\n"
)
end
client:node_children()
-- @param node_id string OPC UA node id
-- @return table, string Return string array and error string
function client:node_children(node_id)
end
Performs get node children initiated with node identifier string (e.g. ns=2;s=Method.Multiply
). Returns two values: node_ids
and error
. When the performed request failed (e.g. network timeout) error
will contain non-nil string. If any response is obtained, error
will be nil.
node_ids
is a string table of child node ids.
Example
-- recursive method to get nodes tree
function browse_tree(node_id)
-- get attributes of parent node
local node_data, err = client:node_attributes(node_id)
if err then
return nil, "node attributes "..node_id..": "..err
end
node_data.references = {}
-- get children node ids
local children_nodes, err = client:node_children(node_data.node_id)
if err then
return nil, "ref node ids: "..err
end
-- get attributes of each child node
for _, child_node_id in ipairs(children_nodes) do
local ch_node_data, err = browse_tree(child_node_id)
if err then
return nil, "recursive browse tree: "..err
end
table.insert(node_data.references, ch_node_data)
end
return node_data, nil
end
local tree_data, err = browse_tree("ns=2;s=Method.Multiply")
if err then
enapter.log("Error browse tree: "..err, "error")
else
enapter.log("Browse tree: "..inspect(tree_data))
end
Output
Browse tree: {
browse_name = "Multiply",
description = "Multiply",
display_name = "Multiply",
node_class = "Method",
node_id = "ns=2;s=Method.Multiply",
references = { {
browse_name = "InputArguments",
data_type = "Argument",
description = "InputArguments",
display_name = "InputArguments",
node_class = "Variable",
node_id = "ns=2;i=10",
references = {}
}, {
browse_name = "OutputArguments",
data_type = "Argument",
description = "OutputArguments",
display_name = "OutputArguments",
node_class = "Variable",
node_id = "ns=2;i=11",
references = {}
} }
}
Request Objects
opcua.read_request()
-- @param node_ids table Node IDs to read
-- @return table Request object
function opcua.read_request(node_ids)
end
Creates a new read request instance with the given node IDs to read.
Example
local request = opcua.read_request({
'ns=1;i=1678',
'ns=2;s=Some.Value'
})
opcua.write_request()
-- @param write_pairs table ID-value pairs to write
-- @return table Request object
function opcua.write_request(write_pairs)
end
Creates a new write request instance. It accepts the write_pairs
table where keys are node IDs and values are values to write.
Lua types are converted to appropriate OPC UA types according to type conversion logic.
Example
local request = opcua.write_request({
{node_id = 'ns=2;s=Some.Double', value = 12.5},
{node_id = 'ns=2;s=Some.String', value = 'test'},
{node_id = 'ns=2;s=Some.Number', value = 59},
{node_id = 'ns=2;s=Some.Guid', value = opcua.types.guid('5C97A069-F8A0-48AC-A66F-446475ABB704')},
{node_id = 'ns=2;s=Some.NodeId', value = opcua.types.node_id('ns=2;s=ServerStatus')},
{node_id = 'ns=2;s=Some.StatusCode', value = opcua.types.status_code(12)},
})
opcua.method_request()
-- @param object_id string Node ID of object that contains method
-- @param method_id string Node ID of method to call
-- @param args table Array of method arguments
-- @return table Request object
function opcua.method_request(object_id, method_id, args)
end
Creates a new method call request with object ID, method ID, and method arguments.
Lua types are converted to appropriate OPC UA types according to type conversion logic.
Example
local request = opcua.method_request(
'ns=2;s=Some', -- object that contains method
'ns=2;s=Some.Multiply', -- method node
{2, 2} -- an array with method arguments
)
Type Conversion
When performing write or method call requests some Lua types are automatically converted to appropriate OPC UA types, others should be explicitly given.
Supported node value types:
string
Lua values are automatically converted to OPC UA String,opcua.types.float()
initiates OPC UA Float values,opcua.types.double()
initiates OPC UA Double values,opcua.types.int64()
initiates OPC UA Int64 values,opcua.types.int32()
initiates OPC UA Int32 values,opcua.types.int16()
initiates OPC UA Int16 values,opcua.types.sbyte()
initiates OPC UA SByte values,opcua.types.uint64()
initiates OPC UA UInt64 values,opcua.types.uint32()
initiates OPC UA UInt32 values,opcua.types.uint16()
initiates OPC UA UInt16 values,opcua.types.byte()
initiates OPC UA Byte values,opcua.types.guid()
initiates OPC UA GUID values,opcua.types.status_code()
initiates OPC UA StatusCode values,opcua.types.node_id()
initiates OPC UA NodeId values.