Thread Rating:
  • 0 Vote(s) - 0 Average
  • 1
  • 2
  • 3
  • 4
  • 5
Need to time arrival of TCP socket data, how?
#1
I am troubleshooting a WiFi UART<=>TCP socket bridge device and I need to verify the arrival times of packets sent via the UART input to the device at the TCP client end.
So in this case I will be sending packets of data via the serial link to the device starting at exactly 1 s intervals.
The packets are rather short, basically date/time strings in pure ASCII like "20181109" and "13:46:17"
My test strings start with STX and end with ETX bytes (0x02 and 0x03 respectively).

Each second the date and time packets are sent back-to-back and then nothing until the next second.
Speed is 38400 baud.

I am using FreePascal 3.0.4 and Lazarus 1.8.0 with the indylaz package installed on a Windows 7 x64 laptop.

Since the data arrive at times the client does not control and indy is blocking I have trouble implementing this checking utility...
What I need is:
- Connect the TIdTCPClient object to the bridge device on port 2101 (this is not a problem)
- Somehow start listening for incoming data
- When a packet has arrived transfer it to the main application for timing and logging purposes.


Probably this needs some kind of thread or a loop with Application.Processmessages, but I am not sure how to approach this...

Any advice available?

I have already implemented a configuration utility for the same WiFi bridge device using Indy, but that only had to deal with handshakes with a command sent from the client and a response being sent back almost instantly.
These commands are not started with STX but ended with ETX.
So this is implemented as follows (excerpt from config utility code), hopefully I could re-use some of that code:


Code:
implementation
const
  STX = 2;
  ETX = 3;

constructor TConfigCommHandler.Create;
begin
  FComm := TIdTCPClient.Create(NIL);
  FComm.IPVersion := Id_IPv4;
  FComm.ReadTimeout := 5000;
  FComm.ConnectTimeout := 5000;
  FTcpConnected := false;
  FComm.OnConnected := OnConnected;
  FComm.OnDisconnected := OnDisconnected;
end;

procedure TConfigCommHandler.OnConnected(Sender: TObject);
begin
  FTcpConnected := true;
end;

procedure TConfigCommHandler.OnDisConnected(Sender: TObject);
begin
  FTcpConnected := false;
end;

procedure TConfigCommHandler.SendCommInfo(Msg: AnsiString);

//Show string in listbox on main form
begin
  if Assigned(FOnComm) then
    FOnComm(Self, Msg);
end;

function TConfigCommHandler.Connect(Server: string; Port: word): boolean;
{Connect connects to the server:port}
begin
  try
    Result := false;
    FComm.Connect(Server, Port);
    while not FTcpConnected do
    begin
      Sleep(1);
    end;
    Result := FTcpConnected;
  except
    on E: Exception do
    begin
      FLastError := E.Message;
    end;
  end;
end;

function TConfigCommHandler.GetItem(Cmd: TIdBytes; var Data: TIdBytes): boolean;
var
  Resp: AnsiString;
  LPos: Integer;
begin
  Result := false;
  SetLength(Data, 0);
  BytesToStr(Cmd, Resp);
  SendCommInfo('=> ' + Resp);
  try
    FComm.IOHandler.Write(Cmd);
    FComm.IOHandler.Write(Byte(ETX));
    FComm.IOHandler.ReadBytes(Data, -1, false);
    Result := Length(Data) > 0;
    if Result then
    begin
      if Data[Length(Data)-1] <> ETX then
      begin
        FLastError := 'Final ETX missing!';
        Result := false;
        SendCommInfo(FLastError);
      end
      else
      begin
        SetLength(Data, Length(Data) -1); //Remove trailing ETX
        BytesToStr(Data, Resp);
        SendCommInfo('<= ' + Resp);
      end;
    end
    else
    begin
      FLastError := 'No data received within timeout!';
      SendCommInfo(FLastError);
    end;
  except
    on E: Exception do
    begin
      Result := false;
      FLastError := 'Exception: ' + E.Message;
      SendCommInfo(FLastError);
      Exit;
    end;
  end;
end;


In the main application the FOnComm procedure is implemented as follows to show incoming data:


Code:
procedure TfrmMainConfig.OnComm(Sender: TObject; Msg: AnsiString);
begin
  lbxComm.Items.Add(Msg);
  lbxComm.ItemIndex := lbxComm.Count-1;
end;

As this test is aimed at nailing some randomly occurring timing problems I need to accurately time the arrival of the packets to see if there is any problem in the bridge device. I want to log any time deviation from the 1000 ms mark so see what is going on.
The real consumer of the data sent trough the bridge is an Android App and I suspect that we might be dealing with a problem in that, but I have to prove it. Different developers....
Reply
#2
ProcessMessages wont help. A thread sounds like what might work best in your scenario.
Reply
#3
And this is what gets me stuck every time I encounter blocking devices....
I never seem able to make any working code using threads. That is why my config code shown above looks like it does...
Do you have any idea how that can be done in detail?
Reply
#4
This is standard threading.

1) Create a thread.
2) Create and connect socket
3) Read and wait for data
4) Synchronize data to main thread.
Reply
#5
Done and working.
Used this webpage as source of ideas.
Synchronize did the trick.
Reply


Forum Jump:


Users browsing this thread: 1 Guest(s)