Your timer code is not reading the data correctly. The Connected() method performs a read operation, so it is likely to receive bytes you are expecting, thus InputBufferIsEmpty() does not return False and you then skip calling AllData(). Which is also the wrong reading method to use, as it reads until the connection is disconnected and then returns what was read. That is not what you want in this situation.
The data you are looking for is JSON formatted data, so you should read based on the JSON format. In this particular case, the greeting and WATCH replies are both JSON objects with no nested sub-objects, so it would be good enough to simply read from the starting curly brace to the ending curly brace once you detect data arriving, eg:
procedure TForm2.Timer1Timer(Sender: TObject);
var
ReceivedText: string;
begin
Timer1.Enabled := False;
try
with IdTCPClient1 do
begin
if not Connected then Exit();
// read any data in
if IOHandler.InputBufferIsEmpty then
begin
IOHandler.CheckForDataOnSource(0);
IOHandler.CheckForDisconnect;
if IOHandler.InputBufferIsEmpty then Exit();
end;
IOHandler.WaitFor('{', False);
ReceivedText := IOHandler.WaitFor('}', True, True, IndyTextEncoding_UTF8);
Memo1.Lines.Add(ReceivedText);
// if not already, send streaming command
if not SentStreamCommand then
begin
IdTCPClient1.IOHandler.WriteLn('?WATCH={"enable":true,"json":true}');
SentStreamCommand := True;
end;
end;
finally
if IdTCPClient1.Connected then
Timer1.Enabled := True;
end;
end;
Though, this really isn't the best way to handle this situation. Knowing that the server always sends a greeting banner, and each request sends a reply, I would simply get rid of the timer altogether and do a blocking read immediately after connecting, and after sending each request. And move the logic into a worker thread so the UI thread is not blocked.
But, if you must use the UI thread, a better option would be to find a JSON parser that supports a push model, then you can push the raw bytes you read from the socket connection into the parser and let it notify you via callbacks whenever it has parsed complete values for you to process. Not all replies in the GPSD protocol are simple objects. Some replies can be quite complex, more than the code above can handle. For instance, the reply to a POLL request contains an array of sub-objects.
An even better option is to use a pre-existing GPSD library (there are C based libraries available for GPSD, and C libraries can be used in Delphi) and let the library handle these kind of details for you.