snmpsharpnet 不透明浮点数
snmpsharpnet Opaque Float
我在 c# 中通过 snmpsharpnet 查询 Synlogy NAS,并获得以下 UPS 电池值:
OID:1.3.6.1.4.1.6574.4.3.1.1.0
类型:不透明
数据:9F 78 04 42 C8 00 00
但是,它应该是一个浮点值 => 100.00
电压相同:
OID:1.3.6.1.4.1.6574.4.4.1.1.0
类型:不透明
数据:9F 78 04 43 65 00 00
浮动值 => 230.00
如何获取值?
我的代码:
// SNMP community name
OctetString communityo = new OctetString(community);
// Define agent parameters class
AgentParameters param = new AgentParameters(communityo);
// Set SNMP version to 1 (or 2)
param.Version = SnmpVersion.Ver1;
// Construct the agent address object
// IpAddress class is easy to use here because
// it will try to resolve constructor parameter if it doesn't
// parse to an IP address
IpAddress agent = new IpAddress(host);
// Construct target
UdpTarget target = new UdpTarget((IPAddress)agent, 161, 2000, 1);
// Pdu class used for all requests
Pdu pdu = new Pdu(PduType.Get);
pdu.VbList.Add(batteryoid); //
pdu.VbList.Add(voltageoid); //
pdu.VbList.Add(statusoid); //
// Make SNMP request
SnmpV1Packet result = (SnmpV1Packet)target.Request(pdu, param);
// If result is null then agent didn't reply or we couldn't parse the reply.
if (result != null)
{
// ErrorStatus other then 0 is an error returned by
// the Agent - see SnmpConstants for error definitions
if (result.Pdu.ErrorStatus != 0)
{
// agent reported an error with the request
Console.WriteLine("Error in SNMP reply. Error {0} index {1}",
result.Pdu.ErrorStatus,
result.Pdu.ErrorIndex);
}
else
{
// Reply variables are returned in the same order as they were added
// to the VbList
Console.WriteLine("battery ({0}) ({1}): {2}",
result.Pdu.VbList[0].Oid.ToString(),
SnmpConstants.GetTypeName(result.Pdu.VbList[0].Value.Type),
result.Pdu.VbList[0].Value.ToString());
Console.WriteLine("voltage ({0}) ({1}): {2}",
result.Pdu.VbList[1].Oid.ToString(),
SnmpConstants.GetTypeName(result.Pdu.VbList[1].Value.Type),
result.Pdu.VbList[1].Value.ToString());
Console.WriteLine("status ({0}) ({1}): {2}",
result.Pdu.VbList[2].Oid.ToString(),
SnmpConstants.GetTypeName(result.Pdu.VbList[2].Value.Type),
result.Pdu.VbList[2].Value.ToString());
}
}
else
{
Console.WriteLine("No response received from SNMP agent.");
}
target.Close();
来自 SNMP 的不透明数据意味着某些字段的值本身是 BER 编码的 ASN.1 数据 - 它的编码语言与 SNMP 查询本身的编码语言相同。
快速了解一下背景知识 ASN.1 是数据建模标准 - 它定义了如何以标准方式构建数据,以便其他程序可以理解该结构。 ASN.1 不是一个以位和字节编码该结构的系统——这是 BER 或 DER 编码标准的工作。
您拥有的数据 - 9F 78 04 42 C8 00 00
- 是 BER 编码数据。 BER 数据分为三部分:type
、length
和value
.
如果我们使用该模板反汇编您的字节,我们得出 9f78
是类型; 04
是长度,42c80000
是值。
根据 NetSnmp's documentation 的一些说法,9f78
的 'type' 代码在 BER 中表示“FLOATTYPE”。看起来很有前途。
下一个字节是长度字节,在本例中为04
。这意味着我们在值中有一个 4 字节的浮点数。
最后,我们有值代码 42c80000
。根据 RFC 6340, this value is to be interpreted as a standard IEEE 754 32 位浮点数。 IEEE 754 是使用最广泛的将浮点值编码为位的标准——这是大多数计算机和编程语言使用的标准。 C# 的 float
类型定义为 IEEE 754 32 位单精度浮点值,而 double
是 IEEE 754 64 位双精度浮点值,例如
如果我们使用 handy-dandy online converter 将原始字节转换为浮点数,我们会发现被视为 IEEE 754 32 位浮点数的 42c80000
的值为“100.0”。瞧,我们有你的价值。
现在我们已经理解了您的数据,让我们弄清楚如何获取代码来处理它。
您从这些设备获得的值应始终采用相同的格式,因此我们可以假设它们始终以 9f78 04
开头。所以你应该检查你得到的值是否包含这些字节,然后将它们切掉,剩下的四个字节存储浮点值。您只需要将这些字节转换为浮点数。
值得庆幸的是,.Net 有一个 class 可以为您做这件事 - BitConverter
:
private static void BytesToSingle()
{
// Remember that 0x42c80000 has the 0x42 at the highest byte, 00 at the lowest byte.
byte[] snmpData = new byte[] { 0x00, 0x00, 0xC8, 0x42 };
single floatVal = BitConverter.ToSingle( snmpData, 0 );
// Prints "100.0".
Console.WriteLine( floatVal );
}
我在 c# 中通过 snmpsharpnet 查询 Synlogy NAS,并获得以下 UPS 电池值:
OID:1.3.6.1.4.1.6574.4.3.1.1.0 类型:不透明 数据:9F 78 04 42 C8 00 00
但是,它应该是一个浮点值 => 100.00
电压相同:
OID:1.3.6.1.4.1.6574.4.4.1.1.0 类型:不透明 数据:9F 78 04 43 65 00 00
浮动值 => 230.00
如何获取值?
我的代码:
// SNMP community name
OctetString communityo = new OctetString(community);
// Define agent parameters class
AgentParameters param = new AgentParameters(communityo);
// Set SNMP version to 1 (or 2)
param.Version = SnmpVersion.Ver1;
// Construct the agent address object
// IpAddress class is easy to use here because
// it will try to resolve constructor parameter if it doesn't
// parse to an IP address
IpAddress agent = new IpAddress(host);
// Construct target
UdpTarget target = new UdpTarget((IPAddress)agent, 161, 2000, 1);
// Pdu class used for all requests
Pdu pdu = new Pdu(PduType.Get);
pdu.VbList.Add(batteryoid); //
pdu.VbList.Add(voltageoid); //
pdu.VbList.Add(statusoid); //
// Make SNMP request
SnmpV1Packet result = (SnmpV1Packet)target.Request(pdu, param);
// If result is null then agent didn't reply or we couldn't parse the reply.
if (result != null)
{
// ErrorStatus other then 0 is an error returned by
// the Agent - see SnmpConstants for error definitions
if (result.Pdu.ErrorStatus != 0)
{
// agent reported an error with the request
Console.WriteLine("Error in SNMP reply. Error {0} index {1}",
result.Pdu.ErrorStatus,
result.Pdu.ErrorIndex);
}
else
{
// Reply variables are returned in the same order as they were added
// to the VbList
Console.WriteLine("battery ({0}) ({1}): {2}",
result.Pdu.VbList[0].Oid.ToString(),
SnmpConstants.GetTypeName(result.Pdu.VbList[0].Value.Type),
result.Pdu.VbList[0].Value.ToString());
Console.WriteLine("voltage ({0}) ({1}): {2}",
result.Pdu.VbList[1].Oid.ToString(),
SnmpConstants.GetTypeName(result.Pdu.VbList[1].Value.Type),
result.Pdu.VbList[1].Value.ToString());
Console.WriteLine("status ({0}) ({1}): {2}",
result.Pdu.VbList[2].Oid.ToString(),
SnmpConstants.GetTypeName(result.Pdu.VbList[2].Value.Type),
result.Pdu.VbList[2].Value.ToString());
}
}
else
{
Console.WriteLine("No response received from SNMP agent.");
}
target.Close();
来自 SNMP 的不透明数据意味着某些字段的值本身是 BER 编码的 ASN.1 数据 - 它的编码语言与 SNMP 查询本身的编码语言相同。
快速了解一下背景知识 ASN.1 是数据建模标准 - 它定义了如何以标准方式构建数据,以便其他程序可以理解该结构。 ASN.1 不是一个以位和字节编码该结构的系统——这是 BER 或 DER 编码标准的工作。
您拥有的数据 - 9F 78 04 42 C8 00 00
- 是 BER 编码数据。 BER 数据分为三部分:type
、length
和value
.
如果我们使用该模板反汇编您的字节,我们得出 9f78
是类型; 04
是长度,42c80000
是值。
根据 NetSnmp's documentation 的一些说法,9f78
的 'type' 代码在 BER 中表示“FLOATTYPE”。看起来很有前途。
下一个字节是长度字节,在本例中为04
。这意味着我们在值中有一个 4 字节的浮点数。
最后,我们有值代码 42c80000
。根据 RFC 6340, this value is to be interpreted as a standard IEEE 754 32 位浮点数。 IEEE 754 是使用最广泛的将浮点值编码为位的标准——这是大多数计算机和编程语言使用的标准。 C# 的 float
类型定义为 IEEE 754 32 位单精度浮点值,而 double
是 IEEE 754 64 位双精度浮点值,例如
如果我们使用 handy-dandy online converter 将原始字节转换为浮点数,我们会发现被视为 IEEE 754 32 位浮点数的 42c80000
的值为“100.0”。瞧,我们有你的价值。
现在我们已经理解了您的数据,让我们弄清楚如何获取代码来处理它。
您从这些设备获得的值应始终采用相同的格式,因此我们可以假设它们始终以 9f78 04
开头。所以你应该检查你得到的值是否包含这些字节,然后将它们切掉,剩下的四个字节存储浮点值。您只需要将这些字节转换为浮点数。
值得庆幸的是,.Net 有一个 class 可以为您做这件事 - BitConverter
:
private static void BytesToSingle()
{
// Remember that 0x42c80000 has the 0x42 at the highest byte, 00 at the lowest byte.
byte[] snmpData = new byte[] { 0x00, 0x00, 0xC8, 0x42 };
single floatVal = BitConverter.ToSingle( snmpData, 0 );
// Prints "100.0".
Console.WriteLine( floatVal );
}