Различия

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

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

Предыдущая версия справа и слева Предыдущая версия
Следующая версия
Предыдущая версия
doc:rpsvrtcp:irregular [2013/09/09 13:16]
denis [Irregular tags]
doc:rpsvrtcp:irregular [2013/09/09 13:46] (текущий)
denis [Подводный камень]
Строка 42: Строка 42:
  
  
-После этого в самом ближайшем будущем этот флаг будет модулем,​ отвечающем за связь с rpsvrtcp, и передан серверу при помощи команды SETFLAG:+После этого в самом ближайшем будущем этот флаг будет ​прочитан ​модулем,​ отвечающем за связь с rpsvrtcp, и передан серверу при помощи команды SETFLAG:
  
 <code delphi> <code delphi>
Строка 57: Строка 57:
 Комманда SETFLAG принимается сервером rpsvrtcp, после чего флаг соответсвующего тега становится ''​tfInUse'':​ Комманда 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.
  
-Запрос от клиента выполняется коммандами:​ 
-  SETFLAG 
-  ​ 
doc/rpsvrtcp/irregular.1378718198.txt.gz · Последние изменения: 2013/09/09 13:16 — denis
Driven by DokuWiki Recent changes RSS feed Valid CSS Valid XHTML 1.0