Android OkSocket設置消息頭,獲取消息體長度;使用OkSocket實現JT808協議通訊;

前言:

以下是我踩過的一個坑,文章的思路和方法還是對的,但是不適合JT808協議,更新了一版:JT808協議通訊,使用OkSocket實現長連接

OkSocket設置消息頭,獲取消息體長度

本文章只講如何使用OkSocket接收JT808消息 ,如何設置解析頭和從消息頭中獲取消息體長度;

查看Android JT808協議通訊請移步;

以下是OkSocket設置消息頭和從消息頭中獲取消息體長度:

OkSocket需要設置解析頭,如下:

//設置自定義解析頭
OkSocketOptions.Builder okOptionsBuilder = new OkSocketOptions.Builder(mOkOptions);
okOptionsBuilder.setReaderProtocol(new IReaderProtocol() {
    @Override
    public int getHeaderLength() {
        / *
         * 返回不能爲零或負數的報文頭長度(字節數)。
         * 您返回的值應符合服務器文檔中的報文頭的固定長度值(字節數),可能需要與後臺同學商定
         * /
        return / *固定報文頭的長度(字節數)* /;
    }

    @Override
    public int getBodyLength(byte[] header, ByteOrder byteOrder) {
     / *
         * 體長也稱爲有效載荷長度,
         * 該值應從作爲函數輸入參數的header中讀取。
         * 從報文頭數據header中解析有效負載長度時,最好注意參數中的byteOrder。
         * 我們強烈建議您使用java.nio.ByteBuffer來做到這一點。
         * 你需要返回有效載荷的長度,並且返回的長度中不應該包含報文頭的固定長度
         * /
        return /*有效負載長度(字節數),固定報文頭長度(字節數)除外*/;
    }
});
//將新的修改後的參配設置給連接管理器
mManager.option(okOptionsBuilder.build());

而JT808得消息頭中就有消息體的長度;

當時跟服務器約定好,"消息包封裝項"沒有數據時返回0即可; 可以確定消息頭的長度是13;

拿到消息頭後開始計算消息體的長度:

public class JT808ReaderProtocol implements IReaderProtocol {
    @Override
    public int getHeaderLength() {
        return 13;
    }

    @Override
    public int getBodyLength(byte[] header, ByteOrder byteOrder) {
        //去除0X7E
        byte[] del7eBytes = Arrays.copyOfRange(header, 1, header.length);
        // 把JT808數據頭解析成爲實體
        Header808Bean header808 = JTT808Coding.resolve808ToHeader(del7eBytes);
        // 從消息頭實體中獲取消息體長度+2(檢驗碼、包尾0X7E
        return header808.getBodyAttr().getBodyLength() + 2;
    }
}

把消息頭中的數據轉爲實體類:

/**
     * 解析808數據解析成實體類
     *
     * @param bytes 去除了7E的數據
     *              eg:80 01 00 05 04 00 45 50 34 32 00 00 00 00 01 02 00
     * @return
     */
    public static Header808Bean resolve808ToHeader(byte[] bytes) {
        Header808Bean header808 = new Header808Bean();
        byte[] msgId = Arrays.copyOfRange(bytes, 0, 2);
        byte[] msgBodyAttributes = Arrays.copyOfRange(bytes, 2, 4);
        byte[] phone = Arrays.copyOfRange(bytes, 4, 10);
        byte[] msgFlowNum = Arrays.copyOfRange(bytes, 10, 12);

        header808.setMsgID(ByteUtil.bytes2Int(msgId));
        header808.setMobile(HexUtil.byte2HexStrNoSpace(phone));
        header808.setSeqNO(ByteUtil.bytes2Int(msgFlowNum));
        Header808Bean.BodyAttrBean  bodyAttrBean = new Header808Bean.BodyAttrBean();
        bodyAttrBean.setBodyLength(BitOperator.msgHeaderGetBodyLength(msgBodyAttributes)); //獲取消息體長度
        String bodyAtteBit = ByteUtil.byteToBit(msgBodyAttributes[0]); //取到前8位
        bodyAttrBean.setEncrypt(!"000".equals(bodyAtteBit.substring(3,6))); //獲取是否加密位
        bodyAttrBean.setSplit(!"0".equals(bodyAtteBit.substring(2,3))); //獲取是否分包位
        header808.setBodyAttr(bodyAttrBean);
        return header808;
    }
    /**
     * Jt808消息頭屬性獲取消息體長度
     *  @param bytes 消息頭屬性  長度是2的byte數組
     */
    public static int msgHeaderGetBodyLength(byte[] bytes) {
        //把數組轉爲Bit
        String property = ByteUtil.byteToBit(bytes[0]) + ByteUtil.byteToBit(bytes[1]);
        //bit刪除前6位,從第7位開始截取
        String msgL = property.substring(6);
        //bit轉Int
        int msgLInt = Integer.parseInt(msgL, 2);
        return msgLInt;
    }

實體類:

public class Header808Bean {

    /**
     * mobile : 00000000
     * msgID : 2
     * bodyAttr : {"split":false,"encrypt":false,"bodyLength":0}
     * seqNO : 1
     */

    public String mobile;
    public int msgID;
    public BodyAttrBean bodyAttr;
    public int seqNO;

    public static class BodyAttrBean {
        public boolean split;
        public boolean encrypt;
        public int bodyLength;
    }
    
}

源碼:https://github.com/CuiChenbo/JT808_OkSocket

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章