<?xml version='1.0' encoding='UTF-8' ?> <!DOCTYPE html PUBLIC '-//W3C//DTD XHTML 1.0 Transitional//EN' 'http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd'> <html class="client-nojs" dir="ltr" lang="en"> <head> <meta charset="UTF-8" /> <title>Modules/OPC UA - OpenSCADAWiki</title> <meta content="MediaWiki 1.26.4" name="generator" /> <link href="https://www.gnu.org/copyleft/fdl.html" rel="copyright" /> <link href="../files/doc.css" rel="stylesheet" /></head> <body><div class="floatright"><a href="../index.html"><img alt="OpenSCADA" src="../../en/files/index.png" /></a></div><div id="mw_header"> <div class="mw-indicators"> </div> <h1 id="firstHeading" lang="en">Modules/OPC UA</h1> </div><div class="mw-content-ltr" dir="ltr" id="mw-content-text" lang="en"><div class="mw-pt-languages" dir="ltr" lang="en"><div class="mw-pt-languages-list autonym"><span class="mw-pt-languages-ui mw-pt-languages-selected mw-pt-progress mw-pt-progress--complete">English</span> • ‎<a class="mw-pt-progress mw-pt-progress--complete" href="../../ru/Modules/OPC_UA.html" title="Модули/OPC UA (96% translated)">mRussian</a> • ‎<a class="mw-pt-progress mw-pt-progress--complete" href="../../uk/Modules/OPC_UA.html" title="Модулі/OPC UA (100% translated)">УкраїнÑька</a></div></div> <table class="wikitable"> <tr> <th> Module </th> <th> Name </th> <th> Version </th> <th> License </th> <th> Source </th> <th> Languages </th> <th> Platforms </th> <th> Type </th> <th> Author </th></tr> <tr> <td> <a href="../Modules/OPC_UA.html" title="Special:MyLanguage/Modules/OPC UA">OPC_UA</a> </td> <td> Client OPC-UA </td> <td> 2.8 </td> <td> GPL2 </td> <td> daq_OPC_UA.so </td> <td> en,uk,ru,de </td> <td> x86,x86_64,ARM </td> <td> DAQ </td> <td> Roman Savochenko<br /> <font size="-2"><i>Maxim Lysenko (2010) — the page initial translation</i></font> </td></tr> <tr> <th colspan="9"> Description </th></tr> <tr> <td colspan="9"> Provides OPC-UA client service implementation. </td></tr> <tr> <td> <a href="../Modules/OPC_UA.html" title="Special:MyLanguage/Modules/OPC UA">OPC_UA</a> </td> <td> Server OPC-UA </td> <td> 2.3 </td> <td> GPL2 </td> <td> daq_OPC_UA.so </td> <td> en,uk,ru,de </td> <td> x86,x86_64,ARM </td> <td> Protocol </td> <td> Roman Savochenko<br /> <font size="-2"><i>Maxim Lysenko (2010) — the page initial translation</i></font> </td></tr> <tr> <th colspan="9"> Description </th></tr> <tr> <td colspan="9"> Provides OPC-UA server service implementation. </td></tr> <tr> <td> <a href="../Modules/OPC_UA.html" title="Special:MyLanguage/Modules/OPC UA">OPC_UA</a> </td> <td> Library of implementing OPC-UA into OpenSCADA </td> <td> 2.3 </td> <td> LGPL3 </td> <td> libOPC_UA.{h,cpp} </td> <td> en </td> <td> x86,x86_64,ARM </td> <td> Library </td> <td> Roman Savochenko </td></tr> <tr> <th colspan="9"> Description </th></tr> <tr> <td colspan="9"> Provides the protocol OPC-UA implementing into parts of client and server, as a separated library. <ul><li> <b>Total complexity:</b> > 50 <span title="human-days, 1 HD — 10 hours">HD<sup style="color: blue">[!]</sup></span></li> <li> <b>Sponsored by, for 2 years TS on 13 <span title="human-days, 1 HD — 10 hours">HD<sup style="color: blue">[!]</sup></span>:</b> Likov Dmitry, Vector LTD</li> <li> <b>Sponsored by, for moving the protocol code to a LGPL library, significant improvement and documenting, on 8.4 <span title="human-days, 1 HD — 10 hours">HD<sup style="color: blue">[!]</sup></span>:</b> Oleksander Leuta, MYSCADA</li> <li> <b>Sponsored by, for working with UAExpert 1.4 and kepware on 0.9 <span title="human-days, 1 HD — 10 hours">HD<sup style="color: blue">[!]</sup></span>:</b> Ustijancev Michael</li> <li> <b>Sponsored by, for <a class="external" href="http://oscada.org/wiki/Special:MyLanguage/Documents/Release_0.9/Update4#OPC_UA" title="Special:MyLanguage/Documents/Release 0.9/Update4">working with UAExpert 1.5, Client's Publish and Chunks implementing, significant refactoring</a>, the Logical Level type support and the document complete revision on 10.4 <span title="human-days, 1 HD — 10 hours">HD<sup style="color: blue">[!]</sup></span>:</b> <a class="external" href="http://oscada.org/wiki/Special:MyLanguage/Fund" title="Special:MyLanguage/Fund">Fund</a></li> <li> <a class="external text" href="http://oscada.org/en/development/tasks/posts/subsystem_daq/module_opc_ua_functions_extending/" rel="nofollow noreferrer noopener" target="_blank">A task of the module extending</a></li> <li> <b><a href="../To_do.html" title="Special:MyLanguage/Works/To do">To Do</a>:</b></li></ul> <dl><dd> - append the automatic creation for input transports and their pre-configuration from the EndPoint object properties;</dd> <dd> - observe deeply the Publish service for the packages loss and the Republish request sending;</dd> <dd> - append for support of the history services of the server part, seeing and testing against UAExpert negotiation;</dd> <dd> - append for support of the history services of the client part.</dd></dl> </td></tr></table> <p>OPC (OLE for Process Control) — it is the family of protocols and technologies what provide the single interface to control the objects of automation and technological processes. The creating and support of specifications of OPC coordinates an international nonprofit organization <a class="external text" href="http://opcfoundation.org" rel="nofollow noreferrer noopener" target="_blank">OPC Foundation</a>, established in 1994 by the leading manufacturers of industrial automation. </p><p>In view of the fact that a significant influence in the OPC Foundation organization has the Microsoft corporation, OPC protocols, until recently, was single platform and closed, due to binding to the closed technologies of MS Windows. However recently the OPC Foundation organization has created multi-platform solutions such as OPC XML-DA and OPC-UA. Most interesting of them is the OPC-UA, as a solution of unifying all the earlier protocols in an open and multi-platform technologies. </p><p>This module implements the interface and protocol support for OPC-UA in the form of client service, and as the OPC-UA server. Client service of OPC-UA is implemented by the same name module of the subsystem "Data acquisition", and the server is implemented by the subsystem's "Protocols" module. The OPC-UA protocol's specific implementing code by the module was moved to a separated library under the LGPL3 license, by the users requests. </p><p>In the current version of these modules and the library it is implemented the binary part of the protocol and basic services in unsafe mode and safe mode of policies "Base128Rsa15" and "Base256". Later it is planned to implementation of other OPC-UA services by the need. </p><p>Although the OPC-UA protocol is multi-platform, its specification and SDK are not freely available, but are provided only to members of the OPC Foundation organization. For this reason, the implementation of these modules has faced significant obstacles and problems. </p><p>Firstly, the protocol OPC-UA is complex and its realization in general without any specification an extremely laborious. For this reason, the work on these modules for a long time was not started, and only thanks to sponsorship by an organization-member of OPC Foundation the OpenSCADA project received documentation of the specification. The SDK and source code ANSIC-API of the OPC-UA protocol have not been received due to their incompatibility with the GPL license and as a consequence, the potential threat of violation of the license when working with the source code, which could lead to subsequent legal problems with the free distribution of these modules. </p><p>Secondly, even the presence of the specification does not allow to solve some technical question without an example of implementation and possibility of test the working prototype of the client and server of OPC-UA. For example, it is the technical features of the implementation of the symmetric encryption algorithms and keys for them do not allowed to make the implementation of support for the security policies at once. </p><p>To debug the operation of the modules, the demonstration software of company <a class="external text" href="http://www.unified-automation.com" rel="nofollow noreferrer noopener" target="_blank">Unified Automation</a> was used, in consist of the OPC-UA client — UAExpert and Server — "OPC-UA Demo Server", from the SDK package. In view of the constantly developing process of the same "UAExpert" client, as the OPC-UA specification implementing, its new versions often have problems in work with the OPC-UA server from OpenSCADA. Generically the results of compatibility in work with clients and servers of different developers you can get in <a href="#TableOfCompat">the table of compatibility</a>. </p> <div class="toc" id="toc"><div id="toctitle"><h2>Contents</h2></div> <ul> <li class="toclevel-1 tocsection-1"><a href="#The_OPC-UA_protocol"><span class="tocnumber">1</span> <span class="toctext">The OPC-UA protocol</span></a></li> <li class="toclevel-1 tocsection-2"><a href="#Module_of_the_protocol_implementation"><span class="tocnumber">2</span> <span class="toctext">Module of the protocol implementation</span></a> <ul> <li class="toclevel-2 tocsection-3"><a href="#Service_of_requests_on_the_OPC-UA_protocol"><span class="tocnumber">2.1</span> <span class="toctext">Service of requests on the OPC-UA protocol</span></a></li> </ul> </li> <li class="toclevel-1 tocsection-4"><a href="#Module_of_the_data_acquisition"><span class="tocnumber">3</span> <span class="toctext">Module of the data acquisition</span></a> <ul> <li class="toclevel-2 tocsection-5"><a href="#Controller_object"><span class="tocnumber">3.1</span> <span class="toctext">Controller object</span></a></li> <li class="toclevel-2 tocsection-6"><a href="#Parameters"><span class="tocnumber">3.2</span> <span class="toctext">Parameters</span></a> <ul> <li class="toclevel-3 tocsection-7"><a href="#Standard_.28_Prm.29"><span class="tocnumber">3.2.1</span> <span class="toctext">Standard (_Prm)</span></a></li> <li class="toclevel-3 tocsection-8"><a href="#Logical_.28_PrmL.29"><span class="tocnumber">3.2.2</span> <span class="toctext">Logical (_PrmL)</span></a></li> </ul> </li> <li class="toclevel-2 tocsection-9"><a href="#User_programming_API"><span class="tocnumber">3.3</span> <span class="toctext"><span>User programming API</span></span></a></li> </ul> </li> <li class="toclevel-1 tocsection-10"><a href="#libOPC_UA_library"><span class="tocnumber">4</span> <span class="toctext">libOPC_UA library</span></a> <ul> <li class="toclevel-2 tocsection-11"><a href="#Service_objects.2C_functions_and_the_class_UA"><span class="tocnumber">4.1</span> <span class="toctext">Service objects, functions and the class UA</span></a> <ul> <li class="toclevel-3 tocsection-12"><a href="#Data"><span class="tocnumber">4.1.1</span> <span class="toctext">Data</span></a></li> <li class="toclevel-3 tocsection-13"><a href="#External_functions"><span class="tocnumber">4.1.2</span> <span class="toctext">External functions</span></a></li> <li class="toclevel-3 tocsection-14"><a href="#Automatic_POSIX_mutex_unlock_object_for_OPC_.28OPCAlloc.29"><span class="tocnumber">4.1.3</span> <span class="toctext">Automatic POSIX mutex unlock object for OPC (OPCAlloc)</span></a></li> <li class="toclevel-3 tocsection-15"><a href="#Error_of_OPC_.28OPCError.29"><span class="tocnumber">4.1.4</span> <span class="toctext">Error of OPC (OPCError)</span></a></li> <li class="toclevel-3 tocsection-16"><a href="#XML-tag_.28XML_N.29"><span class="tocnumber">4.1.5</span> <span class="toctext">XML-tag (XML_N)</span></a></li> <li class="toclevel-3 tocsection-17"><a href="#Node.27s_object_of_OPC-UA_.28NodeId.29"><span class="tocnumber">4.1.6</span> <span class="toctext">Node's object of OPC-UA (NodeId)</span></a></li> <li class="toclevel-3 tocsection-18"><a href="#Root_object_of_the_OPC-UA_protocol_.28UA.29"><span class="tocnumber">4.1.7</span> <span class="toctext">Root object of the OPC-UA protocol (UA)</span></a> <ul> <li class="toclevel-4 tocsection-19"><a href="#Included_object_of_the_security_parameters_.28SecuritySetting.29"><span class="tocnumber">4.1.7.1</span> <span class="toctext">Included object of the security parameters (SecuritySetting)</span></a></li> </ul> </li> </ul> </li> <li class="toclevel-2 tocsection-20"><a href="#Main_object_of_the_Client_.28Client-.3EUA.29"><span class="tocnumber">4.2</span> <span class="toctext">Main object of the Client (Client->UA)</span></a> <ul> <li class="toclevel-3 tocsection-21"><a href="#Complex_Client_session_.28Client::SClntSess.29"><span class="tocnumber">4.2.1</span> <span class="toctext">Complex Client session (Client::SClntSess)</span></a> <ul> <li class="toclevel-4 tocsection-22"><a href="#Client_Subscription_.28Client::Subscr.29"><span class="tocnumber">4.2.1.1</span> <span class="toctext">Client Subscription (Client::Subscr)</span></a> <ul> <li class="toclevel-5 tocsection-23"><a href="#Monitored_Item_of_the_Client_Subscription_.28Client::Subscr::MonitItem.29"><span class="tocnumber">4.2.1.1.1</span> <span class="toctext">Monitored Item of the Client Subscription (Client::Subscr::MonitItem)</span></a></li> </ul> </li> </ul> </li> </ul> </li> <li class="toclevel-2 tocsection-24"><a href="#Main_object_of_the_Server_.28Server-.3EUA.29"><span class="tocnumber">4.3</span> <span class="toctext">Main object of the Server (Server->UA)</span></a> <ul> <li class="toclevel-3 tocsection-25"><a href="#Server_Security_Channel_.28Server::SecCnl.29"><span class="tocnumber">4.3.1</span> <span class="toctext">Server Security Channel (Server::SecCnl)</span></a></li> <li class="toclevel-3 tocsection-26"><a href="#Server_Session_.28Server::Sess.29"><span class="tocnumber">4.3.2</span> <span class="toctext">Server Session (Server::Sess)</span></a> <ul> <li class="toclevel-4 tocsection-27"><a href="#Browse_continuation_point_of_the_Server_Session_.28Server::Sess::ContPoint.29"><span class="tocnumber">4.3.2.1</span> <span class="toctext">Browse continuation point of the Server Session (Server::Sess::ContPoint)</span></a></li> </ul> </li> <li class="toclevel-3 tocsection-28"><a href="#Server_Subscription_.28Server::Subscr.29"><span class="tocnumber">4.3.3</span> <span class="toctext">Server Subscription (Server::Subscr)</span></a> <ul> <li class="toclevel-4 tocsection-29"><a href="#Monitored_Item_of_the_Server_Subscription_.28Server::Subscr::MonitItem.29"><span class="tocnumber">4.3.3.1</span> <span class="toctext">Monitored Item of the Server Subscription (Server::Subscr::MonitItem)</span></a> <ul> <li class="toclevel-5 tocsection-30"><a href="#Value_element_of_the_Monitored_Item_of_the_Server_Subscription_.28Server::Subscr::MonitItem::Val.29"><span class="tocnumber">4.3.3.1.1</span> <span class="toctext">Value element of the Monitored Item of the Server Subscription (Server::Subscr::MonitItem::Val)</span></a></li> </ul> </li> </ul> </li> <li class="toclevel-3 tocsection-31"><a href="#Server_End_Point_.28Server::EP.29"><span class="tocnumber">4.3.4</span> <span class="toctext">Server End Point (Server::EP)</span></a></li> </ul> </li> </ul> </li> <li class="toclevel-1 tocsection-32"><a href="#Private_keys_and_certificates"><span class="tocnumber">5</span> <span class="toctext">Private keys and certificates</span></a></li> <li class="toclevel-1 tocsection-33"><a href="#Notes"><span class="tocnumber">6</span> <span class="toctext">Notes</span></a></li> <li class="toclevel-1 tocsection-34"><a href="#Table_of_compatibility_of_implementations_of_OPC-UA_from_other_developers"><span class="tocnumber">7</span> <span class="toctext"><span>Table of compatibility of implementations of OPC-UA from other developers</span></span></a></li> <li class="toclevel-1 tocsection-35"><a href="#Links"><span class="tocnumber">8</span> <span class="toctext">Links</span></a></li> </ul> </div> <h2><span class="mw-headline" id="The_OPC-UA_protocol"><span class="mw-headline-number">1</span> The OPC-UA protocol</span></h2> <p>OPC-UA — it is a platform-independent standard by means of which the systems and devices of various types can interact by sending messages between the client and the server through various types of networks. The protocol supports secure communication through the validation of clients and servers, as well as the counteraction to attacks. OPC-UA defines the concept <i>Services</i> that the servers can provide, as well as services that the server supports for the client. Information is transmitted as the data types defined by OPC-UA and it producer, in addition the servers define an object model, for which the clients can implement the dynamic review. </p><p>OPC-UA provides the combination of integrated address space with service model. This allows the server to integrate data alarms and events, the history in this address space, as well as provide access to them through the integrated services. Services also provide an integrated security model. </p><p>OPC-UA allows servers to provide for clients the definitions of types for access to the objects of the address space. OPC-UA supports the provision of data in various formats, including binary structures and XML-documents. Through the address space, clients can request the server metadata that describe the data format. </p><p>OPC-UA appends the support for multiple connections between nodes instead of simple hierarchy. Such flexibility, in combination with type definition, allows to use OPC-UA for solving problems in the wide problem area. </p><p>OPC-UA is designed to provide reliable data output. The main feature of all OPC servers is the ability to issue data and events. </p><p>OPC-UA is designed to support wide range of servers, from simple PLC to industrial servers. These servers are characterized by wide range of sizes, performance, platforms and functional capacity. Consequently, the OPC-UA defines the comprehensive set of possibilities, and the server can implement the subset of these possibilities. To compatibility ensure, the OPC-UA defines subsets, named the <i>Profiles</i> that the server can indicate for agreement. Clients may subsequently make the review of server's profiles and make the interaction with the server, based on the profiles. </p><p>OPC-UA specification is designed as the core in the layer, isolated from the underlying computer technologies and network transports. This allows for OPC-UA, if necessary, to expand on the future technologies without excluding the framework of design. Currently, the specification defines two ways to data encode: UA Binary and XML/text. Additionally, the two types of transport layer are defined: TCP and HTTP/SOAP. </p><p>OPC-UA is designed as a solution for migration from OPC clients and servers, which are based on Microsoft COM technologies. OPC COM servers (DA, HDA and A&E) can be easily reflected in OPC-UA. Producers can independently make such migration or recommend users to use wrappers and converters between these protocols. OPC-UA unifies the previous models in the single address space with the single set of the services. </p> <h2><span class="mw-headline" id="Module_of_the_protocol_implementation"><span class="mw-headline-number">2</span> Module of the protocol implementation</span></h2> <p>The server module contains an implementation code for the server part of OPC-UA — server services (Fig.1), in part of the OpenSCADA specific, and using the library in part of the OPC-UA specific. To construct the OPC-UA server it is enough to create an input transport, for ordinarily it is TCP-transport of the module <a href="../Modules/Sockets.html" title="Special:MyLanguage/Modules/Sockets">Sockets</a>, and select in it the module of the protocol, and also configure although one endpoint node of the protocol module, about it see bellow. </p> <div class="center"><div class="thumb tnone"><div class="thumbinner" style="width:910px;"><a class="image" href="http://oscada.org/wiki/File:OPC-UA_prt_serv.png"><img class="thumbimage" height="510" src="../files/OPC-UA_prt_serv.png" width="908" /></a> <div class="thumbcaption">Fig.1. The "Server" common state.</div></div></div></div> <p>The common state of the Server contains only the list of the active secure channels. </p> <h3><span class="mw-headline" id="Service_of_requests_on_the_OPC-UA_protocol"><span class="mw-headline-number">2.1</span> Service of requests on the OPC-UA protocol</span></h3> <p>Input requests to the module-protocol are processed by the module in accordance with configured endpoint nodes of OPC-UA (EndPoints) (Fig.2). </p> <div class="center"><div class="thumb tnone"><div class="thumbinner" style="width:684px;"><a class="image" href="http://oscada.org/wiki/File:OPC-UA_prt_eps.png"><img class="thumbimage" height="509" src="../files/OPC-UA_prt_eps.png" width="682" /></a> <div class="thumbcaption">Fig.2. Endpoint nodes of the protocol.</div></div></div></div> <p>Endpoint node of the OPC-UA protocol is actually the server object of OPC-UA. Endpoint nodes in OPC-UA can be either local or remote. Local ones are designed to provide resources of OpenSCADA station by the protocol OPC-UA, while remote endpoint nodes are both for the service and review of available OPC-UA units, and to forwarding of the requests to remote stations. In this version of the module is only supported the configuration of the local endpoint nodes. </p><p>General configuration of the endpoint node is made on the main tab of the endpoint node's page (Fig.3) with parameters: </p> <ul><li> Node status, as follow: common status, lists of the active sessions and subscriptions, "Enabled" and the name of the database containing the configuration, with tracking the availability of the data in different storages and providing the sequentially removing duplicates.</li> <li> Identifier, name and description of the node.</li> <li> State, in which to transfer the node at the start: "Enabled".</li> <li> Type of the protocol encoding, at the moment it is only "Binary".</li> <li> URL of the endpoint node.</li> <li> Anonymous user of enabling the anonymous access, or only authentication at empty.</li> <li> Server certificate and private key in the PEM format.</li></ul> <dl><dd><a class="image" href="http://oscada.org/wiki/File:At.png"><img alt="At.png" height="22" src="../files/At.png" width="22" /></a> Hidden in the enabled state.</dd></dl> <ul><li> Security Server Policy.</li></ul> <div class="center"><div class="thumb tnone"><div class="thumbinner" style="width:875px;"><a class="image" href="http://oscada.org/wiki/File:OPC-UA_prt_ep_main.png"><img class="thumbimage" height="928" src="../files/OPC-UA_prt_ep_main.png" width="873" /></a> <div class="thumbcaption">Fig.3. Main tab of the endpoint node's page.</div></div></div></div> <h2><span class="mw-headline" id="Module_of_the_data_acquisition"><span class="mw-headline-number">3</span> Module of the data acquisition</span></h2> <p>The data acquisition module provides ability of acquisition and writing the value's attributes (13) of points with the "Variable" type in the direct acquisition mode by the request "Read" and the asynchronous service request "Publish". </p> <h3><span class="mw-headline" id="Controller_object"><span class="mw-headline-number">3.1</span> Controller object</span></h3> <p>To append the OPC-UA data source the controller's object into OpenSCADA is created and configured. An example of the configuration tab of the controller's object is shown in Figure 4. </p> <div class="center"><div class="thumb tnone"><div class="thumbinner" style="width:804px;"><a class="image" href="http://oscada.org/wiki/File:OPC-UA_cntr_main.png"><img class="thumbimage" height="817" src="../files/OPC-UA_cntr_main.png" width="802" /></a> <div class="thumbcaption">Fig.4. Configuration tab of the OPC-UA controller object.</div></div></div></div> <p>From this tab you can set: </p> <ul><li> The state of the controller object, as follows: Status, "Enabled", "Running" and the name of the storage containing the configuration.</li></ul> <dl><dd><a class="image" href="http://oscada.org/wiki/File:At.png"><img alt="At.png" height="22" src="../files/At.png" width="22" /></a> Manual restart of the enabled controller object causes the force reformation of the monitored items list.</dd></dl> <ul><li> Identifier, name and description of the controller.</li> <li> The state "Enabled" and "Running", in which the controller object must be translated at boot.</li> <li> Scheduling policy and priority of the task of the data acquisition.</li> <li> Period of synchronization of the configuration of attributes of the parameters with the remote station, and try time for the connection restore.</li> <li> URL of the endpoint node of the remote station — OPC-UA server. In begin, the address you can point as "<b>opc.tcp://{IP|name}:{port}</b>", after that, at the controller's object enable and allowing the pointed OPC-UA node, there will be emerged to select the refined address.</li></ul> <dl><dd><a class="image" href="http://oscada.org/wiki/File:At.png"><img alt="At.png" height="22" src="../files/At.png" width="22" /></a> Often there meets a situation when the refined address is symbolic which does not resolve into the network by the server incorrect configuration. In this cases you need to keep the original IP-address or the name which resolved to the correct IP.</dd></dl> <ul><li> Security policy and mode of the messaging security.</li> <li> Client certificate and private key in the PEM format.</li></ul> <dl><dd><a class="image" href="http://oscada.org/wiki/File:At.png"><img alt="At.png" height="22" src="../files/At.png" width="22" /></a> Hidden in the running state.</dd></dl> <ul><li> User and password to authenticate on the server, empty value here enable the anonymous access.</li> <li> Asynchronous write. Enables asynchronously writing of the changes to the controller, in the general acquisition cycle and after the data acquisition itself, blocking of reading the written values on one cycle (before the writing buffer clearing).</li></ul> <dl><dd> <a class="image" href="http://oscada.org/wiki/File:At.png"><img alt="At.png" height="22" src="../files/At.png" width="22" /></a> This mode also prevents for loss the writing data at the connection loss and the wrote data will be transmitted just the connection will be restored.</dd></dl> <ul><li> Use the "Read" function, otherwise there is activated and used the Publish (asynchronous) data acquisition service of the OPC-UA protocol.</li></ul> <p>To facilitate the identification of nodes on the remote station, as well as their choice to be inserted in the parameter of the controller, in the controller's object it is provided the tab "Server nodes browser" of navigation on the remote station's nodes, where you can walk through the tree of objects and familiar with their attributes (Fig.5). </p> <div class="center"><div class="thumb tnone"><div class="thumbinner" style="width:689px;"><a class="image" href="http://oscada.org/wiki/File:OPC-UA_cntr_browse.png"><img class="thumbimage" height="672" src="../files/OPC-UA_cntr_browse.png" width="687" /></a> <div class="thumbcaption">Fig.5. The "Server nodes browser" tab of the OPC-UA controller object page.</div></div></div></div> <h3><span class="mw-headline" id="Parameters"><span class="mw-headline-number">3.2</span> Parameters</span></h3> <p>The data acquisition module provides two types of parameter: "Standard (_Prm)" and "Logical (_PrmL)". Additional configuration fields of the parameters of this module are: </p> <ul><li> <i><b>Standard (_Prm)</b></i>: <ul><li> <i>Attributes list</i> — contains a structured list of configuration for the attributes ModBUS.</li></ul></li> <li> <i><b>Logical (_PrmL)</b></i>: <ul><li> <i>Parameter template</i> — address of the DAQ-parameter template.</li></ul></li></ul> <h4><span class="mw-headline" id="Standard_.28_Prm.29"><span class="mw-headline-number">3.2.1</span> Standard (_Prm)</span></h4> <p>Additional configuration field of the type parameter (Fig.6) is the list of OPC-UA nodes and the field of navigation by OPC-UA nodes in single line, for the selected nodes of the type "Variable" insertion to the defined list. Attribute in this list is written as "<b>{ns}:{nid}[|[{flg}][|{id}[|{name}]]]</b>".<br /> Where: </p> <ul><li> <i>ns</i> — name space, number; zero value can be omitted;</li> <li> <i>nid</i> — node identifier by number, string, bytes string and GUID;</li> <li> <i>flg</i> — flags for do not request the metadata on the server: value type (b-Boolean,i-Integer,f-Float,s-String,o-Object), read/write mode (r-read, w-write);</li> <li> <i>id</i> — identifier of the created attribute;</li> <li> <i>name</i> — name of the created attribute.</li></ul> <p>Examples: </p> <dl><dd><b>84</b> — root directory;</dd> <dd><b>3:"BasicDevices2"||var</b> — basic devices node in the name space 3 and the string view with the force attribute ID;</dd> <dd><b>4:"61626364"||var|Variable</b> — node in the names space 4 and the byte string view with the force attribute ID and name;</dd> <dd><b>4:{40d95ab0-50d6-46d3-bffd-f55639b853d4}|irw|var|Variable</b> — node in the names space 4 and the GUID view with no requesting the server metadata for RW Integer and the force attribute ID and name.</dd></dl> <div class="center"><div class="thumb tnone"><div class="thumbinner" style="width:778px;"><a class="image" href="http://oscada.org/wiki/File:OPC-UA_prm.png"><img class="thumbimage" height="668" src="../files/OPC-UA_prm.png" width="776" /></a> <div class="thumbcaption">Fig.6. Configuration tab of the OPC-UA parameter object.</div></div></div></div> <p><a class="image" href="http://oscada.org/wiki/File:At.png"><img alt="At.png" height="22" src="../files/At.png" width="22" /></a> Nodes in type "Variable" with the value view as a structure are impossible typically to read entirely then you need it's elements insert separately to the reading nodes list. </p><p>In accordance with the specified list of nodes there performs acquisition and creation of the parameter's attributes (Fig.7). </p> <div class="center"><div class="thumb tnone"><div class="thumbinner" style="width:678px;"><a class="image" href="http://oscada.org/wiki/File:OPC-UA_prm_atr.png"><img class="thumbimage" height="562" src="../files/OPC-UA_prm_atr.png" width="676" /></a> <div class="thumbcaption">Fig.7. Tab of attributes of the parameter.</div></div></div></div> <h4><span class="mw-headline" id="Logical_.28_PrmL.29"><span class="mw-headline-number">3.2.2</span> Logical (_PrmL)</span></h4> <p>Main page of configuration parameters of the logical type is shown in Figure 8. </p> <div class="center"><div class="thumb tnone"><div class="thumbinner" style="width:760px;"><a class="image" href="http://oscada.org/wiki/File:OPC-UALog_prm.png"><img class="thumbimage" height="595" src="../files/OPC-UALog_prm.png" width="758" /></a> <div class="thumbcaption">РиÑ.8. Configuration tab of the logical parameter type.</div></div></div></div> <p>Link value, when configuring the template (Fig.9), is written in the form "<b>{ns}:{id}</b>".<br /> Where: </p> <ul><li> <i>ns</i> — name space, number; zero value can be omitted;</li> <li> <i>id</i> — node identifier by number, string, bytes string and GUID.</li></ul> <p>Examples: </p> <dl><dd><b>84</b> — root directory;</dd> <dd><b>3:"BasicDevices2"</b> — basic devices node in the name space 3 and the string view;</dd> <dd><b>4:"61626364"</b> — node in the names space 4 and the byte string view;</dd> <dd><b>4:{40d95ab0-50d6-46d3-bffd-f55639b853d4}</b> — node in the names space 4 and the GUID view.</dd></dl> <div class="center"><div class="thumb tnone"><div class="thumbinner" style="width:760px;"><a class="image" href="http://oscada.org/wiki/File:OPC-UALog_tmpl.png"><img class="thumbimage" height="595" src="../files/OPC-UALog_tmpl.png" width="758" /></a> <div class="thumbcaption">РиÑ.9. Tab "Template configuration" of the logical parameter type.</div></div></div></div> <p>The module provides a special processing of a number of attributes of the template: </p> <ul><li> <i>f_frq</i> — frequency of the calculation of the template procedure or the time after the last calculation (negative in seconds) for planning by CRON, read-only.</li> <li> <i>f_start</i> — sign of the first execution of the template procedure — start-up, read-only.</li> <li> <i>f_stop</i> — sign of the last execution of the template procedure — stop, read only.</li> <li> <i>f_err</i> — parameter error, full access. The value of this attribute of the template falls into the error attribute of the parameter "err". Write here <b>EVAL</b> for the possibility of setting the attribute "err" from the outside and all others in the Read Only mode.</li> <li> <i>SHIFR</i> — code of the parameter, read-only.</li> <li> <i>NAME</i> — name of the parameter, read-only.</li> <li> <i>DESCR</i> — description of the parameter, read-only.</li> <li> <i>this</i> — object of the parameter, allows access to the attributes of the parameter, for example, to access archives-history.</li></ul> <p>In accordance with the template, underlying the parameter, we obtain a set of attributes of the parameter (Fig. 10). </p> <div class="center"><div class="thumb tnone"><div class="thumbinner" style="width:760px;"><a class="image" href="http://oscada.org/wiki/File:OPC-UALog_prm_atr.png"><img class="thumbimage" height="595" src="../files/OPC-UALog_prm_atr.png" width="758" /></a> <div class="thumbcaption">Fig.10. Tab of attributes of the logical parameter type.</div></div></div></div> <h3><span class="mw-headline" id="User_programming_API"><span class="mw-headline-number">3.3</span> <span id="UserAPI" title="#UserAPI">User programming API</span></span></h3> <p>Due to the support of the logical type parameters, it makes sense to provide a number of functions of the user API for calling them from the template of the logical parameter. </p><p><b>The object "Parameter" [this]</b> </p> <ul><li> <i>bool attrAdd( string id, string name, string tp = "real", string selValsNms = "" )</i> [<span style="color: red">for enabled parameter of the logical type</span>] — adds the attribute <i>id</i> with the name <i>name</i> and the type <i>tp</i>. If the attribute is already present, the properties will be applied that can be changed on the go: name, selection mode and selection options. <ul><li> <i>id, name</i> — identifier and name of the new attribute;</li> <li> <i>tp</i> — attribute type [boolean | integer | real | string | text | object] + selection mode [sel | seled] + read-only [ro];</li> <li> <i>selValsNms</i> — two lines with values in first and their names in second, separated by ";".</li></ul></li> <li> <i>bool attrDel( string id )</i> [<span style="color: red">for enabled parameter of the logical type</span>] — removes the attribute <i>id</i>.</li></ul> <p><br /> </p> <h2><span class="mw-headline" id="libOPC_UA_library"><span class="mw-headline-number">4</span> libOPC_UA library</span></h2> <p>Grounding on workouts of the module, the protocol OPC-UA code was moved to a different library and published on the LGPLv3 license. That was done to provide the possibility of easy appending of support the OPC-UA protocol by external projects. The library represents by two files libOPC_UA.h, libOPC_UA.cpp; supported and hosted into the module content, then its actual version you can get here: <a class="external free" href="http://oscada.org/svn/trunk/OpenSCADA/src/moduls/daq/OPC_UA/libOPC_UA" rel="nofollow noreferrer noopener" target="_blank">http://oscada.org/svn/trunk/OpenSCADA/src/moduls/daq/OPC_UA/libOPC_UA</a>. </p><p>The library, like to this module code, wrote on C++ programming language. Static classes diagram, which represents the library architecture, shown on Figure 11. Accordingly to the classes diagram, the library implemented into the name space "OPC" and architecturally it can be divided to the "Client" and "Server" parts which inherited from the common class "UA". Besides the direct classes of the protocol "OPC-UA", the library includes to itself a set of functions and classes for processing or storing the protocol data, especially of which it should be noted the class of node of language XML "XML_N", used for requests unification to the library API. </p> <div class="center"><div class="thumb tnone"><div class="thumbinner" style="width:400px;"><a class="image" href="http://oscada.org/wiki/File:OPC-UA_libOPCUA_class.png"><img class="thumbimage" height="311" src="../files/OPC-UA_libOPCUA_class.png" width="398" /></a> <div class="thumbcaption">Fig.11. Static class diagram of the library libOPC_UA.</div></div></div></div> <p>The library using at all lies in inheriting of the class "Client" and/or "Server" accordingly to the end-program functions and next implementing of the virtual functions for the client/server properties into the OPC-UA protocol context, and the transport communication part also, that is — connect/open a TCP-socket and write/read of unstructured data stream. Next requests, and the requested data processing (for server), performed through call the function of requesting to the service <i>reqService()</i> and/or processing of the virtual function of the data requesting <i>reqData()</i> than, in fact, there is integration to the data model of the application. </p><p>After appending to the client for support of the asynchronous data polling by the service "Publish", the integration process was supplemented by periodic call for the <i>Client::poll()</i> function in order to process the asynchronous service. The "Client::poll()" function is also provided with support for synchronous operation, by a separate argument, through the unified subscription-registering infrastructure of monitoring elements, but the "Read" function. That is, now it is enough to register all the elements of monitoring with the function <i>Client::Subscr::monitoredItemAdd()</i> and then call the function <i>Client::poll()</i> to get their data in the desired mode. </p><p>After the last refactoring of the code in version 2, the integration of the server part additionally requires a mandatory start of a separate thread of all subscriptions processing, with call from it for the function <i>Server::EP::subScrCycle()</i> and the argument of the subscription processing cycle counter — the periodicity of the call <i>Server::EP::subscrProcPer()</i>. </p> <h3><span class="mw-headline" id="Service_objects.2C_functions_and_the_class_UA"><span class="mw-headline-number">4.1</span> Service objects, functions and the class UA</span></h3> <h4><span class="mw-headline" id="Data"><span class="mw-headline-number">4.1.1</span> Data</span></h4> <p>Implementation types (enum — SerializerType): </p> <ul><li> <i>ST_Binary = 0</i> — binary.</li></ul> <p>Open secure channel request types (enum — SC_ReqTP): </p> <ul><li> <i>SC_ISSUE = 0</i> — issue;</li> <li> <i>SC_RENEW = 1</i> — renewal.</li></ul> <p>Security mode of the messages (enum — MessageSecurityMode): </p> <ul><li> <i>MS_None = 1</i> — without a security;</li> <li> <i>MS_Sign = 2</i> — sign;</li> <li> <i>MS_SignAndEncrypt = 3</i> — sign and encrypt.</li></ul> <p>Types of the authentication (enum — AuthTp): </p> <ul><li> <i>A_Anon = 0</i> — anonymous;</li> <li> <i>A_UserNm = 1</i> — user+password;</li> <li> <i>A_Cert = 2</i> — certificate.</li></ul> <p>Node classes (enum — NodeClasses): </p> <ul><li> <i>NC_Object = 1</i> — object;</li> <li> <i>NC_Variable = 2</i> — variable;</li> <li> <i>NC_Method = 4</i> — method;</li> <li> <i>NC_ObjectType = 8</i> — object type;</li> <li> <i>NC_VariableType = 16</i> — variable type;</li> <li> <i>NC_ReferenceType = 32</i> — reference type;</li> <li> <i>NC_DataType = 64</i> — data type;</li> <li> <i>NC_View = 128</i> — view.</li></ul> <p>Browse directions (enum — BrowseDirection): </p> <ul><li> <i>BD_FORWARD = 0</i> — forward;</li> <li> <i>BD_INVERSE = 1</i> — inverse;</li> <li> <i>BD_BOTH = 2</i> — forward and inverse.</li></ul> <p>Time stamp to return (enum — TimestampsToReturn): </p> <ul><li> <i>TS_SOURCE = 0</i> — source;</li> <li> <i>TS_SERVER = 1</i> — server;</li> <li> <i>TS_BOTH = 2</i> — source and server;</li> <li> <i>TS_NEITHER = 3</i> — neither.</li></ul> <p>Access (enum — Access): </p> <ul><li> <i>ACS_Read = 0x01</i> — read;</li> <li> <i>ACS_Write = 0x02</i> — write;</li> <li> <i>ACS_HistRead = 0x04</i> — history read;</li> <li> <i>ACS_HistWrite = 0x08</i> — history write;</li> <li> <i>ACS_SemChange = 0x10</i> — ?.</li></ul> <p>Items of the description mask of the browsing request (enum — RefDscrResMask): </p> <ul><li> <i>RdRm_RefType = 0x01</i> — reference type;</li> <li> <i>RdRm_IsForward = 0x02</i> — is forward;</li> <li> <i>RdRm_NodeClass = 0x04</i> — node class;</li> <li> <i>RdRm_BrowseName = 0x08</i> — browse name;</li> <li> <i>RdRm_DisplayName = 0x10</i> — display name;</li> <li> <i>RdRm_TypeDef = 0x20</i> — type of reference.</li></ul> <p>Attribute identifiers of the node (enum — AttrIds): </p> <ul><li> <i>Aid_Error = 0</i> — error;</li> <li> <i>AId_NodeId = 1</i> — node identifier;</li> <li> <i>AId_NodeClass = 2</i> — node class;</li> <li> <i>AId_BrowseName = 3</i> — browse name;</li> <li> <i>AId_DisplayName = 4</i> — display name;</li> <li> <i>AId_Descr = 5</i> — description;</li> <li> <i>AId_WriteMask = 6</i> — write access mask;</li> <li> <i>AId_UserWriteMask = 7</i> — write access mask of user;</li> <li> <i>AId_IsAbstract = 8</i> — is abstract;</li> <li> <i>AId_Symmetric = 9</i> — symmetric;</li> <li> <i>AId_InverseName = 10</i> — inverse name;</li> <li> <i>AId_ContainsNoLoops = 11</i> — contains no loops;</li> <li> <i>AId_EventNotifier = 12</i> — event notifier;</li> <li> <i>AId_Value = 13</i> — value;</li> <li> <i>AId_DataType = 14</i> — data type;</li> <li> <i>AId_ValueRank = 15</i> — value rank;</li> <li> <i>AId_ArrayDimensions = 16</i> — array dimensions;</li> <li> <i>AId_AccessLevel = 17</i> — access level;</li> <li> <i>AId_UserAccessLevel = 18</i> — access level of user;</li> <li> <i>AId_MinimumSamplingInterval = 19</i> — minimal sampling interval;</li> <li> <i>AId_Historizing</i> — historizing;</li> <li> <i>AId_Executable</i> — executable;</li> <li> <i>AId_UserExecutable</i> — executable by user.</li></ul> <p>Subscription statuses (enum — SubScrSt): </p> <ul><li> <i>SS_CUR = 0</i> — current (do not change by command);</li> <li> <i>SS_CLOSED = 1</i> — closed;</li> <li> <i>SS_CREATING = 2</i> — creating;</li> <li> <i>SS_NORMAL = 3</i> — normal;</li> <li> <i>SS_LATE = 4</i> — later;</li> <li> <i>SS_KEEPALIVE = 5</i> — keep alive.</li></ul> <p>Monitoring modes (enum — MonitoringMode): </p> <ul><li> <i>MM_CUR = -1</i> — current (do not change by command);</li> <li> <i>MM_DISABLED = 0</i> — disabled;</li> <li> <i>MM_SAMPLING = 1</i> — sampling;</li> <li> <i>MM_REPORTING = 2</i> — reporting.</li></ul> <h4><span class="mw-headline" id="External_functions"><span class="mw-headline-number">4.1.2</span> External functions</span></h4> <p>To the library included range of external functions of the object <a class="external" href="http://oscada.org/wiki/Documents/API#TSYS" title="Documents/API">TSYS</a> of the OpenSCADA core to make simply and unified of the internal operations range: </p> <ul><li> <i>int64_t curTime( clockid_t clc = CLOCK_REALTIME );</i> — Current time in microseconds for the clock <i>clc</i>, from the Unix epoch (01.01.1970) for the CLOCK_REALTIME.</li> <li> <i>string int2str( int val );</i> — Conversion the signed integer to string into the decimal representing.</li> <li> <i>int str2int( const string &val );</i> — Conversion the string value <i>val</i> to the signed integer into the decimal, hexadecimal or octal representing.</li> <li> <i>string uint2str( unsigned val );</i> — Conversion the unsigned integer to string into the decimal representing.</li> <li> <i>unsigned long str2uint( const string &val );</i> — Conversion the string value <i>val</i> to the unsigned integer into the decimal, hexadecimal or octal representing.</li> <li> <i>string ll2str( int64_t val );</i> — Conversion the signed long integer (64bit) to string into the decimal representing.</li> <li> <i>string real2str( double val, int prec = 15, char tp = 'g' );</i> — Conversion the real value in double precision with precision <i>prec</i> of signs and type <i>tp</i> to string.</li> <li> <i>double str2real( const string &val );</i> — Conversion the string value <i>val</i> to the real value.</li> <li> <i>string strParse( const string &path, int level, const string &sep, int *off = NULL, bool mergeSepSymb = false );</i> — String <i>path</i> parsing to the components, which separated by <i>sep</i>, in single symbols merging <i>mergeSepSymb</i>, starting from the offset <i>off</i> and with control to the item's offset end in it.</li> <li> <i>string strLine( const string &str, int level, int *off = NULL );</i> — Multiline text parsing to separate lines, starting from the offset <i>off</i> and with control to the item's offset end in it.</li> <li> <i>string strMess( const char *fmt, ... );</i> — String forming by the template <i>fmt</i> and the arguments, implemented on the basis of "sprintf".</li></ul> <h4><span class="mw-headline" id="Automatic_POSIX_mutex_unlock_object_for_OPC_.28OPCAlloc.29"><span class="mw-headline-number">4.1.3</span> Automatic POSIX mutex unlock object for OPC (OPCAlloc)</span></h4> <p>The mutex management object is a copy of the "MtxAlloc" object of the OpenSCADA core. </p><p><b>Public methods:</b> </p> <ul><li> <i>OPCAlloc( pthread_mutex_t &iM, bool ilock = false );</i> — Initialization of the automatic unlock mutex for early allocated one <i>iM</i>, with the <i>lock</i> set at creation.</li> <li> <i>int lock( );</i> — The resource lock, return zero at the success.</li> <li> <i>int unlock( );</i> — The resource unlock, return zero at the success.</li> <li> <i>int tryLock( );</i> — The resource try lock without waiting for free, return zero at the success.</li></ul> <h4><span class="mw-headline" id="Error_of_OPC_.28OPCError.29"><span class="mw-headline-number">4.1.4</span> Error of OPC (OPCError)</span></h4> <p>The error object "OPCError" is a trimmed copy of the <a class="external" href="http://oscada.org/wiki/Documents/API#TError" title="Documents/API">TError</a> object of the OpenSCADA core. </p><p><b>Public methods:</b> </p> <ul><li> <i>OPCError( const char *fmt, ... );</i> — Typical error's constructor without a code.</li> <li> <i>OPCError( int cod, const char *fmt, ... );</i> — Typical error's constructor with the code <i>cod</i>.</li></ul> <p><b>Public attributes:</b> </p> <ul><li> <i>int cod;</i> — Error code.</li> <li> <i>string mess;</i> — Error text.</li></ul> <h4><span class="mw-headline" id="XML-tag_.28XML_N.29"><span class="mw-headline-number">4.1.5</span> XML-tag (XML_N)</span></h4> <p>The object "XML_N" is a trimmed copy of the <a class="external" href="http://oscada.org/wiki/Documents/API#XMLNode" title="Documents/API">XMLNode</a> object of the OpenSCADA core. </p><p><b>Public methods:</b> </p> <ul><li> <i>XML_N( const string &name = "" );</i> — Initialization of the tag with the <i>name</i>.</li> <li> <i>XML_N( const XML_N &nd );</i> — Copy constructor.</li> <li> <i>XML_N &operator=( const XML_N &prm );</i> — Copying a branch of the XML-tree from <i>prm</i>.</li> <li> <i>string name( ) const;</i> — the tag name.</li> <li> <i>XML_N* setName( const string &s );</i> — Setting the tag name to <i>s</i>.</li> <li> <i>string text( bool childs = false, bool recursive = false ) const;</i> — the tag text, <i>childs</i> — for text getting from the special text nodes.</li> <li> <i>XML_N* setText( const string &s, bool childs = false );</i> — Setting the tag text to <i>s</i>, <i>childs</i> — for text setting to the special text node.</li> <li> <i>void attrList( vector<string> & list ) const;</i> — <i>List</i> of attributes in the tag.</li> <li> <i>XML_N* attrDel( const string &name );</i> — Deleting of the attribute <i>name</i>.</li> <li> <i>void attrClear( );</i> — Clean up the tag's attributes.</li> <li> <i>string attr( const string &name, bool caseSens = true ) const;</i> — Getting the attribute <i>name</i>.</li> <li> <i>XML_N* setAttr( const string &name, const string &val );</i> — Setting/creation of the attribute <i>name</i> with the value <i>val</i>.</li> <li> <i>XML_N* clear( );</i> — Clear the tag (recursively, including all childs).</li> <li> <i>bool childEmpty( ) const;</i> — Check for empty the included tags.</li> <li> <i>unsigned childSize( ) const;</i> — Number of the included tags.</li> <li> <i>void childAdd( XML_N *nd ); XML_N* childAdd( const string &name = "" );</i> — Adding the included tag.</li> <li> <i>int childIns( unsigned id, XML_N *nd );</i> — Insert of the included tag <i>nd</i> to the position <i>id</i>, negative <i>id</i> counts from the end.</li> <li> <i>XML_N* childIns( unsigned id, const string &name = "" );</i> — Insert of the included tag with the name <i>name</i> to the position <i>id</i>, negative <i>id</i> counts from the end.</li> <li> <i>void childDel( const unsigned id );</i> — Deleting of the included tag <i>id</i>, negative <i>id</i> counts from the end.</li> <li> <i>void childDel( XML_N *nd );</i> — Deleting of the included tag using its address <i>nd</i>.</li> <li> <i>XML_N* childClear( const string &name = "" );</i> — Clean up of the included tag <i>name</i>.</li> <li> <i>XML_N* childGet( const int, bool noex = false ) const;</i> — Getting the included tag by its index number.</li> <li> <i>XML_N* childGet( const string &name, const int numb = 0, bool noex = false ) const;</i> — Getting of the included <i>numb</i> indexed tag by the tag's name <i>name</i>, <i>noex</i> indicates the prohibition of the generation of exception in the case of absence of the tag.</li> <li> <i>XML_N* childGet( const string &attr, const string &name, bool noex = false ) const;</i> — Getting the included tag by its value <i>name</i> of the attribute <i>attr</i>, <i>noex</i> indicates the prohibition of the generation of exception in the case of absence of the tag.</li> <li> <i>XML_N* getElementBy( const string &attr, const string &val );</i> — Included node search by the value <i>val</i> of the attribute <i>attr</i>.</li> <li> <i>XML_N* parent( );</i> — Parent tag of the tag.</li> <li> <i>XML_N* root( );</i> — Root tag of the tag.</li></ul> <h4><span class="mw-headline" id="Node.27s_object_of_OPC-UA_.28NodeId.29"><span class="mw-headline-number">4.1.6</span> Node's object of OPC-UA (NodeId)</span></h4> <p><b>Data:</b><br /> Data types (enum — NodeId::Type): </p> <ul><li> <i>NodeId::Numeric</i> — number.</li> <li> <i>NodeId::String</i> — string.</li> <li> <i>NodeId::Guid</i> — global unique identifier.</li> <li> <i>NodeId::Opaque</i> — opaque.</li></ul> <p><b>Public methods:</b> </p> <ul><li> <i>NodeId( uint32_t n, uint16_t ns = 0 );</i> — Numerical initial constructor for number <i>n</i> in the namespace <i>ns</i>.</li> <li> <i>NodeId( const string &str, uint16_t ns = 0, Type tp = String );</i> — String initial constructor for string <i>str</i> into the namespace <i>ns</i> with the type <i>tp</i>.</li> <li> <i>NodeId( const NodeId &node );</i> — The object copy constructor.</li> <li> <i>NodeId( );</i> — Destructor.</li> <li> <i>bool operator==( const NodeId &node );</i> — Objects comparing.</li> <li> <i>NodeId &operator=( const NodeId &node );</i> — Copying the object.</li> <li> <i>Type type( ) const;</i> — Node type.</li> <li> <i>bool isNull( ) const;</i> — Node is zero — uninitialized.</li> <li> <i>uint16_t ns( ) const;</i> — Namespace.</li> <li> <i>uint32_t numbVal( ) const;</i> — Number value.</li> <li> <i>string strVal( ) const;</i> — String value.</li> <li> <i>void setNs( uint16_t ns );</i> — Name space setting to <i>ns</i>.</li> <li> <i>void setNumbVal( uint32_t n );</i> — Number value setting to <i>n</i>.</li> <li> <i>void setStrVal( const string &str, Type tp = String );</i> — String value setting to <i>str</i> with type <i>tp</i>.</li> <li> <i>static NodeId fromAddr( const string &strAddr, bool strictStr = false, int *off = NULL );</i> — Node's object forming from the address <i>strAddr</i>, as a strict string <i>strictStr</i> and with the address parsing end in <i>off</i>.</li> <li> <i>string toAddr( ) const;</i> — Node's object address getting.</li></ul> <h4><span class="mw-headline" id="Root_object_of_the_OPC-UA_protocol_.28UA.29"><span class="mw-headline-number">4.1.7</span> Root object of the OPC-UA protocol (UA)</span></h4> <p><b>Public methods:</b> </p> <ul><li> <i>virtual string lang2CodeSYS( );</i> — Two-symbol language code of the environment.</li> <li> <i>virtual void debugMess( const string &mess )</i> — Debug messages placing.</li> <li> <i>virtual uint32_t rcvBufSz( );</i> — Receiver buffer size, great for 8192.</li> <li> <i>virtual uint32_t sndBufSz( );</i> — Transmitter buffer size, great for 8192.</li> <li> <i>virtual uint32_t msgMaxSz( );</i> — Maximum message size, 0 for unlimited.</li> <li> <i>virtual uint32_t chunkMaxCnt( );</i> — Maximum chunks counter, 0 for unlimited.</li> <li> <i>static string iErr( const string &buf, int &off );</i> — Error reading from the stream <i>buf</i> by the offset <i>off</i>.</li> <li> <i>static const char *iVal( const string &buf, int &off, char vSz );</i> — Value in size <i>vSz</i> reading from the stream <i>buf</i> by the offset <i>off</i>, as a data part.</li> <li> <i>static int64_t iN( const string &rb, int &off, char vSz );</i> — Value of signed integer in size <i>vSz</i> (1, 2, 4, 8) reading from the stream <i>rb</i> by the offset <i>off</i>.</li> <li> <i>static uint64_t iNu( const string &rb, int &off, char vSz );</i> — Value of unsigned integer in size <i>vSz</i> (1, 2, 4, 8) reading from the stream <i>rb</i> by the offset <i>off</i>.</li> <li> <i>static double iR( const string &rb, int &off, char vSz = 4 );</i> — Value of real in size <i>vSz</i> (4, 8) reading from the stream <i>rb</i> by the offset <i>off</i>.</li> <li> <i>static string iS( const string &buf, int &off );</i> — String reading from the stream <i>buf</i> by the offset <i>off</i>.</li> <li> <i>static string iSl( const string &buf, int &off, string *locale = NULL );</i> — Localized <i>locale</i> string reading from the stream <i>buf</i> by the offset <i>off</i>.</li> <li> <i>static string iSqlf( const string &buf, int &off, uint16_t *nsIdx = NULL );</i> — String with the qualify <i>nsIdx</i> reading from the stream <i>buf</i> by the offset <i>off</i>.</li> <li> <i>static int64_t iTm( const string &buf, int &off );</i> — Time reading from the stream <i>buf</i> by the offset <i>off</i>, with conversion it to the UNIX epoch.</li> <li> <i>static NodeId iNodeId( const string &buf, int &off );</i> — Node identifier reading from the stream <i>buf</i> by the offset <i>off</i>.</li> <li> <i>static string iVariant( const string &buf, int &off, uint8_t *tp = NULL );</i> — Variant type reading from the stream <i>buf</i> by the offset <i>off</i>, returns the variant in string representing of type <i>tp</i>.</li> <li> <i>static void iDataValue( const string &buf, int &off, XML_N &nVal );</i> — Complex value (structure DataValue) reading to <i>nVal</i> from the stream <i>buf</i> by the offset <i>off</i>.</li> <li> <i>static void oN( string &buf, int64_t val, char sz, int off = -1 );</i> — Value of signed integer <i>val</i> in size <i>sz</i> (1, 2, 4, 8) writing to the stream <i>buf</i> by the offset <i>off</i>.</li> <li> <i>static void oNu( string &buf, uint64_t val, char sz, int off = -1 );</i> — Value of unsigned integer <i>val</i> in size <i>sz</i> (1, 2, 4, 8) writing to the stream <i>buf</i> by the offset <i>off</i>.</li> <li> <i>static void oR( string &buf, double val, char sz = 4 );</i> — Value of real <i>val</i> in size <i>sz</i> (4, 8) writing to the stream <i>buf</i> by the offset <i>off</i>.</li> <li> <i>static void oS( string &buf, const string &val, int off = -1 );</i> — String <i>val</i> writing to the stream <i>buf</i> by the offset <i>off</i>.</li> <li> <i>static void oSl( string &buf, const string &val, const string &locale = "" );</i> — Localized <i>locale</i> string <i>val</i> writing to the stream <i>buf</i> by the offset <i>off</i>.</li> <li> <i>static void oSqlf( string &buf, const string &val, uint16_t nsIdx = 0 );</i> — String <i>val</i> with the qualify <i>nsIdx</i> writing to the stream <i>buf</i> by the offset <i>off</i>.</li> <li> <i>static void oTm( string &buf, int64_t val );</i> — Time <i>val</i> (in the UNIX epoch) writing to the stream <i>buf</i> by the offset <i>off</i>.</li> <li> <i>static void oNodeId( string &buf, const NodeId &val );</i> — Node identifier <i>val</i> writing to the stream <i>buf</i> by the offset <i>off</i>.</li> <li> <i>static void oRef( string &buf, uint32_t resMask, const NodeId &nodeId, const NodeId &refTypeId, bool isForward, const string &name, uint32_t nodeClass, const NodeId &typeDef );</i> — Writing to the stream <i>buf</i> of browsing description (structure ReferenceDescription) for the result mask <i>resMask</i>, the node <i>nodeId</i>, the reference type <i>refTypeId</i>, the forward direction <i>isForward</i>, the name <i>name</i>, the node class <i>nodeClass</i>, the definition type <i>typeDef</i>.</li> <li> <i>void oDataValue( string &buf, uint8_t eMsk, const string &vl, uint8_t vEMsk = 0, int64_t srcTmStmp = 0 );</i> — Complex value (structure DataValue) writing to the stream <i>buf</i> for the encoding mask <i>eMsk</i>, the value <i>vl</i>, the value mask <i>vEMsk</i>, the source time <i>srcTmStmp</i>.</li> <li> <i>static string randBytes( int num );</i> — Random data stream generation in the number <i>num</i>.</li> <li> <i>static string certPEM2DER( const string &certPem );</i> — Certificate conversion from PEM <i>certPem</i> to DER form.</li> <li> <i>static string certDER2PEM( const string &certDer );</i> — Certificate conversion from DER <i>certDer</i> to PEM form.</li> <li> <i>static string certThumbprint( const string &certPem );</i> — Sign getting from the certificate PEM <i>certPem</i>.</li> <li> <i>static string asymmetricEncrypt( const string &mess, const string &certPem, const string &secPolicy );</i> — Asymmetric encryption of the message <i>mess</i> stream by the certificate <i>certPem</i> (by the open key) for the policy <i>secPolicy</i>.</li> <li> <i>static string asymmetricDecrypt( const string &mess, const string &pvKeyPem, const string &secPolicy );</i> — Asymmetric decryption of the message <i>mess</i> stream by the key <i>pvKeyPem</i> for the certificate <i>secPolicy</i>.</li> <li> <i>static bool asymmetricVerify( const string &mess, const string &sign, const string &certPem );</i> — Asymmetric verifying of the <i>sign</i> of the message <i>mess</i> by the certificate <i>certPem</i>.</li> <li> <i>static string asymmetricSign( const string &mess, const string &pvPem );</i> — Asymmetric subscription getting by the private key of the certificate <i>pvPem</i> for the message <i>mess</i>.</li> <li> <i>static int asymmetricKeyLength( const string &keyCertPem );</i> — Key length getting of the certificate <i>keyCertPem</i>.</li> <li> <i>static string deriveKey( const string &secret, const string &seed, int keyLen );</i> — Key of the length <i>keyLen</i> derive from the <i>secret</i> and the <i>seed</i>.</li> <li> <i>static string symmetricCrypt( const string &mess, const string &keySet, const string &secPolicy, bool encrypt );</i> — Symmetric encryption at <i>encrypt</i> or decryption of the message <i>mess</i> stream by the key <i>keySet</i> for the policy <i>secPolicy</i>.</li> <li> <i>static string symmetricSign( const string &mess, const string &keySet, const string &secPolicy );</i> — Symmetric sign by key <i>keySet</i> getting for the message <i>mess</i> and the policy <i>secPolicy</i>.</li></ul> <h5><span class="mw-headline" id="Included_object_of_the_security_parameters_.28SecuritySetting.29"><span class="mw-headline-number">4.1.7.1</span> Included object of the security parameters (SecuritySetting)</span></h5> <p><b>Public data:</b> </p> <ul><li> <i>string policy</i> — security policy;</li> <li> <i>MessageSecurityMode messageMode</i> — message mode.</li></ul> <p><b>Public methods:</b> </p> <ul><li> <i>SecuritySetting( const string &plc, int8_t mMode )</i> — Object constructor for the security policy <i>plc</i> and the messages mode <i>mMode</i>.</li> <li> <i>SecuritySetting( )</i> — Object constructor with the security policy "None" and the messages mode <i>MS_None</i>.</li></ul> <h3><span class="mw-headline" id="Main_object_of_the_Client_.28Client-.3EUA.29"><span class="mw-headline-number">4.2</span> Main object of the Client (Client->UA)</span></h3> <p><b>Application:</b> Directly inheritance by a user object — OPC-UA Client. </p><p><b>Public methods:</b> </p> <ul><li> <i>virtual string applicationUri( ) = 0;</i> — Application URI.</li> <li> <i>virtual string productUri( ) = 0;</i> — Product URI.</li> <li> <i>virtual string applicationName( ) = 0;</i> — Application name.</li> <li> <i>virtual string sessionName( ) = 0;</i> — Session name.</li> <li> <i>virtual string endPoint( ) = 0;</i> — Endpoint.</li> <li> <i>virtual string secPolicy( ) = 0;</i> — Security policy.</li> <li> <i>virtual int secMessMode( ) = 0;</i> — Security mode of the messages.</li> <li> <i>virtual string cert( ) = 0;</i> — Certificate.</li> <li> <i>virtual string pvKey( ) = 0;</i> — Private key.</li> <li> <i>virtual string authData( ) = 0;</i> — Authentication data: <ul><li> "<Empty>" — anonymous;</li> <li> "{User}\n{Password}" — by user and password.</li></ul></li> <li> <i>virtual uint8_t publishReqsPool( )</i> — Number of <i>Publish</i> requests of the publication service, typically <b>2(two)</b>.</li> <li> <i>virtual string poll( bool byRead = false );</i> — The function of the publication service processing for: input channel reading for the publication responses, tracing of need number the <i>Publish</i> requests and of the connection lost due to the publication responses missing during something specified lifetime. By the argument <i>byRead</i> the function also provides of direct reading of the registered monitored items by the request "Read".</li> <li> <i>virtual int messIO( const char *oBuf, int oLen, char *iBuf = NULL, int iLen = 0 ) = 0;</i> — Messages exchange, send a request and wait a response.</li></ul> <dl><dd> <a class="image" href="http://oscada.org/wiki/File:At.png"><img alt="At.png" height="22" src="../files/At.png" width="22" /></a> The mixed mode of requesting and free reading/writing is resolving still.</dd></dl> <ul><li> <i>virtual bool connect( int8_t est = -1 );</i> — Connection status obtain, the connection establish at <i>est</i> = 1, disconnecting at <i>est</i> = 0.</li> <li> <i>virtual void protIO( XML_N &io );</i> — Request to the protocol processing.</li> <li> <i>virtual void reqService( XML_N &io );</i> — Complex service request, which is tracing itself for necessary in call the additional requests of opening/closing the secure channel, opening/closing/activation of the session and other.</li></ul> <p><b>Protected attributes:</b> </p> <ul><li> <i>SClntSess sess;</i> — session data;</li> <li> <i>pthread_mutex_t mtxData;</i> — the data accessing lock.</li></ul> <h4><span class="mw-headline" id="Complex_Client_session_.28Client::SClntSess.29"><span class="mw-headline-number">4.2.1</span> Complex Client session (Client::SClntSess)</span></h4> <p><b>Public data:</b> </p> <ul><li> <i>uint32_t servRcvBufSz, servSndBufSz, servMsgMaxSz, servChunkMaxCnt;</i> — parameters of the receiver and transmitter buffer, maximum message size and maximum chunks number; which received from the server by the request "HELLO";</li> <li> <i>string endPoint;</i> — endpoint;</li> <li> <i>XML_N endPointDscr;</i> — active endpoint description;</li> <li> <i>uint32_t secChnl, secToken;</i> — security channel index and token;</li> <li> <i>int secLifeTime;</i> — secure channel lifetime;</li> <li> <i>bool secChnlChanged;</i> — flag of the secure channel changing for reconnection or reactivation of the session;</li> <li> <i>uint32_t sqNumb, sqReqId, reqHndl;</i> — the sequence number, the sequence number of request and the request handler;</li> <li> <i>string secPolicy;</i> — security policy;</li> <li> <i>char secMessMode;</i> — message security mode;</li> <li> <i>int64_t secChnlOpenTm, secLstMessReqTm;</i> — time of opening/renewing the secure channel and the last message request;</li> <li> <i>string sesId, authTkId;</i> — session identifier and token of authentication;</li> <li> <i>double sesLifeTime;</i> — session lifetime;</li> <li> <i>string servCert, servNonce, servKey;</i> — server certificate, random sequence and symmetric key;</li> <li> <i>string clKey;</i> — client symmetric key;</li> <li> <i>vector<Subscr> mSubScr;</i> — subscriptions (the object Subscr) of the Client;</li> <li> <i>vector<uint32_t> mPublSeqs;</i> — the register of the sent requests of the publication by the sequence number of request.</li></ul> <p><b>Public methods:</b> </p> <ul><li> <i>void clearSecCnl( bool inclEP = false )</i> — Cleans the secure channel, including the endpoint description <i>inclEPdescr</i>.</li> <li> <i>void clearSess( bool inclSubscr = true )</i> — Cleans the session, including the subscriptions <i>inclSubscr</i>.</li></ul> <h5><span class="mw-headline" id="Client_Subscription_.28Client::Subscr.29"><span class="mw-headline-number">4.2.1.1</span> Client Subscription (Client::Subscr)</span></h5> <p><b>Public data:</b> </p> <ul><li> <i>bool publEn;</i> — enable publishing;</li> <li> <i>double publInterval;</i> — publish interval in milliseconds;</li> <li> <i>uint32_t subScrId;</i> — subscription identifier: <ZERO> — inactive object;</li> <li> <i>uint32_t lifetimeCnt;</i> — counter, at which and in the absence of notifications, the client deletes this object;</li> <li> <i>uint32_t maxKeepAliveCnt;</i> — counter for which you need to send an empty publication response;</li> <li> <i>uint32_t maxNtfPerPubl;</i> — maximum notifications per single Publish response;</li> <li> <i>uint8_t pr;</i> — priority;</li> <li> <i>vector<MonitItem> mItems;</i> — monitored items container;</li> <li> <i>vector<uint32_t> mSeqToAcq;</i> — register of the sequences of the Publish responses need to be acknowledged in a near Publish request;</li> <li> <i>int64_t lstPublTm;</i> — last publication response time;</li> <li> <i>Client *clnt;</i> — direct link to the Client object.</li></ul> <p><b>Public methods:</b> </p> <ul><li> <i>Subscr( Client *clnt, double publInterval = 1e3 );</i> — Subscription constructor for the Client <i>clnt</i> with the publication interval <i>publInterval</i>.</li> <li> <i>bool isActivated( );</i> — Returns the activation state of the subscription.</li> <li> <i>void activate( bool vl, bool onlyLocally = false );</i> — Activate (<i>vl</i>=TRUE) or deactivate (<i>vl</i>=FALSE) the Subscription. The activation means sending the "CreateSubscription" request with creation the registered but not activated monitored items by the service request "CreateMonitoredItems". The deactivation means sending the service request "DeleteSubscriptions", if the argument <i>onlyLocally</i> is not set, with local data clearing for the monitored items.</li> <li> <i>int monitoredItemAdd( const NodeId &nd, AttrIds aId = AId_Value, MonitoringMode mMode = MM_REPORTING );</i> — Add the node <i>nd</i> for the attribute <i>aId</i> as a monitored item in the monitoring mode <i>mMode</i> and returns the new monitored item identifier. At the active state of the Subscription there also performs the service request "CreateMonitoredItems". The special value "0" of the node <i>nd</i> means of performing the service request "CreateMonitoredItems" for all registered and inactive still items.</li> <li> <i>void monitoredItemDel( int32_t mItId, bool localDeactivation = false, bool onlyNoData = false );</i> — Delete the monitored item <i>mItId</i>, marking that as "FREE" and performing also the service request "DeleteMonitoredItems" for not <i>localDeactivation</i>. <i>onlyNoData</i> is used together <i>localDeactivation</i> for only marking the item as "NODATA" after some connection errors. The special value "-1" of the monitored item <i>mItId</i> means of performing the deactivation for all items.</li></ul> <h6><span class="mw-headline" id="Monitored_Item_of_the_Client_Subscription_.28Client::Subscr::MonitItem.29"><span class="mw-headline-number">4.2.1.1.1</span> Monitored Item of the Client Subscription (Client::Subscr::MonitItem)</span></h6> <p><b>Public data:</b> </p> <ul><li> <i>MonitoringMode md;</i> — monitoring mode;</li> <li> <i>NodeId nd;</i> — target node: <EMPTY> — free monitored item;</li> <li> <i>uint32_t aid;</i> — attribute ID of the node;</li> <li> <i>double smplItv;</i> — sample interval;</li> <li> <i>uint32_t qSz;</i> — queue size;</li> <li> <i>bool active;</i> — activity of the item;</li> <li> <i>uint32_t st;</i> — status code of the item;</li> <li> <i>XML_N val;</i> — value context of the item: the attribute "nodata" presence means the data missing.</li></ul> <p><b>Public methods:</b> </p> <ul><li> <i>MonitItem( NodeId nd, uint32_t aid, MonitoringMode md = MM_REPORTING );</i> — Monitored Item constructor for the node <i>nd</i> and its attribute <i>aid</i> in the monitoring mode <i>md</i>.</li></ul> <h3><span class="mw-headline" id="Main_object_of_the_Server_.28Server-.3EUA.29"><span class="mw-headline-number">4.3</span> Main object of the Server (Server->UA)</span></h3> <p><b>Application:</b> Direct inheritance by a user object — OPC-UA Server. </p><p><b>Public methods:</b> </p> <ul><li> <i>virtual bool debug( );</i> — Debugging is activated.</li> <li> <i>virtual string applicationUri( ) = 0;</i> — Application URI.</li> <li> <i>virtual string productUri( ) = 0;</i> — Product URI.</li> <li> <i>virtual string applicationName( ) = 0;</i> — Application name.</li> <li> <i>virtual uint32_t clientRcvBufSz( const string &inPrtId ) = 0;</i> — Receiver buffer size, taken from client, for the connection <i>inPrtId</i>.</li> <li> <i>virtual uint32_t clientSndBufSz( const string &inPrtId ) = 0;</i> — Transmitter buffer size, taken from client, for the connection <i>inPrtId</i>.</li> <li> <i>virtual uint32_t clientMsgMaxSz( const string &inPrtId ) = 0;</i> — Maximum message size, taken from client, for the connection <i>inPrtId</i>.</li> <li> <i>virtual uint32_t clientChunkMaxCnt( const string &inPrtId ) = 0;</i> — Maximum chunks counter, taken from client, for the connection <i>inPrtId</i>.</li> <li> <i>virtual void discoveryUrls( vector<string> &ls ) = 0;</i> — Discovery server's URLs in <i>ls</i>.</li> <li> <i>virtual bool inReq( string &request, const string &inPrtId, string *answ = NULL );</i> — Input requests <i>request</i> handler for the protocol object <i>inPrtId</i> and the answer <i>answ</i>.</li> <li> <i>virtual int writeToClient( const string &threadId, const string &data ) = 0;</i> — Direct writing to the connected client.</li> <li> <i>virtual string clientAddr( const string &threadId ) = 0;</i> — client address.</li> <li> <i>virtual void clientRcvBufSzSet( const string &inPrtId, uint32_t vl ) = 0;</i> — Set the receiver buffer size, taken from client, to <i>vl</i> for the connection <i>inPrtId</i>.</li> <li> <i>virtual void clientSndBufSzSet( const string &inPrtId, uint32_t vl ) = 0;</i> — Set the transmitter buffer size, taken from client, to <i>vl</i> for the connection <i>inPrtId</i>.</li> <li> <i>virtual void clientMsgMaxSzSet( const string &inPrtId, uint32_t vl ) = 0;</i> — Set the maximum message size, taken from client, to <i>vl</i> for the connection <i>inPrtId</i>.</li> <li> <i>virtual void clientChunkMaxCntSet( const string &inPrtId, uint32_t vl ) = 0;</i> — Set the maximum chunks counter, taken from client, to <i>vl</i> for the connection <i>inPrtId</i>.</li> <li> <i>int chnlSet( int cid, const string &ep, int32_t lifeTm = 0, const string& clCert = "", const string &secPolicy = "None", char secMessMode = 1, const string &clAddr = "", uint32_t seqN = 1 );</i> — Security channel setting with the identifier <i>cid</i> (nonzero value for updating) for the endpoint <i>ep</i>, the lifetime <i>lifeTm</i>, the client certificate <i>clCert</i>, the security policy <i>secPolicy</i>, the messages security mode <i>secMessMode</i>, the client address <i>clAddr</i>, the package sequence number <i>seqN</i>.</li> <li> <i>void chnlClose( int cid );</i> — Security channel <i>cid</i> closing.</li> <li> <i>SecCnl chnlGet( int cid ); SecCnl &chnlGet_( int cid );</i> — Security channel object <i>cid</i> copy getting and accessing.</li> <li> <i>void chnlSecSet( int cid, const string &servKey, const string &clKey );</i> — Security channel <i>cid</i> setting to the symmetric keys of the server <i>servKey</i> and the client <i>clKey</i>.</li> <li> <i>static string mkError( uint32_t errId, const string &err = "" );</i> — Error forming for the identifier <i>errId</i> and the message <i>err</i>.</li></ul> <p><b>Protected methods:</b> </p> <ul><li> <i>virtual void epEnList( vector<string> &ls ) = 0;</i> — handler of request to list of endpoint nodes.</li> <li> <i>virtual EP *epEnAt( const string &ep ) = 0;</i> — handler of request to the endpoint object.</li></ul> <p><b>Protected attributes:</b> </p> <ul><li> <i>pthread_mutex_t mtxData;</i> — the data accessing lock.</li></ul> <h4><span class="mw-headline" id="Server_Security_Channel_.28Server::SecCnl.29"><span class="mw-headline-number">4.3.1</span> Server Security Channel (Server::SecCnl)</span></h4> <p><b>Public methods:</b> </p> <ul><li> <i>SecCnl( const string &ep, uint32_t tokenId, int32_t lifeTm, const string &clCert, const string &secPolicy, char secMessMode, const string &clAddr, uint32_t secN );</i> — Security Channel object constructor for: the endpoint <i>ep</i>, the security token <i>tokenId</i>, the lifetime <i>lifeTm</i>, the client certificate <i>clCert</i>, the security policy <i>secPolicy</i>, the messages security mode <i>secMessMode</i>, the client address <i>clAddr</i>, the sequence number <i>secN</i> of creation the security channel.</li></ul> <p><b>Public attributes:</b> </p> <ul><li> <i>string endPoint;</i> — endpoint;</li> <li> <i>string secPolicy;</i> — security policy;</li> <li> <i>char secMessMode;</i> — security mode of message;</li> <li> <i>int64_t tCreate;</i> — creation time;</li> <li> <i>int32_t tLife;</i> — lifetime;</li> <li> <i>uint32_t tokenId, tokenIdPrev;</i> — current and previous token identifiers;</li> <li> <i>string clCert, clAddr, clKey;</i> — client's certificate, address and symmetric key;</li> <li> <i>string servKey;</i> — server's symmetric key;</li> <li> <i>uint32_t servSeqN, clSeqN, reqId;</i> — current number of the package sequence of server, client and request;</li> <li> <i>int chCnt;</i> — counter of the chunks of the package in the accumulation;</li> <li> <i>string chB;</i> — package accumulation from the chunks.</li></ul> <h4><span class="mw-headline" id="Server_Session_.28Server::Sess.29"><span class="mw-headline-number">4.3.2</span> Server Session (Server::Sess)</span></h4> <p><b>Public methods:</b> </p> <ul><li> <i>Sess( const string &name, double tInact );</i> — Constructor of the Session object with <i>name</i> and timeout of the activity <i>tInact</i>.</li> <li> <i>bool isSecCnlActive( EP *ep );</i> — Returns the activity status of the Secure Channel, linked the session.</li></ul> <p><b>Public attributes:</b> </p> <ul><li> <i>string name, inPrtId;</i> — name and input protocol identifier;</li> <li> <i>string idPolicyId, user;</i> — the policy identifier and user of the authentication;</li> <li> <i>uint32_t secCnl;</i> — security channel, linked the session;</li> <li> <i>double tInact;</i> — inactivity time;</li> <li> <i>int64_t tAccess;</i> — access time;</li> <li> <i>string servNonce;</i> — random sequence of the server;</li> <li> <i>map<string, ContPoint> cntPnts;</i> — browse's continuation points;</li> <li> <i>deque<string> publishReqs;</i> — publish requests list.</li></ul> <h5><span class="mw-headline" id="Browse_continuation_point_of_the_Server_Session_.28Server::Sess::ContPoint.29"><span class="mw-headline-number">4.3.2.1</span> Browse continuation point of the Server Session (Server::Sess::ContPoint)</span></h5> <p><b>Public methods:</b> </p> <ul><li> <i>ContPoint( const string &brNode, const string &lstNode, uint32_t brDir, uint32_t refPerN, const string &refTypeId, uint32_t nClassMask, uint32_t resMask )</i> — Constructor for object of the continuation node's point <i>brNode</i> constructor, of the list node <i>lstNode</i>, of the direction browsing <i>brDir</i>, of the number of references <i>refPerN</i> to a node, of the reference identifier <i>refTypeId</i>, of the node class mask <i>nClassMask</i> and the result mask <i>resMask</i>.</li> <li> <i>bool empty( ) const;</i> — Continuation point is empty.</li></ul> <p><b>Public attributes:</b> </p> <ul><li> <i>uint32_t brDir, refPerN, nClassMask, resMask;</i> — browsing direction, references number to node, class mask of the node, results mask;</li> <li> <i>string brNode, lstNode, refTypeId;</i> — nodes branch, nodes list and the reference's type identifier.</li></ul> <h4><span class="mw-headline" id="Server_Subscription_.28Server::Subscr.29"><span class="mw-headline-number">4.3.3</span> Server Subscription (Server::Subscr)</span></h4> <p><b>Public methods:</b> </p> <ul><li> <i>Subscr copy( bool noWorkData = true );</i> — Copy of the subscription object, without a work data for <i>noWorkData</i>.</li> <li> <i>SubScrSt setState( SubScrSt st = SS_CUR );</i> — Returns the current state and setting to <i>st</i>.</li></ul> <p><b>Public attributes:</b> </p> <ul><li> <i>SubScrSt st;</i> — subscription state;</li> <li> <i>int sess;</i> — session of the subscription;</li> <li> <i>bool publEn;</i> — enabling the publication;</li> <li> <i>bool toInit;</i> — flag of the subscription initiation — sending of the first-empty package of the publication response;</li> <li> <i>double publInterv;</i> — publish interval, milliseconds;</li> <li> <i>uint32_t seqN;</i> — sequence number for responses, wrapped through 1, no increments at the KeepAlive messages;</li> <li> <i>uint32_t pubCntr, pubCntr_;</i> — counter of sending the publish responses for the activity detection;</li> <li> <i>uint32_t lifetimeCnt, wLT;</i> — counter at it exhausting and a message miss from client, the server needs to the object erase;</li> <li> <i>uint32_t maxKeepAliveCnt, wKA;</i> — counter at it exhausting the server needs to send an empty publish response and set the state <i>StatusChangeNotification</i> to <b>Bad_Timeout</b>;</li> <li> <i>uint32_t maxNtfPerPubl;</i> — maximum number of the notifications at one response of the publishing;</li> <li> <i>uint8_t pr;</i> — priority;</li> <li> <i>vector<MonitItem> mItems;</i> — list of the monitored items;</li> <li> <i>deque<string> retrQueue;</i> — retransmission queue, used by the retransmission queue request "RePublish"; cleaned up to the depth according to the <i>KeepAlive</i> or the direct publish request into the acquiring set.</li></ul> <h5><span class="mw-headline" id="Monitored_Item_of_the_Server_Subscription_.28Server::Subscr::MonitItem.29"><span class="mw-headline-number">4.3.3.1</span> Monitored Item of the Server Subscription (Server::Subscr::MonitItem)</span></h5> <p><b>Public methods:</b> </p> <ul><li> <i>MonitoringMode md;</i> — monitoring mode;</li> <li> <i>NodeId nd;</i> — target node;</li> <li> <i>uint32_t aid;</i> — attribute identifier of the node;</li> <li> <i>TimestampsToReturn tmToRet;</i> — timestamps to return;</li> <li> <i>double smplItv;</i> — sampling interval;</li> <li> <i>uint32_t qSz;</i> — queue size;</li> <li> <i>bool dO;</i> — to drop old;</li> <li> <i>uint32_t cH;</i> — client handler;</li> <li> <i>XML_N fltr;</i> — filter;</li> <li> <i>int vTp;</i> — value type;</li> <li> <i>int64_t dtTm;</i> — last value time;</li> <li> <i>deque<Val> vQueue;</i> — value queue.</li></ul> <h6><span class="mw-headline" id="Value_element_of_the_Monitored_Item_of_the_Server_Subscription_.28Server::Subscr::MonitItem::Val.29"><span class="mw-headline-number">4.3.3.1.1</span> Value element of the Monitored Item of the Server Subscription (Server::Subscr::MonitItem::Val)</span></h6> <p><b>Public methods:</b> </p> <ul><li> <i>Val( const string &vl, int64_t tm )</i> — Constructor of the value object <i>vl</i> for the time <i>tm</i>.</li></ul> <p><b>Public attributes:</b> </p> <ul><li> <i>string vl;</i> — value;</li> <li> <i>int64_t tm;</i> — value time;</li> <li> <i>uint32_t st;</i> — status code.</li></ul> <h4><span class="mw-headline" id="Server_End_Point_.28Server::EP.29"><span class="mw-headline-number">4.3.4</span> Server End Point (Server::EP)</span></h4> <p><b>Public methods:</b> </p> <ul><li> <i>EP( Server *serv );</i> — Constructor of the End Point to the Server <i>serv</i>.</li> <li> <i>virtual string id( ) = 0;</i> — Identifier.</li> <li> <i>virtual string url( ) = 0;</i> — URL.</li> <li> <i>virtual string cert( ) = 0;</i> — Certificate, by text in the PEM form.</li> <li> <i>virtual string pvKey( ) = 0;</i> — Private key, by text in the PEM form.</li> <li> <i>virtual double subscrProcPer( ) = 0;</i> — Common minimal period of the publishing and the data processing cycle.</li> <li> <i>virtual uint32_t limSubScr( );</i> — Limit for the subscriptions number.</li> <li> <i>virtual uint32_t limMonitItms( );</i> — Limit for the monitored items number.</li> <li> <i>virtual uint32_t limRetrQueueTm( );</i> — Time limit for the retransmission queue depth.</li> <li> <i>bool enableStat( );</i> — The state "Enabled".</li> <li> <i>virtual void setEnable( bool vl );</i> — Enable.</li> <li> <i>virtual void setPublish( const string &inPrtId );</i> — Initiate the conditions of calling <i>publishCall()</i> from the input stream — cyclic polling of protocol of the input transport and linking it with the EndPoint.</li> <li> <i>void subScrCycle( unsigned cntr, string *answ = NULL, const string &inPrtId = "" );</i> — Function of the subscriptions processing call cycle in the step <i>cntr</i> for responding in the function <i>publishCall()</i> of the input stream.</li> <li> <i>int secN( );</i> — Security policies number.</li> <li> <i>string secPolicy( int sec );</i> — Getting of the security policy <i>sec</i> description.</li> <li> <i>MessageSecurityMode secMessageMode( int sec );</i> — Messages security mode for the security policy <i>sec</i>.</li> <li> <i>unsigned sessN( );</i> — Sessions number.</li> <li> <i>int sessCreate( const string &name, double tInact );</i> — Session creation with the <i>name</i> and the inactivity timeout <i>tInact</i>, returns the session identifier.</li> <li> <i>void sessServNonceSet( int sid, const string &servNonce );</i> — Setting the random sequence of the server to <i>servNonce</i> for the session <i>sid</i>.</li> <li> <i>virtual uint32_t sessActivate( int sid, uint32_t secCnl, bool check = false, const string &inPrtId = "", const XML_N &identTkn = XML_N() );</i> — The session <i>sid</i> activation for link to the security channel <i>secCnl</i>, with the checking <i>check</i> to the possibility-need for reassigning after closing of the previous security channel, returns error (0 — no an error).</li> <li> <i>void sessClose( int sid );</i> — Session <i>sid</i> close.</li> <li> <i>Sess sessGet( int sid );</i> — Getting the session object <i>sid</i> copy.</li> <li> <i>Sess::ContPoint sessCpGet( int sid, const string &cpId );</i> — Getting the continuation point <i>cpId</i> of browsing for the session <i>sid</i>.</li> <li> <i>void sessCpSet( int sid, const string &cpId, const Sess::ContPoint &cp = Sess::ContPoint() );</i> — Setting the continuation point <i>cp</i> of browsing for the session <i>sid</i> and the identifier <i>cpId</i>.</li> <li> <i>uint32_t subscrSet( uint32_t ssId, SubScrSt st, bool en = false, int sess = -1, double publInterval = 0, uint32_t lifetimeCnt = 0, uint32_t maxKeepAliveCnt = 0, uint32_t maxNotePerPubl = OpcUa_NPosID, int pr = -1 );</i> — Creation/setting the subscription <i>ssId</i> for: the state <i>st</i>, the publish enabling <i>en</i>, the session <i>sess</i>, the publication interval <i>publInterv</i>, the counter of lifetime <i>lifetimeCnt</i>, the counter of keeping "alive" <i>maxKeepAliveCnt</i>, the maximum number of notifications in single publication <i>maxNotePerPubl</i>, the priority <i>pr</i>; returns the subscription identifier.</li> <li> <i>Subscr subscrGet( uint32_t ssId, bool noWorkData = true );</i> — Getting the subscription <i>ssId</i> copy, without the working data at <i>noWorkData</i>.</li> <li> <i>uint32_t mItSet( uint32_t ssId, uint32_t mItId, MonitoringMode md = MM_CUR, const NodeId &nd = NodeId(), uint32_t aid = OpcUa_NPosID, TimestampsToReturn tmToRet = TimestampsToReturn(-1), double smplItv = -2, uint32_t qSz = OpcUa_NPosID, int8_t dO = -1, uint32_t cH = OpcUa_NPosID, XML_N *fltr = NULL );</i> — Creating/setting for the monitoring item <i>mItId</i> of the session <i>ssId</i> for: the mode <i>md</i>, the node <i>nd</i>, the attribute <i>aid</i>, the timestamp profile <i>tmToRet</i>, the sampling interval <i>smplItv</i>, the queue size <i>qSz</i>, the old dropping <i>dO</i>, the client handler <i>cH</i>, the filter <i>fltr</i>; returns the monitored item identifier.</li> <li> <i>Subscr::MonitItem mItGet( uint32_t ssId, uint32_t mItId );</i> — Getting of copy of the monitoring item <i>mItId</i> for the session <i>ssId</i>.</li> <li> <i>virtual uint32_t reqData( int reqTp, XML_N &req );</i> — Handler of the data request — the request to the nodes tree of the server.</li></ul> <p><b>Protected methods:</b> </p> <ul><li> <i>XML_N *nodeReg( const NodeId &parent, const NodeId &ndId, const string &name, int ndClass, const NodeId &refTypeId, const NodeId &typeDef = 0 );</i> — Register the node <i>ndId</i> in the nodes of the server tree for: of the <i>parent</i>, of the node class <i>ndClass</i>, of the reference type identifier <i>refTypeId</i> and the definition type <i>typeDef</i>.</li> <li> <i>Sess *sessGet_( int sid );</i> — Getting a link to the session object <i>sid</i>, the access is not protected by the resource locking.</li></ul> <p><b>Protected attributes:</b> </p> <ul><li> <i>char mEn;</i> — state "Enabled";</li> <li> <i>uint64_t cntReq;</i> — requests counter;</li> <li> <i>vector<SecuritySetting> mSec;</i> — list of the security policies of the endpoint node;</li> <li> <i>vector<Sess> mSess;</i> — list of the opened sessions;</li> <li> <i>vector<Subscr> mSubScr;</i> — list of the subscriptions;</li> <li> <i>XML_N objTree;</i> — tree of nodes of the server;</li> <li> <i>map<string, XML_N*> ndMap;</i> — references map to the tree nodes;</li> <li> <i>pthread_mutex_t> mtxData;</i> — mutex of the multithreaded access locking;</li> <li> <i>Server *serv;</i> — reference to the Server — container of the endpoint object.</li></ul> <h2><span class="mw-headline" id="Private_keys_and_certificates"><span class="mw-headline-number">5</span> Private keys and certificates</span></h2> <p>For the client and server-protocol parts of OPC-UA working you need to create and to place the private key and the certificate into configuration of client or server object. In general, there will be enough to create an ordinal selfsigned certificate and a private key without password, but, for exclude warning messages, you need to add range of service fields to the certificate. That you can do taking <a class="external" href="http://oscada.org/wiki/File:OPC-UA_openssl.cnf" title="File:OPC-UA openssl.cnf">the file of configuration of the certificate creation</a> and executing next procedure: </p> <div class="mw-highlight mw-content-ltr" dir="ltr"><pre><span class="c"># Private key creation:</span> openssl genrsa -out key_c.pem -des3 -rand /var/log/messages 2048 <span class="c"># Private key without the password creation:</span> openssl rsa -in key_c.pem -out key_c1.pem <span class="c"># Selfsigned certificate creation:</span> openssl req -x509 -new -key key_c.pem -out cert_c.pem -config ./OPC-UA_openssl.cnf -days 3650 <span class="c"># Files content placing, for the file key_c1.pem to the field of private key and the file cert_c.pem to the certificate field!</span> </pre></div> <h2><span class="mw-headline" id="Notes"><span class="mw-headline-number">6</span> Notes</span></h2> <p>During implementation of the modules of supporting OPC-UA was detected several inconsistencies with the official SDK specification OPC-UA: </p> <ul><li> OPC-UA Part 6 on page 27 contains an image of a handshake to establish a secure channel. The creation message of session signed by a symmetric key of the client and encrypted by server's. In fact, both signature and encryption of the server key made.</li> <li> OPC-UA Part 4 on page 141 contains a description of the data structure signatures, where first goes the data signature, and then the string algorithm. In fact, the reverse order is implemented here.</li></ul> <h2><span class="mw-headline" id="Table_of_compatibility_of_implementations_of_OPC-UA_from_other_developers"><span class="mw-headline-number">7</span> <span id="TableOfCompat" title="#TableOfCompat">Table of compatibility of implementations of OPC-UA from other developers</span></span></h2> <table class="wikitable"> <tr> <th> Software </th> <th> Core </th> <th> Browse </th> <th> Read </th> <th> Write </th> <th> Publish </th> <th> Notes </th></tr> <tr> <td colspan="7"> <i>OpenSCADA parts</i> </td></tr> <tr> <td> OpenSCADA OPC-UA Client (libOPC_UA client part) </td> <td> + </td> <td> + </td> <td> + </td> <td> + </td> <td> + </td> <td> IO requests by XML implemented: HEL (HELLO), OPN (OpenSecureChannel), CLO (CloseSecureChannel), FindServers, GetEndpoints, CreateSession, ActivateSession, CloseSession, Read, Write, Browse, CreateSubscription, DeleteSubscriptions, CreateMonitoredItems, DeleteMonitoredItems, Publish, Poll (the special empty request of checking the input channel). Chunks implemented. </td></tr> <tr> <td> OpenSCADA OPC-UA Server (libOPC_UA server part) </td> <td> + </td> <td> + </td> <td> + </td> <td> + </td> <td> + </td> <td> The requests implemented: HELF, OPNF, CLOF, MSGF: FindServers, GetEndpoints, CreateSession, ActivateSession, CloseSession, CreateSubscription, ModifySubscription, DeleteSubscriptions, MonitoredItems, ModifyMonitoredItems, SetMonitoringMode, DeleteMonitoredItems, SetPublishingMode, TranslateBrowsePathsToNodeIds, RegisterNodes, UnregisterNodes, Browse, BrowseNext, Read, Write, Publish, Republish. Chunks implemented. </td></tr> <tr> <td colspan="7"> <i>Clients</i> </td></tr> <tr> <td> UAExpert 1.2, 1.3 </td> <td> Pass </td> <td> Pass </td> <td> Pass </td> <td> Pass </td> <td> Pass </td> <td> </td></tr> <tr> <td> Indusoft web studio 7.1 </td> <td> Pass </td> <td> Pass </td> <td> Pass </td> <td> Pass </td> <td> Pass </td> <td> </td></tr> <tr> <td> Iconics genesis64 10.8 </td> <td> Pass </td> <td> Pass </td> <td> Pass </td> <td> Pass </td> <td> Pass </td> <td> </td></tr> <tr> <td> Insat masterscada 3.7 </td> <td> Pass </td> <td> Pass </td> <td> Pass </td> <td> Pass </td> <td> Pass </td> <td> </td></tr> <tr> <td> <a class="external text" href="https://opcfoundation.org/developer-tools/developer-kits-unified-architecture/sample-applications" rel="nofollow noreferrer noopener" target="_blank">Sample Applications of Unified Architecture</a> </td> <td> Pass </td> <td> Pass </td> <td> Pass </td> <td> <span style="color: blue">Not tested</span> </td> <td> Pass </td> <td> </td></tr> <tr> <td> Wonderware System Platform </td> <td> Pass </td> <td> Pass </td> <td> Pass </td> <td> <span style="color: blue">Not tested</span> </td> <td> Pass </td> <td> Result mask processing fix into the service "Browse" for nodes of OpenSCADA data model. ... </td></tr> <tr> <td> Kepware </td> <td> Pass </td> <td> Pass </td> <td> Pass </td> <td> Pass </td> <td> Pass </td> <td> Specific value types OpcUa_IntAuto and OpcUa_UIntAuto was added for adaptive integer type selection, mostly for provide integer not fixed as int64. Time stamp was removed from "Write" package but the client tell 0x80730000(OpcUa_BadWriteNotSupported) </td></tr> <tr> <td> UAExpert 1.4 </td> <td> Pass </td> <td> Pass </td> <td> Pass </td> <td> Pass </td> <td> Pass </td> <td> Packages sequence number split from it request and set self managing. </td></tr> <tr> <td> UAExpert 1.5 </td> <td> Pass </td> <td> Pass </td> <td> Pass </td> <td> Pass </td> <td> Pass </td> <td> The Server code cleaned from inconsistency of the data types and the types appended for declaration own OpenSCADA types OpcUa_IntAuto and OpcUa_UIntAuto. </td></tr> <tr> <td colspan="7"> <i>Servers</i> </td></tr> <tr> <td> IgnitionOPC_UA </td> <td> Pass </td> <td> Pass </td> <td> Pass </td> <td> <span style="color: blue">Not tested</span> </td> <td> <span style="color: blue">Not tested</span> </td> <td> </td></tr> <tr> <td> B&R Embedded OPC-UA Server </td> <td> Pass </td> <td> Pass </td> <td> Pass </td> <td> Pass </td> <td> Pass </td> <td> <ul><li> the authenticate process fixed by the server provides self specific identifiers to its. The string of bytes wrong interpretation fixed;</li> <li> 2021.05: has limits on direct reading by the service request "Read", so that was an initiator of implementing the service request "Publish" and Chunks for the Client part, UAExpert 1.5 adaption, significant refactoring and the document complete revision.</li></ul> </td></tr></table> <p><br /> </p> <h2><span class="mw-headline" id="Links"><span class="mw-headline-number">8</span> Links</span></h2> <ul><li> <a class="external" href="http://oscada.org/wiki/File:OPC-UA_libOPCUA_class.odg" title="File:OPC-UA libOPCUA class.odg">Diagram: Static class diagram of the library libOPC_UA.</a></li> <li> <a class="external" href="http://oscada.org/wiki/File:OPC-UA_openssl.cnf" title="File:OPC-UA openssl.cnf">File of configuration of the certificate creation for OPC-UA.</a></li></ul> </div><table style="border-top: dotted 2px #999999; margin-top: 20pt; color: gray;" width="100%"><tr><td style="text-align: left;" width="40%"><a href="http://oscada.org/wiki/Modules/OPC_UA/en">Modules/OPC_UA/en</a> - <a href="http://oscada.org/en/main/about-the-project/licenses/">GFDL</a></td><td style="text-align: center;">April 2025</td><td style="text-align: right;" width="40%">OpenSCADA 1+r3018</td></tr></table></body> </html>