Modules/UserProtocol - OpenSCADAWiki

# Modules/UserProtocol

English • ‎mRussian • ‎Українська

Module | Name | Version | License | Source | Languages | Platforms | Type | Author | Description
--- | --- | --- | --- | --- | --- | --- | --- | --- | ---
UserProtocol | User protocol | 1.6 | GPL2 | prot_UserProtocol.so | en,uk,ru,de | x86,x86_64,ARM | Protocol | Roman Savochenko Maxim Lysenko (2010) — the page initial translation | Provides for creating your own user protocols on internal OpenSCADA language.

The module is designed to allow the user to create own implementations of different protocols in internal OpenSCADA language, usually JavaLikeCalc, without involving low level programming.

The main purpose of the module is to simplify the task of connecting devices of data sources to OpenSCADA, that have limited distribution and/or provide access to their own data on a specific protocol that is usually fairly simple to implement in the internal language of OpenSCADA. For implementation of this the mechanism for the formation of the output request protocol is provided.

In addition to the mechanism of the output request protocol the mechanism for input request protocol is provided, which allows OpenSCADA to process the requests for data get on specific protocols, which simply can be implemented in the internal language of OpenSCADA.

The module provides the ability to create multiple implementations of different protocols in the object "User protocol" (Fig.1), and also use standard DAQ templates for that. Using DAQ templates allows you to create complex protocols' libraries and call them in this module multiple times as their implementations, as well as provide the data context of the input template with their connection to the data of the subsystem "Data Acquisition".

Fig.1. Main tab of an object of the module "User protocol".

The main tab contains the basic settings of the user protocol:

- Section "State" — contains properties that characterize the state of the protocol: Status, "Enabled", the name of the database (containing the configuration and with tracking the availability of the data in different storages and providing the sequentially removing duplicates) and date of the last modification.
- Identifier, name and description of the protocol.
- The state "Enabled", in which the protocol must be translated at boot.
- DAQ-template related to the protocol. Selecting a template here turns off the mode by the direct procedures and access the following options. The DAQ-template mode can work in input, output or both of the requesting modes, related to the required attributes presence.
- An indication of the complete translation of the procedures text and the language of the input and output procedures. Selecting a language for the input and/or output procedure will enable the appropriate part of the protocol and access the corresponding configuration tabs.

## 1 Input part of the protocol

The input requests protocol is working in cooperation with the input transport and the separate object "User Protocol" is pointing in the configuration field of protocol of the transport, together with the UserProtocol module's name. Further, all transport requests will be directed to the direct procedure, or the template procedure, of the protocol request processing (Fig. 2).

Fig.2. Tab of the configuration and the controlling for the input requests.

Tab of the configuration and the controlling of the input requests contains:

- Timeout of a request waiting, in milliseconds. Used to enable the pooling mode, setting to a nonzero value. In the pooling mode, the incoming transport will call the protocol with the empty request, in the absence of a request within the specified time.
- Table of data context for the input request procedure. Preferably, it makes sense only when working on a template and where you can control this processing, including the possibility of intruding through the data values changing.
- The text of the direct procedure of the protocol, missed in the mode of work on the template.
- Links to the data of the "Data Acquisition" subsystem, which are visible and available for determination in the mode of work on the template and in the state "Enabled" of the protocol object.

For the direct processing procedure, and the required or optional ones to create in the template, the following exchange attributes with the input transport are predetermined:

- Input result (rez) <Boolean> — processing result (false — full request; true — not full one, holding the connection); in the DAQ-template mode you must write thither directly, not by the operator "return";
- Input request (request) <String> — full-accumulated request message, what protocol should clear about processed data;
- Input answer (answer) <String> — answer message;
- Input sender (sender) <String> — request sender;
- Transport (tr) <Object> — input transport object;
- This object (this) <Object> — pointer to this protocol's object;
- Scheduling the next service call (schedCall) <Integer> — write here the time value in seconds for scheduling the procedure context execution in a service call; the service calls are performed in the periodicity 10 seconds usually, so you can schedule the calls not often than at 10 seconds.

The overall scenario of the input requests processing:

- Request is formed by the remote station and through the network it gets on the transport of OpenSCADA.
- OpenSCADA transport sends the request to this module, selected in the protocol's field, and to an object of the user protocol, in the form of the variable's "request" values — for the request sequence and "sender" — for the sender address of the request.
- The execution of the procedure of the input request protocol is started, during which the contents of the variable "request" is analyzed and the response in the variable "answer" is formed. At the end of the procedure's execution the variable "rez" is formed, which indicates the transport to the fact of reception of full request and the formation of the correct answer (false) or to the necessity for the transport to expect for the remaining data (true) — holding the connection.
- If the processing result is "false" and the answer is non-zero, the transport sends the response, and the protocol procedure itself must remove the processed part of the "request", because only it can determine the integrity of the package and the potential presence of it for the beginning of the next one.
- If the result of the processing procedure is "true" then transport continues to wait for the data. When the next portion of the data is received, they are added to the "request" variable and the procedure is repeated.

