| Модуль: | JavaLikeCalc |
| Имя: | Вычислитель на Java-подобном языке. |
| Тип: | DAQ |
| Источник: | daq_JavaLikeCalc.so |
| Версия: | 2.0.0 |
| Автор: | Роман Савоченко |
| Описание: | Предоставляет основанные на java подобном языке вычислитель и движок библиотек. Пользователь может создавать и модифицировать функции и их библиотеки. |
| Лицензия: | GPL |
Модуль контроллера JavaLikeCalc предоставляет в систему OpenSCADA механизм создания функций и их библиотек на Java-подобном языке. Описание функции на Java-подобном языке сводится к обвязке параметров функции алгоритмом. Кроме этого модуль наделен функциями непосредственных вычислений путём создания вычислительных контроллеров.
Непосредственные вычисления обеспечиваются созданием контроллера и связыванием его с функцией этого же модуля. Для связанной функции создаётся кадр значений, над которым и выполняются периодические вычисления.
Модулем реализуются функции горизонтального резервирования, а именно совместной работы с удалённой станцией этого-же уровня. Кроме синхронизации значений и архивов атрибутов параметров модулем осуществляется синхронизация значений вычислительной функции, с целью безударного подхвата алгоритмов.
Параметры функции могут свободно создаваться, удаляться или модифицироваться. Текущая версия модуля поддерживает до 65535 параметров функции в сумме с внутренними переменными. Вид редактора функций показан на рис.1.

