![]() |
Daten abholen bei TCPClient
Hallo, ich komme einfach nicht mehr weiter, über einen Timer kann
ich wunderschön meine Daten abholen. Da ich aber mehrere Strings gesendet bekomme will ich warten bis alles da ist. Über meine Procedure TForm1.ReadData; bekomme ich nichts ausgelesen. Über Timer geht es, woran liegt das ? mfg
Delphi-Quellcode:
{#######################################################}
{ Timer1 Interval 100 } {#######################################################} procedure TForm1.Timer1Timer(Sender: TObject); begin if not Form1.TCPClient.Connected = true then Exit; if Form1.TCPClient.IOHandler.InputBufferIsEmpty then Exit; rec_str:= Form1.TCPClient.IOHandler.ReadLn(); edit10.Text:= edit10.Text + rec_str; Memo1.Lines.Add(rec_str); end; {#######################################################} { TCP auslesen } {#######################################################} Procedure TForm1.ReadData; var StartTimeOut : Integer; tmp : String; begin rec_str:= ''; StartTimeOut := Gettickcount + 200; //200Ms bis zum ersten zeichen... while Gettickcount < StartTimeOut do begin if not Form1.TCPClient.IOHandler.InputBufferIsEmpty then begin tmp:= Form1.TCPClient.IOHandler.ReadLn(); rec_str := rec_str + tmp; StartTimeOut := Gettickcount + 100; //100ms TimeOut erhöhung.. end; application.processmessages; //Anti Freeze end; Memo1.Lines.Add(rec_str); end; |
AW: Daten abholen bei TCPClient
Hallo,
ich kenne dioe benutzte Komponente jetzt nicht, aber falls diese ein Event zum Abholen der Daten bereitstellt wäre es sinnvoll dieses zu benutzen. EIn Timer dient dann nur noch der Timeout Erkennung. Application.ProcessMessages sollte man ja schließlich soweit möglich vermeiden. |
AW: Daten abholen bei TCPClient
Es ist die IdTCPClient1 und ich kann nichts erkennen das diese
Komponente ein Event zum Abholen hat. application.processmessages; habe ich mal rausgenommen. mfg |
AW: Daten abholen bei TCPClient
.. gutes neues Jahr.
Vielleicht ist es besser das Auslesen in einen Thread zu packen, Beispiele sind hier: ![]() und hier ![]() Vielleicht kannst Du auch das onWork Event des idTcpClients nutzen? Grüße Klaus |
AW: Daten abholen bei TCPClient
InputBufferIsEmpty wird wahrscheinlich immer True ergeben und somit kommt es nie zum ReadLn.
Der InputBuffer wird erst gefüllt, wenn überhaupt etwas abgefragt wird. Nimm die Prüfung auf InputBufferIsEmpty mal raus, dann wird es wahrscheinlich funktionieren. Testweise kannst auch probieren, vor dem InputBufferIsEmpty TCPClient.IOHandler.CheckForDataOnSource aufzurufen. Das prüft überhaupt erst, ob ein Daten vorhanden sind. Die Lösung mit dem Timeout würde ich aber nochmal überdenken. Du hast auch kein richtiges Kriterium dafür, wann die Daten vollständig gelesen wurden. Das könnte z.B. eine empfangene Leerzeile sein oder das Schließen der Verbindung. Also eine Schleife in der Art "while Connected do" Sinnvoller ist es aber auf jeden Fall, das ganze in einen Thread auszulagern. Dann kann Du auch direkt ReadLn aufrufen, ohne zu prüfen, ob Daten vorhanden sind, da nur dieser Thread und nicht die Benutzeroberfläche (der Main-Thread) blockiert wird. Das ProcessMessages rauszunehmen hat ja jetzt auch nur bewirkt, das das Programm einfriert, solange auf Daten gewartet wird. Warum es mit dem Timer trotzdem funktionierte, kann ich nicht sagen. Evtl. wird InputBufferIsEmpty irgendwann nach dem Schließen der Verbindung False und in der Funktion ReadData brichst Du durch den Timeout schon früher ab. Der Timer ist aber auch keine gute Lösung. |
AW: Daten abholen bei TCPClient
Danke für eure Hilfe.
ich habe mir das mal angeschaut. ![]() ![]() Aber das ist noch zu hoch für mich, da brauche ich noch ein paar Jahre um da durch zu blicken. mfg |
AW: Daten abholen bei TCPClient
Das Thread-Beispiel aus Stackoverflow ist eigentlich recht übersichtlich. Versuch es doch einfach mal damit und melde Dich, wenn Du Fragen hast.
Wenn Du ein aktuelles Delphi verwendet, würde es noch etwas einfacher gehen mit der Parallel Programming Library. Ich meine, das gab es ab Delphi XE7. In etwa so (nicht getestet!)
Delphi-Quellcode:
Da muss natürlich noch eine Abbruchbedingung rein statt dem "while true".
uses System.Threading;
... Procedure TForm1.Readdata; var aTask: ITask; begin aTask := TTask.Create( procedure var s: string; begin while true do begin s := TCPClient.IOHandler.ReadLn(); TThread.Synchronize(nil, procedure begin Memo1.lines.add(s); end); end; end); aTask.Start; end; |
AW: Daten abholen bei TCPClient
Liste der Anhänge anzeigen (Anzahl: 1)
Guten abend,
ich habe dein Code mit dem Thread getestet, aber da bekomme ich noch Probleme. Mein großes Problem ist das ich Daten von einen ESP32 (micro SD Card auslesen) bekomme, aber viele strings mit #13#10 Ich hatte mal vor langer Zeit einen Thread gebastelt und dieser läuft super. Ich habe es jetzt so gemacht.
Delphi-Quellcode:
procedure TMyThread.Execute;
var i : integer; Begin while bool = true do begin if Form1.TCPClient.Connected = true then begin if not Form1.TCPClient.IOHandler.InputBufferIsEmpty then begin rec_str:= Form1.TCPClient.IOHandler.ReadLn(); Form1.Edit10.Text:= Form1.Edit10.Text +rec_str; Form1.Memo1.Lines.Add(rec_str); end; end; end; End; Wenn ich den Befehl ListDir an den ESP32 sende lösche ich vorher Memo1.clear damit ich meinen String alleine im Memo Feld habe, danach kopiere ich Empfstr:= Memo1.lines.text; in den Empfstr.. Weil ich den Empfstr in meiner Procedure ListBox zerlege. aber dieser wird nicht kopiert Empfstr ist leer Deswegen musste ich Edit10 füllen Form1.Edit10.Text:= Form1.Edit10.Text +rec_str; Jetzt drücke ich eine taste Button10
Delphi-Quellcode:
Und jetzt wird die Listbox verarbeitet wie im Bild gezeigt.
procedure TForm1.Button10Click(Sender: TObject);
begin Empfstr:= memo1.Lines.Text; Proc_Fat16_Dir_anzeigen; end; Was passiert da, bin ich zu schnell im Programm ? Das Memo1 noch gar keine Daten hat wenn ich meine Proc_Fat16_Dir_anzeigen; aufrufe ? Aber so bekomme ich meine daten vom ESP32 sehr gut. mfg |
AW: Daten abholen bei TCPClient
Wenn das Readln in meinem Beispiel leere Zeilen zurückgibt, kannst Du die ja ausschließen mit if s<> '' then...
Ich ging davon aus, dass die Funktion erst zurückkehrt, wenn tatsächlich neue Daten gelesen wurden. In Deinem Thread gibt es noch ein Problem: Du solltest nicht einfach aus dem Thread auf die Controls Memo1 und Edit10 zugreifen. Dafür war das Synchronize in meinem Beispiel da. In Deinem Beispiel müsste das etwa so aussehen:
Delphi-Quellcode:
Ich habe nicht ganz verstanden, was Du mit "bin ich zu schnell im Programm" meinst, aber vielleicht ist das damit ja gelöst :)
rec_str:= Form1.TCPClient.IOHandler.ReadLn();
Synchronize( procedure begin Form1.Edit10.Text:= Form1.Edit10.Text +rec_str; Form1.Memo1.Lines.Add(rec_str); end); |
AW: Daten abholen bei TCPClient
Guten morgenm, ich werde mein Problem doch etwas besser beschreiben.
Ich habe an meinen ESP32 eine micro SD Card und diese will ich auch auslesen. Mit Butten ListDir. Der Thread Funktioniert Super ich bekomme alle Daten rein.
Delphi-Quellcode:
Den Dir_List_str:= ''; leere ich bevor ich den Befehl Form1.TCPClient.IOHandler.Writeln('D' +#12); sende.
procedure TMyThread.Execute;
var i : integer; Begin while bool = true do begin if Form1.TCPClient.Connected = true then begin if not Form1.TCPClient.IOHandler.InputBufferIsEmpty then begin rec_str:= Form1.TCPClient.IOHandler.ReadLn(); Synchronize( procedure begin Dir_List_str:= Dir_List_str +rec_str; Form1.Memo1.Lines.Add(rec_str); end); end; end; end; End; Hier meine Button ListDir;
Delphi-Quellcode:
jetzt muss ich showmessage('Dir List eingelesen.!'); vorher machen,
//List Dir
procedure TForm1.ListDirClick(Sender: TObject); begin Dir_List_str:= ''; memo1.Clear; ListBox1.Clear; Form1.TCPClient.IOHandler.Writeln('D' +#12); showmessage('Dir List eingelesen.!'); Proc_Fat16_Dir_anzeigen; end; mache ich das nicht und gehe dann sofort in Proc_Fat16_Dir_anzeigen. Ist der Dir_List_str leer. es ist mir schon klar wenn ich den Befehl Form1.TCPClient.IOHandler.Writeln('D' +#12); sende das es eine Zeitlang dauert bis die Daten da sind. Ich denke ich gehe zu schnell in meine Proc_Fat16_Dir_anzeigen; Ich hoffe ich habe das jetzt besser erklärt. mfg |
AW: Daten abholen bei TCPClient
Hallo Schuby,
also wenn ich dich richtig verstehe sendest du mit Form1.TCPClient.IOHandler.Writeln('D' +#12); deinen Befehl damit dein ESP32 die Daten senden soll. Ich hab mal meine 22 Jahre alte Routine genommen wo ich in einer CNC-Maschine Daten abfrage. Das Gegenstück ist dort ein von mir erstelltes Delphi-Servermodul. Bei meinem Client hole ich es so ab:
Delphi-Quellcode:
Hab mal meinen Befehl mit deinem ersetzt. Statusbar etc. kannst, raus werfen vielleicht funktioniert es mit deinem ESP32.
var
AStream: TMemoryStream; SimulationsPfad, ctdata, LInString: string; begin ... hier müsstest du noch SimulationsPfad, ctdata mit deinem Zielpfad ersetzen if(IdTCPClient.Connected = FALSE) then IdTCPClient.Connect; try StatusBar.Panels.Items[0].Text := 'Werkzeugdaten online aus Maschine abfragen...'; IdTCPClient.IOHandler.WriteLn('D' +#12); // Hier war mein Befehl AStream := TMemoryStream.Create; //OutputDebugString('Readstream...'); IdTCPClient.IOHandler.ReadStream(AStream, -1, FALSE); //ShowMessage(IntToStr(AStream.Position)); AStream.Position := 0; AStream.SaveToFile(SimulationsPfad + ctdata); OutputDebugString(pchar('Stream gelesen und gesichert in ' + SimulationsPfad + ctdata)); FreeAndNil(AStream); LInString := IdTCPClient.IOHandler.ReadLn; // Kann sein das brauchst du nicht finally StatusBar.Panels.Items[0].Text := ''; IdTCPClient.Disconnect; end; |
AW: Daten abholen bei TCPClient
Das war ja noch so eine unklare Geschichte: Wann ist die Übertragung beendet? Schließt die Gegenstelle die Verbindung, wenn alles übertragen wurde? Oder sendet sie ein bestimmtes Zeichen?
Wird denn der Thread beendet, wenn die Übertragung abgeschlossen ist? Du könntest dann entweder nach der Schleife im Thread mit Synchronize die Funktion aufrufen (Proc_Fat16_Dir_anzeigen), um die Daten in der Listbox auszugeben oder Du verwendest das OnTerminate-Ereignis des Threads, das Dich informiert, wenn der Thread beendet wurde. Wird der Thread nicht beendet und wartet ewig auf weitere Daten des ESP32, müsstest Du eine Abbruchbedingung haben. Das müsste ja aus der Dokumentation hervorgehen. Wird evtl. auch ein Zeichen #12 gesendet, wie Du es beim Senden von Daten verwendest? Dann könntest Du evtl. mit ReadLn(#12) arbeiten, das dann in einem Rutsch die Daten bis zu diesem Zeichen zurückgibt. Oder mit WaitFor(#12) auf das Zeichen warten und dann den Buffer auslesen. |
AW: Daten abholen bei TCPClient
Es ist geschafft.! So gehts und ich bin zufrieden.
ok ok das ok1 mit LF könnte ich noch anders machen. Na mal sehen
Delphi-Quellcode:
Ich Danke allen das ihr einen alten Mann (fast 70zig) geholfen habt.
procedure TMyThread.Execute;
var i : integer; Begin while bool = true do begin if Form1.TCPClient.Connected = true then begin if not Form1.TCPClient.IOHandler.InputBufferIsEmpty then begin rec_str:= Form1.TCPClient.IOHandler.ReadLn(); // rec_str:= Form1.TCPClient.IOHandler.InputBufferAsString; if rec_str = 'ok1' then begin Form1.Proc_Fat16_Dir_anzeigen; rec_str:= ''; end; Synchronize( procedure begin Dir_List_str:= Dir_List_str +rec_str; Form1.Memo1.Lines.Add(rec_str); end); end; end; end; End; mfg |
AW: Daten abholen bei TCPClient
Prima, dass es jetzt klappt.
Eine kleine Anmerkung noch: Das "Form1.Proc_Fat16_Dir_anzeigen;" müsste auch in ein Synchronize eingeschlossen werden, da vom Thread aus auf Komponenten der Benutzeroberfläche zugegriffen wird. Wo kommt denn das "Ok1" jetzt her? Schreibst Du auch das Programm auf der Gegenstelle, dem ESP32, selbst? |
AW: Daten abholen bei TCPClient
Ja das würde mich auch interessieren mit dem ok1, aber auch diesem ESP32 kannte ich nicht und scheint ein interessantes Teil zu sein vor allem recht günstig, jetzt braucht man nur noch ein paar Ideen wo man es einsetzt.
|
AW: Daten abholen bei TCPClient
Hallo zusammen, ja den ESP32 Programmiere ich selber mit C/C++ *wüürrg*
Dazu habe ich Visual Studio Code Installiert (free), in VS dann PlatformIO Es gibt viele Youtube Videos wie man das macht. Der ESP32 kann 240Mhz :-) TFT Display / microSD / DHD22 angeschlossen Soll eine Steuerung für meinen Reifeschrank für Salami geben Ich hoffe so ist es richtig weil damit habe ich keine Probleme.
Delphi-Quellcode:
procedure TMyThread.Execute;
var i : integer; Begin while bool = true do begin if Form1.TCPClient.Connected = true then begin if not Form1.TCPClient.IOHandler.InputBufferIsEmpty then begin rec_str:= Form1.TCPClient.IOHandler.ReadLn(); Synchronize( Procedure Begin if rec_str = 'ok1' then begin Form1.Proc_Fat16_Dir_anzeigen; rec_str:= ''; end; Dir_List_str:= Dir_List_str +rec_str; Form1.Memo1.Lines.Add(rec_str); end); end; end; end; End; mfg |
AW: Daten abholen bei TCPClient
Jetzt ergibt auch auch der Screenshot mit dem Dateinamen "Ahleworscht.txt" einen Sinn. Und ich hielt es für einen beliebigen Testdateinamen :)
Dann weiterhin viel Erfolg beim Basteln und dem Reifen der Worscht. Da zeigt sich doch wieder, wie vielseitig Delphi ist. Muss mich momentan auch oft mit C++ herumschlagen und weiß seitdem Delphi besonders zu schätzen... |
AW: Daten abholen bei TCPClient
Hallo @gubbe
ja die Ahle Rote Worscht kommt aus Nord Hessen. :-) Also der ESP32 bringt mich noch um, habe den SD Driver Installiert, aber bekomme nur ab und zu Info ListDir. Im ESP32 habe ich soweit alles hinbekommen. 1. Datum Zeit 2. DHT22 3. TFT ILI9341 4. micro SD funzt nur zum teil Ich glaube ich lasse es mit dem ESP32 und C/C++ und haue mir einen AtXmega drauf und Programmiere den unter Pascal. Pascal Programmiere ich schon seit Jahren. Und der ESP wird nur das WLAN durch schleifen zum AtXmega. mfg |
AW: Daten abholen bei TCPClient
Zitat:
|
AW: Daten abholen bei TCPClient
Zitat:
Allerdings habe ich auch parallel die ArduinoIDE installiert, weil die doch mehr Beispiele und diese übersichtlicher sortiert hat, das fehlt mir ein bischen in PlattformIO. Den Code kann man dann in PlattformIO in der Regel 1:1 übernehmen und damit weiterarbeiten. |
AW: Daten abholen bei TCPClient
@hes
Das mache ich auch morgen, ich fahre zu dem großen MM und hole mir eine neue micro sd card. Ich habe hier min 4 stück, (sehr alte) aber nur eine kann ich ab und zu lesen. Im mom noch fliegender aufbau bevor ich die Platine bestelle. Wichtig ist auch die leitungen kurz zu halten und 100nf und 1uf Kondensator direkt vor dem Reader einlöten. Aber ich bekomme Probleme. Und ich verstehe es nicht @Rollo62 So mache ich das auch. mfg |
Alle Zeitangaben in WEZ +1. Es ist jetzt 00:58 Uhr. |
Powered by vBulletin® Copyright ©2000 - 2025, Jelsoft Enterprises Ltd.
LinkBacks Enabled by vBSEO © 2011, Crawlability, Inc.
Delphi-PRAXiS (c) 2002 - 2023 by Daniel R. Wolf, 2024-2025 by Thomas Breitkreuz