topcua
Not logged in

Name

opcua - Tcl binding to the OPC/UA implementation of http://www.open62541.org

Synopsis

package require topcua
opcua cmd ?arg?

Description

This command provides several operations to manage and communicate using the OPC/UA implementation of http://www.open62541.org. It is available on common POSIX and Windows platforms. cmd indicates which operation to carry out. Any unique abbreviation for cmd is acceptable. The valid commands are:

opcua add handle DataType nodeid parent reftype brname ?attrs?

Adds an new node of node class DataType in the server object handle and returns the node identifer. The parameter nodeid is the requested new node identifier of the node to be created. parent is the parent node identifier and reftype the reference type or node identifier of the reference between the parent and the new node. brname is the browse name (see section Qualified Names) of the new node. The optional attrs parameter specifies attributes for the new node in form of a dictionary (see opcua attr default). If it is omitted, default values are used. The DisplayName attribute if left empty is preset to the name part of the browse name parameter.

opcua add handle Method nodeid parent reftype outargs brname inargs cmd ?attrs?

Adds an new node of node class Method in the server object handle and returns the node identifer. The parameter outargs describes the output arguments of the method as a list of zero or more pairs of data type and argument name. Likewise, inargs describes the input arguments of the method. The parameter cmd is the Tcl callback to handle the method invocation, see section Method Callbacks for more information. For the other parameters, refer to opcua add DataType.

opcua add handle Namespace name

Adds the new namespace name to the server object handle and returns a numeric identifier for this namespace.

opcua add handle Object nodeid parent reftype brname ?typeid attrs?

Adds an new node of node class Object in the server object handle and returns the node identifer. The optional parameter typeid must be a known data type name (see opcua types) or a node identifier of a data type. For the other parameters, refer to opcua add DataType.

opcua add handle ObjectType nodeid parent reftype brname ?attrs?

Adds an new node of node class ObjectType in the server object handle and returns the node identifer. For the other parameters, refer to opcua add DataType.

opcua add handle Reference srcid reftype target ?forward?

Adds a reference of type reftype (see opcua reftype) between the node identifiers srcid and <target on the server object handle. The optional parameter forward must be a boolean indicating the direction of the reference (true, the default, is forward, false is inverse).

opcua add handle ReferenceType nodeid parent reftype brname ?attrs?

Adds an new node of node class ReferenceType in the server object handle and returns the node identifer. For the other parameters, refer to opcua add DataType.

opcua add handle Variable nodeid parent reftype brname ?typeid attrs cmd?

Adds an new node of node class Variable in the server object handle and returns the node identifer. The optional parameter typeid must be a known data type name (see opcua types) or a node identifier of a data type or an empty string for a default value. Parameter cmd is an optional data source callback which produces (read operation) or consumes (write operation) the variable's value. See section Data Source Callbacks for more information. For the other parameters, refer to opcua add DataType.

opcua add handle VariableType nodeid parent reftype brname ?typeid attrs?

Adds an new node of node class VariableType in the server object handle and returns the node identifer. The optional parameter typeid must be a known data type name (see opcua types) or a node identifier of a data type or an empty string for a default value. For the other parameters, refer to opcua add DataType.

opcua add handle View nodeid parent reftype brname ?attrs?

Adds an new node of node class View in the server object handle and returns the node identifer. For the other parameters, refer to opcua add DataType.

opcua attrs ?list|default? ?name?

Without further arguments returns a list of attribute names the opcua read and opcua write commands support, e.g. Value, NodeClass, etc. With the list keyword a list of the data types used as attributes for creation of nodes with the opcua add command is returned. With the default keyword combined with the name of the data type a dictionary describing the default attributes of this type is returned, e.g opcua attrs default DataTypeAttributes yields a default dictionary for creation of a DataType node.

opcua browse handle nodeid ?dir refid mask ...?

Performs a browse operation on the client or server object handle starting at the node nodeid. The browse direction can be specified with the dir parameter as Forward, Inverse, or Both. Forward is the default direction. The optional mask and following parameters select specific node classes Object, Variable, Method, ObjectType, VariableType, ReferenceType, DataType, and View. The result of the browse operation is a list where each item is made up of node identifier, browse name (qualified name), display name (locale and text), node class, reference node identifier, and type node identifier.

opcua call handle nodeid methodid ?type value ...?

