<?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="uk">Модулі/Протокол кориÑтувача</h1> </div><div class="mw-content-ltr" dir="ltr" id="mw-content-text" lang="uk"><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=uk" 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 100% 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> • ‎<a class="mw-pt-progress mw-pt-progress--complete" href="../../ru/Modules/UserProtocol.html" title="Модули/Протокол Ð¿Ð¾Ð»ÑŒÐ·Ð¾Ð²Ð°Ñ‚ÐµÐ»Ñ (96% translated)">mRussian</a> • ‎<span class="mw-pt-languages-selected mw-pt-progress mw-pt-progress--complete">УкраїнÑька</span></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> Забезпечує ÑÑ‚Ð²Ð¾Ñ€ÐµÐ½Ð½Ñ Ð²Ð»Ð°Ñних протоколів кориÑтувача на внутрішній мові OpenSCADA. </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:747px;"><a class="image" href="http://oscada.org/wiki/File:UserProtocol_up_main_uk.png"><img class="thumbimage" height="579" src="../files/UserProtocol_up_main_uk.png" width="745" /></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.D1.96.D0.B4.D0.BD.D0.B0_.D1.87.D0.B0.D1.81.D1.82.D0.B8.D0.BD.D0.B0_.D0.BF.D1.80.D0.BE.D1.82.D0.BE.D0.BA.D0.BE.D0.BB.D1.83"><span class="tocnumber">1</span> <span class="toctext">Вхідна чаÑтина протоколу</span></a></li> <li class="toclevel-1 tocsection-2"><a href="#.D0.92.D0.B8.D1.85.D1.96.D0.B4.D0.BD.D0.B0_.D1.87.D0.B0.D1.81.D1.82.D0.B8.D0.BD.D0.B0_.D0.BF.D1.80.D0.BE.D1.82.D0.BE.D0.BA.D0.BE.D0.BB.D1.83"><span class="tocnumber">2</span> <span class="toctext">Вихідна чаÑтина протоколу</span></a></li> </ul> </div> <h2><span class="mw-headline" id=".D0.92.D1.85.D1.96.D0.B4.D0.BD.D0.B0_.D1.87.D0.B0.D1.81.D1.82.D0.B8.D0.BD.D0.B0_.D0.BF.D1.80.D0.BE.D1.82.D0.BE.D0.BA.D0.BE.D0.BB.D1.83"><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:842px;"><a class="image" href="http://oscada.org/wiki/File:UserProtocol_up_in_uk.png"><img class="thumbimage" height="687" src="../files/UserProtocol_up_in_uk.png" width="840" /></a> <div class="thumbcaption">РиÑ.2. Вкладка конфігурації та контролю вхідних запитів.</div></div></div></div> <p>Вкладка конфігурації та контролю вхідних запитів міÑтить: </p> <ul><li> Ð§Ð°Ñ Ð¾Ñ‡Ñ–ÐºÑƒÐ²Ð°Ð½Ð½Ñ Ð·Ð°Ð¿Ð¸Ñ‚Ñƒ, у міліÑекундах. ВикориÑтовуєтьÑÑ Ð´Ð»Ñ Ð²Ð²Ñ–Ð¼ÐºÐ½ÐµÐ½Ð½Ñ Ñ€ÐµÐ¶Ð¸Ð¼Ñƒ пулінгу-опробуваннÑ, вÑтановленнÑм у ненульове значеннÑ. У режимі пулінгу-Ð¾Ð¿Ñ€Ð¾Ð±ÑƒÐ²Ð°Ð½Ð½Ñ Ð²Ñ…Ñ–Ð´Ð½Ð¸Ð¹ транÑпорт буде викликати протокол з порожнім запитом, у випадку відÑутноÑті запиту протÑгом визначеного чаÑу.</li> <li> Таблицю контекÑту даних процедури вхідного запиту. Переважно має ÑÐµÐ½Ñ Ð»Ð¸ÑˆÐµ при роботі за шаблоном та де можна контролювати цей Ð¿Ñ€Ð¾Ñ†ÐµÑ Ð¾Ð±Ñ€Ð¾Ð±ÐºÐ¸, включно з можливіÑтю Ð²Ñ‚Ñ€ÑƒÑ‡Ð°Ð½Ð½Ñ Ñ‡ÐµÑ€ÐµÐ· зміну значень даних.</li> <li> ТекÑÑ‚ прÑмої процедури протоколу, відÑутній у режимі роботи за шаблоном.</li> <li> Зв'Ñзки на дані підÑиÑтеми "Збір Даних", Ñкі видимі та доÑтупні Ð´Ð»Ñ Ð²Ð¸Ð·Ð½Ð°Ñ‡ÐµÐ½Ð½Ñ Ñƒ режимі роботи за шаблоном та у ввімкненому Ñтані об'єкту протоколу.</li></ul> <p>Ð”Ð»Ñ Ð¿Ñ€Ñмої процедури обробки предвизначено, та обов'Ñзкові або опціональні до ÑÑ‚Ð²Ð¾Ñ€ÐµÐ½Ð½Ñ Ñƒ шаблоні, наÑтупні атрибути обміну з вхідним транÑпортом: </p> <ul><li> <i><b>Вхідний результат (rez)</b></i> <Логічний> — результат обробки (false — повний запит; true — неповний, утримувати підключеннÑ); у режимі DAQ-шаблону Ви маєте пиÑати Ñюди прÑмо, не оператором "return";</li> <li> <i><b>Вхідний запит (request)</b></i> <Ð Ñдок> — повне-акумульоване Ð¿Ð¾Ð²Ñ–Ð´Ð¾Ð¼Ð»ÐµÐ½Ð½Ñ Ð·Ð°Ð¿Ð¸Ñ‚Ñƒ, Ñке протокол має очищати щодо оброблених даних;</li> <li> <i><b>Вхідна відповідь (answer)</b></i> <Ð Ñдок> — Ð¿Ð¾Ð²Ñ–Ð´Ð¾Ð¼Ð»ÐµÐ½Ð½Ñ Ð²Ñ–Ð´Ð¿Ð¾Ð²Ñ–Ð´Ñ–;</li> <li> <i>Вхідний відправник (sender)</i> <Ð Ñдок> — відправник запиту;</li> <li> <i>ТранÑпорт (tr)</i> <Об'єкт> — об'єкт вхідного транÑпорту;</li> <li> <i>Цей об'єкт (this)</i> <Об'єкт> — вказівник на об'єкт цього протоколу;</li> <li> <i>ÐŸÐ»Ð°Ð½ÑƒÐ²Ð°Ð½Ð½Ñ Ð½Ð°Ñтупного ÑервіÑного виклику (schedCall)</i> <Ціле> — запишіть тут Ð·Ð½Ð°Ñ‡ÐµÐ½Ð½Ñ Ñ‡Ð°Ñу у Ñекундах Ð´Ð»Ñ Ð¿Ð»Ð°Ð½ÑƒÐ²Ð°Ð½Ð½Ñ Ð²Ð¸ÐºÐ¾Ð½Ð°Ð½Ð½Ñ ÐºÐ¾Ð½Ñ‚ÐµÐºÑту процедури у ÑервіÑному виклику; <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> ÑервіÑні виклики зазвичай здійÑнюютьÑÑ Ñ–Ð· періодичніÑтю 10 Ñекунд, тож ви можете планувати такі виклики не чаÑтіше за 10 Ñекунд.</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.D0.B8.D1.85.D1.96.D0.B4.D0.BD.D0.B0_.D1.87.D0.B0.D1.81.D1.82.D0.B8.D0.BD.D0.B0_.D0.BF.D1.80.D0.BE.D1.82.D0.BE.D0.BA.D0.BE.D0.BB.D1.83"><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:842px;"><a class="image" href="http://oscada.org/wiki/File:UserProtocol_up_out_uk.png"><img class="thumbimage" height="687" src="../files/UserProtocol_up_out_uk.png" width="840" /></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/uk">Modules/UserProtocol/uk</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>