Python 如何对pysnmp获取的不透明数据进行解码?
我将通过Python 如何对pysnmp获取的不透明数据进行解码?,python,python-3.x,encoding,snmp,pysnmp,Python,Python 3.x,Encoding,Snmp,Pysnmp,我将通过pysnmp库通过其OID从SNMP设备读取数据。但是,我正在处理来自不透明类型的错误: 从pysnmp导入hlapi def构造对象类型(OID列表): 对象类型=[] 对于\u oid列表中的oid: object_types.append(hlapi.ObjectType(hlapi.ObjectIdentity(oid))) 返回对象类型 def get(目标,OID,凭证,端口=161,引擎=hlapi.SnmpEngine(), context=hlapi.ContextDa
pysnmp
库通过其OID从SNMP设备读取数据。但是,我正在处理来自不透明类型的错误:
从pysnmp导入hlapi
def构造对象类型(OID列表):
对象类型=[]
对于\u oid列表中的oid:
object_types.append(hlapi.ObjectType(hlapi.ObjectIdentity(oid)))
返回对象类型
def get(目标,OID,凭证,端口=161,引擎=hlapi.SnmpEngine(),
context=hlapi.ContextData()):
handler=hlapi.getCmd(
引擎,
资格证书
hlapi.udptTransportTarget((目标,端口)),
上下文
*构造对象类型(OID)
)
返回获取(处理程序,1)[0]
def cast(值):
尝试:
返回int(值)
除了(ValueError、TypeError):
尝试:
返回浮动(值)
除了(ValueError、TypeError):
尝试:
返回str(值)
除了(ValueError,TypeError)作为exc:
打印(exc)
返回值
def fetch(处理程序,计数):
结果=[]
对于范围内的i(计数):
(错误指示、错误状态、,
错误索引,变量绑定)=下一个(处理程序)
如果非错误指示和非错误状态:
项目={}
打印(变量绑定)
对于var_绑定中的var_绑定:
items[str(变量绑定[0])]=cast(变量绑定[1])
结果。追加(项)
其他:
引发运行时错误(f'SNMP错误:{error\u indication}')
返回结果
打印(获取(“192.168.100.112”、[”.1.3.6.1.4.1.9839.1.2.532.0”,
'.1.3.6.1.4.1.9839.1.2.513.0'],
hlapi.CommunityData(“public”))
输出:
[ObjectType(ObjectIdentity(),),ObjectType(ObjectIdentity(),)]
{'1.3.6.1.4.1.9839.1.2.532.0':'\x9fx\x04AÌF','1.3.6.1.4.1.9839.1.2.513.0':10}
第一个OID(.1.3.6.1.4.1.9839.1.2.532.0
)返回不透明值(\x9fx\x04AÌF
),我不知道如何将其转换为浮点值。我应该补充一点,那就是温度值25.5℃
换句话说,我如何通过彼此达到以下值
25.5
编码iso-8859-1,有效载荷[0x9f780441ccb646]
'\x9fx\x04ĄF'
0x9f780441ccb646
可以
- 分成两个浮动,其中一个是
,另一个是其他部分,或者25.589001
- 中间是
对象(pysnmp
)的表示,没有已知的解释(可能缺少MIB),或者\uuuu repr\uuuu
- 已转换为字节表示形式(使用iso-8859-1编码),即字符串
'\x9fx\x04ĄF'
导入结构
data=0x9f780441ccb646#这是您从pysnmp获得的数据
字节=结构包(“l”,数据)
打印(字节.解码('latin1'))
打印(字节)
打印(结构解包(“ff”,字节))
给予
FÌAx
b'F\xb6\xccA\x04x\x9f\x00'
(25.58900071904297、1.4644897383138518e-38)
MIB将告诉您应该如何解释其他数据,而不是将数据解包为两个浮点,因此,您可能不需要解包(“ff”…
,而是查看可用的,例如“fhh”
将给出(25.5890007190429730724159)
编辑:
TL;DR:
data = '\0\x9fx\x04A̶F'
print("temperature: %f°C" % struct.unpack('>ff', data.encode('latin1'))[1])
详细说明字符串表示法:您看到的字节的顺序与我的打印语句中的字节的顺序相反,因为它们的顺序不同。字节顺序已在您在输出中提供的、我在co中使用的int
转换数据0x9f780441ccb646
中更正转换示例。如果要从编码字符串开始,首先需要将其转换回正确的内存表示形式:
data = '\0\x9fx\x04A̶F' # (initial '\0' is for filling the 8-bytes in correct alignment)
thebytes = data.encode('latin1')
但这只是技巧的一半,因为现在endianess仍然是错误的。幸运的是,struct
有相应的标志来纠正这一点。您可以按两个字节顺序解包并选择正确的一个
print("unpacked little-endian: ", struct.unpack("<ff", thebytes))
print("unpacked big-endian: ", struct.unpack(">ff", thebytes))
unknown, temperature = struct.unpack(">ff", thebytes)
print("temperature: %f°C" % temperature)
不透明数据包的正确端号是SNMP标准的一部分(那么“网络字节顺序”可能是正确的),或也应在MIB中与需要作为格式说明符提供的正确字段类型一起提供。如果数据包的长度始终为7字节,则可以尝试将其添加到7字节而不是8字节的组合(ff
=4+4),那么您也可以省略添加填充字节。根据加上一些更改,并且知道不透明的帧由7个字节组成,其中3个字节是常量(\x9fx\x04
或159\120\4
),我编写了以下代码片段来处理该问题:
。。。
handler=get(“192.168.100.112”,[”.1.3.6.1.4.1.9839.1.2.532.0”,
'.1.3.6.1.4.1.9839.1.2.513.0'],
hlapi.CommunityData('public'))
对于键,handler.items()中的值:
尝试:
如果len(value)==7和值[0],则编码('latin1')[0]==159\
和值[1]。编码('latin1')[0]==120\
和值[2]。编码('latin1')[0]==4:
数据=值[3:]
打印(结构解包('>f',数据编码('latin1'))[0])
其他:
打印(值)
除属性错误外:
打印(值)
输出:
[注意]:
- 不透明是一种小的尾端格式(
结构中的)
[更新]:
更多智慧
data = '\0\x9fx\x04A̶F' # (initial '\0' is for filling the 8-bytes in correct alignment)
thebytes = data.encode('latin1')
print("unpacked little-endian: ", struct.unpack("<ff", thebytes))
print("unpacked big-endian: ", struct.unpack(">ff", thebytes))
unknown, temperature = struct.unpack(">ff", thebytes)
print("temperature: %f°C" % temperature)
unpacked little-endian: (2.9225269119838333e-36, 23398.126953125)
unpacked big-endian: (1.4644897383138518e-38, 25.589000701904297)
temperature: 25.589001°C
25.589001
10