Struckt.unpack was mache ich falsch ?

Python in C/C++ embedden, C-Module, ctypes, Cython, SWIG, SIP etc sind hier richtig.
Antworten
Tyll
User
Beiträge: 21
Registriert: Dienstag 6. August 2013, 12:52

Hallo Leute,
ich empfange von einem C - Programm über ethernet ein Struckt und das möchte ich mit struckt.unpack entpacken aber ich bekommen immer die Fehlermeldung struct.error: unpack requires a string argument of length XY.
Also gehe ich davon aus das mein formatstring nicht dem entspricht was ich empfange nur habe ich alles schon mehrmal überprüft und es sollte eigentlich funktionieren. :K

Die entsprechungen !

Code: Alles auswählen

typedef unsigned char  BYTE;
typedef unsigned short WORD;
typedef unsigned long  DWORD;
typedef unsigned int   tUINT16;
typedef unsigned char  BOOL;
Das Struckt in c

Code: Alles auswählen

 
typedef struct {
	WORD TYPE;
	WORD ID;
	DWORD version;
	float translation;
	float rotation;
	float x_position;
	float y_position;
	float orientation;
	DWORD total_distance;								// in m Meter
	DWORD robot_alive_time;								// in min
	WORD Akku_Voltage;
	short Akku_Current;
	WORD Akku_Status;
	WORD Akku_Charge_Ah;
	WORD Akku_Discharge_Ah;
	WORD Akku_Regen_Ah;
	WORD DUMMY_Akku_Portcontroll;
	WORD DUMMY_Akku_Project_Status;
	BYTE Akku_Max_Cell_Voltage;
	BYTE Akku_Min_Cell_Voltage;
	BYTE Akku_System_Temp;
	BYTE Akku_Max_Cell_Temp;
	BYTE Akku_Min_Cell_Temp;
	BYTE not_in_use;
//	WORD Akku_Cell_Voltage[16];
//	WORD Satel_Handnotaus_Sendeleistung;
	WORD Bamobil_Initialise[2];
	WORD Bamobil_Status[2];
	WORD Bamobil_Logic[2];
	WORD Bamobil_Error[2];
	short Bamobil_latest_upm[2];
	short Bamobil_latest_Current[2];
	short Bamobil_latest_v_out[2];					// Mittelwert der Ausgangsspannung zu den Motoren
	WORD Bamobil_latest_p_motor[2];					//Leistung Motor
	WORD Bamobil_latest_t_motor[2];					//Temperatur Motor
	WORD Bamobil_latest_t_igbt[2];					//Temperatur Regler
	BYTE Front_light_intensity;
	BYTE Autonomic_drive;
	BYTE flags[3];}
Mein Python Testcode

Code: Alles auswählen

import socket
import struct

s = socket.socket(socket.AF_INET, socket.SOCK_DGRAM)

try: 
    s.bind(("", 38296)) 
    while True: 
        daten, addr = s.recvfrom(1024)
        int_data = struct.unpack('<hhqfffffqqhhhhhhhhsssssshhhhhhhhhhhhsss',daten)

        print "[%s] %s" % (addr[0], daten)
        print int_data 
        if daten == "exit":
        	break
        	pass
finally: 
    s.close()
Sirius3
User
Beiträge: 17711
Registriert: Sonntag 21. Oktober 2012, 17:20

Hallo Tyll,

da ist so einiges falsch:
- q sind 64bit, nicht 32
- s ist string nicht byte
- Du unterschlägst die Arrays
BlackJack

@Tyll: Zumindest das Ende ist falsch. Du hast da nur drei 's' stehen, es gibt aber fünf Bytewerte. Als letzten Wert in der Struktur steht ein *Array* mit drei Bytewerten. Vielleicht hast Du diesen Fehler bei den anderen Arrays auch gemacht, da bin ich jetzt zu faul zum Zählen.

Letztendlich sollte man hier IMHO aber mit `ctypes` arbeiten statt ein riesiges Tupel mit Werten zu erstellen wo man sich dann die Indizes zu den Werten heraus suchen muss und wo die Arrays einfach so ”platt geklopft” werden.
EyDu
User
Beiträge: 4881
Registriert: Donnerstag 20. Juli 2006, 23:06
Wohnort: Berlin

Und dann hast du am Ende noch 12 shorts, obwohl es nur 10 sind.
Das Leben ist wie ein Tennisball.
BlackJack

@EyDu: An der Stelle haben mich die beiden auskommentierten Zeilen in der C-Struktur verwirrt. Falls die doch da sind…
Tyll
User
Beiträge: 21
Registriert: Dienstag 6. August 2013, 12:52

Omg die auskommentierung habe ich vollkommen übersehen :shock: :shock:
und das mit den Arrays leider auch jetzt noch zur frage wie bediene ich den solche Arrays ?
BlackJack

@Tyll: Das sind x Werte vom Typ aus dem das Array zusammengesetzt ist. Wobei x die Grösse des Arrays ist.
Tyll
User
Beiträge: 21
Registriert: Dienstag 6. August 2013, 12:52

Also ich habe die Fehler jetzt mal rausgemacht wie ich hoffe aber es läuft immer noch nicht!
Benutze ich irgentwo den falschen Typ oder was mach ich falsch :|

Code: Alles auswählen

daten, addr = s.recvfrom(1024)
int_data = struct.unpack('<2hl5f2l8h6c20h5c',daten)
EyDu
User
Beiträge: 4881
Registriert: Donnerstag 20. Juli 2006, 23:06
Wohnort: Berlin

Wie sehen denn deine Daten aus? Wie viele Bytes empfängst du und welche Länge erwartet das unpack? Das struct-Modul hat dafür eine schöne calcsize-Funktion. Und dann kann es natürlich noch passieren, dass du nicht alle Daten auf einmal empfängst.
Das Leben ist wie ein Tennisball.
Tyll
User
Beiträge: 21
Registriert: Dienstag 6. August 2013, 12:52

Die Daten sind das im ersten Post gezeigte Struckt.
Aber wie Funktioniert den die calcsize-Funktion da muss ich doch auch einen Formatstring eingeben und dann hab ich doch wieder das gleich oder nicht ?
BlackJack

@Tyll: `calcsize()` sagt Dir zur gegebenen Formatzeichenkette wie viele Bytes das sind. Und dann kannst Du Dir mal die Länge der empfangenen Daten anzeigen lassen. Und wenn die Unterschiedlich sind, siehst Du um wie viel die sich Unterscheiden. Das hilft vielleicht das Problem zu finden. Du könntest auch mal mit einem C-Programm die Grösse der Struktur ausgeben lassen.

Edit: Deine Formatzeichenkette enthält 103 Bytes, die Struktur ist laut `clang`-Compiler 104 Bytes gross. Falls die Anzahlen und Typen stimmen würde ich auf „padding” tippen. Ein Grund warum man eigentlich keine `struct`\s direkt über Leitungen schicken sollte. Was welcher Compiler mit undefinierten Bytes auffüllt ist zu einem grossen Teil implementationsabhängig.
Antworten