编辑代码

package com.example.SecondProject.Utils;
 
import java.util.Arrays;
 
// 协议解析/封装工具
public class ProtocolUtil {
    public static String TAG = "ProtocolUtil";
 
    private static String data = "";
    // 北斗指令拼接:每次接收的都是碎片数据,需要自行拼接为完整的指令,例如:$CCIC     A,1595   0044,0,1,33    3211*99
    public static void parseData_fragment(String str){
        // 拼接数据
        data +=  str;
        // 找到 $ 符,如果没有的话,这条数据就丢弃,重置数据,如果有的话就从 $ 开始截取到后面的所有字符
        int startIndex = data.indexOf("$");
        if (startIndex < 0){
            data = "";
            return;
        }
        if (startIndex > 0) {
            data = data.substring(startIndex);
        }
        // 找到 * 符,如果没有代表接收的是中间的数据,退出接收下一串,如果有代表这是这条指令的最后一段 *+校验
        int endIndex = data.indexOf("*");
        if( endIndex < 1 ) return;
 
        String intactData;
        // 先判断一下长度,不然的话长度不足会断掉
        if(data.length() < endIndex+3){
            intactData = data;
        }else {
            intactData = data.substring(0,endIndex+3);  // 截出 $---*66
            data = data.substring(endIndex+3);  // 多出来的是下一条指令的开头部分,保留到下一次用
        }
        // 这里偷懒了,没有对最后两位校验符做验证,有强迫症的话可以自行添加
        String XOR_str = intactData.substring(intactData.length() - 2);  // 异或校验符
        parseData(intactData);  // 解析协议
    }
 
    // 解析数据
    public static void parseData(String intactData){
        // 拿到 * 的位置
        int xorIndex = intactData.indexOf("*");
        if(xorIndex == -1){return;}
        String data_str = intactData.substring(0, xorIndex);  // 截取到 * 之前,例:$CCICR,0,00
        if(!data_str.contains(",")){return;}
        String[] values = data_str.split(",", -1);  // , 分割,例:["$CCICR","0","00"]
//        Log.e(TAG, "正在解析的数据:"+ Arrays.toString(values));
        if (data_str.contains("FKI")) {  // 反馈信息
            BDFKI(values);
        }else if (data_str.contains("ICP")) {  // IC 信息
            BDICP(values);
        } else if (data_str.contains("PWI")) {  // 波束信息
            BDPWI(values);
        } else if (data_str.contains("TCI")){  // 北斗三代通信信息
            BDTCI(values);
        }
        // 其余类型的应该都是 RNSS 定位数据
        else {
            parseRNSS(values);
        }
 
    }
 
 
    public  static void BDICP(String[] value){
        try {
            String cardID = value[1];
            String cardFrequency = value[14];
            String cardLevel = value[15];
            System.out.println(TAG + "收到IC信息: 卡号-" + cardID + " 频度-" + cardFrequency + " 等级-" + cardLevel);
        }catch (Exception e){
            System.out.println(TAG+ "BDICP: 解析错误" + e.toString());
            e.printStackTrace();
            return;
        }
    }
 
 
    public static void BDPWI(String[] values){
        // 尽量用 try 避免线程中断
        try {
            int rdss2Count1 = Integer.parseInt(values[2]);
            int index = 2 + (rdss2Count1*3) + 1;
            int rdss3Count = Integer.parseInt(values[index]);
            index++;
            int s21[] = {0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0};
            for (int i = 0 ;i < rdss3Count; i++) {
                if(values.length < index+2){
                    return;  // 越界检测
                }
                int id = Integer.parseInt(values[index]);
                if (id > 21 || id <= 0) continue;
                int number = Integer.parseInt(values[index+1]);
                s21[id-1] = number;
                index += 4;
            }
            System.out.println(TAG+  "收到信号数据:"+Arrays.toString(s21));
 
        }catch (Exception e){
           System.out.println(TAG+ "BDPWI: 解析错误" + e.toString());
            e.printStackTrace();
            return;
        }
    }
 
