
[英]UnicodeDecodeError: 'utf-8' codec can't decode byte 0x87 in position 1551: invalid start byte
[英]Decode Payload of TCP connection: 'utf-8' codec can't decode byte 0x87 in position 4: invalid start byte
我通过 TCP 从传感器节点发送到我的 TCP 服务器。 原始接收数据如下所示:
b'A\\x10Vu\\x87%\\x00x\\x0c\\xc7\\x03\\x01\\x00\\x00\\x00\\x00&\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00'
尝试使用 utf-8 对其进行解码时,我收到以下错误。 代码:
my_variable = b'A\x10Vu\x87%\x00x\x0c\xc7\x03\x01\x00\x00\x00\x00&\x00\x00\x00\x00\x00\x00\x00\x00'
print(my_variable.decode('utf-8'))
错误:
打印(my_variable.decode('utf-8'))UnicodeDecodeError:'utf-8'编解码器无法解码位置4的字节0x87:无效的起始字节
所以问题是 Payload 显然包含非 ascii 格式的字符。
我怎样才能将此有效载荷解码为某物。 人类可读?
基于文档不是human readable
,您不应该对其进行解码,但您应该编写特殊代码将每个值从十六进制转换为整数,并最终将其转换为带有额外值的字符串 - 即。 版本号中的点。
这里是有效载荷起始值的代码
data = b'A\x10Vu\x87%\x00x\x0c\xc7\x03\x01\x00\x00\x00\x00&\x00\x00\x00\x00\x00\x00\x00\x00'
ID = data[:6].hex()
print('ID:', ID)
hardware = data[6]
if hardware == 1:
hardware = 'NBSN95'
print('hardware version:', hardware)
software = data[7]
print('software version (raw):', software)
software = '.'.join(list(str(software)))
print('software version:', software)
battery = data[8:10].hex()
print('battery (raw):', battery)
battery = int(battery, 16)
print('battery:', battery, 'mV =', battery/1000, 'V')
signal = data[10]
print('signal (raw):', signal)
if signal == 0:
signal = '-113dBm or less'
elif signal == 1:
signal = '-111dBm'
elif 2 <= signal <= 30:
signal = '-109dBm ... -53dBm'
elif signal == 31:
signal = '-51dBm or greater'
elif signal == 99:
signla = 'Not known or not detectable'
print('signal:', signal)
temp = data[11:13].hex()
print('temperature (raw):', temp)
temp = int(temp, 16)
if temp & 0xFC00 == 0:
temp = temp/10
elif temp & 0xFC00 == 1:
temp = (temp-65536)/10
print('temperature:', temp, 'degree')
结果:
ID: 411056758725
hardware version: 0
software version (raw): 120
software version: 1.2.0
battery (raw): 0cc7
battery: 3271 mV = 3.271 V
signal (raw): 3
signal: -109dBm ... -53dBm
temperature (raw): 0100
temperature: 25.6 degree
您可以在 Python 提示中找到答案。 事实上,我使用dir(my_variable)
开始了我的探索:
my_variable = b'A\x10Vu\x87%\x00x\x0c\xc7\x03\x01\x00\x00\x00\x00&\x00\x00\x00\x00\x00\x00\x00\x00'
# dir(my_variable)
my_variable.hex
<built-in method hex of bytes object at 0x00000232BDF129F0>
help(my_variable.hex) # truncated
Help on built-in function hex: hex(...) method of builtins.bytes instance Create a str of hexadecimal numbers from a bytes object.
my_variable.hex()
'41105675872500780cc7030100000000260000000000000000'
数据是原始字节数据,不应被解码。 相反,使用struct
模块将原始字节解包为字节和数据字。 规范(第 22 页)指示每个字段的字节数:
struct 模块还有一个优点,您不必手动计算每个字段的偏移量,如果解包模式与数据长度不匹配,它将捕获错误。
注意2字节版本是硬件版本字节和软件版本字节,所以我用BB
(2字节)分别提取出来。 温度被记录为二进制补码,因此我为它们使用了h
(有符号的 16 位值)。 还要注意数据是大端的,所以使用>
。
另请参阅struct - Format String
文档。
import struct
from datetime import datetime
from pytz import UTC
data = b'A\x10Vu\x87%\x00x\x0c\xc7\x03\x01\x00\x00\x00\x00&\x00\x00\x00\x00\x00\x00\x00\x00'
devid,hw,sw,bat,ss,mod,t1,dii,adc,t2,h,ts = struct.unpack('>6sBBHBBhBHhHL',data)
# fields that needed processing are done in the f-strings below
print(f"DeviceID={devid.hex()} HW={hw} SW={'.'.join(str(sw))}\n"
f"BAT={bat:.3f}mV SignalStrength={-113+2*ss}dBm Mode={mod} Temp={t1/10}\N{DEGREE CELSIUS}\n"
f"Door={dii==0x80} ADC={adc}mv Temp2={t1/10:.1f}\N{DEGREE CELSIUS} Humidity={h/10:.1f}%\n"
f"Timestamp={datetime.fromtimestamp(ts,UTC)}")
输出:
DeviceID=411056758725 HW=0 SW=1.2.0
BAT=3.271V SignalStrength=-107dBm Mode=1 Temp=0.0℃
Door=False ADC=38mv Temp2=0.0℃ Humidity=0.0%
Timestamp=1970-01-01 00:00:00+00:00
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.