Модуль | Имя | Версия | Лицензия | Источник | Языки | Платформы | Тип | Автор | Описание |
---|---|---|---|---|---|---|---|---|---|
UserProtocol | Пользовательский протокол | 1.6 | GPL2 | prot_UserProtocol.so | en,uk,ru,de | x86,x86_64,ARM | Протокол | Роман Савоченко |
Обеспечивает создание собственных пользовательских протоколов на внутреннем языке OpenSCADA. |
Модуль предназначен для предоставления пользователю возможности создания реализаций различных протоколов собственными силами на внутреннем языке OpenSCADA, обычно JavaLikeCalc, не прибегая к низкоуровневому программированию.
Основная цель модуля — упростить задачу подключения к OpenSCADA устройств источников данных, которые имеют незначительное распространение и/или предоставляют доступ к собственным данным по специфическому протоколу, обычно достаточно простому для реализации на внутреннем языке OpenSCADA. Для реализации этого предоставляется механизм формирования протокола исходящего запроса.
Кроме механизма протокола исходящего запроса предоставляется механизм протокола входящего запроса, который позволяет OpenSCADA обслуживать запросы на получение данных по специфическим протоколам, которые достаточно просто могут быть реализованы на внутреннем языке OpenSCADA.
Модуль предоставляет возможность создания реализаций множества различных протоколов в объекте "Пользовательский протокол" (рис.1), а также использовать для этого стандартные шаблоны DAQ. Использование шаблонов DAQ позволяет создавать библиотеки комплексных протоколов и вызов их в этом модуле многократно, как их реализации, а также предоставляет контекст данных исполнения входного шаблона с их связыванием с данными подсистемы "Сбор Данных".
Главная вкладка содержит основные настройки пользовательского протокола:
Протокол входных запросов работает в кооперации с входным транспортом и отдельный объект "Пользовательского протокола" указывается в поле конфигурации протокола транспорта, вместе с именем модуля UserProtocol. Далее все запросы к транспорту будут направляться к прямой процедуре, или процедуре шаблону, с обработки запроса протокола (рис.2).
Вкладка конфигурации и контроля входных запросов содержит:
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:
Общий сценарий обработки входящих запросов:
В качестве примера рассмотрим реализацию обработки запросов по протоколу DCON для некоторых запросов к источнику данных с адресом "10":
var enCRC = true;
//SYS.messDebug("/DCON/in","REQ: "+request);
//Проверка запроса на полноту
if(request.length < 4 || request[request.length-1] != "\r") {
if(request.length > 10) request = "";
return true;
}
//Проверка запроса на целостность (CRC) и адрес
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;
}
//Анализ запроса и подготовка ответа
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 = "?";
//Завершение ответа
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;
Протокол исходящих запросов работает в кооперации с исходящим транспортом и отдельным объектом "Пользовательского протокола". Источником запроса через протокол может выступать функция общесистемного API пользовательского программирования выходного транспорта "int messIO( XMLNodeObj req, string prt );", в параметрах которой указывается:
Запрос, отправленный вышеуказанным образом, направляться в прямую процедуру обработки запроса протокола (рис.3), или процедуру шаблона, с идентификатором пользовательского протокола, указываемым в атрибуте req.attr("ProtIt").
Вкладка процедуры обработки выходных запросов содержит только поле текста прямой процедуры обработки на внутреннем языке программирования OpenSCADA, который указан в предыдущей вкладке. Эта вкладка отсутствует для режима работы по шаблону.
Для процедуры обработки предопределены, и обязательные или опциональные для создания в шаблоне, следующие атрибуты обмена:
Общий сценарий формирования выходного запроса:
Суть выделения протокольной части кода в процедуру пользовательского протокола заключается в упрощении и унификации интерфейса клиентского обмена при многократном использовании и предполагает формирование структуры XML-узла обмена в виде атрибутов адресов удалённых станций, адресов читаемых и записываемых переменных, а также значений самих переменных. При этом весь груз непосредственного кодирования запроса и декодирования ответа возлагается на процедуру пользовательского протокола. Если это одноразовая реализация, которая к тому-же не предусматривает реализации входной части, то проще это сделать прямо в исходном шаблоне к источнику данных, в виде встроенной функции.
В качестве примера рассмотрим реализацию запросов посредством протокола DCON к обработчику, реализованному в предыдущем разделе. Начнём с реализации протокольной части:
//Формирование конечного запроса
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";
//Отправка запроса
resp = tr.messIO(request);
while(resp[resp.length-1] != "\r") {
tresp = tr.messIO("");
if(!tresp.length) break;
resp += tresp;
}
//Анализ ответа
if(io.attr("CRC").toInt()) {
if(resp.length < 4 || resp[resp.length-1] != "\r") { io.setAttr("err","10:"+tr("Error or no response.")); return; }
//Проверка ответа на целостность (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; }
//Возврат результата
io.setAttr("err","");
io.setText(resp.slice(1,resp.length-3));
И процедура непосредственной отправки DCON запроса, через предыдущую процедуру протокола. Эту процедуру необходимо поместить в нужную задачу или промежуточную функцию OpenSCADA, например, в процедуру объекта контроллера DAQ.JavaLikeCalc:
//Подготовка запроса
req = SYS.XMLNode("#").setAttr("ProtIt","DCON").setAttr("addr",10);
//Отправка запроса
SYS.Transport["Serial"]["out_TestDCON"].messIO(req,"UserProtocol");
if(!req.attr("err").length) SYS.messDebug("TEST REQ","RES: "+req.text());
//Подготовка второго запроса
req = SYS.XMLNode("@").setAttr("ProtIt","DCON").setAttr("addr",10);
//Отправка второго запроса
SYS.Transport["Serial"]["out_TestDCON"].messIO(req,"UserProtocol");
if(!req.attr("err").length) SYS.messDebug("TEST REQ","RES: "+req.text());
Modules/UserProtocol/ru - GFDL | December 2024 | OpenSCADA 1+r3000 |