<?xml version='1.0' encoding='UTF-8' ?> <!DOCTYPE html PUBLIC '-//W3C//DTD XHTML 1.0 Transitional//EN' 'http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd'> <html class="client-nojs" dir="ltr" lang="en"> <head> <meta charset="UTF-8" /> <title>Модули/Протокол Ð¿Ð¾Ð»ÑŒÐ·Ð¾Ð²Ð°Ñ‚ÐµÐ»Ñ - OpenSCADAWiki</title> <meta content="MediaWiki 1.26.4" name="generator" /> <link href="https://www.gnu.org/copyleft/fdl.html" rel="copyright" /> <link href="../../en/files/doc.css" rel="stylesheet" /></head> <body><div class="floatright"><a href="../index.html"><img alt="OpenSCADA" src="../../en/files/index.png" /></a></div><div id="mw_header"> <div class="mw-indicators"> </div> <h1 id="firstHeading" lang="ru">Модули/Протокол пользователÑ</h1> </div><div class="mw-content-ltr" dir="ltr" id="mw-content-text" lang="ru"><div class="mw-pt-translate-header noprint" dir="ltr" lang="en">This page is a <span class="plainlinks"><a class="external text" href="http://oscada.org/wiki/index.php?title=Special:Translate&group=page-Modules%2FUserProtocol&action=page&filter=&language=ru" rel="nofollow noreferrer noopener" target="_blank">translated version</a></span> of the page <a class="external" href="http://oscada.org/wiki/Modules/UserProtocol" title="Modules/UserProtocol">Modules/UserProtocol</a> and the translation is 96% complete.</div><hr /><div class="mw-pt-languages" dir="ltr" lang="en"><div class="mw-pt-languages-list autonym"><a class="mw-pt-languages-ui mw-pt-progress mw-pt-progress--complete" href="../../en/Modules/UserProtocol.html" title="Modules/UserProtocol (100% translated)">English</a> • ‎<span class="mw-pt-languages-selected mw-pt-progress mw-pt-progress--complete">mRussian</span> • ‎<a class="mw-pt-progress mw-pt-progress--complete" href="../../uk/Modules/UserProtocol.html" title="Модулі/Протокол кориÑтувача (100% translated)">УкраїнÑька</a></div></div> <table class="wikitable"> <tr> <th> Модуль </th> <th> Ð˜Ð¼Ñ </th> <th> ВерÑÐ¸Ñ </th> <th> Ð›Ð¸Ñ†ÐµÐ½Ð·Ð¸Ñ </th> <th> ИÑточник </th> <th> Языки </th> <th> Платформы </th> <th> Тип </th> <th> Ðвтор </th> <th> ОпиÑание </th></tr> <tr> <td> <a href="../Modules/UserProtocol.html" title="Special:MyLanguage/Modules/UserProtocol">UserProtocol</a> </td> <td> ПользовательÑкий протокол </td> <td> 1.6 </td> <td> GPL2 </td> <td> prot_UserProtocol.so </td> <td> en,uk,ru,de </td> <td> x86,x86_64,ARM </td> <td> Протокол </td> <td> Роман Савоченко </td> <td> <p>ОбеÑпечивает Ñоздание ÑобÑтвенных пользовательÑких протоколов на внутреннем Ñзыке OpenSCADA. </p> </td></tr></table> <p>Модуль предназначен Ð´Ð»Ñ Ð¿Ñ€ÐµÐ´Ð¾ÑÑ‚Ð°Ð²Ð»ÐµÐ½Ð¸Ñ Ð¿Ð¾Ð»ÑŒÐ·Ð¾Ð²Ð°Ñ‚ÐµÐ»ÑŽ возможноÑти ÑÐ¾Ð·Ð´Ð°Ð½Ð¸Ñ Ñ€ÐµÐ°Ð»Ð¸Ð·Ð°Ñ†Ð¸Ð¹ различных протоколов ÑобÑтвенными Ñилами на внутреннем Ñзыке OpenSCADA, обычно <a href="../Modules/JavaLikeCalc.html" title="Special:MyLanguage/Modules/JavaLikeCalc">JavaLikeCalc</a>, не Ð¿Ñ€Ð¸Ð±ÐµÐ³Ð°Ñ Ðº низкоуровневому программированию. </p><p>ОÑÐ½Ð¾Ð²Ð½Ð°Ñ Ñ†ÐµÐ»ÑŒ Ð¼Ð¾Ð´ÑƒÐ»Ñ â€” упроÑтить задачу Ð¿Ð¾Ð´ÐºÐ»ÑŽÑ‡ÐµÐ½Ð¸Ñ Ðº OpenSCADA уÑтройÑтв иÑточников данных, которые имеют незначительное раÑпроÑтранение и/или предоÑтавлÑÑŽÑ‚ доÑтуп к ÑобÑтвенным данным по ÑпецифичеÑкому протоколу, обычно доÑтаточно проÑтому Ð´Ð»Ñ Ñ€ÐµÐ°Ð»Ð¸Ð·Ð°Ñ†Ð¸Ð¸ на внутреннем Ñзыке OpenSCADA. Ð”Ð»Ñ Ñ€ÐµÐ°Ð»Ð¸Ð·Ð°Ñ†Ð¸Ð¸ Ñтого предоÑтавлÑетÑÑ Ð¼ÐµÑ…Ð°Ð½Ð¸Ð·Ð¼ Ñ„Ð¾Ñ€Ð¼Ð¸Ñ€Ð¾Ð²Ð°Ð½Ð¸Ñ Ð¿Ñ€Ð¾Ñ‚Ð¾ÐºÐ¾Ð»Ð° иÑходÑщего запроÑа. </p><p>Кроме механизма протокола иÑходÑщего запроÑа предоÑтавлÑетÑÑ Ð¼ÐµÑ…Ð°Ð½Ð¸Ð·Ð¼ протокола входÑщего запроÑа, который позволÑет OpenSCADA обÑлуживать запроÑÑ‹ на получение данных по ÑпецифичеÑким протоколам, которые доÑтаточно проÑто могут быть реализованы на внутреннем Ñзыке OpenSCADA. </p><p>Модуль предоÑтавлÑет возможноÑÑ‚ÑŒ ÑÐ¾Ð·Ð´Ð°Ð½Ð¸Ñ Ñ€ÐµÐ°Ð»Ð¸Ð·Ð°Ñ†Ð¸Ð¹ множеÑтва различных протоколов в объекте "ПользовательÑкий протокол" (риÑ.1), а также иÑпользовать Ð´Ð»Ñ Ñтого <a href="../Program_manual.html#DAQTmpl" title="Special:MyLanguage/Documents/Program manual">Ñтандартные шаблоны DAQ</a>. ИÑпользование шаблонов DAQ позволÑет Ñоздавать библиотеки комплекÑных протоколов и вызов их в Ñтом модуле многократно, как их реализации, а также предоÑтавлÑет контекÑÑ‚ данных иÑÐ¿Ð¾Ð»Ð½ÐµÐ½Ð¸Ñ Ð²Ñ…Ð¾Ð´Ð½Ð¾Ð³Ð¾ шаблона Ñ Ð¸Ñ… ÑвÑзыванием Ñ Ð´Ð°Ð½Ð½Ñ‹Ð¼Ð¸ подÑиÑтемы "Сбор Данных". </p> <div class="center"><div class="thumb tnone"><div class="thumbinner" style="width:754px;"><a class="image" href="http://oscada.org/wiki/File:UserProtocol_up_main_ru.png"><img class="thumbimage" height="573" src="../files/UserProtocol_up_main_ru.png" width="752" /></a> <div class="thumbcaption">РиÑ.1. ОÑÐ½Ð¾Ð²Ð½Ð°Ñ Ð²ÐºÐ»Ð°Ð´ÐºÐ° объекта "ПользовательÑкий протокол".</div></div></div></div> <p>Ð“Ð»Ð°Ð²Ð½Ð°Ñ Ð²ÐºÐ»Ð°Ð´ÐºÐ° Ñодержит оÑновные наÑтройки пользовательÑкого протокола: </p> <ul><li> Раздел "СоÑтоÑние" — Ñодержит ÑвойÑтва, характеризующие ÑоÑтоÑние протокола: ÑтатуÑ, "Включен", Ð¸Ð¼Ñ Ð‘Ð” (Ñодержащей конфигурацию и Ñ Ð¾Ñ‚Ñлеживанием Ð½Ð°Ð»Ð¸Ñ‡Ð¸Ñ Ð´Ð°Ð½Ð½Ñ‹Ñ… в различных хранилищах и предоÑтавлением поÑледовательного ÑƒÐ´Ð°Ð»ÐµÐ½Ð¸Ñ Ð´ÑƒÐ±Ð»Ð¸ÐºÐ°Ñ‚Ð¾Ð²) и дату поÑледней модификации.</li> <li> Идентификатор, Ð¸Ð¼Ñ Ð¸ опиÑание узла протокола.</li> <li> СоÑтоÑние "Включен", в которое переводить протокол при загрузке.</li> <li> <a href="../Program_manual.html#DAQTmpl" title="Special:MyLanguage/Documents/Program manual">DAQ шаблон</a>, ÑвÑзанный Ñ Ð¿Ñ€Ð¾Ñ‚Ð¾ÐºÐ¾Ð»Ð¾Ð¼. Выбор шаблона тут выключает режим работы по прÑмым процедурам и доÑтуп к Ñледующим опциÑм. Режим DAQ-шаблона может работать во входном, выходном или обоих режимах запроÑа, в завиÑимоÑти от Ð½Ð°Ð»Ð¸Ñ‡Ð¸Ñ Ð½ÐµÐ¾Ð±Ñ…Ð¾Ð´Ð¸Ð¼Ñ‹Ñ… атрибутов.</li> <li> Признак полного перевода текÑта процедур и Ñзыка входной и выходной процедур. Выбор Ñзыка Ð´Ð»Ñ Ð²Ñ…Ð¾Ð´Ð½Ð¾Ð¹ и/или выходной процедур включает ÑоответÑтвующую чаÑÑ‚ÑŒ протокола и открывает доÑтуп к ÑоответÑтвующим вкладкам конфигурации.</li></ul> <div class="toc" id="toc"><div id="toctitle"><h2>Contents</h2></div> <ul> <li class="toclevel-1 tocsection-1"><a href="#.D0.92.D1.85.D0.BE.D0.B4.D0.BD.D0.B0.D1.8F_.D1.87.D0.B0.D1.81.D1.82.D1.8C_.D0.BF.D1.80.D0.BE.D1.82.D0.BE.D0.BA.D0.BE.D0.BB.D0.B0"><span class="tocnumber">1</span> <span class="toctext">Ð’Ñ…Ð¾Ð´Ð½Ð°Ñ Ñ‡Ð°ÑÑ‚ÑŒ протокола</span></a></li> <li class="toclevel-1 tocsection-2"><a href="#.D0.92.D1.8B.D1.85.D0.BE.D0.B4.D0.BD.D0.B0.D1.8F_.D1.87.D0.B0.D1.81.D1.82.D1.8C_.D0.BF.D1.80.D0.BE.D1.82.D0.BE.D0.BA.D0.BE.D0.BB.D0.B0"><span class="tocnumber">2</span> <span class="toctext">Ð’Ñ‹Ñ…Ð¾Ð´Ð½Ð°Ñ Ñ‡Ð°ÑÑ‚ÑŒ протокола</span></a></li> </ul> </div> <h2><span class="mw-headline" id=".D0.92.D1.85.D0.BE.D0.B4.D0.BD.D0.B0.D1.8F_.D1.87.D0.B0.D1.81.D1.82.D1.8C_.D0.BF.D1.80.D0.BE.D1.82.D0.BE.D0.BA.D0.BE.D0.BB.D0.B0"><span class="mw-headline-number">1</span> Ð’Ñ…Ð¾Ð´Ð½Ð°Ñ Ñ‡Ð°ÑÑ‚ÑŒ протокола</span></h2> <p>Протокол входных запроÑов работает в кооперации Ñ Ð²Ñ…Ð¾Ð´Ð½Ñ‹Ð¼ транÑпортом и отдельный объект "ПользовательÑкого протокола" указываетÑÑ Ð² поле конфигурации протокола транÑпорта, вмеÑте Ñ Ð¸Ð¼ÐµÐ½ÐµÐ¼ Ð¼Ð¾Ð´ÑƒÐ»Ñ UserProtocol. Далее вÑе запроÑÑ‹ к транÑпорту будут направлÑÑ‚ÑŒÑÑ Ðº прÑмой процедуре, или процедуре шаблону, Ñ Ð¾Ð±Ñ€Ð°Ð±Ð¾Ñ‚ÐºÐ¸ запроÑа протокола (риÑ.2). </p> <div class="center"><div class="thumb tnone"><div class="thumbinner" style="width:893px;"><a class="image" href="http://oscada.org/wiki/File:UserProtocol_up_in_ru.png"><img class="thumbimage" height="690" src="../files/UserProtocol_up_in_ru.png" width="891" /></a> <div class="thumbcaption">РиÑ.2. Вкладка конфигурации и ÐºÐ¾Ð½Ñ‚Ñ€Ð¾Ð»Ñ Ð²Ñ…Ð¾Ð´Ð½Ñ‹Ñ… запроÑов.</div></div></div></div> <p>Вкладка конфигурации и ÐºÐ¾Ð½Ñ‚Ñ€Ð¾Ð»Ñ Ð²Ñ…Ð¾Ð´Ð½Ñ‹Ñ… запроÑов Ñодержит: </p> <ul><li> Ð’Ñ€ÐµÐ¼Ñ Ð¾Ð¶Ð¸Ð´Ð°Ð½Ð¸Ñ Ð·Ð°Ð¿Ñ€Ð¾Ñа, в миллиÑекундах. ИÑпользуетÑÑ Ð´Ð»Ñ Ð²ÐºÐ»ÑŽÑ‡ÐµÐ½Ð¸Ñ Ñ€ÐµÐ¶Ð¸Ð¼Ð° пулинга-опробованиÑ, уÑтановкой в ненулевое значение. Ð’ режиме пулинга-Ð¾Ð¿Ñ€Ð¾Ð±Ð¾Ð²Ð°Ð½Ð¸Ñ Ð²Ñ…Ð¾Ð´Ð½Ð¾Ð¹ транÑпорт будет вызывать протокол Ñ Ð¿ÑƒÑтым запроÑом, в Ñлучае отÑутÑÑ‚Ð²Ð¸Ñ Ð·Ð°Ð¿Ñ€Ð¾Ñа в течении указанного времени.</li> <li> Таблицу контекÑта данных процедуры входного запроÑа. Ð’ оÑновном имеет ÑмыÑл только при работе по шаблону и где можно контролировать Ñтот процеÑÑ Ð¾Ð±Ñ€Ð°Ð±Ð¾Ñ‚ÐºÐ¸, Ð²ÐºÐ»ÑŽÑ‡Ð°Ñ Ð²Ð¾Ð·Ð¼Ð¾Ð¶Ð½Ð¾ÑÑ‚ÑŒ вмешательÑтва через изменение значений данных.</li> <li> ТекÑÑ‚ прÑмой процедуры протокола, отÑутÑтвует в режиме работы по шаблону.</li> <li> СвÑзи на данные подÑиÑтемы "Сбор Данных", которые видимы и доÑтупны Ð´Ð»Ñ Ð¾Ð¿Ñ€ÐµÐ´ÐµÐ»ÐµÐ½Ð¸Ñ Ð² режиме работы по шаблону и во включенном ÑоÑтоÑнии объекта протокола.</li></ul> <p>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: </p> <ul><li> <i><b>Input result (rez)</b></i> <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";</li> <li> <i><b>Input request (request)</b></i> <String> — full-accumulated request message, what protocol should clear about processed data;</li> <li> <i><b>Input answer (answer)</b></i> <String> — answer message;</li> <li> <i>Input sender (sender)</i> <String> — request sender;</li> <li> <i>Transport (tr)</i> <Object> — input transport object;</li> <li> <i>This object (this)</i> <Object> — pointer to this protocol's object;</li> <li> <i>Scheduling the next service call (schedCall)</i> <Integer> — write here the time value in seconds for scheduling the procedure context execution in a service call; <a class="image" href="http://oscada.org/wiki/File:At.png"><img alt="At.png" height="22" src="../../en/files/At.png" width="22" /></a> the service calls are performed in the periodicity 10 seconds usually, so you can schedule the calls not often than at 10 seconds.</li></ul> <p>Общий Ñценарий обработки входÑщих запроÑов: </p> <ul><li> Ð—Ð°Ð¿Ñ€Ð¾Ñ Ñ„Ð¾Ñ€Ð¼Ð¸Ñ€ÑƒÐµÑ‚ÑÑ ÑƒÐ´Ð°Ð»Ñ‘Ð½Ð½Ð¾Ð¹ Ñтанцией и через Ñеть попадает на <a href="../Program_manual.html#Communication" title="Special:MyLanguage/Documents/Program manual">транÑпорт OpenSCADA</a>.</li> <li> OpenSCADA транÑпорт передаёт Ð·Ð°Ð¿Ñ€Ð¾Ñ Ñтому модулю, выбранному в поле протокола, и объекту пользовательÑкого протокола, в виде значений переменной "request" — Ð´Ð»Ñ Ð¿Ð¾ÑледовательноÑти запроÑа и "sender" — Ð´Ð»Ñ Ð°Ð´Ñ€ÐµÑа Ð¾Ñ‚Ð¿Ñ€Ð°Ð²Ð¸Ñ‚ÐµÐ»Ñ Ð·Ð°Ð¿Ñ€Ð¾Ñа.</li> <li> ЗапуÑкаетÑÑ Ð²Ñ‹Ð¿Ð¾Ð»Ð½ÐµÐ½Ð¸Ðµ процедуры протокола входÑщего запроÑа, в процеÑÑе которой анализируетÑÑ Ñодержимое переменной "request" и формируетÑÑ Ð¾Ñ‚Ð²ÐµÑ‚ в переменной "answer". По окончанию Ð²Ñ‹Ð¿Ð¾Ð»Ð½ÐµÐ½Ð¸Ñ Ð¿Ñ€Ð¾Ñ†ÐµÐ´ÑƒÑ€Ñ‹ формируетÑÑ Ð¿ÐµÑ€ÐµÐ¼ÐµÐ½Ð½Ð°Ñ "rez", ÐºÐ¾Ñ‚Ð¾Ñ€Ð°Ñ ÑƒÐºÐ°Ð·Ñ‹Ð²Ð°ÐµÑ‚ транÑпорту на факт Ð¿Ð¾Ð»ÑƒÑ‡ÐµÐ½Ð¸Ñ Ð¿Ð¾Ð»Ð½Ð¾Ð³Ð¾ запроÑа и формирование корректного ответа (false) или необходимоÑÑ‚ÑŒ транÑпорту ожидать оÑтатка данных (true) — удерживать подключение.</li> <li> ЕÑли результат обработки равен "false", и ответ ненулевой, то транÑпорт отправлÑет ответ, а Ñама процедура протокола должна удалить обработанную чаÑÑ‚ÑŒ запроÑа "request", поÑкольку только она может определить целоÑтноÑÑ‚ÑŒ поÑылки и потенциальное наличие за ней начала Ñледующей.</li> <li> ЕÑли результат процедуры обработки равен "true" то транÑпорт продолжает ожидать данные. При получении Ñледующей порции данных они добавлÑÑŽÑ‚ÑÑ Ðº переменной "request" и выполнение процедуры повторÑетÑÑ.</li></ul> <p>Ð’ качеÑтве примера раÑÑмотрим реализацию обработки запроÑов по протоколу DCON Ð´Ð»Ñ Ð½ÐµÐºÐ¾Ñ‚Ð¾Ñ€Ñ‹Ñ… запроÑов к иÑточнику данных Ñ Ð°Ð´Ñ€ÐµÑом "10": </p> <div class="mw-highlight mw-content-ltr" dir="ltr"><pre><span class="kd">var</span> <span class="nx">enCRC</span> <span class="o">=</span> <span class="kc">true</span><span class="p">;</span> <span class="c1">//SYS.messDebug("/DCON/in","REQ: "+request);</span> <span class="c1">//Проверка запроÑа на полноту</span> <span class="k">if</span><span class="p">(</span><span class="nx">request</span><span class="p">.</span><span class="nx">length</span> <span class="o"><</span> <span class="mi">4</span> <span class="o">||</span> <span class="nx">request</span><span class="p">[</span><span class="nx">request</span><span class="p">.</span><span class="nx">length</span><span class="o">-</span><span class="mi">1</span><span class="p">]</span> <span class="o">!=</span> <span class="s2">"\r"</span><span class="p">)</span> <span class="p">{</span> <span class="k">if</span><span class="p">(</span><span class="nx">request</span><span class="p">.</span><span class="nx">length</span> <span class="o">></span> <span class="mi">10</span><span class="p">)</span> <span class="nx">request</span> <span class="o">=</span> <span class="s2">""</span><span class="p">;</span> <span class="k">return</span> <span class="kc">true</span><span class="p">;</span> <span class="p">}</span> <span class="c1">//Проверка запроÑа на целоÑтноÑÑ‚ÑŒ (CRC) и адреÑ</span> <span class="k">if</span><span class="p">(</span><span class="nx">enCRC</span><span class="p">)</span> <span class="p">{</span> <span class="nx">CRC</span> <span class="o">=</span> <span class="mi">0</span><span class="p">;</span> <span class="k">for</span><span class="p">(</span><span class="nx">i</span> <span class="o">=</span> <span class="mi">0</span><span class="p">;</span> <span class="nx">i</span> <span class="o"><</span> <span class="p">(</span><span class="nx">request</span><span class="p">.</span><span class="nx">length</span><span class="o">-</span><span class="mi">3</span><span class="p">);</span> <span class="nx">i</span><span class="o">++</span><span class="p">)</span> <span class="nx">CRC</span> <span class="o">+=</span> <span class="nx">request</span><span class="p">.</span><span class="nx">charCodeAt</span><span class="p">(</span><span class="nx">i</span><span class="p">);</span> <span class="k">if</span><span class="p">(</span><span class="nx">CRC</span> <span class="o">!=</span> <span class="nx">request</span><span class="p">.</span><span class="nx">slice</span><span class="p">(</span><span class="nx">request</span><span class="p">.</span><span class="nx">length</span><span class="o">-</span><span class="mi">3</span><span class="p">,</span><span class="nx">request</span><span class="p">.</span><span class="nx">length</span><span class="o">-</span><span class="mi">1</span><span class="p">).</span><span class="nx">toInt</span><span class="p">(</span><span class="mi">16</span><span class="p">)</span> <span class="o">||</span> <span class="nx">request</span><span class="p">.</span><span class="nx">slice</span><span class="p">(</span><span class="mi">1</span><span class="p">,</span><span class="mi">3</span><span class="p">).</span><span class="nx">toInt</span><span class="p">(</span><span class="mi">16</span><span class="p">)</span> <span class="o">!=</span> <span class="mi">10</span><span class="p">)</span> <span class="k">return</span> <span class="kc">false</span><span class="p">;</span> <span class="p">}</span> <span class="c1">//Ðнализ запроÑа и подготовка ответа</span> <span class="k">if</span><span class="p">(</span><span class="nx">request</span><span class="p">[</span><span class="mi">0</span><span class="p">]</span> <span class="o">==</span> <span class="s2">"#"</span><span class="p">)</span> <span class="nx">answer</span> <span class="o">=</span> <span class="s2">">+05.123+04.153+07.234-02.356+10.000-05.133+02.345+08.234"</span><span class="p">;</span> <span class="k">else</span> <span class="k">if</span><span class="p">(</span><span class="nx">request</span><span class="p">[</span><span class="mi">0</span><span class="p">]</span> <span class="o">==</span> <span class="s2">"@"</span><span class="p">)</span> <span class="nx">answer</span> <span class="o">=</span> <span class="s2">">AB3C"</span><span class="p">;</span> <span class="k">else</span> <span class="nx">answer</span> <span class="o">=</span> <span class="s2">"?"</span><span class="p">;</span> <span class="c1">//Завершение ответа</span> <span class="k">if</span><span class="p">(</span><span class="nx">enCRC</span><span class="p">)</span> <span class="p">{</span> <span class="nx">CRC</span> <span class="o">=</span> <span class="mi">0</span><span class="p">;</span> <span class="k">for</span><span class="p">(</span><span class="nx">i</span><span class="o">=</span><span class="mi">0</span><span class="p">;</span> <span class="nx">i</span> <span class="o"><</span> <span class="nx">answer</span><span class="p">.</span><span class="nx">length</span><span class="p">;</span> <span class="nx">i</span><span class="o">++</span><span class="p">)</span> <span class="nx">CRC</span> <span class="o">+=</span> <span class="nx">answer</span><span class="p">.</span><span class="nx">charCodeAt</span><span class="p">(</span><span class="nx">i</span><span class="p">);</span> <span class="nx">answer</span> <span class="o">+=</span> <span class="p">(</span><span class="nx">CRC</span><span class="o">&</span><span class="mh">0xFF</span><span class="p">).</span><span class="nx">toString</span><span class="p">(</span><span class="mi">16</span><span class="p">,</span><span class="mi">2</span><span class="p">)</span><span class="o">+</span><span class="s2">"\r"</span><span class="p">;</span> <span class="p">}</span> <span class="c1">//SYS.messDebug("/DCON/in","ANSV: "+answer[0]);</span> <span class="k">return</span> <span class="mi">0</span><span class="p">;</span> </pre></div> <h2><span class="mw-headline" id=".D0.92.D1.8B.D1.85.D0.BE.D0.B4.D0.BD.D0.B0.D1.8F_.D1.87.D0.B0.D1.81.D1.82.D1.8C_.D0.BF.D1.80.D0.BE.D1.82.D0.BE.D0.BA.D0.BE.D0.BB.D0.B0"><span class="mw-headline-number">2</span> Ð’Ñ‹Ñ…Ð¾Ð´Ð½Ð°Ñ Ñ‡Ð°ÑÑ‚ÑŒ протокола</span></h2> <p>Протокол иÑходÑщих запроÑов работает в кооперации Ñ Ð¸ÑходÑщим транÑпортом и отдельным объектом "ПользовательÑкого протокола". ИÑточником запроÑа через протокол может выÑтупать <a href="../User_API.html#SYSTransport" title="Special:MyLanguage/Documents/User API">Ñ„ÑƒÐ½ÐºÑ†Ð¸Ñ Ð¾Ð±Ñ‰ÐµÑиÑтемного API пользовательÑкого Ð¿Ñ€Ð¾Ð³Ñ€Ð°Ð¼Ð¼Ð¸Ñ€Ð¾Ð²Ð°Ð½Ð¸Ñ Ð²Ñ‹Ñ…Ð¾Ð´Ð½Ð¾Ð³Ð¾ транÑпорта</a> "<b>int messIO( XMLNodeObj req, string prt );</b>", в параметрах которой указываетÑÑ: </p> <ul><li> <i>req</i> — Ð·Ð°Ð¿Ñ€Ð¾Ñ Ð² виде дерева XML Ñо Ñтруктурой, ÑоответÑтвующей входному формату реализованного протокола;</li> <li> <i>prt</i> — Ð¸Ð¼Ñ Ñтого Ð¼Ð¾Ð´ÑƒÐ»Ñ â€” "UserProtocol".</li></ul> <p>ЗапроÑ, отправленный вышеуказанным образом, направлÑÑ‚ÑŒÑÑ Ð² прÑмую процедуру обработки запроÑа протокола (риÑ.3), или процедуру шаблона, Ñ Ð¸Ð´ÐµÐ½Ñ‚Ð¸Ñ„Ð¸ÐºÐ°Ñ‚Ð¾Ñ€Ð¾Ð¼ пользовательÑкого протокола, указываемым в атрибуте <b>req.attr("ProtIt")</b>. </p> <div class="center"><div class="thumb tnone"><div class="thumbinner" style="width:893px;"><a class="image" href="http://oscada.org/wiki/File:UserProtocol_up_out_ru.png"><img class="thumbimage" height="690" src="../files/UserProtocol_up_out_ru.png" width="891" /></a> <div class="thumbcaption">РиÑ.3. Вкладка прÑмой процедуры обÑÐ»ÑƒÐ¶Ð¸Ð²Ð°Ð½Ð¸Ñ Ð¸ÑходÑщих запроÑов.</div></div></div></div> <p>Вкладка процедуры обработки выходных запроÑов Ñодержит только поле текÑта прÑмой процедуры обработки на внутреннем Ñзыке Ð¿Ñ€Ð¾Ð³Ñ€Ð°Ð¼Ð¼Ð¸Ñ€Ð¾Ð²Ð°Ð½Ð¸Ñ OpenSCADA, который указан в предыдущей вкладке. Ðта вкладка отÑутÑтвует Ð´Ð»Ñ Ñ€ÐµÐ¶Ð¸Ð¼Ð° работы по шаблону. </p><p>Ð”Ð»Ñ Ð¿Ñ€Ð¾Ñ†ÐµÐ´ÑƒÑ€Ñ‹ обработки предопределены, и обÑзательные или опциональные Ð´Ð»Ñ ÑÐ¾Ð·Ð´Ð°Ð½Ð¸Ñ Ð² шаблоне, Ñледующие атрибуты обмена: </p> <ul><li> <i><b>Выходной Ð’Ð’ (io)</b></i> <Объект::XMLNode> — XML узел обмена Ñ ÐºÐ»Ð¸ÐµÐ½Ñ‚Ð¾Ð¼, через который протокол принимает запроÑÑ‹ и в который помещаетÑÑ Ñ€ÐµÐ·ÑƒÐ»ÑŒÑ‚Ð°Ñ‚ в формате, который реализуетÑÑ Ð¿Ñ€Ð¾Ñ†ÐµÐ´ÑƒÑ€Ð¾Ð¹;</li> <li> <i><b>ТранÑпорт (tr)</b></i> <Объект> — объект транÑпорта, предназначено Ð´Ð»Ñ Ð²Ñ‹Ð·Ð¾Ð²Ð° функции транÑпорта <i>string messIO( string mess, real timeOut = 1000 );</i> — <b>tr.messIO(req)</b>, блокируетÑÑ Ð½Ð° Ð²Ñ€ÐµÐ¼Ñ Ð²Ñ‹Ð·Ð¾Ð²Ð° процедуры.</li></ul> <p>Общий Ñценарий Ñ„Ð¾Ñ€Ð¼Ð¸Ñ€Ð¾Ð²Ð°Ð½Ð¸Ñ Ð²Ñ‹Ñ…Ð¾Ð´Ð½Ð¾Ð³Ð¾ запроÑа: </p> <ul><li> Формирование XML-дерева ÑоглаÑно Ñтруктуре, ÐºÐ¾Ñ‚Ð¾Ñ€Ð°Ñ Ñ€ÐµÐ°Ð»Ð¸Ð·ÑƒÐµÑ‚ÑÑ Ð¿Ñ€Ð¾Ñ‚Ð¾ÐºÐ¾Ð»Ð¾Ð¼, и указание идентификатора пользовательÑкого протокола в атрибуте "ProtIt".</li> <li> Отправка запроÑа транÑпорту через Ñтот протокол — "<b>SYS.Transport["{Modul}"]["out_{OutTransp}"].messIO(req, "UserProtocol");</b>".</li> <li> Выбор пользовательÑкого протокола ÑоглаÑно <b>req.attr("ProtIt")</b> и Ð¸Ð½Ð¸Ñ†Ð¸Ð°Ð»Ð¸Ð·Ð°Ñ†Ð¸Ñ Ð¿ÐµÑ€ÐµÐ¼ÐµÐ½Ð½Ñ‹Ñ… выходного транÑпорта: <i>io</i> — ÑоглаÑно первому аргументу <b>messIO()</b> и <i>tr</i> — объект "OutTransp".</li> <li> Вызов процедуры на иÑполнение, котораÑ, оÑущеÑтвив обработку Ñтруктуры <i>io</i>, формирует прÑмой Ð·Ð°Ð¿Ñ€Ð¾Ñ Ñ‚Ñ€Ð°Ð½Ñпорта <i>tr.messIO(req);</i>, результат которого обрабатываетÑÑ Ð¸ помещаетÑÑ Ð½Ð°Ð·Ð°Ð´ в <i>io</i>.</li></ul> <p>Суть Ð²Ñ‹Ð´ÐµÐ»ÐµÐ½Ð¸Ñ Ð¿Ñ€Ð¾Ñ‚Ð¾ÐºÐ¾Ð»ÑŒÐ½Ð¾Ð¹ чаÑти кода в процедуру пользовательÑкого протокола заключаетÑÑ Ð² упрощении и унификации интерфейÑа клиентÑкого обмена при многократном иÑпользовании и предполагает формирование Ñтруктуры XML-узла обмена в виде атрибутов адреÑов удалённых Ñтанций, адреÑов читаемых и запиÑываемых переменных, а также значений Ñамих переменных. При Ñтом веÑÑŒ груз непоÑредÑтвенного ÐºÐ¾Ð´Ð¸Ñ€Ð¾Ð²Ð°Ð½Ð¸Ñ Ð·Ð°Ð¿Ñ€Ð¾Ñа и Ð´ÐµÐºÐ¾Ð´Ð¸Ñ€Ð¾Ð²Ð°Ð½Ð¸Ñ Ð¾Ñ‚Ð²ÐµÑ‚Ð° возлагаетÑÑ Ð½Ð° процедуру пользовательÑкого протокола. ЕÑли Ñто Ð¾Ð´Ð½Ð¾Ñ€Ð°Ð·Ð¾Ð²Ð°Ñ Ñ€ÐµÐ°Ð»Ð¸Ð·Ð°Ñ†Ð¸Ñ, ÐºÐ¾Ñ‚Ð¾Ñ€Ð°Ñ Ðº тому-же не предуÑматривает реализации входной чаÑти, то проще Ñто Ñделать прÑмо в иÑходном шаблоне к иÑточнику данных, в виде вÑтроенной функции. </p><p>Ð’ качеÑтве примера раÑÑмотрим реализацию запроÑов поÑредÑтвом протокола DCON к обработчику, реализованному в предыдущем разделе. Ðачнём Ñ Ñ€ÐµÐ°Ð»Ð¸Ð·Ð°Ñ†Ð¸Ð¸ протокольной чаÑти: </p> <div class="mw-highlight mw-content-ltr" dir="ltr"><pre><span class="c1">//Формирование конечного запроÑа</span> <span class="nx">request</span> <span class="o">=</span> <span class="nx">io</span><span class="p">.</span><span class="nx">name</span><span class="p">().</span><span class="nx">slice</span><span class="p">(</span><span class="mi">0</span><span class="p">,</span><span class="mi">1</span><span class="p">)</span> <span class="o">+</span> <span class="nx">io</span><span class="p">.</span><span class="nx">attr</span><span class="p">(</span><span class="s2">"addr"</span><span class="p">).</span><span class="nx">toInt</span><span class="p">().</span><span class="nx">toString</span><span class="p">(</span><span class="mi">16</span><span class="p">,</span><span class="mi">2</span><span class="p">)</span> <span class="o">+</span> <span class="nx">io</span><span class="p">.</span><span class="nx">text</span><span class="p">();</span> <span class="k">if</span><span class="p">(</span><span class="nx">io</span><span class="p">.</span><span class="nx">attr</span><span class="p">(</span><span class="s2">"CRC"</span><span class="p">).</span><span class="nx">toInt</span><span class="p">())</span> <span class="p">{</span> <span class="nx">CRC</span> <span class="o">=</span> <span class="mi">0</span><span class="p">;</span> <span class="k">for</span><span class="p">(</span><span class="nx">i</span> <span class="o">=</span> <span class="mi">0</span><span class="p">;</span> <span class="nx">i</span> <span class="o"><</span> <span class="nx">request</span><span class="p">.</span><span class="nx">length</span><span class="p">;</span> <span class="nx">i</span><span class="o">++</span><span class="p">)</span> <span class="nx">CRC</span> <span class="o">+=</span> <span class="nx">request</span><span class="p">.</span><span class="nx">charCodeAt</span><span class="p">(</span><span class="nx">i</span><span class="p">);</span> <span class="nx">request</span> <span class="o">+=</span> <span class="p">(</span><span class="nx">CRC</span><span class="o">&</span><span class="mh">0xFF</span><span class="p">).</span><span class="nx">toString</span><span class="p">(</span><span class="mi">16</span><span class="p">,</span><span class="mi">2</span><span class="p">)</span> <span class="o">+</span> <span class="s2">"\r"</span><span class="p">;</span> <span class="p">}</span> <span class="k">else</span> <span class="nx">request</span> <span class="o">+=</span> <span class="s2">"\r"</span><span class="p">;</span> <span class="c1">//Отправка запроÑа</span> <span class="nx">resp</span> <span class="o">=</span> <span class="nx">tr</span><span class="p">.</span><span class="nx">messIO</span><span class="p">(</span><span class="nx">request</span><span class="p">);</span> <span class="k">while</span><span class="p">(</span><span class="nx">resp</span><span class="p">[</span><span class="nx">resp</span><span class="p">.</span><span class="nx">length</span><span class="o">-</span><span class="mi">1</span><span class="p">]</span> <span class="o">!=</span> <span class="s2">"\r"</span><span class="p">)</span> <span class="p">{</span> <span class="nx">tresp</span> <span class="o">=</span> <span class="nx">tr</span><span class="p">.</span><span class="nx">messIO</span><span class="p">(</span><span class="s2">""</span><span class="p">);</span> <span class="k">if</span><span class="p">(</span><span class="o">!</span><span class="nx">tresp</span><span class="p">.</span><span class="nx">length</span><span class="p">)</span> <span class="k">break</span><span class="p">;</span> <span class="nx">resp</span> <span class="o">+=</span> <span class="nx">tresp</span><span class="p">;</span> <span class="p">}</span> <span class="c1">//Ðнализ ответа</span> <span class="k">if</span><span class="p">(</span><span class="nx">io</span><span class="p">.</span><span class="nx">attr</span><span class="p">(</span><span class="s2">"CRC"</span><span class="p">).</span><span class="nx">toInt</span><span class="p">())</span> <span class="p">{</span> <span class="k">if</span><span class="p">(</span><span class="nx">resp</span><span class="p">.</span><span class="nx">length</span> <span class="o"><</span> <span class="mi">4</span> <span class="o">||</span> <span class="nx">resp</span><span class="p">[</span><span class="nx">resp</span><span class="p">.</span><span class="nx">length</span><span class="o">-</span><span class="mi">1</span><span class="p">]</span> <span class="o">!=</span> <span class="s2">"\r"</span><span class="p">)</span> <span class="p">{</span> <span class="nx">io</span><span class="p">.</span><span class="nx">setAttr</span><span class="p">(</span><span class="s2">"err"</span><span class="p">,</span><span class="s2">"10:"</span><span class="o">+</span><span class="nx">tr</span><span class="p">(</span><span class="s2">"Error or no response."</span><span class="p">));</span> <span class="k">return</span><span class="p">;</span> <span class="p">}</span> <span class="c1">//Проверка ответа на целоÑтноÑÑ‚ÑŒ (CRC)</span> <span class="nx">CRC</span> <span class="o">=</span> <span class="mi">0</span><span class="p">;</span> <span class="k">for</span><span class="p">(</span><span class="nx">i</span> <span class="o">=</span> <span class="mi">0</span><span class="p">;</span> <span class="nx">i</span> <span class="o"><</span> <span class="p">(</span><span class="nx">resp</span><span class="p">.</span><span class="nx">length</span><span class="o">-</span><span class="mi">3</span><span class="p">);</span> <span class="nx">i</span><span class="o">++</span><span class="p">)</span> <span class="nx">CRC</span> <span class="o">+=</span> <span class="nx">resp</span><span class="p">.</span><span class="nx">charCodeAt</span><span class="p">(</span><span class="nx">i</span><span class="p">);</span> <span class="k">if</span><span class="p">(</span><span class="nx">CRC</span> <span class="o">!=</span> <span class="nx">resp</span><span class="p">.</span><span class="nx">slice</span><span class="p">(</span><span class="nx">resp</span><span class="p">.</span><span class="nx">length</span><span class="o">-</span><span class="mi">3</span><span class="p">,</span><span class="nx">resp</span><span class="p">.</span><span class="nx">length</span><span class="o">-</span><span class="mi">1</span><span class="p">).</span><span class="nx">toInt</span><span class="p">(</span><span class="mi">16</span><span class="p">))</span> <span class="p">{</span> <span class="nx">io</span><span class="p">.</span><span class="nx">setAttr</span><span class="p">(</span><span class="s2">"err"</span><span class="p">,</span><span class="s2">"11:"</span><span class="o">+</span><span class="nx">tr</span><span class="p">(</span><span class="s2">"CRC error."</span><span class="p">));</span> <span class="k">return</span><span class="p">;</span> <span class="p">}</span> <span class="p">}</span> <span class="k">else</span> <span class="k">if</span><span class="p">(</span><span class="nx">resp</span><span class="p">.</span><span class="nx">length</span> <span class="o"><</span> <span class="mi">2</span> <span class="o">||</span> <span class="nx">resp</span><span class="p">[</span><span class="nx">resp</span><span class="p">.</span><span class="nx">length</span><span class="o">-</span><span class="mi">1</span><span class="p">]</span> <span class="o">!=</span> <span class="s2">"\r"</span><span class="p">)</span> <span class="p">{</span> <span class="nx">io</span><span class="p">.</span><span class="nx">setAttr</span><span class="p">(</span><span class="s2">"err"</span><span class="p">,</span><span class="s2">"10:"</span><span class="o">+</span><span class="nx">tr</span><span class="p">(</span><span class="s2">"Error or no response."</span><span class="p">));</span> <span class="k">return</span><span class="p">;</span> <span class="p">}</span> <span class="k">if</span><span class="p">(</span><span class="nx">resp</span><span class="p">[</span><span class="mi">0</span><span class="p">]</span> <span class="o">!=</span> <span class="s2">">"</span><span class="p">)</span> <span class="p">{</span> <span class="nx">io</span><span class="p">.</span><span class="nx">setAttr</span><span class="p">(</span><span class="s2">"err"</span><span class="p">,</span><span class="s2">"12:"</span><span class="o">+</span><span class="nx">resp</span><span class="p">[</span><span class="mi">0</span><span class="p">]</span><span class="o">+</span><span class="s2">":"</span><span class="o">+</span><span class="nx">tr</span><span class="p">(</span><span class="s2">"DCON error."</span><span class="p">));</span> <span class="k">return</span><span class="p">;</span> <span class="p">}</span> <span class="c1">//Возврат результата</span> <span class="nx">io</span><span class="p">.</span><span class="nx">setAttr</span><span class="p">(</span><span class="s2">"err"</span><span class="p">,</span><span class="s2">""</span><span class="p">);</span> <span class="nx">io</span><span class="p">.</span><span class="nx">setText</span><span class="p">(</span><span class="nx">resp</span><span class="p">.</span><span class="nx">slice</span><span class="p">(</span><span class="mi">1</span><span class="p">,</span><span class="nx">resp</span><span class="p">.</span><span class="nx">length</span><span class="o">-</span><span class="mi">3</span><span class="p">));</span> </pre></div> <p>И процедура непоÑредÑтвенной отправки DCON запроÑа, через предыдущую процедуру протокола. Ðту процедуру необходимо помеÑтить в нужную задачу или промежуточную функцию OpenSCADA, например, в процедуру объекта контроллера <a href="../Modules/JavaLikeCalc.html#Examples" title="Special:MyLanguage/Modules/JavaLikeCalc">DAQ.JavaLikeCalc</a>: </p> <div class="mw-highlight mw-content-ltr" dir="ltr"><pre><span class="c1">//Подготовка запроÑа</span> <span class="nx">req</span> <span class="o">=</span> <span class="nx">SYS</span><span class="p">.</span><span class="nx">XMLNode</span><span class="p">(</span><span class="s2">"#"</span><span class="p">).</span><span class="nx">setAttr</span><span class="p">(</span><span class="s2">"ProtIt"</span><span class="p">,</span><span class="s2">"DCON"</span><span class="p">).</span><span class="nx">setAttr</span><span class="p">(</span><span class="s2">"addr"</span><span class="p">,</span><span class="mi">10</span><span class="p">);</span> <span class="c1">//Отправка запроÑа</span> <span class="nx">SYS</span><span class="p">.</span><span class="nx">Transport</span><span class="p">[</span><span class="s2">"Serial"</span><span class="p">][</span><span class="s2">"out_TestDCON"</span><span class="p">].</span><span class="nx">messIO</span><span class="p">(</span><span class="nx">req</span><span class="p">,</span><span class="s2">"UserProtocol"</span><span class="p">);</span> <span class="k">if</span><span class="p">(</span><span class="o">!</span><span class="nx">req</span><span class="p">.</span><span class="nx">attr</span><span class="p">(</span><span class="s2">"err"</span><span class="p">).</span><span class="nx">length</span><span class="p">)</span> <span class="nx">SYS</span><span class="p">.</span><span class="nx">messDebug</span><span class="p">(</span><span class="s2">"TEST REQ"</span><span class="p">,</span><span class="s2">"RES: "</span><span class="o">+</span><span class="nx">req</span><span class="p">.</span><span class="nx">text</span><span class="p">());</span> <span class="c1">//Подготовка второго запроÑа</span> <span class="nx">req</span> <span class="o">=</span> <span class="nx">SYS</span><span class="p">.</span><span class="nx">XMLNode</span><span class="p">(</span><span class="s2">"@"</span><span class="p">).</span><span class="nx">setAttr</span><span class="p">(</span><span class="s2">"ProtIt"</span><span class="p">,</span><span class="s2">"DCON"</span><span class="p">).</span><span class="nx">setAttr</span><span class="p">(</span><span class="s2">"addr"</span><span class="p">,</span><span class="mi">10</span><span class="p">);</span> <span class="c1">//Отправка второго запроÑа</span> <span class="nx">SYS</span><span class="p">.</span><span class="nx">Transport</span><span class="p">[</span><span class="s2">"Serial"</span><span class="p">][</span><span class="s2">"out_TestDCON"</span><span class="p">].</span><span class="nx">messIO</span><span class="p">(</span><span class="nx">req</span><span class="p">,</span><span class="s2">"UserProtocol"</span><span class="p">);</span> <span class="k">if</span><span class="p">(</span><span class="o">!</span><span class="nx">req</span><span class="p">.</span><span class="nx">attr</span><span class="p">(</span><span class="s2">"err"</span><span class="p">).</span><span class="nx">length</span><span class="p">)</span> <span class="nx">SYS</span><span class="p">.</span><span class="nx">messDebug</span><span class="p">(</span><span class="s2">"TEST REQ"</span><span class="p">,</span><span class="s2">"RES: "</span><span class="o">+</span><span class="nx">req</span><span class="p">.</span><span class="nx">text</span><span class="p">());</span> </pre></div> </div><table style="border-top: dotted 2px #999999; margin-top: 20pt; color: gray;" width="100%"><tr><td style="text-align: left;" width="40%"><a href="http://oscada.org/wiki/Modules/UserProtocol/ru">Modules/UserProtocol/ru</a> - <a href="http://oscada.org/en/main/about-the-project/licenses/">GFDL</a></td><td style="text-align: center;">April 2025</td><td style="text-align: right;" width="40%">OpenSCADA 1+r3018</td></tr></table></body> </html>