    // 通信申请后的反馈信息
    public static void BDFKI(String[] values){
        try {
            String type = values[2];  // 反馈的指令类型 :只用 TCQ
            String result = values[3];  // 反馈结果 : Y / N
            String reason = values[4];  // 失败原因
 
            if(result.equals("Y")){
               System.out.println(TAG+  "收到反馈信息: " + type + "指令发送成功");
            } else {
                switch ( reason ){
                    case "1":
                       System.out.println(TAG+  "收到反馈信息: " + type + "指令发送失败:频度未到,发射被抑制");
                        break;
                    case "2":
                       System.out.println(TAG+ "收到反馈信息: " + type + "指令发送失败:接收到系统的抑制指令,发射被抑制");
                        break;
                    case "3":
                      System.out.println(TAG+ "收到反馈信息: " + type + "指令发送失败:当前设置为无线电静默状态,发射被抑制");
                        break;
                    case "4":
                     System.out.println(TAG+  "收到反馈信息: " + type + "指令发送失败:功率未锁定");
                        break;
                    case "5":
                     System.out.println(TAG+  "收到反馈信息: " + type + "指令发送失败:未检测到IC模块信息");
                        break;
                    default:
                     System.out.println(TAG+  "收到反馈信息: " + type + "指令发送失败,原因码是" + reason);
                        break;
                }
            }
 
        }catch (Exception e){
            System.out.println(TAG+  "BDFKI: 解析错误" + e.toString());
            e.printStackTrace();
            return;
        }
 
    }
 
 
    // 收到了 TCI 通信信息
    public static void BDTCI(String[] values){
        try {
            String fromNumber = values[1];  // 发送发地址
            String toNumber = values[2];  // 收信方地址
            String messageType = values[5];  // 消息类型:汉字/代码/混合
            String timeHour = values[4];  // 消息时间
            String content = values[7];  // 消息内容
          System.out.println(TAG+ "收到通信信息: 发送号码-" + fromNumber + " 接收号码-" + toNumber + " 消息类型-" + messageType + " 消息时间-" + timeHour + " 消息内容-" + content );
        }catch (Exception  e){
           System.out.println(TAG+  "BDTCI: 解析错误" + e.toString());
            e.printStackTrace();
            return;
        }
    }
 
    // 解析 RNSS 位置数据,只解析了 GGA 和 GLL ,其余的参考文档自行解析
    public static void parseRNSS(String[] values){
        try {
            // 拆分数据
            String head = values[0];
            if (head.contains("GGA")){
                if (values[6].equals("0")) return;  // 0 就是无效定位,不要
                String latitude = analysisLonlat(values[2]) + "";  // 纬度
                String longitude = analysisLonlat(values[4]) + "";  // 经度
                String altitude;  // 海拔
                if(values[9] != null || !values[9].equals("")){
                    altitude = values[9];
                }else {
                    altitude = "0";
                }
                System.out.println(TAG+ "解析RNSS定位数据(GGA): 纬度-" + latitude + " 经度-" + longitude + " 高度-" + altitude );
            }else if (head.contains("GLL")){
                if (values[6].equals("V")) return;  // V - 无效  A - 有效
                String latitude = analysisLonlat(values[1]) + "";  // 纬度
                String longitude = analysisLonlat(values[3]) + "";  // 经度
                System.out.println(TAG+  "解析RNSS定位数据(GLL): 纬度-" + latitude + " 经度-" + longitude );
            }
            else {
                return;
            }
        }catch (Exception e){
            System.out.println(TAG+  "parseRNSS: 解析错误" + e.toString());
            e.printStackTrace();
            return;
        }
    }
 
    public static double analysisLonlat(String value){
        if(value.contains("N") || value.contains("E")){
            return 0.0;
        }
        if (value.equals("")|| value == null) return 0.0;
        double lonlat = Double.valueOf(value);
        int dd = (int)lonlat / 100;
        int mm = (int)lonlat % 100;
        double ms = lonlat - (int)lonlat;
        return dd+((mm+ms)/60.0);
    }
 
// 封装 ---------------------------------------------------------------------------------------
    // 查询 IC 信息:type - 0检测本机IC信息,1检测本机编组信息,2检测下属用户,3检测IC模块工作模式
    public static String CCICR(int type, String info) {
        String command = "CCICR," + type + "," + info;
        return packaging(command);
    }
 
 
    // 打包,加上 $ 和 * 和 校验和,输出 hex_str
    public static String packaging(String tmp){
        String hexCommand = DataUtil.string2Hex(tmp);
        String hh = getCheckCode0007(hexCommand).toUpperCase();  // 检验和
        return "24"+hexCommand+"2A"+DataUtil.string2Hex(hh)+"0D0A";
    }
 
    // 计算异或校验和
    public static String getCheckCode0007(String strProtocol) {
        strProtocol.replace(" ",  "");
        byte chrCheckCode = 0;
        for (int i = 0; i < strProtocol.length(); i += 2) {
            char chrTmp ;
            chrTmp = strProtocol.charAt(i);
            if (chrTmp == ' ') continue;
            byte chTmp1 = (byte) (DataUtil.char2HexByte(chrTmp) << 4);
            chrTmp = strProtocol.charAt(i + 1);
            byte chTmp2 = (byte) (chTmp1 + (DataUtil.char2HexByte(chrTmp) & 15));
            chrCheckCode = i == 0 ? chTmp2 : (byte) (chrCheckCode ^ chTmp2);
        }
        String strHexCheckCode = String.format("%x", Byte.valueOf(chrCheckCode));
        if ((strHexCheckCode = strHexCheckCode.toUpperCase()).length() != 2) {
            if (strHexCheckCode.length() > 2) {
                strHexCheckCode = strHexCheckCode.substring(strHexCheckCode.length() - 2);
            } else if (strHexCheckCode.length() < 2 && strHexCheckCode.length() > 0) {
                strHexCheckCode = "0" + strHexCheckCode;
            }
        }
        return strHexCheckCode;
    }
 
}
class Main {
	public static void main(String[] args) {
        //JSRUN引擎2.0,支持多达30种语言在线运行,全仿真在线交互输入输出。
		System.out.println("Hello world!   - java.jsrun.net ");
	}
}