Newsgroups : Borland : borland.public.delphi.internet.winsock : 2008 Feb : Lag in data reurns using TCP_Infeed

www.cryer.info
Managed Newsgroup Archive

Lag in data reurns using TCP_Infeed

Subject:Lag in data reurns using TCP_Infeed
Posted by:"Larry Killen" (lkill..@charter.net)
Date:Thu, 7 Feb 2008 22:23:16

I am in the field at one of my clients and I am tearing my hair out.  It
seems that I am making requests to a scale indicator and their is a
progressive lag in the returns as the shift runs.  A little back drop.

I have a small application whose sole puporse is to poll a GSE/SPX scale
indicator and capture that the data that is sent back and write it to a
database.  Most of the data is returned as a result of a request GETDATA but
on occasion, some data is sent.  I am able to monitor my requests and the
return data.  At first the data is returned as soon as I call for it but
after some time, their is a lag of a few seconds and eventually up to two
hours!  I must also tell you that I communicate with the GSE indicator via a
DCBNet device that converts serial to TCP/IP and TCP/IP to serial.  The GSE
is on the serial side and the PC on teh TCP/IP side.

I poll the GSE every five seconds and set the timer enabled to false.
I listen for the returns on the thread below and process it in the thread.
When I recieve data and process it, I restore the timer.  After five
seconds, I do this again.  I am doing this with two GSE's on 2 separate
threads.  The infeed data is much simpler to process and does not lag as
much.  The other  "Outfeed" devise is far more complicated to process.

I have ticked timed the processes and they run under 20 ms so I can hardly
believe that this is causing the delay.  It would appear that the data is
buffering up somewhat but where?

When the GSE's quit sending data, that data will still come for up to 2
hours and be processed?  Where is this data coming from?  The DCBNet devise
does have a buffer but I have it set to send the buffer when a 50 ms idle is
detected.

Please advise.
Larry


unit ReadOutfeedGSE;

interface

uses
  Classes, IdTCPConnection, StrUtils;

type
  TReadingOutfeedThread = class(TThread)
  private
    { Private declarations }
    FConn: TIdTCPConnection;
    FBuffer : string;
  protected
    procedure Execute; override;
  public
    procedure AfterConstruction; override;
    constructor Create(AConn: TIdTCPConnection); reintroduce;
    Procedure ProcessData;
  end;

var
  ReadingOutfeedThread: TReadingOutfeedThread = nil;

  OUTFEEDRESULTS : string;

implementation

uses Main;

{ ReadingOutfeedThread }

procedure TReadingOutfeedThread.AfterConstruction;
begin
  inherited;
  Resume;
end;

constructor TReadingOutfeedThread.Create(AConn: TIdTCPConnection);
begin
  inherited Create(True);
  FConn := AConn;
end;

procedure TReadingOutfeedThread.Execute;
begin
  while not Terminated do
  begin
    FConn.IOHandler.WaitFor(chr(2));
    FBuffer := FConn.IOHandler.ReadLn(chr(3));
    ProcessData;
  end;
end;


procedure TReadingOutfeedThread.ProcessData;
begin
   frmMain.ProcessOutFeedData(FBuffer);
end;

end.


procedure TfrmMain.ProcessOutFeedData( Buffer : string);
var
  TxID : integer;
  SecondsToGive : Integer;
  RecordDateTime : TDateTime;
  Station, ActiveProdID : Integer;
  IntEmpID : Integer;
  ByPassMode : TByPassStatus;
  i : Integer;
  oActiveShift : Integer;
  oProdWorkDate : TDateTime;
const
  BaseDateTime =  '12/1/2007 12:00 AM';
  CHECKED = 1;
  BYPASSED = 0;
begin

Station := 0;
IntEmpID := 0;
CommaDataOutfeed.Clear;
CommaDataOutfeed.StrictDelimiter := True;
CommaDataOutfeed.CommaText := Buffer;
ProcessData(cdtOutFeed);
LastOutfeed := Now;
TxID := StrToInt(CommaDataOutfeed[0]);
case TxID of
   11 : Begin  //SessionWT
         RecordDateTime := SysUtils.StrToDateTime(CommaDataOutfeed[6]);

         If RecordDateTime < StrToDateTime(BaseDateTime) then
          Begin
             DM.insExceptions.Parameters.ParamByName('DateOccurred').Value
:= Now;
             DM.insExceptions.Parameters.ParamByName('Message').Value :=
SysUtils.StrToDateTime(CommaDataOutfeed[6]+' '+'Outfeed');
             DM.insExceptions.ExecSQL;
             Begin
               exit;
               tmrPollOutData.Enabled := true;
             End;
          End;

          try
            DM.spgetshiftproddate.Close;
            DM.spgetshiftproddate.Parameters.ParamByName('@CurrentDateTime').Value
