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"
}

Sandbox example: https://onlinephp.io?s=JU7RSsQwEHw_uH84yj1UONhN0tYrp8gRlT6KJ_goabqlpTYXY1r1703ahR12Z4eZvXuwnd1utpv9t3e7-12S3yLysmRtgTliqXQhMs6Q4VI1sUwgiuMxbqIOzVAICohtxgUKVWIeJYhUJKfFuVFeBeuOfnndmzQm3ayXOdCTsUoPaVJlemygYsWoNFQcp8GAvHjlCcyjlJNzZHwcX64_5MA8tW2vezL6D_RZPjv6AnOW8_XTg36j0YJ578AMEYKdfJXJYflkjZ6V-2im0ab7eSX-AQ%2C%2C&v=8.1.10

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

Asked By: bulldog5046

||

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']
Answered By: norok2
Categories: questions Tags:
Answers are sorted by their score. The answer accepted by the question owner as the best is marked with
at the top-right corner.