1. 程式人生 > >android串列埠通訊接受自定義協議資料並解析問題

android串列埠通訊接受自定義協議資料並解析問題

1.一般自定義的串列埠協議

 串列埠傳輸介面底層是按位(bit)傳送的,上層是按byte傳送和接收的,但協議為了方便描述,每個byte用十六進位制數(0x00~0xFF)表示,範相當於十進位制的0~255,而byte為八位且是有符號型別,相當於十進位制的-128~127,明顯0x8F~0xFF(128~255)是不能準確轉換為byte的,咋辦?

byte b = 0xFF;

編譯器會提示出錯,因為0xFF被當作255整數處理,255超過了byte(-128~127)的範圍,不能直接賦值,那咋辦?強轉啊!

 byte b = (byte) 0xFF;

這樣就沒問題了,但此時你會不會覺得這樣寫就和協議想傳送0xFF的想法不匹配了呢,我明明想發個255來著,那我告訴你,你一個一個位元組的發,每個位元組就只能是-128~127,不能在其他範圍,所以強轉的目的是你可以傳送這個0xFF的前提,傳送的值肯定不是255,具體是啥:

public class Main {

    public static void main(String[] args) {
        byte c1 = (byte) 0xFF;
        int c2 = c1 & 0xFF;
        System.out.println(""+c1);
        System.out.println(""+c2);
    }
}
-1
255

Process finished with exit code 0

可見,實際上是一個-1,但接受端為了表達這是個傳送端傳送給我的是0xFF(255)而不是-1,你可以通過取到該位元組值後 “ 該值 & 0xFF”轉為無符號值即255.

通常自定義協議的格式:

一.接收到資料是不固定的長度,協議是起始是AA AA    結束是DE D0
接收到的資料有可能是AA AA 08 56 82 44 DE DO

二.接受到資料是不固定的長度,協議的起始A0 55  第三個位元組為協議長度,結束位元組是傳送資料的異或校驗值,

列如:A0 55 04 51 00 00    55 A0 55 04 53 00 01 56

結束位元組是前面各個位元組異或後的值:

 /**
     * 異或校驗和
     * @param data
     * @return
     */
    public static byte getXor(byte[] data){
        byte temp=data[0];
        for (int i = 1; i <data.length; i++) {
            temp ^=data[i];
        }
        return temp;
    }

2.分段接收資料不好解析

在讀取串列埠資料時,通常線上程中讀取輸入流中的資料,這時接受的位元組數是不固定的,一條指令被分成若干段,接受到的散亂位元組不好處理,看到網上有做延時接受處理,也就是輸入流可用的時候就延時一會兒,等接受完了再一次性讀出來,效果不錯:

/**
     * 4.接收串列埠資料的執行緒
     */
    private class ReceiveThread extends Thread {
        @Override
        public void run() {
            //條件判斷,只要條件為true,則一直執行這個執行緒
            while (isStart) {
                if (inputStream == null) {
                    return;
                }
                byte[] readData = new byte[1024*4];
                try {
                    String receiveCmd = "";
                    String HEAD = "A055";
                    StringBuilder sb = new StringBuilder();
                    // 為了一次性讀完,做了延遲讀取
                    if (inputStream.available() > 0 ) {
                        SystemClock.sleep(200);
                        int size = inputStream.read(readData);
                        if (size > 0) {
                            String readString = DataUtils.ByteArrToHex(readData, 0, size);
                            LogUtils.d(readString);
                            if(!TextUtils.isEmpty(readString)){
                                String[] split = readString.split(HEAD);
                                for (int i = 1; i < split.length; i++) {
                                    receiveCmd = HEAD+split[i];
                                    sb.append(receiveCmd+"\n");
                                    LogUtils.e(receiveCmd);
                                }
                            }
                            EventBus.getDefault().post(sb.toString());
                            sb.setLength(0);
                        }
                    }

                } catch (IOException e) {
                    e.printStackTrace();
                }
            }

        }
    }