【问题标题】:snmpsharpnet Opaque Floatsnmpsharpnet 不透明浮点数
【发布时间】:2023-03-04 18:08:01
【问题描述】:

我在 c# 中通过 snmpsharpnet 查询 Synology 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();

【问题讨论】:

    标签: c# snmp snmpsharpnet


    【解决方案1】:

    来自 SNMP 的不透明数据意味着某些字段的值本身就是 BER 编码的 ASN.1 数据 - 它采用 SNMP 查询本身的编码语言。

    对于一些快速的背景知识,ASN.1 是一种数据建模标准 - 它定义了如何以标准方式构造数据,以便其他程序可以理解该结构。 ASN.1 不是一个以位和字节对该结构进行编码的系统 - 这是 BER 或 DER 编码标准的工作。

    您拥有的数据 - 9F 78 04 42 C8 00 00 - 是 BER 编码的数据。 BER 数据分为三部分:typelengthvalue

    如果我们使用该模板反汇编您的字节,我们会得出9f78 是类型; 04 是长度,42c80000 是值。

    根据NetSnmp's documentation 的某些部分,9f78 的“类型”代码在 BER 中表示“FLOATTYPE”。看起来很有希望。

    下一个字节是长度字节,在本例中为04。这意味着我们的值中有一个 4 字节的浮点数。

    最后,我们有值代码42c80000。根据RFC 6340,该值将被解释为标准IEEE 754 32 位浮点数。 IEEE 754 是将浮点值编码为位的最广泛使用的标准 - 这是大多数计算机和编程语言使用的标准。 C#的float类型定义为IEEE 754 32位单精度浮点值,double是IEEE 754 64位双精度浮点值,例如

    如果我们使用handy-dandy online converter 将原始字节转换为浮点数,我们会发现42c80000 被视为 IEEE 754 32 位浮点数是值“100.0”。瞧,我们有你的价值。

    现在我们已经理解了您的数据,让我们弄清楚如何让代码来处理它。

    您从这些设备获得的值应始终采用相同的格式,因此我们可以假设它们始终以9f78 04 开头。所以你应该检查你得到的值是否包含这些字节,然后将它们切掉,剩下的四个字节存储浮点值。您只需要将这些字节转换为浮点数。

    谢天谢地,.Net 有一个课程可以为你做这件事 - 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 );
        }
    

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2013-05-14
      • 1970-01-01
      • 1970-01-01
      • 2015-05-12
      • 2014-08-08
      • 1970-01-01
      相关资源
      最近更新 更多