NMEA0183-AIS数据解析

public class AisParser {

    public void ParseNmeaMessage() {
        String nmeaMessage = "!AIVDM,1,1,,B,16:Erk00008PI@h>EMB7R4E@049T,0*04";
        if (isValidChecksum(nmeaMessage)) {
            parseNmeaMessage(nmeaMessage);
        } else {
            System.out.println("校验和验证失败");
        }
    }

    // 校验NMEA消息的校验和
    private boolean isValidChecksum(String nmeaMessage) {
        int asteriskIndex = nmeaMessage.indexOf('*');
        if (asteriskIndex == -1 || asteriskIndex + 3 != nmeaMessage.length()) {
            return false;
        }

        String checksumString = nmeaMessage.substring(asteriskIndex + 1);
        int checksum = Integer.parseInt(checksumString, 16);

        String dataToCheck = nmeaMessage.substring(1, asteriskIndex);
        int calculatedChecksum = 0;
        for (char ch : dataToCheck.toCharArray()) {
            calculatedChecksum ^= ch;
        }

        return calculatedChecksum == checksum;
    }

    // 解析NMEA消息
    private void parseNmeaMessage(String nmeaMessage) {
        if (nmeaMessage.startsWith("!AIVDM") || nmeaMessage.startsWith("!AIVDO")) {
            String[] parts = nmeaMessage.split(",");
            String payload = parts[5];
            parsePayload(payload);
        }
    }

    // 解析PayLoad数据
    private void parsePayload(String payload) {
        String binaryPayload = convertSixBitAsciiToBinary(payload);
        int messageType = Integer.parseInt(binaryPayload.substring(0, 6), 2);

        System.out.println("消息类型: " + messageType);

        switch (messageType) {
            case 1:
            case 2:
            case 3:
                parseDynamicData(binaryPayload);
                break;
            case 5:
                parseStaticData(binaryPayload);
                break;
            default:
                System.out.println("不支持的消息类型: " + messageType);
        }
    }

    // 转换6位ASCII到二进制字符串
    private String convertSixBitAsciiToBinary(String payload) {
        StringBuilder binaryString = new StringBuilder();
        for (char c : payload.toCharArray()) {
            int value = c - 48;
            if (value > 40) value -= 8;
            String binaryChar = String.format("%6s", Integer.toBinaryString(value)).replace(' ', '0');
            binaryString.append(binaryChar);
        }
        return binaryString.toString();
    }

    // 解析动态数据
    private void parseDynamicData(String binaryPayload) {
        int mmsi = Integer.parseInt(binaryPayload.substring(8, 38), 2);
        int navigationStatus = Integer.parseInt(binaryPayload.substring(38, 42), 2);
        float speedOverGround = Integer.parseInt(binaryPayload.substring(50, 60), 2) / 10.0f;
        int longitude = Integer.parseInt(binaryPayload.substring(61, 89), 2) - 180000000;
        int latitude = Integer.parseInt(binaryPayload.substring(89, 116), 2) - 90000000;

        System.out.println("MMSI: " + mmsi);
        System.out.println("导航状态: " + navigationStatus);
        System.out.println("对地速度: " + speedOverGround + " 节");
        System.out.println("经度: " + (longitude / 600000.0) + " 度");
        System.out.println("纬度: " + (latitude / 600000.0) + " 度");
    }

    // 解析静态数据
    private void parseStaticData(String binaryPayload) {
        int mmsi = Integer.parseInt(binaryPayload.substring(8, 38), 2);
        String vesselName = convertBinaryToString(binaryPayload.substring(112, 232));
        int shipType = Integer.parseInt(binaryPayload.substring(232, 240), 2);
        int dimensionToBow = Integer.parseInt(binaryPayload.substring(240, 249), 2);

        System.out.println("MMSI: " + mmsi);
        System.out.println("船名: " + vesselName);
        System.out.println("船型: " + shipType);
        System.out.println("船首到船长距离: " + dimensionToBow + " 米");
    }

    // 将二进制字符串转换为ASCII字符串
    private String convertBinaryToString(String binary) {
        StringBuilder text = new StringBuilder();
        for (int i = 0; i < binary.length(); i += 6) {
            String byteString = binary.substring(i, i + 6);
            int charCode = Integer.parseInt(byteString, 2);
            if (charCode <= 31) {
                charCode += 64;
            }
            text.append((char) charCode);
        }
        return text.toString().trim();
    }
}

 

posted @ 2024-05-24 14:13  方大帝的博客  阅读(228)  评论(0编辑  收藏  举报