Implementierung Protokoll (Gps-Empfänger)

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
maxwell
User
Beiträge: 69
Registriert: Samstag 11. Juli 2009, 15:36
Wohnort: am Fernsehturm in B.

Donnerstag 1. März 2012, 09:22

Hallo @ all,
ich bin gerade dabei das binary Protokoll eines GPS-Empfängers zu implementieren. Oder besser gesagt mache ich mir gerade Gedanken dazu wie es am gescheitesten zu implementieren ist.

Das Protokoll:

Code: Alles auswählen

'''
     0                   1                   2                   3
    |0|1|2|3|4|5|6|7|8|9|0|1|2|3|4|5|6|7|8|9|0|1|2|3|4|5|6|7|8|9|0|1|
    +-------+-------+-------+-------+---------------+---------------+
    |       |       |       |       |     LENGTH    |               |
    | SYNC1 | SYNC2 | CLASS |   ID  | Little Endian | Payload Data  :
    |       |       |       |       |    (2 Byte)   |               |
    +-------+-------+-------+-------+---------------+ - - - - - - - +
    :                     Payload Data continued ...                :
    + - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - +
    :                     Payload Data continued ...                :
    +-------+-------+-----------------------------------------------+
    | CK_A  | CK_B  |                                               |
    +-------+-------+-----------------------------------------------+

'''

Es gibt folgende Typen von Nachrichten: POLL, GET/SET, PERIODIC und CMD (command)
Die Implementierung einer Nachricht würde ich wie folgt vornehmen:

Code: Alles auswählen


U1 = "B"        # XXX
I1 = "b"
X1 = I1
X2 = 'h'
X4 = "i"
R4 = "f"
R8 = "d"
U4 = 'L'
I4 = 'l'
I2 = X2
U2 = 'H'
XX = 's'
RAW = '%i'+XX


class Raw(object):
    __metaclass__ = _MyMetaClass # meta msg 
    __payload__ = ((RAW, 'payload', ''),)

    def __init__(self, file, *args, **kwds): pass
    def wait(self, timeout=None, exception=None): pass
    def send(self): pass

# Beispiel Navigationslösung
class NavSol(Raw):
    __whoiam__ = 0x0106 
    __payload__ = ((U4, 'iTOW', 0), (I4, 'fTOW', 0), (I2, 'week', 0), 
        (U1, 'gpsFix', 0), 	# range 0..5; see at gps fix constants
        (X1, 'flags', 0x00), # see at status flags       
        (I4, 'ecefX', 0), 
        (I4, 'ecefY', 0), 
        (I4, 'ecefZ', 0), # ECEF X,Y,Z coordinate (cm)
        (U4, 'pAcc', 0), # 3D Position Accuracy Estimate
        (I4, 'ecefVX', 0), 
        (I4, 'ecefVY', 0), 
        (I4, 'ecefVZ', 0), # ECEF X,Y,Z velocity (cm/s)        
        (U4, 'sAcc', 0), # Speed Accuracy Estimate
        (U2, 'pDOP', 0), # Position DOP       
        (U1, 'res1', 0), 
        (U1, 'numSV', 0), # Number of SV's used in Nav.-Solution
        (U4, 'res2', 0))

Die Definition des Payloads beinhaltet die Typen für unpack/pack des struct Moduls und die Namen der Attribute.
Die Attributnamen habe gemäß des Protokolls der Übersicht halber so gelassen. Normalerweise hätte ich sie durch einen Unterstrich getrennt.

Die Benutzung sehe dann wie folgt aus:

Code: Alles auswählen


# open tty com2usb
ttyACMx = open('tty/ttyACM0', 'r')

##########################
# 1: when we got the solution permanently:
##########################
# init the navigation solution:
navi = NavSol(file=ttyACMx)
while 1:
	navi.wait(timeout=1)
	print navi.ecefX, navi.ecefY, navi.ecefZ

##########################
# 2: send a message and wait for acknowledge 
##########################
# kill a config, for exampl. clear the navigation config on the battery bracket rack
cfg = CfgCfg(file=ttyACMx, clearMask=CfgCfg.NAV_CFG, devMask=CfgCfg.BBR)
cfg.send()
# wait for acknowledge in view of sent message:
ack = AckAck(file=ttyACMx)

try:
	# if the time is over then raise the given exception ...
	ack.wait(timeout=1, exception=Timeout) 
except Timeout:
	pass	# no acknowledge returned ...

# #########################
# 3: get a message with repeated blocks (get the current receiver version):
##########################
message = MonVer(file=ttyACMx)
message.send()
# wait for answering:
message.wait(timeout=1)

print message.swVersion, message.hwVersion, message.romVersion

for block in message.repeated_blocks:
	print block.extension

Das Problem ist die Benutzung der Nachrichten mit einem sich wiederholendem Block. Oben in 3. dargestellt.

Code: Alles auswählen


class MonVer(Raw):
    __whoiam__ = 0x050A
    
    __payload__ = (('30'+XX, 'swVersion', ''), ('10'+XX, 'hwVersion', ''),
        ('30'+XX, 'romVersion', ''), 
        ('30'+XX, 'extension', '') # <--- REPEATED BLOCK !!!
        )



Ich habe diesen "repeated block" einfach erstmal aus Übersichtsgründen in die payload Liste geschrieben.
Aber genau hier liegt der Haken. Dieser Block kann sich N'mal wiederholen bzw. auch mehrere Felder enthalten.

Code: Alles auswählen

    __payload__ = (('30'+XX, 'swVersion', ''), ('10'+XX, 'hwVersion', ''),
        ('30'+XX, 'romVersion', ''), 
        # START REPEATED BLOCK > :
        (U1, 'field1', ''), (U1, 'field2', '') ...
        # < END REPEATED BLOCK
        )
Die Frage ist wie ich diesen am gescheitesten zerlege und die Daten in der Klasse kapsel. Bzw. wie kann ich am besten über einen solchen wiederholten Block iterieren.

Code: Alles auswählen


for block in my_message.XXXX:
    print block.MyFieldx


Hat jemand eine Idee? Oder bin ich komplett auf dem Holzweg.
Ich freue mich auf Feedback.
Gr. Chris
be or not to be
BlackJack

Donnerstag 1. März 2012, 09:42

@maxwell: Gibt es einen Grund warum Du so etwas wie `construct` noch einmal selber erfindest?
maxwell
User
Beiträge: 69
Registriert: Samstag 11. Juli 2009, 15:36
Wohnort: am Fernsehturm in B.

Donnerstag 1. März 2012, 10:00

Hi BlackJack,
wie meinst Du das genau? Du meinst sicher die Definition d. Payloads?
Ich habe in einer früheren Version die Möglichkeit vorgesehen die Rohdaten direkt als Argument zu übergeben
die dann zelegt werden. Dies ist ein Relikt. Sicher man kann auch einfach __init__ mit den entsprechenden Attributen neu definieren - da hast Du recht.
be or not to be
EyDu
User
Beiträge: 4872
Registriert: Donnerstag 20. Juli 2006, 23:06
Wohnort: Berlin

Donnerstag 1. März 2012, 10:04

Nein, BlackJack mein das construct-Modul.
Das Leben ist wie ein Tennisball.
maxwell
User
Beiträge: 69
Registriert: Samstag 11. Juli 2009, 15:36
Wohnort: am Fernsehturm in B.

Donnerstag 1. März 2012, 10:17

Sorry uuuuups ....
Sieht gut aus - dann hat sich das ja erledigt.
be or not to be
Antworten