Seite 1 von 1
Schnittstelle mitschneiden und Daten auswerten
Verfasst: Sonntag 31. Mai 2009, 19:37
von würmchen
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.
Verfasst: Sonntag 31. Mai 2009, 22:47
von Dauerbaustelle
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
Verfasst: Montag 1. Juni 2009, 08:59
von würmchen
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.
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.
Verfasst: Montag 1. Juni 2009, 09:33
von 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.
Verfasst: Montag 1. Juni 2009, 10:00
von würmchen
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....

Verfasst: Montag 1. Juni 2009, 11:14
von 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').