如何从串行数据包中提取字节序列并将其更改为 python 中的正确整数表示形式?
How to extract and change a sequence of bytes from a serial packet to the correct integer representation in python?
374c4f4f00000800ff74**d102**29190300006f00fffffffffffffffffffff
这是我用pyserial处理的串口数据包。粗体的两个字节实际上对应于真实世界的测量值,对应于 721
(十进制)或 02d1
(十六进制)。我如何提取 python 中的那些字节并获得正确的 int 值 721?
使用 struct
库函数 pack
/pack_to
和 unpack
/unpack_from
可以快速轻松地处理此类字节串:
虽然 unpack/unpack 整个数据包通常是最佳做法,但您可以使用 _from 和 _to 版本来选择性地处理数据包。
你的情况:
>>> import struct
>>> val # Generated using binascii.unhexlify
b'7LOO\x00\x00\x08\x00\xfft\xd1\x02)\x19\x03\x00\x00o\x00\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff'
>>> struct.unpack_from('<H', val, 10)
(721,) # Note the return is a tupple so you need the 0th element
>>> struct.unpack_from('<H', val, 10)[0]
721
更多信息
>>> import struct
>>> help (struct.unpack)
Help on built-in function unpack in module _struct:
unpack(...)
unpack(fmt, buffer) -> (v1, v2, ...)
Return a tuple containing values unpacked according to the format string
fmt. Requires len(buffer) == calcsize(fmt). See help(struct) for more
on format strings.
>>> help (struct.pack)
Help on built-in function pack in module _struct:
pack(...)
pack(fmt, v1, v2, ...) -> bytes
Return a bytes object containing the values v1, v2, ... packed according
to the format string fmt. See help(struct) for more on format strings.
>>> help(struct)
Help on module struct:
NAME
struct
DESCRIPTION
Functions to convert between Python values and C structs.
Python bytes objects are used to hold the data representing the C struct
and also as format strings (explained below) to describe the layout of data
in the C struct.
The optional first format char indicates byte order, size and alignment:
@: native order, size & alignment (default)
=: native order, std. size & alignment
<: little-endian, std. size & alignment
>: big-endian, std. size & alignment
!: same as >
The remaining chars indicate types of args and must match exactly;
these can be preceded by a decimal repeat count:
x: pad byte (no data); c:char; b:signed byte; B:unsigned byte;
?: _Bool (requires C99; if not available, char is used instead)
h:short; H:unsigned short; i:int; I:unsigned int;
l:long; L:unsigned long; f:float; d:double.
Special cases (preceding decimal count indicates length):
s:string (array of char); p: pascal string (with count byte).
Special cases (only available in native format):
n:ssize_t; N:size_t;
P:an integer type that is wide enough to hold a pointer.
Special case (not in native mode unless 'long long' in platform C):
q:long long; Q:unsigned long long
Whitespace between formats is ignored.
The variable struct.error is an exception raised on errors.
您的十六进制编码字符串的长度是奇数,所以我不知道填充从哪里丢失,见下文
In [18]: s = '374c4f4f00000800ff74d10229190300006f00fffffffffffffffffffff0' # a nibble of padding at the end
In [19]: buffer = binascii.unhexlify(s)
In [20]: buffer
Out[20]: b'7LOO\x00\x00\x08\x00\xfft\xd1\x02)\x19\x03\x00\x00o\x00\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xf0'
In [21]: struct.unpack('<10BH18B', buffer)
Out[21]:
(55,
76,
79,
79,
0,
0,
8,
0,
255,
116,
721,
...
有关 pack
和 unpack
中格式字符串的更多信息,请参阅 documentation。简而言之,<
代表little-endian,B
代表unsigned char(假设8位宽),H
简称(假设16位宽)。
由于实际的格式字符串乍一看有些奇怪,我已经根据上面的答案给了你一个解决方案:
- 命令 unhexlify 会将 4 字节的 ascii 表示形式转换回整数的两字节二进制表示形式。
- “<”处理整数中的反转字节顺序 (Formatting details)
- 'i'表示我们面对的是一个二字节整数
希望对您有所帮助。
import struct
from binascii import unhexlify
s ="374c4f4f00000800ff74d10229190300006f00fffffffffffffffffffff"
s1= s[20:24]
print struct.unpack('<h', unhexlify(s1))[0]
374c4f4f00000800ff74**d102**29190300006f00fffffffffffffffffffff
这是我用pyserial处理的串口数据包。粗体的两个字节实际上对应于真实世界的测量值,对应于 721
(十进制)或 02d1
(十六进制)。我如何提取 python 中的那些字节并获得正确的 int 值 721?
使用 struct
库函数 pack
/pack_to
和 unpack
/unpack_from
可以快速轻松地处理此类字节串:
虽然 unpack/unpack 整个数据包通常是最佳做法,但您可以使用 _from 和 _to 版本来选择性地处理数据包。
你的情况:
>>> import struct
>>> val # Generated using binascii.unhexlify
b'7LOO\x00\x00\x08\x00\xfft\xd1\x02)\x19\x03\x00\x00o\x00\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff'
>>> struct.unpack_from('<H', val, 10)
(721,) # Note the return is a tupple so you need the 0th element
>>> struct.unpack_from('<H', val, 10)[0]
721
更多信息
>>> import struct
>>> help (struct.unpack)
Help on built-in function unpack in module _struct:
unpack(...)
unpack(fmt, buffer) -> (v1, v2, ...)
Return a tuple containing values unpacked according to the format string
fmt. Requires len(buffer) == calcsize(fmt). See help(struct) for more
on format strings.
>>> help (struct.pack)
Help on built-in function pack in module _struct:
pack(...)
pack(fmt, v1, v2, ...) -> bytes
Return a bytes object containing the values v1, v2, ... packed according
to the format string fmt. See help(struct) for more on format strings.
>>> help(struct)
Help on module struct:
NAME
struct
DESCRIPTION
Functions to convert between Python values and C structs.
Python bytes objects are used to hold the data representing the C struct
and also as format strings (explained below) to describe the layout of data
in the C struct.
The optional first format char indicates byte order, size and alignment:
@: native order, size & alignment (default)
=: native order, std. size & alignment
<: little-endian, std. size & alignment
>: big-endian, std. size & alignment
!: same as >
The remaining chars indicate types of args and must match exactly;
these can be preceded by a decimal repeat count:
x: pad byte (no data); c:char; b:signed byte; B:unsigned byte;
?: _Bool (requires C99; if not available, char is used instead)
h:short; H:unsigned short; i:int; I:unsigned int;
l:long; L:unsigned long; f:float; d:double.
Special cases (preceding decimal count indicates length):
s:string (array of char); p: pascal string (with count byte).
Special cases (only available in native format):
n:ssize_t; N:size_t;
P:an integer type that is wide enough to hold a pointer.
Special case (not in native mode unless 'long long' in platform C):
q:long long; Q:unsigned long long
Whitespace between formats is ignored.
The variable struct.error is an exception raised on errors.
您的十六进制编码字符串的长度是奇数,所以我不知道填充从哪里丢失,见下文
In [18]: s = '374c4f4f00000800ff74d10229190300006f00fffffffffffffffffffff0' # a nibble of padding at the end
In [19]: buffer = binascii.unhexlify(s)
In [20]: buffer
Out[20]: b'7LOO\x00\x00\x08\x00\xfft\xd1\x02)\x19\x03\x00\x00o\x00\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xf0'
In [21]: struct.unpack('<10BH18B', buffer)
Out[21]:
(55,
76,
79,
79,
0,
0,
8,
0,
255,
116,
721,
...
有关 pack
和 unpack
中格式字符串的更多信息,请参阅 documentation。简而言之,<
代表little-endian,B
代表unsigned char(假设8位宽),H
简称(假设16位宽)。
由于实际的格式字符串乍一看有些奇怪,我已经根据上面的答案给了你一个解决方案:
- 命令 unhexlify 会将 4 字节的 ascii 表示形式转换回整数的两字节二进制表示形式。
- “<”处理整数中的反转字节顺序 (Formatting details)
- 'i'表示我们面对的是一个二字节整数
希望对您有所帮助。
import struct
from binascii import unhexlify
s ="374c4f4f00000800ff74d10229190300006f00fffffffffffffffffffff"
s1= s[20:24]
print struct.unpack('<h', unhexlify(s1))[0]