После любого изменения программы или конфигурации параметров выполняется перекомпиляция программы с упреждением связанных с функцией объектов значений TValCfg. Компилятор языка построен с использованием известного генератора грамматики «Bison», который совместим с не менее известной утилитой Yacc.
Язык использует неявное определение локальных переменных, которое заключается в определении новой переменной в случае присваивания ей значения. Причём тип локальной переменной устанавливается в соответствии с типом присваиваемого значения. Например, выражение <Qr=Q0*Pi+0.01;> определит переменную Qr с типом переменной Q0.
В работе с различными типами данных язык использует механизм автоматического приведения типов в местах, где подобное приведение является целесообразным.
Для комментирования участков кода в языке предусмотрены символы «//» и "/* ... */". Всё, что идёт после "//" до конца строки и между "/* ... */", игнорируется компилятором.
В процессе генерации кода компилятор языка производит оптимизацию по константам и приведение типов констант к требуемому типу. Под оптимизацией констант подразумевается выполнение вычислений в процессе построения кода над двумя константами и вставка результата в код. Например, выражение <y=pi*10;> свернётся в простое присваивание <y=31.4159;>. Под приведением типов констант к требуемому типу подразумевается формирования в коде константы, которая исключает приведение типа в процессе исполнения. Например, выражение <y=x*10>, в случае вещественного типа переменной x, преобразуется в <y=x*10.0>.
Язык поддерживает вызовы внешних и внутренних функций. Имя любой функции вообще воспринимается как символ, проверка на принадлежность которого к той или иной категории производится в следующем порядке:
Вызов внешней функции, как и атрибута системного параметра, записывается как адрес к объекту динамического дерева объектной модели системы OpenSCADA в виде: <DAQ.JavaLikeCalc.lib_techApp.klapNotLin>.
Для предоставления возможности написания пользовательских процедур управления различными компонентами OpenSCADA модулем предоставляется реализация API прекомпиляции пользовательских процедур отдельных компонентов OpenSCADA на реализации Java-подобного языка. Такими компонентами уже являются: Шаблоны параметров подсистемы "Сбор данных" и Среда визуализации и управления (СВУ).
Ключевые слова: if, else, while, for, break, continue, return, using, true, false.
Постоянные:
Типы переменных:
Встроенные константы: pi = 3.14159265, e = 2.71828182, EVAL_BOOL(2), EVAL_INT(-2147483647), EVAL_REAL(-3.3E308), EVAL_STR("<EVAL>")
Атрибуты параметров системы OpenSCADA (начиная с подсистемы DAQ, в виде <Тип модуля DAQ>.<Контроллер>.<Параметр>.<Атрибут>).
Функции объектной модели системы OpenSCADA.
Операции, поддерживаемые языком, представлены в таблице ниже. Приоритет операций уменьшается сверху вниз. Операции с одинаковым приоритетом входят в одну цветовую группу.
| Символ | Описание |
| () | Вызов функции. |
| {} | Программные блоки. |
| ++ | Инкремент (пост и пре). |
| -- | Декремент (пост и пре). |
| - | Унарный минус. |
| ! | Логическое отрицание. |
| ~ | Побитовое отрицание. |
| * | Умножение. |
| / | Деление. |
| % | Остаток от целочисленного деления. |
| + | Сложение |
| - | Вычитание |
| << | Поразрядный сдвиг влево |
| >> | Поразрядный сдвиг вправо |
| > | Больше |
| >= | Больше или равно |
| < | Меньше |
| <= | Меньше или равно |
| == | Равно |
| != | Неравно |
| | | Поразрядное «ИЛИ» |
| & | Поразрядное «И» |
| ^ | Поразрядное «Исключающее ИЛИ» |
| && | Логический «И» |
| || | Логический «ИЛИ» |
| ?: | Условная операция (i=(i<0)?0:i;) |
| = | Присваивание. |
| += | Присваивание со сложением. |
| -= | Присваивание с вычитанием. |
| *= | Присваивание с умножением. |
| /= | Присваивание с делением. |
Виртуальной машиной языка предусматривается следующий набор встроенных функций общего назначения:
Для обеспечения высокой скорости работы в математических вычислениях модуль предоставляет встроенные математические функции, которые вызываются на уровне команд виртуальной машины:
Общий перечень операторов языка:
Языком модуля поддерживаются два типа условий. Первый — это операции условия для использования внутри выражения, второй — глобальный, основанный на условных операторах.
Условие внутри выражения строится на операциях «?» и «:». В качестве примера можно записать следующее практическое выражение <st_open=(pos>=100)?true:false;>, что читается как «Если переменная <pos> больше или равна 100, то переменной st_open присваивается значение true, иначе — false.
Глобальное условие строится на основе условных операторов «if» и «else». В качестве примера можно привести тоже выражение, но записанное другим способом <if(pos>100) st_open=true; else st_open=false;>. Как видно, выражение записано по другому, но читается также.
Поддерживаются три типа циклов: while, for и for-in. Синтаксис циклов соответствует языкам программирования: C++, Java и JavaScript.
Цикл while в общем записывается следующим образом: while(<условие>) <тело цикла>;
Цикл for записывается следующим образом: for(<пре-инициализ>;<условие>;<пост-вычисление>) <тело цикла>;
Цикл for-in записывается следующим образом: for( <переменная> in <объект> ) <тело цикла>;
Где:
Языком предусмотрена поддержка следующих специальных символов строковых переменных:
Языком предоставляется поддержка типа данных объект "Object". Объект представляет собой ассоциативный контейнер свойств и функций. Свойства могут содержать как данные четырёх базовых типов, так и другие объекты. Доступ к свойствам объекта может осуществляться посредством записи имён свойств через точку к объекту <obj.prop>, а также посредством заключения имени свойства в квадратные скобки <obj["prop"]>. Очевидно, что первый механизм статичен, а второй позволяет указывать имя свойства через переменную. Создание объекта осуществляется посредством ключевого слова <new>: <varO = new Object()>. Базовое определение объекта не содержит функций. Операции копирования объекта на самом деле делают ссылку на исходный объект. При удалении объекта осуществляется уменьшение счётчика ссылок, а при достижении счётчика ссылок нуля объект удаляется физически.
Разные компоненты могут доопределять базовый объект особыми свойствами и функциями. Стандартным расширением объекта является массив "Array", который создаётся командой <varO = new Array(prm1,prm2,prm3,...,prmN)>. Перечисленные через запятую параметры помещаются в массив в исходном порядке. Если параметр только один то массив инициируется указанным количеством пустых элементов. Особенностью массива является то, что он работает со свойствами как с индексами и полное их именование бессмысленно, а значит доступен механизм обращения только заключением индекса в квадратные скобки <arr[1]>. Массив хранит свойства в собственном контейнере одномерного массива. Цифровые свойства массива используются для доступа непосредственно к массиву, а символьные работают как свойства объекта. Детальнее про свойства и функции массива можно прочитать по ссылке.
Объект регулярного выражения RegExp создаётся командой <varO = new RegExp(pat,flg)>, где <pat> — шаблон регулярного выражения, а <flg> — флаги поиска. Объект работы с регулярными выражениями, основан на библиотеке PCRE. При глобальном поиске устанавливается атрибут объекта "lastIndex", что позволяет продолжить поиск при следующем вызове функции. В случае неудачного поиска атрибут "lastIndex" сбрасывается в ноль. Детальнее про свойства и функции массива можно прочитать по ссылке.
Для произвольного доступа к аргументам функции предусмотрен объект аргументов, обратиться к которому можно посредством символа "arguments". Этот объект содержит свойство "length" с количеством аргументов у функции и позволяет обратиться к значению аргумента посредством его номера или идентификатора. Рассмотрим перебор аргументов по циклу:
args = new Array();
for(var i=0; i < arguments.length; i++)
arg[i] = arguments[i];
Частичными свойствами объекта обладают и базовые типы. Свойства и функции базовых типов приведены ниже:
Функции:
Функции:
var rez = "Java123Script".search("script","i"); // rez = 7
var rez = "Java123Script".search(new RegExp("script","i")); // rez = 7
var rez = "1 плюс 2 плюс 3".match("\\d+","g"); // rez = [1], [2], [3]
var rez = "1 плюс 2 плюс 3".match(new RegExp("\\d+","g")); // rez = [1], [2], [3]
rez = "1,2, 3 , 4 ,5".split(new RegExp("\\s*,\\s*")); // rez = [1], [2], [3], [4], [5]
rez = "Javascript".replace(4,3,"67"); // rez = "Java67ipt"
rez = "123 321".replace("3","55"); // rez = "1255 5521"
rez = "value = \"123\"".replace(new RegExp("\"([^\"]*)\"","g"),"``$1''")); // rez = "value = ``123''"
Для доступа к системным объектам(узлам) OpenSCADA предусмотрен соответствующий объект, который создаётся путём простого указания точки входа "SYS" корневого объекта OpenSCADA, а затем, через точку указываются вложенные объекты в соответствии с иерархией. Например, вызов функции запроса через исходящий транспорт осуществляется следующим образом: SYS.Transport.Sockets.out_testModBus.messIO(strEnc2Bin("15 01 00 00 00 06 01 03 00 00 00 05"));.
Приведём несколько примеров программ на Java-подобном языке:
//Модель хода исполнительного механизма шарового крана
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;
}
//Модель клапана
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);
Контроллер этого модуля связывается с функциями из библиотек, построенных с его помощью, для обеспечения непосредственных вычислений. Для предоставления вычисленных данных в систему OpenSCADA в контроллере могут создаваться параметры. Пример вкладки конфигурации контроллера данного типа изображен на рис.2.

