Schnittstelle mitschneiden und Daten auswerten

Wenn du dir nicht sicher bist, in welchem der anderen Foren du die Frage stellen sollst, dann bist du hier im Forum für allgemeine Fragen sicher richtig.
Antworten
würmchen
User
Beiträge: 255
Registriert: Mittwoch 7. November 2007, 14:17

Hallo alle,
ich bin gerade dabei einer Schnittstelle zu lauschen und die Daten mitzuschneiden.
Ich habe ein Schnittstellenprotokoll, somit kann ich eigentlich übersetzen, was ich da empfange. Ich bin mir aber im Moment unsicher, wie ich am besten vorgehen soll um mein Ziel zu erreichen.

Ich habe mir das uspp Paket heruntergeladen und kann damit im Moment meine Schnittstelle auslesen, das klappt wunderbar und ich mache das im prinziep in einer while schleife...

Code: Alles auswählen

import uspp
tty = uspp.SerialPort("/dev/ttyS0",1000,1200,"485")
while(True):
    tty.read(1).encode("hex")
Ergebnis sind dann eben die Bytes die über den Seriellen Port gehen.

Ich bin jetzt am überlegen wie ich es am geschicktesten mache, das in zusammengehörige Pakete einzubauen. Gesendet werden immer 4 Byte und die Antwort besteht auch aus 4 Byte.
Von der Geschwindigkeit sind es 40 Byte pro Sekunde. Ich bin mir jetzt nicht sicher ob ich mit einem regexp oder etwas anderem nach "Frage und dazugehöriger Antwort" suchen soll oder irgendwie anders.

Vielleicht gibt es auch bessere Methoden als mit uspp die Schnittstelle abzuhören, aber ich habe im Netz nicht so viele Infos dazu bekommen.

Vielleicht kann mir da jemand ein paar Tipps geben, auch wie ich die Daten am besten speichere und ob ich mir von der Geschwindigkeit Gedanken machen muss oder so.

Achja, wie stoppe ich so ein System, wollte so eine Art Daemon laufen lassen oder sowas.

Danke schon mal.
Dauerbaustelle
User
Beiträge: 996
Registriert: Mittwoch 9. Januar 2008, 13:48

Naja, ich würde mich da nicht auf die Zeit verlassen (es sei denn, das Protokoll verlangt das ausdrücklich, d.h. wenn mal nicht 4 Bytes pro Zeiteinheit da sind, dass das trotzdem gleich behandelt wird) und Bytes zählen. Und alle 4 Bytes machst du im Hintergrund irgendwas anderes tolles, zB speicherst die Bytes oder so.

Wie du das beendest? Strg+C? :D
würmchen
User
Beiträge: 255
Registriert: Mittwoch 7. November 2007, 14:17

Ok, also ich hab an der Geschichte weiter gemacht und festgestellt, dass ich einfach immer 8 Byte einlesen kann und somit die Frage und die Antwort bekomme.
Ich hab das jetzt mehrfach getestet und es gibt mir immer genau den richtigen Bereich aus, somit kann ich den jetzt im Prinzip verarbeiten.

Wie mache ich das am besten.

Code: Alles auswählen

print tty.read(8).encode("hex")
liefert mir zum beispiel sowas:
1f01019001010172
Wobei 1f010190 vom Master kommt und 01010172 die Antwort von einem Gerät ist.

Ich weiß das 1f die Funktionsnummer ist
01 die Adresse
01 der Datenwert
90 die Prüfsumme ist. Wie kann ich so etwas komfortabel verarbeiten. Ich lese mir gerade die Dokumentation zu struct durch, wobei ich mir nicht sicher bin, ob es das richtige ist. Habe es bei der Suche hier im Forum gefunden.
BlackJack

@würmchen: Wenn es sich immer um Bytes handelt, kann man auch das `array`-Modul verwenden. Bei 8 Werten ist aber vielleicht auch ein einfaches ``map(ord, data)`` schon genug.
würmchen
User
Beiträge: 255
Registriert: Mittwoch 7. November 2007, 14:17

Also ich hab jetzt mal ein wenig mit struct gespielt und folgendes gebastelt (ich weiß der String ist zu lange, aber so sieht die Ausgabe gut aus... :-) )

Code: Alles auswählen

#!/usr/bin/python

import uspp
import struct

tty = uspp.SerialPort("/dev/ttyS0",10000,1200,"485")
while(True):
    i = tty.read(8)
    print "Frage:\t\tFunktion\t%3s\tAdresse\t%3s\tDaten\t%3s\tPruefsumme\t%3s\nAntwort:\tAdresse\t\t%3s\tLow\t%3s\tHigh\t%3s\tPruefsumme\t%3s" \
        % tuple([struct.unpack("B",a)[0] for a in i])
Die Ausgabe ist dann folgende:

Code: Alles auswählen

