1

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();
4

1 に答える 1

2

SNMP からの不透明なデータは、一部のフィールドの値自体が BER エンコードされた ASN.1 データであることを意味します。これは、SNMP クエリ自体がエンコードされているのと同じ言語でエンコードされています。

簡単な背景として、ASN.1 はデータをモデリングするための標準です。これは、他のプログラムが構造を理解できるように、標準的な方法でデータを構造化する方法を定義しています。ASN.1 は、その構造をビットとバイトでエンコードするためのシステムではありません。これは、BER または DER エンコード標準の仕事です。

あなたが持っているデータ - 9F 78 04 42 C8 00 00- はBERでエンコードされたデータです。typeBER データは、 、length、およびの 3 つの部分に分けられvalueます。

そのテンプレートを使用してバイトを逆アセンブルする9f78と、型がわかります。04は長さ、42c80000は値です。

一部のNetSnmp のドキュメントによると、BER の「タイプ」コード9f78は「FLOATTYPE」を意味します。有望に見えます。

この場合、次のバイトは長さバイト04です。これは、値に 4 バイトの float があることを意味します。

最後に、値 code があります42c80000RFC 6340によると、この値は標準のIEEE 754 32 ビット float として解釈されます。IEEE 754 は、浮動小数点値をビットにエンコードするために最も広く使用されている標準であり、ほとんどのコンピューターやプログラミング言語で使用されています。C# のfloat型は、IEEE 754 32 ビット単精度浮動小数点値として定義され、doubleIEEE 754 64 ビット倍精度浮動小数点値です。たとえば、

生のバイトを浮動小数点数に変換する便利なオンライン コンバーターを使用する42c80000と、IEEE 754 の 32 ビット浮動小数点数として扱われる値が '100.0' であることがわかります。出来上がり、私たちはあなたの価値を持っています。

データの意味がわかったので、コードでデータを処理する方法を考えてみましょう。

これらのデバイスから取得する値は常に同じ形式である必要があるため、常に で始まると想定でき9f78 04ます。したがって、取得した値にこれらのバイトが含まれていることを確認してから、それらを切り捨てて、浮動小数点値を格納する残りの 4 バイトを残す必要があります。これらのバイトを float に変換するだけです。

ありがたいことに、.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 );
    }
于 2016-02-08T19:17:18.117 に答える