Client - Getting Started
An OPC UA client is a network client that interacts with an OPC UA server via a collection of abstract Remote Procedure Calls (RPC), which is a request/response protocol. An RPC is initiated by the client, which sends a request message to the server. The OPC UA server then sends a response to the client, and the application continues its process. While the OPC UA server is processing the call, the OPC UA client is blocked (it waits until the server has finished processing before resuming execution), unless the OPC UA client operates in asynchronous callback mode.
The OPC UA client can operate in standard blocking socket call (default) or nonblocking cosocket mode. Blocking sockets must run in the context of a native thread, such as a thread running an LSP page. See Asynchronous Cosocket Mode for details.
Connecting to Server
A client is created by first loading the OPC-UA stack and then creating a client as follows:
local ua = require("opcua.api")
local config = {
applicationName = 'RealTimeLogic example',
applicationUri = "urn:opcua-lua:example",
productUri = "urn:opcua-lua:example",
securePolicies = {
{ -- #1
securityPolicyUri = ua.Types.SecurityPolicy.None
}
},
}
local client = ua.newClient(config)
Next, connect to the server, open an OPC-UA channel and finally create an OPC-UA session:
local resp, err
local endpointUrl = "opc.tcp://localhost:4841"
client:connect(endpointUrl, connectCallback)
resp, err = client:openSecureChannel(120000, ua.Types.SecurityPolicy.None, ua.Types.MessageSecurityMode.None)
resp, err = client:createSession("test_session", 3600000)
resp, err = client:activateSession()
You can start browsing the address space as soon as a session has been established.
Browsing Address Space
Call the’ browse’ method to browse the server’s address space.
local RootFolder = "i=84"
local BaseDataVariableType = "i=63"
local FolderType = "i=61"
local ObjectsFolder = "i=85"
local Organizes = "i=35"
local UInt32 = "i=24"
local HierarchicalReferences = "i=33"
local TypesFolder = "i=86"
-- Browse one node by ID.
resp, err = client:browse(RootFolder)
-- Browse array of Node IDs.
resp, err = client:browse({RootFolder, TypesFolder})
if err ~= nil then
return
end
for _,res in ipairs(resp.Results) do
if res.StatusCode ~= ua.StatusCode.Good then
trace(string.format("Cannot browse node: 0x%X", res.StatusCode))
else
trace("References:")
for i,ref in ipairs(res.References) do
trace(string.format("%d: NodeId=%s Name=%s", i, ref.NodeId, ref.DisplayName.Text))
end
end
end
The Address Space Browsing user guide has a detailed overview of all parameters.
Reading Node Attributes
local ua = require("opcua.api")
local config = {
local ObjectsFolder = "i=85"
local TypesFolder = "i=86"
-- Read all possible attributes of the any node
-- For part of attributes will be returned a valus
-- and for part of attributes will be returned a status code BadAttributeIdInvalid
resp,err = client:read(ObjectsFolder)
for i,result in ipairs(resp.Results) do
if result.StatusCode == 0 then
ua.Tools.printTable("result", result.Value)
else
trace(string.format("Read attributes error: 0x%X", result.StatusCode))
end
end
-- Read all possible attributes of several nodes
-- For part of attributes will be returned a valus
-- and for part of attributes will be returned a status code BadAttributeIdInvalid
resp,err = client:read({ObjectsFolder, TypesFolder})
See Reading and Writing Data for parameters and detailed information.
Closing Server Connection
When finished using the server, close the server connection as follows:
resp, err = client:closeSession()
client:disconnect()
Asynchronous Cosocket Mode
Clients, by default, use blocking sockets. However, a client can be configured to operate in cosocket mode, a lightweight Lua coroutine socket thread. All client methods can accept a callback that will be called when the corresponding request completes. The OPC UA methods can also be called without providing a callback when running in cosocket mode if the caller is running in the context of another cosocket. When another cosocket calls an OPC UA client in cosocket mode without providing a callback, the calling cosocket will block. Not having to provide a callback when operating in cosocket mode makes designing OPC UA clients easier.
We recommend reading the Barracuda App Server’s Socket Design User Guide for an introduction to cosockets and for details on the various socket modes.
The cosocket mode is set in the configuration table with the flag ‘cosocketMode’.
local ua = require("opcua.api")
local config = {
applicationName = 'RealTimeLogic example',
applicationUri = "urn:opcua-lua:example",
productUri = "urn:opcua-lua:example",
securePolicies = {
{ -- #1
securityPolicyUri = ua.Types.SecurityPolicy.None
}
},
cosocketMode = true, -- Start socket read loop in separate cosocket
}
local client = ua.newClient(config)
All callbacks, except for the connect method must accept two arguments. The connect method receives one argument as shown in the two examples below.
local endpointUrl = "opc.tcp://localhost:4841"
client:connect(endpointUrl, connectCallback)
The connect method’s error argument is nil if the connection succeeded.
local function connectCallback(err)
if err ~= nil then
trace("connection error: "..err)
return
end
trace("Opening secure channel")
local secureChannelTimeout = 60000 -- ms
client:openSecureChannel(secureChannelTimeout, ua.Types.SecurityPolicy.None, ua.Types.MessageSecurityMode.None, nil, onChannelOpened)
end
All other callbacks receive two arguments: the response and an error code. This corresponds to the two return values returned when operating in blocking mode (when not providing a callback). The methods return response,nil on success and nil,error on failure.
local function onChannelOpened(resp, err)
if err ~= nil then
trace("Secure channel error: "..tostring(err))
return
end
ua.Tools.printTable("SecureChannel", resp)
trace("Disconnecting from server")
pcall(client.disconnect, client)
end