Delphi-PRAXiS
Seite 1 von 2  1 2      

Delphi-PRAXiS (https://www.delphipraxis.net/forum.php)
-   Netzwerke (https://www.delphipraxis.net/14-netzwerke/)
-   -   Daten aus TClientSocket verarbeiten (https://www.delphipraxis.net/206692-daten-aus-tclientsocket-verarbeiten.html)

js747a 19. Jan 2021 19:35

Daten aus TClientSocket verarbeiten
 
Ich schreibe ein Programm zur steuerung eine Modellbahn. Ich schicke Daten über TCP (TClientSocket) an eine Modellbahn Zentrale.
Die Daten bestehen aus 13 Bytes

Ich bekomme diese 13 Byte leicht verändert wieder zurück.

- Bytes 1 bis 4 sind die Meldungskennung.
- Byte 5 entspricht dem DLC der CAN-Meldung.
- Bytes 6 - 13 sind die entsprechenden Nutzdaten.

Wie kan ich diese jetzt wieder zerlegen um

Zun Beispiel den PowerOn Button schickt 00004711 5 00 00 00 00 01

procedure TForm1.PowerOnButtonClick(Sender: TObject); //00004711 5 00 00 00 00 01 GO Alle
Var i : Integer;
mySendingString : String;
myDLC : Byte; //Anzahl der Datenbytes im CAN-Paket, 1 Byte
myPrio : Byte; //Priorität des befehls
myResponseBit : Byte; // wenn wir als PC-Programm senden, ist dieses Bit immer 0
myStartWord : SmallInt; // die Kombination aus Prio, Command und Responsebit
myUID : Integer; // Zieladresse des Objektes auf dem CAN, 32 Bits
myHash : SmallInt; // unser Hash, 16 Bits
myCommand : Byte; // unser Befehl, 8 Bits
mySubCommand : Byte; // unser Unterbefehl, 8 Bits
myDataBytes : Array[0..7] of Byte; // array[0..7] of Byte,

begin
myPrio := 0; // wir haben keine Priorität
myCommand := 0; // 0x00 = 0 Systembefehl
mySubCommand := 1; // Power ON - System Go (0x01)
myHash := 18193; // wie im Beispiel, kann aber auch &h0300 sein (als Minimum)
myDLC := 5; // 5 Bytes Nutzdatenlänge
myUID := 0; // UID = 0 bedeutet: sende den Befehl an alle
for i := 0 to 7 do myDataBytes[i] := 0; //Märklins Doku zählt auch von D0 .. D7

myStartWord := ( ((myPrio SHL 12) + (myCommand SHL 1) + (myResponseBit AND 1)) AND 255 );
myDataBytes[0] := ((myUID SHR 24) AND 255); // Big Endian encoding
myDataBytes[1] := ((myUID SHR 16) AND 255);
myDataBytes[2] := ((myUID SHR 8) AND 255);
myDataBytes[3] := (myUID AND 255);
myDataBytes[4] := mySubCommand;

mySendingString := Chr((myStartWord SHR 8) AND 255) + Chr(myStartWord AND 255);
mySendingString := mySendingString + Chr((myHash SHR 8) AND 255) + Chr(myHash AND 255);
mySendingString := mySendingString + Chr(myDLC AND 255);
for i := 0 to 7 do mySendingString := mySendingString + Chr(myDataBytes[i] AND 255);

CS2ClientSocketSend.Socket.SendText(mySendingStrin g);

end;


Wenn ich die Antwort in eine Memo gebe sehe ich nichts.

CS2MeldungenMemo.lines.add('Empfangen : ' + Socket.ReceiveText + IntToStr(Length(Socket.ReceiveText)));

zeigt mir nur 'Empfangen :'

jaenicke 19. Jan 2021 20:02

AW: Daten aus TClientSocket verarbeiten
 
Sinnvoller wäre hier Indy (TIdTcpClient) zu verwenden und echte Bytes zu schicken statt die in Strings zu quetschen... (Davon abgesehen von TClientSocket und TServerSocket nach Delphi 7 gar nicht mehr standardmäßig mit installiert, sprich sie sind veraltet.)
Vielleicht kommen die Bytes so gar nicht richtig an, auch wenn das bei Delphi 7 noch ein kleineres Problem war (ohne Unicode).

In welcher Methode holst du denn die Antwort ab?

js747a 19. Jan 2021 20:29

AW: Daten aus TClientSocket verarbeiten
 
Eigentlich sollte es ja uber UDP gehen aber da komme ich auch nicht weiter.

Hier mal Tekst aus der Protocol Beschreibung.

Wenn gestartet, lauscht das Gateway auf dem Ethernet Empfangsport 15731. Es verwirft alle UDP-Pakete,
die eine Länge ungleich 13 haben. Pakete der Länge 13 werden als Can-Bus-Pakete interpretiert: 4 Byte
Can-Bus-Id (BigEndian oder Network-Order), 1 Byte Länge und 8 Byte Daten, die ggf. mit Nullbytes
aufzufüllen sind. Dieses Paket wird dann als Can-Bus-Botschaft auf den Can-Bus gegeben. Nicht
abzubildende Bits oder Bytes auf dem CAN-Bus werden nicht beachtet und sollten auf "0" gesetzt werden.
Umgekehrt liest das Gateway alle Can-Bus-Botschaften, wandelt sie in analoger Weise in UDP-Pakete der
Länge 13 um und verschickt diese an die spezifizierte IP-Adresse und den Sendeport (15730).

Ich musste auf dem Port 15731 Senden aber empfangen auf dem Port 15730.

Wenn ich die 13 Bytes so verpacke und dan über TCP verschicke kommen sie an und die Zentrale reagiert auch.
Ich bekomme nur immer 0 Byte zuruck.

Ich hole die Antwort mit
procedure TForm1.CS2ClientSocketSendRead(Sender: TObject; Socket: TCustomWinSocket);

und bearbeite dan Socket.ReceiveText

Klaus01 19. Jan 2021 20:39

AW: Daten aus TClientSocket verarbeiten
 
.. Deine IP Adresse ist in der Zentral hinterlegt worden?
Lauscht Du auf Port 15730 TCP oder UDP.
Laut Text schickt die Zentrale UDP Pakete.

Für die 13 Byte wäre ein Record zum Schreiben und Lsene vielleicht besser?

Grüße
Klaus

js747a 19. Jan 2021 21:07

AW: Daten aus TClientSocket verarbeiten
 
Meine IP Adresse ist in der Zentral hinterlegt worden
Ich Lausche Du auf Port 15730 TCP

Laut Text schickt die Zentrale UDP Pakete. Aber mann kan auch über TCP zenden. Die zentrale reagiert ja.

Wie könnte ich das über UDP machen.

Klaus01 20. Jan 2021 06:13

AW: Daten aus TClientSocket verarbeiten
 
Guten Morgen,

für UDP Daten gibt es TIdUdpClient und TIdUdpServer.
Ob etwas auf Deinem Port 15730 ankommt, kannst Du auch mit Hilfe von Wireshark feststellen.
Dort kannst Du dann auch sehen, ob die Daten auf TCP oder UDP daher kommen.

Grüße
Klaus

jaenicke 20. Jan 2021 06:43

AW: Daten aus TClientSocket verarbeiten
 
Zitat:

Zitat von js747a (Beitrag 1481249)
Meine IP Adresse ist in der Zentral hinterlegt worden
Ich Lausche Du auf Port 15730 TCP

Du schreibst aber etwas von CS2ClientSocketSendRead. Wenn du auf dem Port lauschen möchtest, brauchst du aber einen TServerSocket oder eben die Indy Alternative TIdTcpServer bzw. TIdUdpServer.

Wenn du das nicht kommerziell machst, wäre auch ein Update auf eine aktuelle Delphiversion (Delphi Community Edition) sinnvoll, auch wenn die Funktionalität auch mit Delphi 7 klappen würde. Aber warum ein neues Projekt mit einer so alten Delphiversion beginnen?

js747a 20. Jan 2021 16:13

AW: Daten aus TClientSocket verarbeiten
 
Ich habe schon mal Delpi 10.3 installiert und ausprobiert. Da ich in Meinem Programm zur steuerung auch andere Zentralen habe brauch ich auch einen Comport zugriff.
Das habe ich mit Delphi 10.3 versucht aber die Daten die ich dort bekam waren nicht wie in Delphi 7.
Etwas mit der veränderung der Variabelen ab Delphi 9 glaub ich. AnsiString und AnsiChar


https://www.delphipraxis.net/204574-...ml#post1466719

Deshab bin ich wieder zu Delphi 7 zurück.

Ich verwende ein TClientSocket und damit kann ich nachrichten schicken die von der zentrale erkannt werden.
Die Zentrale musste mir dieselbe nachricht, nur 1 Byte verändert wieder zuruck schicken. Ich sehe aber keine Antwort.


###Meine Senden Procedure
Var i : Integer;
mySendingString : String;
myDLC : Byte; //Anzahl der Datenbytes im CAN-Paket, 1 Byte
myPrio : Byte; //Priorität des befehls
myResponseBit : Byte; // wenn wir als PC-Programm senden, ist dieses Bit immer 0
myStartWord : SmallInt; // die Kombination aus Prio, Command und Responsebit
myUID : Integer; // Zieladresse des Objektes auf dem CAN, 32 Bits
myHash : SmallInt; // unser Hash, 16 Bits
myCommand : Byte; // unser Befehl, 8 Bits
mySubCommand : Byte; // unser Unterbefehl, 8 Bits
myDataBytes : Array[0..7] of Byte; // array[0..7] of Byte,

begin
myPrio := 0; // Byte - wir haben keine Priorität immer 0
myCommand := 0; // Byte - 0x00 = 0 Systembefehl
mySubCommand := 1; // Power ON - System Go (0x01)
myHash := 18193; // SmallInt - wie im Beispiel, kann aber auch &h0300 sein (als Minimum)
myDLC := 5; // Byte
myUID := 0; // Integer - UID = 0 bedeutet: sende den Befehl an alle
for i := 0 to 7 do myDataBytes[i] := 0; //Märklins Doku zählt auch von D0 .. D7

myStartWord := ( ((myPrio SHL 12) + (myCommand SHL 1) + (myResponseBit AND 1)) AND 255 );
myDataBytes[0] := ((myUID SHR 24) AND 255); // Big Endian encoding
myDataBytes[1] := ((myUID SHR 16) AND 255);
myDataBytes[2] := ((myUID SHR 8) AND 255);
myDataBytes[3] := (myUID AND 255);
myDataBytes[4] := mySubCommand;

mySendingString := Chr((myStartWord SHR 8) AND 255) + Chr(myStartWord AND 255);
mySendingString := mySendingString + Chr((myHash SHR 8) AND 255) + Chr(myHash AND 255);
mySendingString := mySendingString + Chr(myDLC AND 255);
for i := 0 to 7 do mySendingString := mySendingString + Chr(myDataBytes[i] AND 255);

ClientSocket1.Socket.SendText(mySendingString );
###

Antwort in
procedure TForm1.ClientSocket1Read(Sender: TObject; Socket: TCustomWinSocket);
Begin
CS2MeldungenMemo.lines.add('Empfangen : ' + Socket.ReceiveText);
End;

Die Antwort sollte immer Ursprünglicher Befehl mit gesetztem Response Bit sein.

Wie zerlege ich die antwort wieder in Bytes.

Klaus01 20. Jan 2021 16:24

AW: Daten aus TClientSocket verarbeiten
 
.. in Delphi 10.3 sind Character 2 Byte groß (UniCode).
Die Strings die Du nun verschickst enthalten das doppelte der 13 Bytes.
Verabschiede Dich bitte von Strings bei der Datenübertragung (auf dem Layer 4)-
da wird in der Regel mit Bytes gearbeitet.

Wie schon mal angemerkt, versuche es mal mit einem Datenrecord.

Grüße
Klaus

js747a 20. Jan 2021 19:31

AW: Daten aus TClientSocket verarbeiten
 
Danke ich muss mir das noch mal ansehen.
Im Moment kann ich die Antwort in Bytes umwandeln und anzeigen.

Gruß John


Alle Zeitangaben in WEZ +1. Es ist jetzt 04:20 Uhr.
Seite 1 von 2  1 2      

Powered by vBulletin® Copyright ©2000 - 2024, Jelsoft Enterprises Ltd.
LinkBacks Enabled by vBSEO © 2011, Crawlability, Inc.
Delphi-PRAXiS (c) 2002 - 2023 by Daniel R. Wolf, 2024 by Thomas Breitkreuz