Frage:		Funktion	 40	Adresse	  4	Daten	  0	Pruefsumme	155
Antwort:	Adresse		  4	Low	  6	High	  3	Pruefsumme	124
Frage:		Funktion	 31	Adresse	  5	Daten	  1	Pruefsumme	148
Antwort:	Adresse		  5	Low	  1	High	  1	Pruefsumme	118
Frage:		Funktion	 40	Adresse	  5	Daten	  0	Pruefsumme	156
Antwort:	Adresse		  5	Low	 27	High	  3	Pruefsumme	146
Frage:		Funktion	 31	Adresse	  6	Daten	  1	Pruefsumme	149
Antwort:	Adresse		  6	Low	  1	High	  1	Pruefsumme	119
Frage:		Funktion	 40	Adresse	  6	Daten	  0	Pruefsumme	157
Antwort:	Adresse		  6	Low	  9	High	  3	Pruefsumme	129
Frage:		Funktion	 31	Adresse	  1	Daten	  1	Pruefsumme	144
Antwort:	Adresse		  1	Low	  1	High	  1	Pruefsumme	114
Frage:		Funktion	 41	Adresse	  1	Daten	  0	Pruefsumme	153
Antwort:	Adresse		  1	Low	  5	High	174	Pruefsumme	 35
Frage:		Funktion	 42	Adresse	  1	Daten	  0	Pruefsumme	154
Antwort:	Adresse		  1	Low	 43	High	  0	Pruefsumme	155
Frage:		Funktion	 43	Adresse	  1	Daten	  0	Pruefsumme	155
Antwort:	Adresse		  1	Low	254	High	  0	Pruefsumme	110
Frage:		Funktion	 31	Adresse	  2	Daten	  1	Pruefsumme	145
Antwort:	Adresse		  2	Low	  1	High	  1	Pruefsumme	115
Frage:		Funktion	 41	Adresse	  2	Daten	  0	Pruefsumme	154
Antwort:	Adresse		  2	Low	133	High	  2	Pruefsumme	248
Frage:		Funktion	 42	Adresse	  2	Daten	  0	Pruefsumme	155
Antwort:	Adresse		  2	Low	 41	High	  0	Pruefsumme	154
Frage:		Funktion	 43	Adresse	  2	Daten	  0	Pruefsumme	156
Antwort:	Adresse		  2	Low	253	High	  0	Pruefsumme	110
Frage:		Funktion	 31	Adresse	  3	Daten	  1	Pruefsumme	146
Antwort:	Adresse		  3	Low	  1	High	  1	Pruefsumme	116
Frage:		Funktion	 41	Adresse	  3	Daten	  0	Pruefsumme	155
Antwort:	Adresse		  3	Low	 53	High	155	Pruefsumme	 66
Frage:		Funktion	 42	Adresse	  3	Daten	  0	Pruefsumme	156
Antwort:	Adresse		  3	Low	 44	High	  0	Pruefsumme	158
Frage:		Funktion	 43	Adresse	  3	Daten	  0	Pruefsumme	157
Antwort:	Adresse		  3	Low	  5	High	  1	Pruefsumme	120
Frage:		Funktion	 31	Adresse	  4	Daten	  1	Pruefsumme	147
Antwort:	Adresse		  4	Low	  1	High	  1	Pruefsumme	117
Frage:		Funktion	 41	Adresse	  4	Daten	  0	Pruefsumme	156
Antwort:	Adresse		  4	Low	 88	High	161	Pruefsumme	108
Frage:		Funktion	 42	Adresse	  4	Daten	  0	Pruefsumme	157
Antwort:	Adresse		  4	Low	 44	High	  0	Pruefsumme	159
Die Antwort besteht immer aus einem Low und einem High Byte. Ich wollte jetzt weiter schauen wie ich die beiden zusammen füge, damit ich immer einen Integer wert heraus bekomme, das sollte ja irgendwie auch mit struct gehen.

Würde dann praktisch immer folgende Daten zusammen fassen:

Funktion, Adresse, Wert (nur noch einer, weil ich ja Low und High zusammenfasse)

Wenn ich jetzt beim schreiben so nachdenke sollte ich auch die Prüfsumme checken, um sicher zu sein das ich auch richtige Daten bekomme... Ich weiß nicht wie oft sich hier Fehler einschleichen...

Jemand noch eine Idee was ich noch beachten sollte?


@BlackJack dieses map(ord,data) schau ich mir jetzt auch mal an, vielleicht hilft es mir ja eher als das komische Zeug was ich die ganze Zeit mache.... :-)
BlackJack

@würmchen: `i` ist ein ungünstiger Name, da erwartet man eigentlich eine ganze Zahl hinter und keine Zeichenkette.

Das was Du mit `struct.unpack()` machst, ist vom Effekt ja nichts anderes als ein einfaches `map()` mit `ord()`. Du müsstest da schon das Format für alle 8 Bytes beschreiben. Also zum Beispiel 'BBBBBBBB' bzw. '8B', dann bekommst Du gleich ein Tupel mit allen Werten:

Code: Alles auswählen

In [680]: data
Out[680]: '(\x04\x00\x9b\x04\x06\x03|'

In [681]: struct.unpack('8B', data)
Out[681]: (40, 4, 0, 155, 4, 6, 3, 124)

In [682]: struct.unpack('< 4B BHB', data)
Out[682]: (40, 4, 0, 155, 4, 774, 124)
Das letzte Beispiel zeigt, wie man den Low- und High-Wert zusammenfassen kann. Man kann in der Formatangabe beliebig Leerzeichen einfügen -- das habe ich mal gemacht, um die "Endianess"-Angabe und die beiden "Pakete" optisch voneinander zu trennen. Also einzeln: "little endian"-Format ('<'), also erst Low- und dann Highbyte. Vier Bytes für die Frage ('4B') und für die Antwort ein Byte, gefolgt von einem "short", und einem weiteren Byte ('BHB').
Antworten