As an example, let's consider the implementation of DCON request processing for some requests to a data source with the address "10":

    var enCRC = true;
    //SYS.messDebug("/DCON/in","REQ: "+request);
    //Testing the request for completity
    if(request.length < 4 || request[request.length-1] != "\r") {
      if(request.length > 10) request = "";
      return true;
    }
    //Checking the request for the integrity (CRC) and the address
    if(enCRC) {
      CRC = 0;
      for(i = 0; i < (request.length-3); i++) CRC += request.charCodeAt(i);
      if(CRC != request.slice(request.length-3,request.length-1).toInt(16) || request.slice(1,3).toInt(16) != 10) return false;
    }
    //Analysis the request and the response preparing
    if(request[0] == "#") answer = ">+05.123+04.153+07.234-02.356+10.000-05.133+02.345+08.234";
    else if(request[0] == "@") answer = ">AB3C";
    else answer = "?";
    //Finishing the response
    if(enCRC) {
      CRC = 0;
      for(i=0; i < answer.length; i++) CRC += answer.charCodeAt(i);
      answer += (CRC&0xFF).toString(16,2)+"\r";
    }
    //SYS.messDebug("/DCON/in","ANSV: "+answer[0]);
    return 0;

## 2 Output part of the protocol

The output requests protocol is working in cooperation with the output transport and with the separate object of the "User Protocol". The source of the request through the protocol may be a function of the system-wide API of the user programming of the output transport "int messIO(XMLNodeObj req, string prt );", in the parameters of which it must be specified:

- req — request as an XML tree with the structure corresponding to the input format of the implemented protocol;
- prt — name of this module — "UserProtocol".

The request which is sent with the aforesaid way is directed to the direct procedure of the protocol's request processing (Fig. 3), or to the template procedure, with the user protocol's ID which is specified in the attribute req.attr("ProtIt").

Fig.3. Tab of a direct procedure of the output requests processing.

The processing procedure tab for output requests contains only text field of direct processing procedure for an internal programming language OpenSCADA, which are pointed in the previous tab. This tab is missing for the template mode.

For the direct processing procedure, and the required or optional ones to create in the template, the following exchange attributes are predetermined:

- Output IO (io) <Object::XMLNode> — XML node of the exchange with the client, through which the protocol gets the requests and into which it puts the result with the format implemented in the procedure;
- Transport (tr) <Object> — the transport object, provided to call the transport function string messIO( string mess, real timeOut = 1000 ); — tr.messIO(req), is blocked during the procedure call.

The overall scenario of the output request formation:

- Building of the XML-tree in accordance with the structure, implemented by the protocol, and setting of the user protocol identifier in the attribute "ProtIt".
- Sending the request to the transport through the protocol — "SYS.Transport["{Modul}"]["out_{OutTransp}"].messIO(req, "UserProtocol");".
- Selection of the user protocol in accordance with req.attr("ProtIt") and initialization of variables of the output transport: io — respectively to the first argument messIO() and tr — object of the "OutTransp".
- Calling the procedure for execution, which, after the processing the io structure, forms the direct request to the transport tr.messIO(req);, result of which is processed and put back to io.

The meaning of separating the protocol part of a code into the procedure of a user protocol or template is to simplify and unify the client exchenge interface for multiple use and foresees the formation of an XML-node structure in the form of attributes of remote station addresses, addresses of read and written variables, as well as the values of the variables themselves. The entire work of direct coding of the request and decoding of the response is assigned to the user protocol procedure. If this is a one-time implementation, which in addition does not involve the implementation of the input part, it is easier to do it immediately in the original template to the data source, in the form of a built-in function.

As an example, consider the implementation of the requests by the protocol DCON to the handler, implemented in the previous section. Let's start with the implementation of the protocol part:

    //Preparing the result request
    request = io.name().slice(0,1) + io.attr("addr").toInt().toString(16,2) + io.text();
    if(io.attr("CRC").toInt()) {
      CRC = 0;
      for(i = 0; i < request.length; i++) CRC += request.charCodeAt(i);
        request += (CRC&0xFF).toString(16,2) + "\r";
    }
    else request += "\r";
    //Sending the request
    resp = tr.messIO(request);
    while(resp[resp.length-1] != "\r") {
      tresp = tr.messIO("");
      if(!tresp.length) break;
      resp += tresp;
    }
    //Analysis the response
    if(io.attr("CRC").toInt()) {
      if(resp.length < 4 || resp[resp.length-1] != "\r") { io.setAttr("err","10:"+tr("Error or no response.")); return; }
      //Checking the response to the integrity (CRC)
      CRC = 0;
      for(i = 0; i < (resp.length-3); i++) CRC += resp.charCodeAt(i);
        if(CRC != resp.slice(resp.length-3,resp.length-1).toInt(16)) { io.setAttr("err","11:"+tr("CRC error.")); return; }
    }
    else if(resp.length < 2 || resp[resp.length-1] != "\r") { io.setAttr("err","10:"+tr("Error or no response.")); return; }
    if(resp[0] != ">") { io.setAttr("err","12:"+resp[0]+":"+tr("DCON error.")); return; }
    //Returning the result
    io.setAttr("err","");
    io.setText(resp.slice(1,resp.length-3));

And a procedure of sending the DCON request directly, through the previous protocol procedure. This procedure should be placed in the desired task or an interim function of OpenSCADA, for example, in the procedure of the controller object DAQ.JavaLikeCalc:

    //Preparing the first request
    req = SYS.XMLNode("#").setAttr("ProtIt","DCON").setAttr("addr",10);
    //Sending the request
    SYS.Transport["Serial"]["out_TestDCON"].messIO(req,"UserProtocol");
    if(!req.attr("err").length) SYS.messDebug("TEST REQ","RES: "+req.text());

    //Preparing the second request
    req = SYS.XMLNode("@").setAttr("ProtIt","DCON").setAttr("addr",10);
    //Sending the request
    SYS.Transport["Serial"]["out_TestDCON"].messIO(req,"UserProtocol");
    if(!req.attr("err").length) SYS.messDebug("TEST REQ","RES: "+req.text());

Modules/UserProtocol/en - GFDL | May 2026 | OpenSCADA 0.9.9