:= RecordDateTime;
            DM.spgetshiftproddate.ExecProc;
            IF
DM.spgetshiftproddate.Parameters.ParamByName('@RETURN_VALUE').Value = 0 then
              oActiveShift :=
DM.spgetshiftproddate.Parameters.ParamByName('@shift').Value
            Else
             oActiveShift := 0;
           oProdWorkDate :=
DM.spgetshiftproddate.Parameters.ParamByName('@prodworkdate').Value;
          Finally
            DM.spgetshiftproddate.close;
          end;

          If StrToFloat(CommaDataOutfeed[5]) < MinOutFeedWt then
          Begin
             DM.insExceptions.Parameters.ParamByName('DateOccurred').Value
:= Now;
             DM.insExceptions.Parameters.ParamByName('Message').Value :=
'Sta '+CommaDataOutfeed[4]+
             ' Wt '+CommaDataOutfeed[5]+' '+'Outfeed';
             DM.insExceptions.ExecSQL;
             Begin
               exit;
               tmrPollOutData.Enabled := true;
             End;
          End;
          OutFeedBroadCast := '';
          OutfeedProdID := StrToInt(CommaDataOutfeed[1]);
          For i := 0 to  CommaDataOutfeed.Count -1 do
          Begin
            OutFeedBroadCast := OutFeedBroadCast +' '+ CommaDataOutfeed[i];
          End;
          If ShowStream then DisplayOutFeedData;

        If LastOutShift <> oActiveShift then
        Begin
          TCP_Outfeed.IOHandler.WriteLn('GATETOTALS'+#13#10);{ TODO : move
to zero flag }
          LastOutShift := oActiveShift;
        End;

        OutFeedBroadCast := 'Active Shift '+ IntToStr(oActiveShift);
        If ShowStream then DisplayOutFeedData;
        Try
          Try
            Begin
              Station := StrToInt(CommaDataOutfeed[4]);
              DM.qryGetIntEmpID.close;
              DM.qryGetIntEmpID.Parameters.ParamByName('Shift').Value :=
oActiveShift;
              DM.qryGetIntEmpID.Parameters.ParamByName('Station').Value :=
Station;
              DM.qryGetIntEmpID.Open;
              IntEmpID :=
DM.qryGetIntEmpID.FieldByName('IntEmpID').AsInteger;
              DM.qryGetIntEmpID.close;
            End;
          Except
            On E:Exception do
            Begin
              OutFeedBroadCast := 'Broke ' + E.Message+' Station '+
IntToStr(Station)+
              ' ActiveShift '+ IntToStr(oActiveShift)+
              ' IntEmpID '+ IntToStr(IntEmpID);
              If ShowStream then DisplayOutFeedData;
            End;
          End;

          With DM.insOutFeed do
          Begin
            Parameters.ParamByName('Station').Value       := Station;
            Parameters.ParamByName('Shift').Value         := oActiveShift;
            Parameters.ParamByName('IntEmpID').Value      := IntEmpID;
            Parameters.ParamByName('Weight').Value        :=
StrToFloat(CommaDataOutfeed[5]);
            Parameters.ParamByName('WeighTime').Value     := RecordDateTime;
            Parameters.ParamByName('ProdID').Value        := OutfeedProdID;
            Parameters.ParamByName('ProdWorkDate').Value  := oProdWorkDate;
            Parameters.ParamByName('BatchSeq').Value      :=
StrToInt(CommaDataOutfeed[7]);
            ExecSQL;
          End;
        except
            on E:Exception do
            Begin
              For i := 0 to  CommaDataOutfeed.Count -1 do
              Begin
                OutFeedBroadCast := OutFeedBroadCast +'
'+CommaDataOutfeed[i];
              End;
              DM.insExceptions.Parameters.ParamByName('DateOccurred').Value
:= Now;
              DM.insExceptions.Parameters.ParamByName('Message').Value :=
OutFeedBroadCast;
              DM.insExceptions.ExecSQL;
              If ShowStream then DisplayOutFeedData;
            End;
        End;   // Try-Except

        OutFeedBroadCast := 'Assigned Outfeed to DB for Shift
