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();
}
}