Модуль | Ім'я | Версія | Ліцензія | Джерело | Мови | Платформи | Тип | Автор | Опис |
---|---|---|---|---|---|---|---|---|---|
UserProtocol | Користувацький протокол | 0.8 | GPL2 | prot_UserProtocol.so | en,uk,ru,de | x86,x86_64,ARM | Протокол | Роман Савоченко | Дозволяє створювати власні протоколи користувача на будь якій мові OpenSCADA. |
Модуль транспортного протоколу UserProtocol призначений для надання користувачу можливості створення реалізацій різних протоколів власними силами на одній з внутрішніх мов OpenSCADA, зазвичай це JavaLikeCalc, не залучаючи низькорівневого програмування OpenSCADA.
Основна мета модуля — спростити завдання підключення до OpenSCADA пристроїв джерел даних, які мають незначне розповсюдження та/або надають доступ до власних даних за специфічним протоколом, зазвичай достатньо простому для реалізації на внутрішній мові OpenSCADA. Для реалізації цього надається механізм формування протоколу вихідного запиту.
Крім механізму протоколу вихідного запиту надається механізм протоколу вхідного запиту, який дозволяє OpenSCADA обслуговувати запити на отримання даних за специфічними протоколами, які достатньо просто можуть бути реалізовані на внутрішній мові OpenSCADA.
Модуль надає можливість створення реалізацій багатьох різних протоколів у об'єкті "Користувацький протокол" (рис.1).
Головна вкладка містить основні налаштування користувацького протоколу:
Протокол вхідних запитів працює у кооперації з вхідним транспортом, та окремий об'єкт "Користувацького протоколу" визначається у полі конфігурації протоколу транспорту разом з іменем модуля UserProtocol. Надалі всі запити до транспорту будуть спрямовуватися у процедуру обробки запиту протоколу (рис.2).
Вкладка процедури обробки вхідних запитів містить:
Для процедури обробки предвизначено наступні змінні обміну з вхідним транспортом:
Загальний сценарій обробки вхідних запитів:
У якості прикладу розглянемо реалізацію обробки запитів за протоколу DCON, для деяких запитів до джерела даних з адресою "10":
//SYS.messDebug("TEST REQ: ",request); //Перевірка запиту на повноту if(request.length < 4 || request[request.length-1] != "\r") { if(request.length > 10) request = ""; return true; } //Перевірка запиту на цілісність (CRC) та адресу 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.charCodeAt(0) == "#") answer = ">+05.123+04.153+07.234-02.356+10.000-05.133+02.345+08.234"; else if(request.charCodeAt(0) == "@") answer = ">AB3C"; else answer = "?"; //Завершення відповіді CRC = 0; for(i=0; i < answer.length; i++) CRC += answer.charCodeAt(i); answer += (CRC&0xFF).toString(16)+"\r"; //SYS.messDebug("TEST ANSV: "+answer.charCodeAt(0),answer); 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(); CRC = 0; for(i=0; i < request.length; i++) CRC += request.charCodeAt(i); request += (CRC&0xFF).toString(16)+"\r"; //Відправка запиту resp = tr.messIO(request); while(resp[resp.length-1] != "\r") { tresp = tr.messIO(""); if(!tresp.length) break; resp += tresp; } //Аналіз відповіді if(resp.length < 4 || resp[resp.length-1] != "\r") { io.setAttr("err","10:Помилка або немає відповіді."); 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:Помилка CRC."); return; } if(resp[0] != ">") { io.setAttr("err","12:"+resp[0]+":Помилка DCON."); 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());