'+IntToStr(ActiveShift);
        If ShowStream then DisplayOutFeedData;
        End;
   12 : Begin  //NODATA%e
          OutFeedBroadCast := '';
          For i := 0 to  CommaDataOutfeed.Count -1 do
          Begin  { TODO 1 -oLarry -cNext Release : update shift and
prodworkdate }
            OutFeedBroadCast := OutFeedBroadCast +' '+CommaDataOutfeed[i];
          End;
          If ShowStream then DisplayOutFeedData;
        End;
   13 : Begin  //RESETTOTALS%e;
          For i := 0 to  CommaDataOutfeed.Count -1 do
          Begin
            OutFeedBroadCast := OutFeedBroadCast +' '+CommaDataOutfeed[i];
          End;
          If ShowStream then DisplayOutFeedData;
          {At End of Shift.  Store to totals table}
        End;
   15 : Begin  //ZEROFLAG%e
          For i := 0 to  CommaDataOutfeed.Count -1 do
          Begin
            OutFeedBroadCast := OutFeedBroadCast +' '+CommaDataOutfeed[i];
          End;
          If ShowStream then DisplayOutFeedData;

          try   { TODO 1 -oLarry -cNext Release : remove after adding to
infeed trigger }
            DM.spgetshiftproddate.Close;
            DM.spgetshiftproddate.Parameters.ParamByName('@CurrentDateTime').Value
:= now;
            DM.spgetshiftproddate.ExecProc;
            ActiveShift :=
DM.spgetshiftproddate.Parameters.ParamByName('@shift').Value;
            ProdWorkDate :=
DM.spgetshiftproddate.Parameters.ParamByName('@prodworkdate').Value;
          Finally
            DM.spgetshiftproddate.close;
          end;

          SetTimeAllGSE;
          OutFeedBroadCast := 'Synching ALL GSE times';
          If ShowStream then DisplayOutFeedData;

          NewZeroFlag  := Now;
          OutFeedBroadCast := 'Recording Zero Flag Time';
          If ShowStream then DisplayOutFeedData;

          SecondsToGive := ABS(SecondsBetween(LastZeroFlag, NewZeroFlag));
          OutFeedBroadCast := 'Seconds to give '+IntToStr(SecondsToGive);
          If ShowStream then DisplayOutFeedData;

          If SecondsToGive < 600 then
          Begin
            dm.spIncrementAccumulator.Parameters.ParamByName('@Shift').Value
:= ActiveShift;
            dm.spIncrementAccumulator.Parameters.ParamByName('@Seconds').Value
:= SecondsToGive;
            dm.spIncrementAccumulator.Parameters.ParamByName('@ProdWorkDate').Value
:= ProdWorkDate;
            dm.spIncrementAccumulator.Parameters.ParamByName('@ProdID').Value
:= OutfeedProdID;
            dm.spIncrementAccumulator.ExecProc;
          End;

//  Update Station_Worker from Staged_Station_Worker
          Begin
            dm.spPushStagedWorker.Parameters.ParamByName('@Shift').Value :=
ActiveShift;
            dm.spPushStagedWorker.ExecProc;
          End;
          OutFeedBroadCast := 'Updating StationWorker from Staging';
          If ShowStream then DisplayOutFeedData;
          LastZeroFlag := NewZeroFlag;

//  Update Infeed to Status of all stations
          Try   { TODO 1 -oLarry -cNext Release : Must use real time shift.
Look at ZeroActive Shift. }
            StationsStatus := '';
            DM.qryGetStationStatus.Close;
            DM.qryGetStationStatus.Parameters.ParamByName('Shift').Value :=
