手动解析snmp的dateAndTime类型

Technorati 标签: snmp, dateAndTime

原始blog:http://blog.csdn.net/byalc/article/details/486927

 

由于原作者是基于c++的,我稍作修改,改为JAVA版的.

 

DateAndTime是Snmpv2中的一种数据类型,它主要提供了对日期时间的描述。我在使用Snmp4j开发包时,发现其不提供对DateAndTime类型的支持,而有时又需要用到该类型,于是,自己写了一个方法解析该类型,可以实现对DateAndTime类型的格式化,并且可以方便地提取各时间项。

下面是RFC中对DateAndTime的定义:

DateAndTime ::= OCTET STRING (SIZE (8 | 11))

-- A date-time specification for the local time of day.

-- This data type is intended to provide a consistent

-- method of reporting date information.

--

-- field octets contents range

-- _____ ______ ________ _____

-- 1 1-2 year 0..65536

-- (in network byte order)

-- 2 3 month 1..12

-- 3 4 day 1..31

-- 4 5 hour 0..23

-- 5 6 minutes 0..59

-- 6 7 seconds 0..60

-- (use 60 for leap-second)

-- 7 8 deci-seconds 0..9

-- 8 9 direction from UTC "+" / "-"

-- (in ascii notation)

-- 9 10 hours from UTC 0..11

-- 10 11 minutes from UTC 0..59

--

-- Note that if only local time is known, then

-- timezone information (fields 8-10) is not present.

由定义可见,DateAndTime仍然是OCTET STRING类型的数据,只是对每个字节进行了具体的定义。比如前两个字节表示年,第五个字节表示小时等。所以如果某个开发包中没有DateAndTime类型,那么大可以用Octet类型去代替。但是这样做得到的只是一些无意义的乱码而已。因此,实现的关键就在于按照定义对特殊的Octet数据进行正确的解析。

既然DateAndTime也是Octet String,那么我们就可以按照字节数组来处理他。

 

 

 
 
import java.util.Vector;
 
import org.apache.log4j.Logger;
import org.snmp4j.CommandResponderEvent;
import org.snmp4j.PDU;
import org.snmp4j.smi.OctetString;
import org.snmp4j.smi.Variable;
import org.snmp4j.smi.VariableBinding;
 
import com.asb.mediation.snmp.SNMPManager;
import com.asb.mediation.util.INMSLog;
 
 
public class SNMPAdapter  extends SNMPManager{
    private Logger adapterlog = INMSLog.getInstance().getAdapterLog();
    private Logger recvlog = INMSLog.getInstance().getReceiveLog();
    
    public SNMPAdapter(String snmpIP, String snmpPort){
        super(snmpIP, snmpPort);
    }
    
    @Override
    protected void notifyMsg(CommandResponderEvent event) {
        adapterlog.info("Mapper::notifyMsg>>    =====NOTIFY_ALARM=====");
        
        PDU pdu = event.getPDU();
        Vector vec = pdu.getVariableBindings();
        adapterlog.info("YYWifiMapper::process>>    oid size = " + vec.size());
        
        for (int i = 0; i < vec.size(); i++) {
            String oidNameValue = "";
            VariableBinding vb = (VariableBinding)vec.get(i);
            if (vb.getVariable() instanceof OctetString) {
                String value = new String(((OctetString)vb.getVariable()).getValue());
                            
                if(vb.getOid().toString().trim().equals("1.3.6.1.4.1.88888.2") ){
                    oidNameValue = "OID:"+vb.getOid()+"\t"+"value:" + parseDateAndTime(vb.getVariable());    
                }
                else{
                    oidNameValue = "OID:"+vb.getOid()+"\t"+"value:" + value.trim();
                }
            }
            else{                
                //略
            }
        }
        
    }
    
    public String parseDateAndTime(Variable v){
        adapterlog.info("YYWifiMapper::parseDateAndTime>>    v="+v);
//        adapterlog.info("YYWifiMapper::parseDateAndTime>>    v string="+v.toString());
        
        OctetString oct = (OctetString)v;
//        adapterlog.info("YYWifiMapper::parseDateAndTime>>    v hex="+ oct.toHexString());
        
        byte[] bts = oct.getValue();
        
        byte[] format_str = new byte[128];   //保存格式化过后的时间字符串
        int year;
        int month;
        int day;
        int hour;
        int minute;
        int second;
        int msecond;
        
//        for(byte b:bts){
//            adapterlog.info("YYWifiMapper::parseDateAndTime>>    bts:"+b);
//        }
        year=bts[0]*256+256+bts[1];        //adapterlog.info("YYWifiMapper::parseDateAndTime>>    year:"+year);
 
        month=bts[2];
        day=bts[3];
        hour=bts[4];
        minute=bts[5];
        second=bts[6];
        msecond=bts[7];
        //以下为格式化字符串
        int index=3;
        int temp=year;
        for(; index>=0; index--){
            format_str[index]=(byte)(48+(temp-temp/10*10));
            temp/=10;
        } 
        
        format_str[4]='-';
        index=6;
        temp=month;
        for(; index>=5; index--){
            format_str[index]=(byte)(48+(temp-temp/10*10));
            temp/=10;
        }
 
        format_str[7]='-';
        index=9;
        temp=day;
        for(; index>=8; index--){
            format_str[index]=(byte)(48+(temp-temp/10*10));
            temp/=10;
        }
 
        format_str[10]=' ';
        index=12;
        temp=hour;
        for(; index>=11; index--){
            format_str[index]=(byte)(48+(temp-temp/10*10));
            temp/=10;
        }
 
        format_str[13]=':';
        index=15;
        temp=minute;
        for(; index>=14; index--){
            format_str[index]=(byte)(48+(temp-temp/10*10));
            temp/=10;
        }
 
        format_str[16]=':';
        index=18;
        temp=second;
        for(; index>=17; index--){
            format_str[index]=(byte)(48+(temp-temp/10*10));
            temp/=10;
        }
 
        
//        format_str[19]='.';
//        index=21;
//        temp=msecond;
//        for(; index>=20; index--){
//            format_str[index]=(byte)(48+(temp-temp/10*10));
//            temp/=10;
//        }
//
//        format_str[22]=0;  
//        adapterlog.info("YYWifiMapper::parseDateAndTime>>    format_str = " + new String(format_str));
        
        return new String(format_str);
    }
}

 

 

 

 

实际运行log如下(注意值为16进制):

YYWifiMapper::parseDateAndTime>>  v=07:dc:09:17:11:01:1b:02:2b:08:00

YYWifiMapper::parseDateAndTime>>  format_str = 2012-09-23 17:01:27

 

 

处理年的时候稍有不同,因为年是由两个字节表示,所以要用高位字节乘256再加低位字节,处理语句为year=bts[0]*256+256+bts[1];标准的时间输出格式应该为YYYY-MM-DD HH:MM:SS形式。

 

其实自己用计算器就能算出时间,很简单了。

主要是年的计算byte是可以为负值,所以手动计算的公式:

07*256 + dc = 07*256 + 220 = 2012年;或者07*256 + (256 + dc) = 07*256 + (256 + (-36)) = 2012年;

09 = 09月

17 = 23日

11 = 17时

01 = 01分

1b = 27秒

你可能感兴趣的:(手动解析snmp的dateAndTime类型)