Calls the method with node identifier methodid on the object with node identifier nodeid on the client or server object handle with parameters described by pairs of type (data type, e.g. Int32 or String) and value (the parameter's value). The method's result is returned. The method is carried out on the server, i.e. when directly used with a server handle there's no network traffic since the method is run locally.

opcua children handle nodeid

Returns the child node identifiers of the given node identifier nodeid on the client or server object handle.

opcua connect handle url ?user password?

Connects the client object handle to the URL url using the optional credentials user and password.

opcua datasources handle

Returns information on data sources (variable nodes with callbacks) for the server object handle. For each data source two list elements with node identifier and callback command are added to the result.

opcua datetime ?seconds|...|utc ?value??

Returns either POSIX or OPC/UA timestamps as Tcl_WideInt values. If called without further parameters the current OPC/UA local DateTime is returned. If called with the single keyword utc the current OPC/UA UtcTime is returned. Otherwise, value is required and converted from POSIX to OPC/UA UtcTime for the keywords seconds, milliseconds, and microseconds, and from OPC/UA UtcTime to POSIX for the keywords unixseconds, unixmillis, and unixmicros, respectively.

opcua deftypes handle nsuri defs

Defines custom datatypes (currently only structures) in the server object handle and namespace URI nsuri. The namespace is created with the opcua add Namespace command and must exist before the opcua deftypes command is called. The parameter defs describes the structures to be created. The command does all necessary steps to create the required nodes in the server object's address space and to store an XML bytestring describing the (de)serialization for the structures as extension objects. That XML is later to be reparsed with the opcua gentypes command. For details refer to section Defining Custom Data Structures below.

opcua delete handle Node nodeid ?withrefs?

Deletes the node with identifier nodeid on the server object handle. If withrefs is true, the references of the node are deleted, too.

opcua delete handle Reference srcid reftypeid targetid ?forward? ?bidir?

Deletes the reference described by srcid, reftypeid, and targetid on the server object handle. The boolean flag forward selects forward or inverse direction of the reference to be deleted. The boolean flag bidir requests a bidirectional reference to be deleted. The default is to delete in forward direction only.

opcua destroy handle

Destroys the client or server object handle and releases its resources, e.g. closes network connections, tears down the handle specific namespace, etc.

opcua disconnect handle

Disconnects the client object handle.

opcua endpoints ?url?

Queries the local OPC/UA server opc.tcp://localhost:4840 or the server specified by the url parameter for endpoints and returns a list of URLs describing the endpoints found.

opcua genstubs handle ?strip ...?

Generates stubs for methods in the handle specific address space derived from the client or server object handle. The address space is traversed and browse paths and node class paths are accumulated. The resulting browse paths optionally get the prefix strip stripped off from the beginning and optionally filtered using the glob patterns following the strip parameter. For all nodes matching the node class path pattern Object/Method the optional InputArguments and OutputArguments child nodes are retrieved and stub procedures are written using the browse path and argument information.

opcua gentypes handle

Generates custom data type mappings using information obtained from analyzing the address space derived from the client or server object handle. This feature is highly experimental and requires the tDOM package for parsing XML. It can create encoders/decoders for simple structure data types defined in the address space which perform a mapping from/to Tcl dictionaries. For further information, see the server_types.tcl and client_types.tcl scripts in the examples directory. If this command is used, it should be invoked prior to creating method stubs, since methods may require custom data types in their arguments.

opcua info ?handle?

Returns the object type of handle, either client or server. If handle is omitted, a list of all known client and server object handles is returned.

opcua methods handle

Returns information on methods for the server object handle. For each method three list elements with node identifier, result type name, and callback command are added to the result.

opcua monitor handle configure subid monid ?cmd mode interval?

Configures the monitor monid in subscription subid on the client object handle with the provided parameters, see opcua monitor new for further information.

opcua monitor handle destroy subid monid

Destroys the monitor monid in subscription subid on the client object handle and releases all its resources.

opcua monitor handle info subid ?monid?

Returns information on monitor monid in subscription subid on the client object handle. The result is a list of monitor type (data or event), the node identifier, the callback command, the attribute, and the interval. If monid is omitted, a list of all monitor identifers registered in the subscription is returned.

opcua monitor handle new subid type cmd nodeid ?attr mode interval?

Creates a monitored item of type (data or event) for the node identifier nodeid in the subscription subid on the client object handle. The optional parameter attr selects the attribute of the node to be monitored (Value is the default). The monitor mode mode must be one of Disabled, Sampling, and Reporting. The monitoring interval interval must be given as number of milliseconds, if omitted its value is derived from the subscription. The callback command parameter cmd is discussed in section Monitor Callbacks below. The command returns a numeric identifier of the newly created monitor.

opcua namespace handle ?uri?

Returns the namespace index for the namespace uri of the client or server object handle (or throws an error e.g. when the namespace doesn't exist). If uri is omitted, a list of all known namespace indices and corresponding URIs is returned.

opcua new ?client|server port name?

Creates a new client or server object and returns its handle. The port parameter must be present for server objects and specifies the server's TCP port. The optional name is the object name (the handle). If no arguments are given to opcua new a client object with an automatic name is created. During that process the Tcl namespace ::opcua::name is created which later is used to hold method stub procedures and other information. That namespace is tied to the life time of the client or server object.

opcua parent handle nodeid

Returns the parent node identifier of the given node identifier nodeid on the client or server object handle.

opcua ptree handle ?nodeid?

Returns information similar to opcua tree using the client or server object handle. The address space is traversed starting at the node identifier nodeid (the root node if omitted). The result list is made up of browse path name, node identifier, node class path, reference node identier, and type node identifier. The browse path name is a path name like notation made up of the browse names pointing to the final node as seen from the starting node. Browse names are written as qualified names, i.e. including the numeric namespace index if not in root namespace. Similarly, the node class path is a path name like notation made up of the node classes of all nodes along the path. The opcua ptree command is used internally by the opcua genstubs command in order to filter out objects and methods when creating stub Tcl commands to invoke methods on objects.

opcua read handle nodeid ?attr?

Performs a read operation on the client or server object handle and returns the value of attribute attr of the node identifier nodeid. If attr is omitted, it defaults to the Value attribute.

opcua reftype ?name?

Returns the node identifier for the reference type name. When name is omitted, a list of all reference type names is returned.

opcua root

Returns the node identifier of the root node.

opcua run handle ?ms?

Runs asynchronous operations (subscriptions, monitored items) on the client object handle for ms milliseconds. If ms is omitted, that duration defaults to one millisecond.

opcua sc2str code

Translates the numeric status code code to an error message string.

opcua servers ?url?

Queries the local OPC/UA server opc.tcp://localhost:4840 or the server specified by the url parameter for server information and returns a list made up of three elements per server with server name, server URL, and server description.

opcua start handle

Starts the server object handle. See section Server Object And Event Loop below for further information.

opcua stop handle

Stops the server object handle.

opcua subscription handle configure id ?interval lifetime keepalive max prio?

Configures the subscription id on the client object handle. See opcua subscription new for the optional arguments.

opcua subscription handle destroy id

Destroys the subscription id on the client object handle.

opcua subscription handle info ?id?

Returns information about subscription id on the client object handle as a list of enable flag, interval, lifetime, keepalive, and maximum counters, and the priority value. If id is omitted, a list of all subscription identifiers of the client object is returned.

opcua subscription handle new ?flag interval lifetime keepalive max prio?

Creates a new subscription (a container for monitored items, see opcua monitor) on the client object handle and returns a numeric identifier of it. The following optional parameters control properties of the subscription: flag is the initial enable state (on by default), interval, lifetime, keepalive, and max the timing and queuing parameters, and prio the subscription's priority.

opcua subscription handle off id

Disables the subscription id on the client object handle.

opcua subscription handle on id

Enables the subscription id on the client object handle.

opcua translate handle nodeid reftype target ...

Performs a translate operation on the client or server object handle. The operation starts at node identifier nodeid and traverses the object tree along the references reftype and browse name target. A list made up of the node identifier, namespace URI, and server index of the final target is returned as the result. References can be preceeded with an exclamation mark in order to reverse their direction. A reference may be abbreviated as slash for HierarchicalReferences or as dot for Aggregates.

opcua tree handle ?nodeid?

Returns information similar to opcua browse using the client or server object handle. The address space is traversed starting at the node identifier nodeid (the root node if omitted). The result list is made up of tree level (0-based), node identifier, browse name (qualified name), display name (locale and text), node class, reference node identifier, and type node identifier.

opcua type handle nodeid ?attr?

Performs a read operation on the client or server object handle like opcua read but instead of the attribute's value returns the type name of attribute attr of the node identifier nodeid. If attr is omitted, it defaults to the Value attribute.

opcua types basic|empty|list|nodeid ?name?

Returns a list of OPC/UA type names for the basic and list subcommands. Basic types are primitives (e.g. integer numbers) for which a mapping to Tcl objects is provided. The empty subcommand requires name to be a known OPC/UA type name and produces and returns an empty value of this type, e.g. 0.0 for a floating point type. The nodeid subcommand returns the node identifier for the type name.

opcua write handle nodeid ?attr? type value

Performs a write operation on the client or server object handle writing value with type type into the attribute attr of the node identifier nodeid. If attr is omitted, it defaults to Value.

OPC/UA Ensemble

The current implementation uses an ensemble and namespace opcua, i.e. the command opcua info can be alternatively written as opcua::info. Some more complex subcommands of the opcua namespace are implemented in Tcl, namely the opcua tree and opcua genstubs procedures.

Node Identifiers

Numeric node identifiers can be written as ns=N;i=I where N is the numeric namespace, and I the numeric identifier. Likewise, string node identifiers are written as ns=N;s=S with S being the string identifier. GUID node identifiers are written as ns=N;g=G where the GUID is G with the usual format as sequence of hexadecimal numbers and dashes. The namespace part can be left out when namespace zero is addressed. Currently, byte string node identifiers are not supported. If the format cannot be determined (e.g. since the equal sign is missing) the fallback chosen is string node identifier in namespace zero. String named namespaces are not supported.

Qualified Names

Qualified names are used for example in the opcua browse and opcua translate operations as so called browse names. These are made up of an optional numeric namespace prefix (a number followed by a colon) and a name, e.g. 2:MyObject. The namespace prefix is left out if the name refers to namespace zero.

Supported Data Types

Currently, most of the data types of namespace zero are supported and can be mapped to/from Tcl, i.e. integral and floating point numbers, strings, GUIDs, and interal extension objects (similar to structures). For the latter, dictionaries are used in both directions, i.e. for encoding, a dictionary is searched for the respective member names, for decoding, a dictionary is created from the internal representation using the member names of the data type, see opcua attrs default for example. Support for custom data types is highly experimental and underdocumented (see opcua gentypes).

Monitor Callbacks

Monitor callbacks are invoked when a monitored item (data or event) is received. The callback parameter given in opcua monitor new must have proper list format and gets a single value (data) or a list of values (event) appended prior to invocation.

Data Source Callbacks

Data source callbacks are invoked when a DataValue is read or written to. The callback parameter given in the node creation (opcua add Variable) must have proper list format and gets the following parameters appended prior to invocation: the node identifier of the DataValue, the operation (either read or write), and the value attribute for write operations. For read operations the callback must return a two element list of the data type (e.g. String or Int32) and the value itself. If the callback returns the TCL_BREAK return code, the value is assumed to be an array and splitted into list elements which then are converted to OPC/UA data in an OPC/UA array.

Method Callbacks

Method callbacks are invoked when a Method node is called. The callback parameter given in the node creation (opcua add Method) must have proper list format and gets the following parameters appended prior to invocation: the object node identifier, the method node identifier, and zero or more parameters as decribed in the input argument list at creation time of the Method node. The callback must return a single value which is converted to the respective OPC/UA data value according to the output argument information at creation of the Method node. Multiple output arguments are not supported. The same rule regarding the TCL_BREAK return code as described in section Data Source Callbacks is applied to support array results.

Client Object And Event Loop

A client object obtained with opcua new client requires a running event loop only when subscriptions and/or monitored items are involved. All other operations are performed synchronously (and thus blocking). In order to receive monitored information the opcua run operation must be invoked regularly e.g. in a timed after procedure.

Client Example


    package require topcua

    # create client
    opcua new client C

    # connect to server
    opcua connect C opc.tcp://localhost:4840

    # get MyNamespace
    set ns [opcua namespace C MyNamespace]

    # generate stub procs to methods in server
    # these are created in the client specific ::opcua::C namespace
    opcua genstubs C /Root/Objects/${ns}:MyObject/${ns}:

    # list all procs in client specific namespace
    puts stderr [info procs ::opcua::C::*]

    # call stubs
    puts stderr [::opcua::C::Reverse esreveR]
    puts stderr [::opcua::C::WordSplit "word\n\nsplit"]

    # read a variable
    puts stderr [opcua read C "ns=${ns};ItsTclTime"]

    # monitor callback proc
    proc monitor {data} {
        puts stderr "Monitor: $data"
    }

    # make a subscription
    set sub [opcua subscription C new 1 1000.0]

    # make a monitor
    set mon [opcua monitor C new $sub data monitor "ns=${ns};ItsTclTime"]
    puts stderr "Subscription: $sub"
    puts stderr "Monitor: $mon"

    # handle monitors for a few seconds
    set count 0
    while {$count < 600} {
        update
        opcua run C 20
        incr count
    }

    # delete monitor and subscription
    opcua monitor C destroy $sub $mon
    opcua subscription C destroy $sub

    # shut down the server using a method call
    ::opcua::C::Exit

    # destroy the client
    opcua destroy C

Server Object And Event Loop

A server object obtained with opcua new server requires a running event loop as long as it is in running state (started with opcua start). It re-dispatches itself using a Tcl timer callback whose interval is controlled by the protocol timers of the OPC/UA stack implementation.

Server Example


    package require topcua

    # create server
    opcua new server 4840 S

    # implementations of methods etc.
    namespace eval ::opcua::S {
        # method callback
        proc _reverse {obj meth string} {
            return [string reverse $string]
        }
        # method callback
        proc _wordsplit {obj meth string} {
            set w [regexp -all -inline {\S+} $string]
            # return code break makes into an array result
            return -code break $w
        }
        # method callback
        proc _exit {obj meth} {
            after 1000 [namespace current]::_real_exit
            return {}
        }
        # helper proc
        proc _real_exit {} {
            catch {
                ::opcua::stop S
                ::opcua::destroy S
            }
            exit 0
        }
        # data source callback
        proc _its_tcl_time {node op {value {}}} {
            if {$op eq "read"} {
                return [list String [clock format [clock seconds]]]
            }
            return {}
        }
    }

    # create our OPC/UA namespace
    set ns [opcua add S Namespace MyNamespace]

    # get Objects folder
    set OF [lindex [opcua translate S [opcua root] / Objects] 0]

    # create an object in our namespace in Objects folder
    set obj [opcua add S Object "ns=$ns;s=MyObject" $OF Organizes \
        "$ns:MyObject"]

    # create methods on object
    set meth [opcua add S Method "ns=$ns;s=Reverse" \
                  $obj HasComponent \
                  {String out} "$ns:Reverse" {String in} \
                  ::opcua::S::_reverse]
    set meth [opcua add S Method "ns=$ns;s=WordSplit" \
                  $obj HasComponent \
                  {String out} "$ns:WordSplit" {String in} \
                  ::opcua::S::_wordsplit]
    set meth [opcua add S Method "ns=$ns;s=Exit" \
                  $obj HasComponent \
                  {} "$ns:Exit" {} \
                  ::opcua::S::_exit]

    # create a variable in our namespace in Objects folder
    set var [opcua add S Variable "ns=$ns;s=ItsTclTime" \
                 $OF Organizes \
                 "$ns:ItsTclTime" {} {} \
                 ::opcua::S::_its_tcl_time]

    # dump methods
    puts stderr [opcua methods S]

    # generate stubs to methods in server
    # these are created in the server specific ::opcua::S namespace
    opcua genstubs S /Root/Objects/${ns}:MyObject/${ns}:

    # list all procs in server specific namespace
    puts stderr [info procs ::opcua::S::*]

    # call stubs directly on server
    puts stderr [::opcua::S::Reverse esreveR]
    puts stderr [::opcua::S::WordSplit "word\n\nsplit"]

    # read our variable
    puts stderr [opcua read S $var]

    # start server
    opcua start S

    # enter event loop
    vwait forever

Defining Custom Data Structures


    package require topcua

    # create server
    opcua new server 4840 S

    # create our namespace
    set NS http://www.androwish.org/TestNS/
    set nsidx [opcua add S Namespace $NS]

    # create structs
    opcua deftypes S $NS {
        struct KVPair {
            String name
            String value
        }
        struct RGB {
            UInt16 red
            UInt16 green
            UInt16 blue
        }
        struct NamedColor {
            String name
            RGB color
        }
    }

    # import type defs
    opcua gentypes S

    # make some variables using the structs from above
    set OF [lindex [opcua translate S [opcua root] / Objects] 0]
    foreach {name type} {
        X1 KVPair
        X2 RGB
        X3 NamedColor
    } {
        set att [opcua attrs default VariableAttributes]
        dict set att dataType [opcua types nodeid S $type]
        dict set att value [list $type [opcua types empty S $type]]
        opcua add S Variable "ns=${nsidx};s=$name" $OF Organizes \
            "${nsidx}:$name" {} $att
    }

    # start server
    opcua start S

    # enter event loop
    vwait forever