Python unpack() binary string
Question:
I have unpacked binary data with PHP and now i’m trying to achieve the same result in python but failing to grasp it.
$str = "57002991f605009ac6342101000000be1430038800003b0031033e3100f42303a905430000e6";
$data = hex2bin($str);
$v = unpack("H4cmd/H16mac/H20ukn/CState/nDCCurrent/nDCPower/nEfficiency/cACFreq/nACvolt/cTemp/nWh/nkWh/n/H2CRC",$data);
Result:
array(14) {
["cmd"]=>
string(4) "5700"
["mac"]=>
string(16) "2991f605009ac634"
["ukn"]=>
string(20) "2101000000be14300388"
["State"]=>
int(0)
["DCCurrent"]=>
int(59)
["DCPower"]=>
int(49)
["Efficiency"]=>
int(830)
["ACFreq"]=>
int(49)
["ACvolt"]=>
int(244)
["Temp"]=>
int(35)
["Wh"]=>
int(937)
["kWh"]=>
int(1347)
[1]=>
int(0)
["CRC"]=>
string(2) "e6"
}
I’ve tried with both struct.unpack() and rawutils.unpack() but i cannot replicate the result. This is as far as i’ve been able to get;
import rawutil
str = b"x57x00xefx55xf7x05x00x9axc6x34x21x01x00x00x00xbex14x30x03x88x00x00x3bx00x31x03x3ex31x00xf4x23x03xa9x05x43x00x00xe6"
v = rawutil.unpack("2X8X10XBXHB2s$",str)
Result:
['5700', 'ef55f705009ac634', '2101000000be14300388', 0, '00', 59, 49, b'x03>', b'1x00xf4#x03xa9x05Cx00x00xe6']
I cannot seem to get the string to unpack correctly any further
Answers:
As soon as you know how the format for PHP’s pack()
maps into the format for Python’s struct
, it is just a matter of picking the correct format.
In particular, the following mappings are needed:
H[N]
-> s[N/2]
(with a small catch that it needs to be converted afterwards to hexadecimal via bytes.hex()
)
C
-> B
n
-> H
c
-> b
Below is some working Python code:
import struct
b = b"x57x00xefx55xf7x05x00x9axc6x34x21x01x00x00x00xbex14x30x03x88x00x00x3bx00x31x03x3ex31x00xf4x23x03xa9x05x43x00x00xe6"
to_hex = {0, 1, 2, 13}
x = [x.hex() if i in to_hex else x for i, x in enumerate(struct.unpack(">2s8s10sBHHHbHbHHHs", b))]
print(x)
# ['5700', 'ef55f705009ac634', '2101000000be14300388', 0, 59, 49, 830, 49, 244, 35, 937, 1347, 0, 'e6']
I have unpacked binary data with PHP and now i’m trying to achieve the same result in python but failing to grasp it.
$str = "57002991f605009ac6342101000000be1430038800003b0031033e3100f42303a905430000e6";
$data = hex2bin($str);
$v = unpack("H4cmd/H16mac/H20ukn/CState/nDCCurrent/nDCPower/nEfficiency/cACFreq/nACvolt/cTemp/nWh/nkWh/n/H2CRC",$data);
Result:
array(14) {
["cmd"]=>
string(4) "5700"
["mac"]=>
string(16) "2991f605009ac634"
["ukn"]=>
string(20) "2101000000be14300388"
["State"]=>
int(0)
["DCCurrent"]=>
int(59)
["DCPower"]=>
int(49)
["Efficiency"]=>
int(830)
["ACFreq"]=>
int(49)
["ACvolt"]=>
int(244)
["Temp"]=>
int(35)
["Wh"]=>
int(937)
["kWh"]=>
int(1347)
[1]=>
int(0)
["CRC"]=>
string(2) "e6"
}
I’ve tried with both struct.unpack() and rawutils.unpack() but i cannot replicate the result. This is as far as i’ve been able to get;
import rawutil
str = b"x57x00xefx55xf7x05x00x9axc6x34x21x01x00x00x00xbex14x30x03x88x00x00x3bx00x31x03x3ex31x00xf4x23x03xa9x05x43x00x00xe6"
v = rawutil.unpack("2X8X10XBXHB2s$",str)
Result:
['5700', 'ef55f705009ac634', '2101000000be14300388', 0, '00', 59, 49, b'x03>', b'1x00xf4#x03xa9x05Cx00x00xe6']
I cannot seem to get the string to unpack correctly any further
As soon as you know how the format for PHP’s pack()
maps into the format for Python’s struct
, it is just a matter of picking the correct format.
In particular, the following mappings are needed:
H[N]
->s[N/2]
(with a small catch that it needs to be converted afterwards to hexadecimal viabytes.hex()
)C
->B
n
->H
c
->b
Below is some working Python code:
import struct
b = b"x57x00xefx55xf7x05x00x9axc6x34x21x01x00x00x00xbex14x30x03x88x00x00x3bx00x31x03x3ex31x00xf4x23x03xa9x05x43x00x00xe6"
to_hex = {0, 1, 2, 13}
x = [x.hex() if i in to_hex else x for i, x in enumerate(struct.unpack(">2s8s10sBHHHbHbHHHs", b))]
print(x)
# ['5700', 'ef55f705009ac634', '2101000000be14300388', 0, 59, 49, 830, 49, 244, 35, 937, 1347, 0, 'e6']