Различия

Здесь показаны различия между двумя версиями данной страницы.

Ссылка на это сравнение

Предыдущая версия справа и слева Предыдущая версия
Следующая версия
Предыдущая версия
doc:rpsvrtcp:irregular [2013/09/09 12:51]
denis
doc:rpsvrtcp:irregular [2013/09/09 13:46] (текущий)
denis [Подводный камень]
Строка 16: Строка 16:
  
 ===== Irregular tags ===== ===== Irregular tags =====
-Все теги в rpsvrtcp имеют свойства:​+Все теги в rpsvrtcp ​и его клиентах ​имеют свойства:​
   TWorkRecTagProp = (tpNormal, tpIrregular);​   TWorkRecTagProp = (tpNormal, tpIrregular);​
   TWorkRecTagFlag = (tfNone, tfInUse, tfUpdated);   TWorkRecTagFlag = (tfNone, tfInUse, tfUpdated);
  
-Теги типа ''​tpIrregular''​ запрашиваются из конечного устройства (ПЛК) только тогда, когда этого требует клиент,​ подключенный к rpsvrtcp.+Теги типа ''​tpIrregular''​ запрашиваются из конечного устройства (ПЛК) только тогда, когда этого требует клиент,​ подключенный к rpsvrtcp. Делается это так.
  
-Запрос от клиента выполняется коммандами:​ +Пусть клиентом будет ​приложение visscada. При использовании ​тега внутри приложения выполняется проверка на тип ''​tpIrregular''​ и, если да, то тегу устанавливается флаг ''​tfInUse'':​ 
-  ​+<code delphi>​ 
 +// 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; 
 +</​code>​ 
 + 
 + 
 +После этого ​в самом ближайшем будущем этот флаг будет прочитан модулем,​ отвечающем за связь с rpsvrtcp, и передан серверу при помощи команды SETFLAG: 
 + 
 +<code delphi>​ 
 +// 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; 
 +</​code>​ 
 + 
 +Комманда SETFLAG ​принимается сервером rpsvrtcp, после чего флаг соответсвующего тега становится ''​tfInUse'':​ 
 + 
 +<code delphi>​ 
 +// 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; 
 +</​code>​ 
 + 
 +А в это время в том же rpsvrtcp живет своей жизнью модуль robo - обменивается ​данными с ПЛК, посылая ему запросы чтения тегов типа ''​requested''​. При этом он следит и за тегами ''​irregular''​ - если у тега флаг ''​tfInUse'',​ то посылется запрос на одиночное чтение данного тега. 
 + 
 +<code delphi>​ 
 +// 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; 
 +</​code>​ 
 + 
 +При установке значеня тега в ПЛК модуль robo также уделяет irr-тегам немного больше внимания, чем ​другим: после каждой записи robo сам устанавливает тегу флаг ''​tfInUse'',​ чтобы новое значение обновилось
 + 
 +<code delphi>​ 
 +// D:​\promauto-src\Work_shd\rpsvrtcp\sources\Robo.pas  
 + 
 +    // Передача тэгов 
 +    // writing all tags (per, req, irr) 
 +    for i:=0 to TagCount-1 do 
 +    begin 
 + 
 +      // Передача тега 
 +      if Tags[i].GotOut then begin 
 +        if Tags[i].ValOut > $FFFF then 
 +          TransStr := '​^'​ 
 +        else 
 +          TransStr := '​@';​ 
 +        TransStr := TransStr + Tags[i].Address + DecHexW(Tags[i].ValOut and $FFFF); 
 + 
 +        w:=0; 
 +        if UseCRC8 then 
 +          w := GetCRC8(TransStr) 
 +        else 
 +          for k:=1 to 11 do w :=w + ord(TransStr[k]);​ 
 + 
 +        TransStr := TransStr + DecHexB(w and $FF) + #13; 
 +        Tags[i].GotOut := false; 
 + 
 +        Attemp := 0; 
 +        repeat 
 +          sio_sendstring( PortHolder_Port,​ TransStr);​ 
 +          flag := sio_getstring( PortHolder_Port,​ s); 
 + 
 +          if (Tags[i].TagProp = tpIrregular) then 
 +            Tags[i].TagFlag := tfInUse; 
 + 
 + 
 +          if UseLogging then 
 +            LoggerSaveDayMessage( 
 +                  inttostr(Attemp) + ': ' + 
 +                  copy(TransStr,​1,​13) + '​|'​ + s + ' ' + 
 +                  iif(copy(TransStr,​1,​13) = copy(s,​2,​13),​ '​ok',​ '​TAG_WRITE_ERROR'​) ); 
 + 
 +          if (flag) and (copy(s,​1,​1) = '​!'​) then 
 +            break; 
 + 
 +          sleep(50);​ 
 +          sio_flush( PortHolder_Port,​ 2 ); 
 +          inc(Attemp);​ 
 +          if Attemp > AttempMax then err := true; 
 +        until Attemp > AttempMax;​ 
 +      end; 
 +    end;   
 + 
 +</​code>​ 
 + 
 +==== Подводный камень ==== 
 +Очень редко случается доселе не локализованный баг - после записи в irr-теги ПЛК значения не обновляются в rpsvrtcp, но сами значения уходят в ПЛК нормально. Помогает перезапуск rpsvrtcp.
  
doc/rpsvrtcp/irregular.1378716701.txt.gz · Последние изменения: 2013/09/09 12:51 — denis
Driven by DokuWiki Recent changes RSS feed Valid CSS Valid XHTML 1.0