Newsgroups : Borland : borland.public.delphi.internet.winsock : 2008 Feb : 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;