Это старая версия документа.
Содержание
Типы тегов
Формат записи в mtr-файле
%EXTERNAL=1E6C %EXTMAIN=01E3 %EXTREQ=0995 %EXTIRR=12F4
Таблица вшешних тэгов имеет структуру:
type | size |
---|---|
periodic | EXTMAIN |
requested | EXTREQ |
irregular | EXTIRR |
Irregular tags
Все теги в rpsvrtcp и его клиентах имеют свойства:
TWorkRecTagProp = (tpNormal, tpIrregular); TWorkRecTagFlag = (tfNone, tfInUse, tfUpdated);
Теги типа tpIrregular
запрашиваются из конечного устройства (ПЛК) только тогда, когда этого требует клиент, подключенный к rpsvrtcp. Делается это так.
Пусть клиентом будет приложение visscada. При использовании тега внутри приложения выполняется проверка на тип tpIrregular
и, если да, то тегу устанавливается флаг tfInUse
:
// D:\promauto-src\VisScada\Common\TagStorage.pas function GetTagValue(idx: integer): integer; begin result := 0; if not DataClient.Connected then exit; if (idx >= 0) and (idx < DataClient.client.TagCount) then begin if DataClient.client.Tags[idx].TagProp = tpIrregular then DataClient.client.Tags[idx].TagFlag := tfInUse; result := DataClient.client.Tags[idx].ValIn; end else result := -1; end;
После этого в самом ближайшем будущем этот флаг будет модулем, отвечающем за связь с rpsvrtcp, и передан серверу при помощи команды SETFLAG:
// D:\promauto-src\Lib\delphi\rpTcpLib\TcpImportClient.pas // Передача флага для irregular тегов if (Tags[i].TagProp = tpIrregular) and (Tags[i].TagFlag <> tfNone) then begin s := IntToHex(i, 1) + ' ' + IntToHex(integer(Tags[i].TagFlag), 1); clnt.IOHandler.WriteLn( 'SETFLAG ' + s + ' ' + IntToHex(CRC16($FFFF, s), 1) ); if not GetAnswer('117 !', false, s, c) then raise Exception.Create(''); Tags[i].TagFlag := tfNone; end;
Комманда SETFLAG принимается сервером rpsvrtcp, после чего флаг соответсвующего тега становится tfInUse
:
// D:\promauto-src\Work_shd\rpsvrtcp\sources\TcpExpSvr.pas procedure TTcpExportSvr.OnCommandSETFLAG(ASender: TIdCommand); var i: Integer; clnt: TTcpExportClient; s: string; label M; begin clnt := FindModuleByContext( ASender.Context ); if clnt<>nil then with clnt do begin ASender.Reply.Text.Text := '?'; if ASender.Params.Count>=3 then begin s := ASender.Params[0] + ' ' + ASender.Params[1]; if (ASender.Params[2]='****') then goto M; if CRC16($FFFF, s) = HexToInt(uppercase(ASender.Params[2])) then M: begin if SetFlagByNum( HexToInt(uppercase(ASender.Params[0])), HexToInt(uppercase(ASender.Params[1])) ) then ASender.Reply.Text.Text := '!'; end; end; inc(CntRequest); end; end; // D:\promauto-src\Work_shd\rpsvrtcp\sources\ExpSvr.pas function TCustomExportClient.SetFlagByNum(item_num, value: integer): Boolean; begin result := false; if (item_num<0) or (item_num >= TagCount) then exit; Tags[item_num].ptrTag^.TagFlag := TWorkRecTagFlag( value ); result := true; end;
А в это время в том же rpsvrtcp живет своей жизнью модуль robo - обменивается данными с ПЛК, посылая ему запросы чтения тегов типа requested
. При этом он следит и за тегами irregular
- если у тега флаг tfInUse
, то посылется запрос на одиночное чтение данного тега.
// D:\promauto-src\Work_shd\rpsvrtcp\sources\Robo.pas // Прием irrgular тега if (Tags[i].TagProp = tpIrregular) then begin if Tags[i].TagFlag = tfUpdated then Tags[i].TagFlag := tfNone; if Tags[i].TagFlag = tfInUse then begin inc(irrCnt); Tags[i].TagFlag := tfUpdated; newCmdDollarFlag := cmdDollarSupported; if (cmdDollarSupported) then begin TransStr := '$' + Tags[i].Address; w := GetCRC8(TransStr); TransStr := TransStr + DecHexB(w and $FF) + #13; end else TransStr := '!' + Tags[i].Address + #13; Attemp := 0; repeat sio_sendstring( PortHolder_Port, TransStr); flag := sio_getstring( PortHolder_Port, s); if (cmdDollarSupported) then begin if (not flag) and (s='') then begin sio_sendstring( PortHolder_Port, '!' + Tags[i].Address + #13); newCmdDollarFlag := not (sio_getstring( PortHolder_Port, s) and (copy(s,1,1) = '!')); end else newCmdDollarFlag := True; end; if (flag) and (copy(s,1,1) = '!') then begin k := pos('=', s); sum1 := HexDec(copy(s,k+1,length(s)-k)); sum2 := GetCRC8(copy(s,1,k)); if sum1 = sum2 then begin s := copy(s,2,k-2); v := HexDec(s); if Tags[i].ValIn <> v then begin Tags[i].ValIn := v; Tags[i].Changed := true; end; break; end; end; sleep(50); sio_flush( PortHolder_Port, 2 ); inc(Attemp); if Attemp > AttempMax then err := true; until Attemp > AttempMax; cmdDollarSupported := newCmdDollarFlag; end; end;