Ìîäóëü: | UserProtocol |
Èìÿ: | Ïîëüçîâàòåëüñêèé ïðîòîêîë |
Òèï: | Ïðîòîêîë |
Èñòî÷íèê: | prot_UserProtocol.so |
Âåðñèÿ: | 0.8 |
Àâòîð: | Ðîìàí Ñàâî÷åíêî |
Îïèñàíèå: | Ïîçâîëÿåò ñîçäàâàòü ñîáñòâåííûå ïîëüçîâàòåëüñêèå ïðîòîêîëû íà ëþáîì OpenSCADA ÿçûêå. |
Ëèöåíçèÿ: | GPL |
Ìîäóëü òðàíñïîðòíîãî ïðîòîêîëà 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());