0

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"\x57\x00\xef\x55\xf7\x05\x00\x9a\xc6\x34\x21\x01\x00\x00\x00\xbe\x14\x30\x03\x88\x00\x00\x3b\x00\x31\x03\x3e\x31\x00\xf4\x23\x03\xa9\x05\x43\x00\x00\xe6"

v = rawutil.unpack("2X8X10XBXHB2s$",str)

Result:

['5700', 'ef55f705009ac634', '2101000000be14300388', 0, '00', 59, 49, b'\x03>', b'1\x00\xf4#\x03\xa9\x05C\x00\x00\xe6']

I cannot seem to get the string to unpack correctly any further

0

1 Answer 1

1

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"\x57\x00\xef\x55\xf7\x05\x00\x9a\xc6\x34\x21\x01\x00\x00\x00\xbe\x14\x30\x03\x88\x00\x00\x3b\x00\x31\x03\x3e\x31\x00\xf4\x23\x03\xa9\x05\x43\x00\x00\xe6"

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']
Sign up to request clarification or add additional context in comments.

1 Comment

It might also be convenient to construct b by using bytes.fromhex.

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.