ActiveShift;
            DM.qryGetStationStatus.Open;
            DM.qryGetStationStatus.First;
            While not(DM.qryGetStationStatus.Eof) do
            Begin
              // Build string to send station status
              StationsStatus := (StationsStatus + 'G' +
              DM.qryGetStationStatus.FieldByName('Station').AsString +
              DM.qryGetStationStatus.FieldByName('StationOn').AsString);
              DM.qryGetStationStatus.Next;
            End;

           TCP_Infeed.IOHandler.WriteLn(StationsStatus + #13#10);

          Finally
            DM.qryGetStationStatus.Close;
          End;
           OutFeedBroadCast := 'Updating Station status for Infeed as
:'+StationsStatus;
           If ShowStream then DisplayOutFeedData;

//Pull in settings table
          try
           DM.qryGetSettings.open;
           RandomByPassCount :=
DM.qryGetSettings.FieldByName('RandomByPassCount').AsInteger;
           FixedCountDesired :=
DM.qryGetSettings.FieldByName('FixedCountDesired').AsInteger;
           ForcedCount :=
DM.qryGetSettings.FieldByName('ForcedCount').AsInteger;
           BypassCount :=
DM.qryGetSettings.FieldByName('BypassCount').AsInteger;
           MinScore := DM.qryGetSettings.FieldByName('MinScore').AsInteger;
           ByPassMode :=
TByPassStatus(DM.qryGetSettings.FieldByName('ByPassMode').AsInteger);
           StationCount :=
DM.qryGetSettings.FieldByName('StationCount').AsInteger;
           QCcalcTime :=
DM.qryGetSettings.FieldByName('QCTimeOutComp').AsBoolean;
           ActiveProdID :=
DM.qryGetSettings.FieldByName('ActiveProdID').AsInteger;
          finally
           DM.qryGetSettings.close;
          end;

    //Process Product ID
          Begin // send the active product ID
            If TCP_Infeed.Connected = true then
            TCP_Infeed.IOHandler.WriteLn('PRODID'+IntToStr(ActiveProdID)+#13#10);
            InFeedBroadCast := 'Sent ProdID';
            If ShowStream then DisplayInFeedData;

            If TCP_Outfeed.Connected = true then
            TCP_Outfeed.IOHandler.WriteLn('PRODID'+IntToStr(ActiveProdID)+#13#10);
            OutFeedBroadCast := 'Sent ProdID';
            If ShowStream then DisplayOutFeedData;
          End;


         Case ByPassMode of
          bpNone : Begin   //QC all    0
                      DM.updAllByPassStatus.Parameters.ParamByName('BypassStatus').Value
:= CHECKED;
                      DM.updAllByPassStatus.Parameters.ParamByName('Shift').Value
:= ActiveShift;
                      DM.updAllByPassStatus.ExecSQL;
                      OutFeedBroadCast := 'Processing BPMode None';
                      If ShowStream then DisplayOutFeedData;
                   End;
          bpFull :  Begin  //QC None      1
                      DM.updAllByPassStatus.Parameters.ParamByName('BypassStatus').Value
:= BYPASSED;
                      DM.updAllByPassStatus.Parameters.ParamByName('Shift').Value
:= ActiveShift;
                      DM.updAllByPassStatus.ExecSQL;
                      OutFeedBroadCast := 'Processing BPMode ALL';
                      If ShowStream then DisplayOutFeedData;
                    End;
          bpRandom :  Begin  //Random   2
                        SetRandomBypass;
                         // Set QCTimeOut value  8 X RandomByPassCount
                        OutFeedBroadCast := 'SetRandomBypass';
                        If ShowStream then DisplayOutFeedData;
                      End;
          bpFixedCount : Begin   //Fixed Count   3
                            SetMeritSystemBypass(bpFixedCount);
                            OutFeedBroadCast := ' Fixed Count Bypass Set';
                            If ShowStream then DisplayOutFeedData;
                         End;
          bpMinScore  :  Begin  //Min Score 4
                            SetMeritSystemBypass(bpMinScore);
                            OutFeedBroadCast := ' Min Score Bypass Set';
                            If ShowStream then DisplayOutFeedData;
                         End;

         End;

        SendOutFeedBypassState;
        IF QCcalcTime then
        Begin
          DM.upDateQCTimeOut.Parameters.ParamByName('QCTimeOut').Value :=
QCTimeOut;
          DM.upDateQCTimeOut.ExecSQL;
          OutFeedBroadCast := 'QC Timeout is ' +IntToStr(QCTimeOut);
          If ShowStream then DisplayOutFeedData;
        End;

          OutFeedBroadCast:= 'Send OutFeed Stations to Bypass
'+BypassStatus;
          If ShowStream then DisplayOutFeedData;

          OutFeedBroadCast :=  ' Processed Zero Flag
Complete'+DateTimeToStr(Now);
          If ShowStream then DisplayOutFeedData;
        End;   //ZEROFLAG%e
   50 : Begin  //GateTotals
          If ProcessNewShiftOutfeed then
          Begin
            TCP_Outfeed.IOHandler.WriteLn('RESETTOTALS'+#13#10);
            OutFeedBroadCast := 'RESETTOTALS ';
            For i := 0 to  CommaDataOutfeed.Count -1 do
            Begin
              OutFeedBroadCast := OutFeedBroadCast +' '+CommaDataOutfeed[i];
            End;
            If ShowStream then DisplayOutFeedData;
          End;
        End;   //GateTotals
   59 : Begin   //BypassStatus
          OutFeedBroadCast := 'Bypass Status ';
          For i := 0 to  CommaDataOutfeed.Count -1 do
          Begin
            OutFeedBroadCast := OutFeedBroadCast +' '+CommaDataOutfeed[i];
          End;
          If ShowStream then DisplayOutFeedData;
        End; //BypassStatus
end; //case of
CommaDataOutfeed.Clear;
tmrPollOutData.Enabled := true;
end;

procedure TfrmMain.ConnectOutFeed;
begin
  try
    TCP_Outfeed.Connect;
  except
    on E:Exception do
    Begin
      Application.Terminate;
    End;
  end;
    ReadingOutfeedThread := TReadingOutfeedThread.Create(TCP_Outfeed);
end;

procedure TfrmMain.PollInfeedData;
Const
  REQUEST = 'GETDATA'+#13#10;
begin
    TCP_Infeed.IOHandler.WriteLn(REQUEST);
end;

procedure TfrmMain.tmrPollInfDataTimer(Sender: TObject);
begin
  tmrPollInfData.Enabled := false;
  PollInfeedData;
end;

Replies:

www.cryer.info
Managed Newsgroup Archive