Author: Roman Savochenko
Translated: Maxim Lysenko
Open SCADA system OpenSCADA belongs to the class of SCADA (Supervisory Control and Data Aquisition) systems. Systems of this class are used as an element of automation of technological processes (ACS TP).
In some cases, SCADA systems can be used at the controller level, combining the functions of the controller with the functions of SCADA systems.
To organize the users' calculations if the area of industrial controllers and SCADA systems the different programming languages are used. In the case of controllers the low-level languages (assemblers) are often used, but in recent years the high-level languages (C, Pascal and others) are used more and more, as well as formal languages (block scheme, relay scheme, logic scheme and others). In the case of SCADA systems the calculations most of all are provided by the high-level programming languages and formal languages.
Providing the user programming area by any software system in general is an important indicator of quality and maturity ùof the system.
This project is provided to develop the programming area of the OpenSCADA system.
Functionally the development is intended to create in OpenSCADA system the components of programming are with which you can implement various calculations and control algorithms within the OpenSCADA system.
Operating appointment of the development is:
Under the architectural requirements it is meant with what structure the development should follow.
The peculiarity of the OpenSCADA system architecture imposes the relevant requirements to the development's architecture. Thus, taking into account the modularity, flexibility and scalability of the OpenSCADA system, it is necessary to ensure these characteristics with this development.
With this purpose the programming area architecturally can be divided into three parts:
Objects of functions should contain only the structure of functions' parameters and computation's algorithm. The real values must be passed to the functions' object in the form of values' frame by different computation controllers and nodes.
Declaring objects must be contained in the OpenSCADA kernel to provide the access to all components of the programming area.
Values' frames that pass to the functions' objects in during the calculations should be stored in the nodes that require the calculations. These nodes can be:
Lets show the requirements for the programming area, based on the architectural requirements, which require the separation of the programming area into three parts.
The OpenSCADA system core must provide:
Within the project it must be implemented the following function libraries and calculation controllers:
Module(s) of the static functions' libraries must provide:
Module of the calculator on the high-level programming language and the module of the functions' libraries on this language should provide:
Module of the calculator on the block's language must provide:
To implementation of the calculator module on the high-level programming language and the module of functions' libraries on the same language you must use the grammar of one of the known high-level languages.
Program in the chosen language must be compiled into the code of the internal virtual machine. The main requirements for the virtual machine are: high reliability and performance. To get the high reliability of the virtual machine it must contain mechanisms for accounting and limiting the calculation time.
It is obligatory to be implemented the following features of programming language:
Language of the block schemes can be based on the available functions of functions' libraries of the object model of OpenSCADA. Each block may be associated with the function and form the structure of values in accordance with the structure of function. Each block must ensure the inclusion and exclusion from the processing action, not stopping the calculation of the whole scheme.
To tie(link) the blocks with one another the support for the following types of links must be provided:
Links must maintain their "hot" in the process of calculating setting.
Any complex software system should contain a programming area. The presence of such an area significantly enhances the flexibility of the system and, consequently, the scope of its application. Programming area, which is used in such software systems, may be based on different programming languages. However, the most commonly used languages, endowed with a high level of formalism, for example, languages of blocks (block schemes, logical schemes, relay schemes and others). But, together with them the high-level languages such as C and C++ in its simplified reincarnation: Java and JavaScript are frequently used. Sometimes the languages of the logical output: Prolog and Lisp are also used.
OpenSCADA system is developed as the flexible and highly scalable SCADA system, so creating of own programming area is an important task. The main purpose of creating the user programming area is to provide the OpenSCADA system with the flexible and powerful programming mechanism.
In addition, a programming area is designed to provide an opportunity for creation of:
The key element of the programming area as an object the function is selected, where the function is defined as the container that contains the data structures (parameters) and an algorithm for their calculation. The parameters can be both inputs and outputs. This somewhat simplified object structure that combines the object with the mechanism, thus simplifying the initial perception and the creation of the programming area. In addition, this choice does not exclude the possibility of creation of the full-fledged object model (OM) in the future.
That is, we have an elementary module - Figure 1.
Where:
As you can see, this module does not contain the states, because it does not store any values of inputs or outputs. Adding the state, as the current context, the module receives in the so-called calculators. This scheme allows the single module of the function to use in various modules of the calculators (Fig. 2).
To implement high-level language it is necessary to define the language to be used as the basis. Based on the principle that language must be sufficiently well-known and, if possible, be used by other projects as the internal language of calculation, lets examine the following languages: C, C++, Java, JavaScript and Phyton. Since C, C++, Java and JavaScript is practically came from the language C, we'll take into account the languages C++, Java and JavaScript. Language C++ is somewhat complicated, because it contains mechanisms to work with addresses and pointers. These opportunities are abundant for the tasks of the user programming area.
Lets stop on the languages of Java and JavaScript, which have simplified grammar. First, we'll implement the common grammar for Java and JavaScript with the further tendency to the language of JavaScript, since it is often used in other projects (Web-browser, KDE).
We know that to build a compiler or interpreter you need to create a lexical analyzer, parser and code generator or interpreter.
The lexical analyzer is constructed quite simply.
The parser is based on the concept of formal grammars and its creation - a nontrivial task. Therefore, there are ready-made tools to build a parser with the specified grammar. They include the parser's generator Yacc (AT&T and Berkeley). On the basis of this well-known parser generator many others are created, such as Bison and Zubr. All of them are compatible and can replace one another.
To develop the programming language the parsers' generator Bison was chosen, because it is distributed freely with almost all modern distributions of OS Linux, is developing and is multiplatform.
Any formal grammar can be written as:
G = <A, N, ã, P>
where :
Lets write the terminal and nonterminal alphabets:
A = {ERR, IF, ELSE, =, ADDEQ, SUBEQ, MULEQ, DIVEQ, FUNC, B_FUNC, B_FUNC1, B_FUNC2, VAR, CONST, ?, :, OR, AND, |, &, ^, >, <, GE, LE, EQ, NE, +, -, *, /, %, UN_MINUS, !, , ',', (, ), '{', '}', ; }
N = {root, solver, solve,assign, expr, prmlst, if, if_expr, end }
Description of the terminal alphabet is given in Table 1. Description of the nonterminal alphabet is given in Table 2. P grammar rules are given in Table 3. As the axioms of grammar it is defined: r = root;
Table 1: Terminal alphabet of the Java-like language (A)
Terminal | Description |
ERR | Error. Is injected by the lexical analyzer in case of an error in it. |
error | Error. Terminates the job of parser. |
IF | Keyword of the condition - “if”. |
ELSE | Keyword of the condition - “else”. |
= | Operation - to assign. |
ADDEQ | Operation - “+=” |
SUBEQ | Operation - “-=” |
MULEQ | Operation - “*=” |
DIVEQ | Operation - “/=” |
FUNC | External function. |
B_FUNC | Built-in function without parameters. |
B_FUNC1 | Built-in function with one parameter. |
B_FUNC2 | Built-in function with two parameters. |
VAR | Variable, automatic variable, attribute of the system parameter or a function's parameter. |
CONST | Constant. |
? | The first character of the operation “?:” |
: | The second character of the operation “?:” |
OR | Logical operation - “||” |
AND | Logical operation - “&&” |
| | Operation - bitwise OR |
& | Operation - bitwise AND |
^ | Operation - exclusive OR |
> | Operation - more. |
< | Operation - less. |
GE | Operation - more than or equal. |
LE | Operation - less than or equal. |
EQ | Operation - equivalent. |
NE | Operation - not equivalent. |
+ | Operation - addition. |
- | Operation - subtraction. |
* | Operation - multiplication. |
/ | Operation - division. |
% | Operation - the remainder in integer division. |
UN_MINUS | Operation - unary minus. |
! | Operation - inversion. |
~ | Operation - bitwise inversion. |
, | Separator (separates the parameters ôin functions). |
( | Select the priority in expressions and function's parameters. |
) | Select the priority in expressions and function's parameters. |
{ | Select the expressions block. |
} | Select the expressions block. |
; | Completion of the expression. |
Table 2: Nonterminal alphabet of the Java-like language (N)
Not terminal | Description |
root | Root. All expressions must be turn to it. |
solver | Solution. |
solve | Element of the solution. |
assign | Assignment. |
expr | Expression. |
prmlst | Function's parameters list. |
if | Condition. |
if_expr | Condition expression. |
end | End of the condition or of the program. |
Table 3: Grammar of Java-like language
Rule | Description |
root: solver end | error | solution and end of the program; error. |
solver: /*empty*/ | solver solve | empty solution; recursion of the solution. |
solve: assign ';' | IF '(' expr ')' if solve end | IF '(' expr ')' if solve end ELSE solve end | FUNC '(' prmlst ')' ';' | '{' solver '}' | assignment; global short condition; global full condition; procedural call of the the outer function; blocks of code in brackets “{“ “}”. |
assign: VAR '=' expr | VAR ADDEQ expr | VAR SUBEQ expr | VAR MULEQ expr | VAR DIVEQ expr | simple assignment; assignment with the addition; assignment with the subtraction; assignment with the multiplication; assignment with the division. |
expr: CONST | VAR | VAR '=' expr | B_FUNC '(' ')' | B_FUNC1 '(' expr ')' | B_FUNC2 '(' expr ',' expr ')' | FUNC '(' prmlst ')' | expr '+' expr | expr '-' expr | expr '*' expr | expr '/' expr | expr '%' expr | expr '|' expr | expr '&' expr | expr '^' expr | '(' expr ')' | expr OR expr | expr AND expr | expr '<' expr | expr '>' expr | expr GE expr | expr LE expr | expr EQ expr | expr NE expr | '!' expr | '~' expr | '-' expr | expr if_expr expr end ':' expr end | constant; variable; assigning the variable inside an expression; built-in function without parameters; built-in function with one parameter; built-in function with two parameters; external function; addition; subtraction; multiplication; division; remainder of integer division; bitwise OR; bitwise AND; bitwise exclusive OR; brackets in the expression; logical OR; logical AND; less; more; more and equal; less and equal;; equal; not equal; logical negation; bitwise inversion; unary minus; condition within an expression; |
prmlst: /*empty*/ | expr | prmlst ',' prmlst | empty list of parameters; expression as a parameter; list of parameters through “,”. |
if: /*empty*/ | Start of the conditions (for condition's code generation). |
if_expr: '?' | Start of the conditions inside the expression. |
end: /*empty*/ | End of program or of the condition. |
Based on these rules we can construct a parser. However, the parser needs the lexical analyzer, which should perform an analysis of the stream of the input program, to allocate the lexemes and give them to the parser.
We'll make the lexical analyzer, which should perform the following functions:
To simplify the language we'll use an implicit definition of local variables, which implies the definition of new variables, while giving it the first value. In addition, the type of local variable must be set in accordance with the type of value, which was firstly assigned to it. For example, the expression <Qr=Q0*Pi+0.01;> must define the variable type of variable Qr as the type of Q0.
In working with various types of data we'll user the mechanism of automatic casting in places where such casting has sense.
To comment the sections of code the characters «//» is provided. Everything that is after these characters until the end of the line should be ignored by the compiler (lexical analyzer).
Lets foresee that in the process of code generation of the virtual machine, compiler performs the optimization on the constants, and casts the constants' types to the desired one.
The optimizing on constant means the making of calculations on the two constants in the process of building the code and following pasting the result into the code. For example, the expression <y=pi*10;> should roll up to the simple assignment <y=31.4159;>.
The casting the constants' to the desired type is the formation the constant in the code, which eliminates the cast in the execution process. For example, the expression <y=x*10> in the case of a real type of variable <x>, must be transformed into <y=x*10.0>.
As a result of the development there are implemented the following elements of programming language:
Key words: if, else, true, false.
Constants:
Variables' types:
Built-in constants: pi = 3.14159265, e = 2.71828182.
Attributes of the system's parameters OpenSCADA.
Functions of the object model of the system OpenSCADA.
Operations, which will be supported by the programming language are presented in Table 4. The priority of operations is reduced from the top to the bottom. Operations with the same priority will be in one color group.
Table 4. Operations of the Java-like language
Character | Description |
() | Call of the function. |
{} | Program blocks. |
- | Unary minus. |
! | Logical negation. |
~ | Bitwise negation. |
* | Multiplication. |
/ | Division. |
% | The remainder of integer division. |
+ | Addition |
- | Subtraction |
> | More |
>= | More or equal |
< | Less |
<= | Less or equal |
== | Equal |
!= | Unequal |
| | Bitwise "OR" |
& | Bitwise "AND" |
^ | Bitwise "Exclusive OR" |
&& | Logical "AND" |
|| | Logical "OR" |
?: | Conditional operation (i=(i<0)?0:i;) |
= | Assignmentå. |
+= | Assignment with the addition. |
-= | Assignment with subtraction. |
*= | Assignment with multiplication. |
/= | Assignment with division. |
To provide high speed in mathematical calculations module provides built-in mathematical functions that are called on the instruction-level of the virtual machine. Built-in math functions:
The language supports two types of conditional operators. First - this is the conditional operator for use inside an expression, the second is the global one.
Conditional operator for use inside an expression based on the operations "?" and ":". As an example, we can write the following practical expression <st_open=(pos>=100)? True:false;>, which reads as "If the variable <pos> greater than or equal to 100, the variable <st_open> is set to "true", otherwise to "false".
The global condition is based on the keywords "if" and "else". As an example, the same expression, but otherwise <if(pos> 100) st_open = true; else st_open = false;>. As can be seen, it is recorded in the different way, but it reads equally.
Here are some examples of programs on the developed Java-like language:
//Model of the motion of the ball valve
if( !(st_close && !com) && !(st_open && com) )
{
tmp_up=(pos>0&&pos<100)?0:(tmp_up>0&&lst_com==com)?tmp_up-1./frq:t_up;
pos+=(tmp_up>0)?0:(100.*(com?1.:-1.))/(t_full*frq);
pos=(pos>100)?100:(pos<0)?0:pos;
st_open=(pos>=100)?true:false;
st_close=(pos<=0)?true:false;
lst_com=com;
}
//Valve model
Qr=Q0+Q0*Kpr*(Pi-1)+0.01;
Sr=(S_kl1*l_kl1+S_kl2*l_kl2)/100.;
Ftmp=(Pi>2.*Po)?Pi*pow(Q0*0.75/Ti,0.5):(Po>2.*Pi)?Po*pow(Q0*0.75/To,0.5):pow(abs(Q0*(pow(Pi,2)-pow(Po,2))/Ti),0.5);
Fi-=(Fi-7260.*Sr*sign(Pi-Po)*Ftmp)/(0.01*lo*frq);
Po+=0.27*(Fi-Fo)/(So*lo*Q0*frq);
Po=(Po<0)?0:(Po>100)?100:Po;
To+=(abs(Fi)*(Ti*pow(Po/Pi,0.02)-To)+(Fwind+1)*(Twind-To)/Riz)/(Ct*So*lo*Qr*frq);
The result of work of the parser with the lexical analyzer may be the directly interpretation (the program execution) or generation of the code inside the virtual machine.
Interpretation does not require additional efforts to develop the virtual machine and is a good solution in the case of not very demanding algorithms.
Virtual Machine allows you to implement high-performance computings by means of optimizing the code and exception of the superfluous analysis of lexical and syntactic analyzers, however, it requires considerable efforts to be developed.
As there is the paragraph in the development conditions, that requires providing of high-performance computings, then we'll stop on the development of the virtual machine.
There are many ways of constructing a virtual machine, one can note:
Stack machines are the convenient way to build the virtual machine. The feature of the stack virtual machine is:
The disadvantage of stack machines is that the stack is a dynamic structure to work with which a lot of time is spent on, in addition, to implement the memory for static figures in a separate computing session it must be provided the separate data structure.
Another class of virtual machines are virtual machines, based on the so-called quadruples. The essence of the quadruples is that the command consists of: <code> <result> <operand1> <operand2>
Where the result and the operands are references to registers of memory or structures. Code of the virtual machine of this class is somewhat more, but the structure of memory is static and can combine the functions of storage of static and dynamic calculations' data. Therefore, to build the virtual machine we'll choose the scheme based on quadruples.
All data in the virtual machine will be placed in registers. Register of the virtual machine must provide the structure that can store the following data:
Commands of the built virtual machine is given in Appendix A. The mechanism of the virtual machine's work will be as follows:
The parser allocates the commands and generates code in the semantic procedures of Bison. During the code generation virtual machine forms the list of registers. Registers, which contain references to the parameters of this function, attributes of parameters of the subsystem "DAQ" and internal variables, are to be initialized during code generation and no longer be used for other purposes. Other registers (dynamic data of the intermediate calculations) should be set aside and used for temporary purposes. Such registers are initiated by specific values at runtime of the program in the virtual machine. The resulting configuration of registers (the structure of memory) and the program code of virtual machine are used in the mode of calculating of the virtual machine. At the same time the configuration of registers does not change that allows to use of rapid mechanisms for access to registers and for the primary initialization of the registers' frame.
For addressing of the registers it used the one byte, which provides support for up to 255 parameters of the function (in the amount with internal variables).
Languages of the block programming based on the concept of block diagrams. With that, depending on the nature of the block, block scheme can be: logic circuits, relay logic circuits, the model of technological process and more. The essence of the block scheme is that it contains the list of blocks and links between them.
From the formal point of view the block is an element which has inputs, outputs and an algorithm for computing. Based on the concept of the programming area and its basis (Fig. 2), block is the frame of parameters' values, associated with the function's object.
Of course, the inputs and outputs of blocks it is necessary to connect to get the whole block scheme. The following types of links will be provided:
Ñonnections of blocks can be represented as links between the blocks as a whole (Fig. 3) or detail of the links (Fig. 4). In the process of binding the parameters of the blocks we will not adhere to strict compliance with types of parameters. This means that the parameters of different types can easily communicate with one another. And in the process of calculation it will be performed automatically casting.
Since the block calculator is based on the objects of the functions of an object model of the OpenSCADA system, then the parameter types of blocks are the same, that is: an integer, real, boolean and string.
Based on the modular architecture of OpenSCADA system and reflections contained in the sections above, it was developed the following architecture of the programming area (Fig. 5).
As you can see, the architecture of the programming area consists of three parts:
This architecture of the programming area allows to distribute the process of creation and using. That is, the algorithms for computing in the form of functions' objects are provided by the one components, and are used for the calculations by the other ones.
In such a scheme there should be a layer that combines the components that provide algorithms with components that use them, which is especially important in the light of the fact that these components can be separated from the system, that is to by the modules. This layer should be the API of an object model of OpenSCADA system.
Based on the structure of the programming area, lets create classes of objects. Static class diagram with the separation of each component of the programming area is shown in Figure 6. Classes description is given in Table 5.
Table 5. Classes of the programming area
Class | Responsibility | Links |
TFunction | The class of the function. It contains the description of the parameters (IO). In the ancestor it must include the implementation of the function's algorithm. | It is used be the calculators to associate it with the frame of values. It is the abstract, inherited by components that provide their own functions' libraries. |
TValFunc | Class of the function's values. Contains the values of function in accordance with the composition of the parameters (IO) of the TFunction class. | It is aggregated with the object of the function TFunction for collaborative computing. It can inherited by classes of the calculator. An instance of the TValFunc class passed to the TFunction class during the computation to execute the algorithm in TFunction over the values in TValFunc. |
IO | The class of the function's parameter. It contains the description of the parameter, its type and attributes. | It is used by the class of TValFunc values to determine the values of parameters. |
UserLib | Class of the user's library . | It may provide the tool for creating user's functions. |
UserFunc | Class of the user's functions. It provides the function's parameters and the computing algorithm. | It inherits the function's TFunction class. |
Block | User's calculator class. It contains associated with the function TFunction frame of TValFunc values. It executes the process of calculating | It inherits the values frame class . |
Based on the structure of the programming area (Fig. 5) and its class diagram (Fig. 6), we'll create classes of the calculator on the Java-like language (Fig. 7). Description of the classes is given in Table 6.
Table 6. Classes of the JavaLikeCalc module
In order to provide the directly calculation it must be provided the creation and linkage of the controller with the function of the same module. For the linkage with the function in the controller it is created the frame of values TValFunc, over which the periodic calculations are made.
To export the obtained values from the controller in the OpenSCADA system and to import values from the system to the controller the parameters of the controller of subsystem "DAQ" must be used. The parameters of the controller associated with the parameter of computing function (field of the data table) and must comply the reflection of values.
Based on the structure of the programming area (Fig. 5) and its class diagram (Fig. 6), lets create the classes of calculator on the blocks language (Fig. 8). Description of the classes is given in Table 7.
Table 6. Classes of the BlockCalc module
Class | Responsibility | Links |
TipContr | Root class of the module, the main purpose of which is the access point into the module. | Inherits the class of the interface of the modules of subsystem 'Data sources' TTypeDAQ for integration into the OpenSCADA system. |
Contr | The class of implementation of the controller. It contains the mechanism of periodic calculations over the algorithm of block scheme. | Inherits the controller's interface class TController. Contains the blocks of the block scheme. |
Prm | The class of the implementation of parameter of subsystem "DAQ". It contains the mechanism of reflection of parameters of blocks of block scheme on the structure of parameter of the subsystem "DAQ" of OpenSCADA system. | Inherits the class of the interface of the parameter TParamSontr. It contains the links to the parameter of the block of block scheme. |
Block | The class of the block. It contains the frame of values in accordance with the associated function. It contains the mechanism of links. | Inherits the class of the interface of values' frame TValFunc. It is referenced by the object of the parameter's class (Prm). Instances of the class of this type may contain links to one another. |
Each controller of this module contains the block scheme, which it should calculate in accordance with specified intervals.
The blocks in this case does not contain the structure of inputs/outputs (IO), but only contain the values based on the structure of the parameters of linked function. To connect with the block any functions of the object model (OM) of the OpenSCADA system can be used.
To provide an opportunity to export values from the block scheme to the OpenSCADA system lets envisage the possibility of reflecting the attributes of blocks on the parameters of the controller of the OpenSCADA system. Similarly, the values from the OpenSCADA system can get to the block scheme of the controller.
Based on the structure of the programming area (Fig. 5) and its class diagram (Fig. 6), lets create the architecture of classes for libraries of static functions (Fig. 9). Description of the classes is given in the Table 8.
Table 7. Classes of the static library of functions
Class | Responsibility | Links |
Lib | Root class of the module, the main purpose of which is the access point to the module. Serves as the library, and thus contains objects of static functions. | Inherits the class of the interface of modules of subsystem "Specials" TSpecial for integration into the OpenSCADA system. It contains the function objects. |
Func | The class of functions. It contains the structure of parameters and the algorithm of their calculation. | Inherits the class of the interface of function TFunction. |
Based on this architecture there are constructed the following static libraries of functions:
Table 8. The function of the Complex1 library
Id | Name | Description of the functions. Formulas of the functions' calculations |
alarm | Alarm | The signal on the scale of the parameter:
out = if(val>max || val<min) then true; else false;
|
cond < | Condition '<' | Condition '<' formula:
out=if(in1<(in2_1*in2_2*in2_3*in2_4)) |
cond > | Condition '>' | Condition '>' formula:
out=if(in1>(in2_1*in2_2*in2_3*in2_4)) |
cond_full | Full condition | Full condition formula:
out = if(in1<(in2_1*in2_2*in2_3*in2_4)) |
digitBlock | Digit block | Set of digit signals. |
div | Divider | Divider formula:
out = (in1_1*in1_2*in1_3*in1_4*in1_5 + in2_1*in2_2*in2_3*in2_4*in2_5 + in3) / |
exp | Exponent | Exponent formula:
out=exp (in1_1*in1_2*in1_3*in1_4*in1_5 + (in2_1*in2_2*in2_3*in2_4*in2_5+in3) / |
flow | Flow | Calculation of the flow formula:
f = K1*((K3+K4*x)^K2);
|
increment | Increment | Increment formula:
out = if( in1 > in2 ) then in2 + in3*(in1-in2); |
lag | Lag | Lag formula:
y = y - Klag*( y - x );
|
mult | Simple multiplication | Simple multiplication formula:
out=(in1_1*in1_2*in1_3*in1_4*in1_5*in1_6)/ |
multDiv | Multiplication + Division | Multiplication + Division formula:
out=in1_1*in1_2*in1_3*in1_4*in1_5* |
pid | PID controller | PID controller |
pow | Power | Power formula:
out=(in1_1*in1_2*in1_3*in1_4*in1_5)^ |
select | Select | Select formula:
out = if( sel = 1 ) then in1_1*in1_2*in1_3*in1_4; |
sum | Simple adder | Simple adder formula:
out=in1_1*in1_2+in2_1*in2_2+in3_1*in3_2+in4_1*in4_2 |
sum_div | Sum with division | Sum with division formula:
out = in1_1*in1_2*(in1_3+in1_4/in1_5) + |
sum_mult | Sum with multiplication | Sum with multiplication formula:
out = in1_1*in1_2*(in1_3*in1_4+in1_5) + |
Table 9. Standard mathematical functions
Id | Name | Description |
abs | Module | Math. function - module of the number. |
acos | Arc cosine | Math. function - arc cosine. |
asin | Arc sine | Math. function - arc sine. |
atan | Arc tangent | Math. function - arc tangent. |
ceil | Round to greater | Math. function - rounding to the greater integer. |
cos | Cosine | Math. function - cosine. |
cosh | Hyperbolic cosine | Math. function - hyperbolic cosine. |
exp | Exponent | Math. function - exponent. |
floor | Round to the lower | Math. function - rounding to the lower integer |
if | Condition If | Function - condition "If". |
lg | Common logarithm | Math. function - common logarithm. |
ln | Natural logarithm | Math. function - natural logarithm. |
pow | Power | Math. function - powering. |
rand | Random number | Math. function - random number. |
sin | Sine | Math. function - sine. |
sinh | Hyperbolic sine | Math. function - hyperbolic sine. |
sqrt | Square root | Math. function - square root. |
tan | Tangent | Math. function - tangent. |
tanh | Tangent hyperbolic | Math. function - tangent hyperbolic. |
Table 10. Time functions
Id | Name | Description |
date | Full data | Returns the full date of: second, minute, hour, day of the month, month, year, day of week, day of the year. |
time | Full time (from 01.01.1970) | Returns the full time as the number of seconds since the epoch |
ctime | Full time as a string | Returns the string of full-time "Wed Jun 30 21:49:08 1993". |
Initial implementation of the programming area in the code was done using the obtained UML-model through the generation of C++ code in the program Umbrello. As the result, it was designed the object model interface (API) and components in the form of modules to the OpenSCADA system:
The general structure of all these components and API is shown in Figure 10.
Table. Commands of the internal virtual machine of the “JavaLikeCalc” module
Command | Êîä | Description |
End | 01 | The end of the program or conditional command. |
MviB | 02 R V | Download the logical feature [V] in the register [R]. The initialization of the register. |
MviI | 03 R V V V V | Download the integer [VVVV] to register [R]. The initialization of the register. |
MviR | 04 R V V V V V V | ÇDownloading a real number [VVVVVV] to register [R]. The initialization of the register. |
MviS | 05 R N S . . | Download the string [S. .] with the length [N] into the register [R]. The initialization of the register. |
AssB | 06 R0 R1 | Assigning of the logical feature from the register [R1] to the register [R0]. |
AssI | 07 R0 R1 | Assignment of the integer number from the register [R1] to the register [R0]. |
AssR | 08 R0 R1 | Assigning of the real number from the register [R1] to the register [R0]. |
AssS | 09 R0 R1 | Assigning of the string from the register [R1] to the register [R0]. |
MovB | 0A R0 R1 | Moving the logical feature from the register [R1] to the register [R0]. The initialization of the register. |
MovI | 0B R0 R1 | Moving the integer from the register [R1] to the register [R0]. The initialization of the register. |
MovR | 0C R0 R1 | Moving the real from the register [R1] to the register [R0]. The initialization of the register. |
MovS | 0D R0 R1 | Moving the string from the register [R1] to the register [R0]. The initialization of the register. |
AddI | OE R0 R1 R2 | Addition of integers: R0 = R1 + R2. |
AddR | OF R0 R1 R2 | Addition of reals: R0 = R1 + R2. |
AddS | 1O R0 R1 R2 | Addition of strings: R0 = R1 + R2. |
SubI | 11 R0 R1 R2 | Subtraction of integers: R0 = R1 - R2. |
SubR | 12 R0 R1 R2 | Subtraction of reals: R0 = R1 - R2. |
MultI | 13 R0 R1 R2 | Multiplication of integers: R0 = R1 * R2. |
MultR | 14 R0 R1 R2 | Multiplication of reals: R0 = R1 * R2. |
DivI | 15 R0 R1 R2 | Division of integers: R0 = R1 / R2. |
DivR | 16 R0 R1 R2 | Division of reals: R0 = R1 / R2. |
RstI | 17 R0 R1 R2 | Remainder of the integer division: R0 = R1 % R2. |
BitOr | 18 R0 R1 R2 | Bitwise "OR": R0 = R1 | R2. |
BitAnd | 19 R0 R1 R2 | Bitwise "AND": R0 = R1 & R2. |
BitXor | 1A R0 R1 R2 | Bitwise exclusive "OR": R0 = R1 ^ R2. |
LOr | 1B R0 R1 R2 | Boolean "OR": R0 = R1 || R2. |
LAnd | 1C R0 R1 R2 | Boolean "AND": R0 = R1 && R2. |
LTI | 1D R0 R1 R2 | Integer is less: R0 = R1 < R2. |
LTR | 1E R0 R1 R2 | Real is less: R0 = R1 < R2. |
GTI | 1F R0 R1 R2 | Integer is greater: R0 = R1 > R2. |
GTR | 20 R0 R1 R2 | Real is greater: R0 = R1 > R2. |
LEI | 21 R0 R1 R2 | Integer is less or equal: R0 = R1 <= R2. |
LER | 22 R0 R1 R2 | Real is less or equal: R0 = R1 <= R2. |
GEI | 23 R0 R1 R2 | Integer is greater or equal: R0 = R1 >= R2. |
GER | 24 R0 R1 R2 | Real is greater or equal: R0 = R1 >= R2. |
EQI | 25 R0 R1 R2 | Integer is equal: R0 = R1 == R2. |
EQR | 26 R0 R1 R2 | Real is equal: R0 = R1 == R2. |
EQS | 27 R0 R1 R2 | String is equal: R0 = R1 == R2. |
NEI | 28 R0 R1 R2 | Integer is not equal: R0 = R1 != R2. |
NER | 29 R0 R1 R2 | Real is not equal: R0 = R1 != R2. |
NES | 2A R0 R1 R2 | String is not equal: R0 = R1 != R2. |
Not | 2B R0 R1 | Denial: R0 = !R1. |
BitNot | 2Ñ R0 R1 | Bitwise inversion: R0 = ~R1. |
NegI | 2D R0 R1 | Inversion of the integer: R0 = -R1. |
NegR | 2E R0 R1 | Inversion of real: R0 = -R1. |
If | 2F R E E N N | The condition, if [R] is real, then the commands are executed after this operation and after the completion the transition is performed by the relative address [N N]; other the commands are executed by the relative address [EE] and in the end the transition to the relative address [NN] is done. |
FSin | 30 R0 R1 | Sine function: R0 = sin(R1). |
FCos | 31 R0 R1 | Cosine function: R0 = cos(R1). |
FTan | 32 R0 R1 | Tangent function: R0 = tan(R1). |
FSinh | 33 R0 R1 | Hyperbolic sine function: R0 = sinh(R1). |
FCosh | 34 R0 R1 | Hyperbolic cosine function: R0 = cosh(R1). |
FTanh | 35 R0 R1 | Hyperbolic tangent function: R0 = tanh(R1). |
FAsin | 36 R0 R1 | Arcsine function: R0 = asin(R1). |
FAcos | 37 R0 R1 | Arc cosine function: R0 = acos(R1). |
FAtan | 38 R0 R1 | Arc tangent function: R0 = atan(R1). |
FRand | 39 R0 R1 | Random number: R0 = rand(R1). |
FLg | 3A R0 R1 | Common logarithm: R0 = lg(R1). |
FLn | 3B R0 R1 | Natural logarithm: R0 = ln(R1). |
FExp | 3Ñ R0 R1 | Exponent: R0 = exp(R1). |
FPow | 3D R0 R1 R2 | Powering: R0 = pow(R1,R2). |
FSqrt | 3E R0 R1 | Square-root: R0 = sqrt(R1). |
FAbs | 3F R0 R1 | Modulus: R0 = |R1|. |
FSign | 40 R0 R1 | Sign: R0 = sign(R1). |
FCeil | 41 R0 R1 | Rounding to the greater: R0 = ceil(R1). |
FFloor | 42 R0 R1 | Rounding to the less: R0 = floor(R1). |
CProc | 43 F N R P P . . | The procedural call of the external function [F], with parameters [PP. .], in the number [N]. [R] - is not used. |
CFunc | 44 F N R P P . . | Call of the external function [F], with parameters [PP. .], in the number [N]. The result of the function is placed in the [R]. |