I am trying to unpack a C struct that is handed to my Python program in binary form and includes another nested struct. The relevant part of the C header looks like this:
typedef struct {
uint8_t seq;
uint8_t type;
uint16_t flags;
uint16_t upTimestamp;
}__attribute__ ((packed)) mps_packet_header;
typedef struct {
mps_packet_header header;
int16_t x[6];
int16_t y[6];
int16_t z[6];
uint16_t lowTimestamp[6];
}__attribute__((packed)) mps_acc_packet_t;
typedef mps_acc_packet_t accpacket_t;
Now, in my Python program, I want to use struct.unpack
to unpack an accpacket
. However, I don't know what the format string for the unpack should be as the accpacket
contains a nested mps_packet_header
. I have tried just inserting the format string for the mps_packet_header
at the beginning and then continuing with the rest of the accpacket
:
s = struct.Struct('= B B H H 6h 6h 6h H')
seq, _type, flags, upTimestamp, x, y, z, lowTimestamp = s.unpack(packet_data)
However, this is apparently not correct; the format string has a calcsize
of 44, while the struct itself has a size of 54.
How do I formulate a correct format string for this struct?
Struct
format does not match with C structure. (final H
should be 6H
)6h
, ..) does return 6 fields. (not one with 6 elements)So your code should looks like ..
s = struct.Struct('= B B H H 6h 6h 6h 6H')
fields = s.unpack(packet_data)
seq, _type, flags, upTimestamp = fields[:4]
x = fields[4:10]
y = fields[10:16]
z = fields[16:22]
lowTimestamp = fields[22:]
You can try construct http://construct.readthedocs.io/en/latest/
import construct as cstruct
def mps_packet_header(name):
return cstruct.Struct(
name,
cstruct.UNInt8('seq'),
cstruct.UNInt8('type'),
cstruct.UNInt16('flags'),
cstruct.UNInt16('upTimestamp'),
)
mps_acc_packet_t = cstruct.Struct(
'mps_acc_packet_t',
mps_packet_header('header')
cstruct.Array(6, cstruct.NInt16('x')),
cstruct.Array(6, cstruct.NInt16('y')),
cstruct.Array(6, cstruct.NInt16('z')),
cstruct.Array(6, cstruct.UNInt16('lowTimestamp')),
)
accpacket_t = mps_acc_packet_t
...
...
packet_data = ....
packet = accpacket_t.parse(packet_data)
print(packet)
print(packet.header)
print(packet.x, packet.y, packet.z)
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With