С помощью этой вкладки можно установить:
Вкладка "Вычисления" контроллера(Рис. 3) содержит параметры и текст программы, непосредственно выполняемой контроллером. Модулем предусмотрен ряд специальных параметров, доступных в программе контроллера:

Параметр контроллера данного модуля выполняет функцию предоставления доступа к результатам вычисления контроллера в систему OpenSCADA посредством атрибутов параметров. Из специфических полей вкладка конфигурации параметра контроллера содержит только поле перечисления параметров вычисляемой функции, которые необходимо отразить.
Модуль предоставляет механизм для создания библиотек пользовательских функций на Java-подобном языке. Пример вкладки конфигурации библиотеки изображен на Рис.4. Вкладка содержит базовые поля: состояния, идентификатор, имя и описание, а также адрес таблицы, хранящей библиотеку. Во вкладке "Функции" библиотеки кроме перечня функций содержится форма копирования функций.

Функция, также как и библиотека, содержит базовую вкладку конфигурации, вкладку формирования программы и параметров функции (Рис.1), а также вкладку исполнения созданной функции.
Некоторые объекты модуля предоставляют функции пользовательского программирования.
Объект "Библиотека функций" (SYS.DAQ.JavaLikeCalc["lib_Lfunc"])
Объект "Пользовательская функция" (SYS.DAQ.JavaLikeCalc["lib_Lfunc"]["func"])