| | |
| | | * 解析GNGGA数据返回Coordinate对象列表(增强版,包含高程数据) |
| | | */ |
| | | public static void parseGNGGAToCoordinateList(String gnggaData) { |
| | | if(isStartSaveGngga) { |
| | | String[] records = gnggaData.split("\\$GNGGA"); |
| | | if (!isStartSaveGngga || gnggaData == null || gnggaData.isEmpty()) { |
| | | return; |
| | | } |
| | | |
| | | // 处理完整的GNGGA数据(可能包含$GNGGA前缀) |
| | | String cleaned = gnggaData.trim(); |
| | | if (cleaned.startsWith("$GNGGA")) { |
| | | // 如果数据以$GNGGA开头,直接解析 |
| | | String record = cleaned.substring("$GNGGA".length()); |
| | | Coordinate coord = parseSingleGnggaRecord(record, false); |
| | | if (coord != null) { |
| | | coordinates.add(coord); |
| | | } |
| | | } else { |
| | | // 处理可能包含多个$GNGGA记录的情况 |
| | | String[] records = cleaned.split("\\$GNGGA"); |
| | | for (String record : records) { |
| | | try { |
| | | String trimmedRecord = record.trim(); |
| | | if (trimmedRecord.isEmpty()) continue; |
| | | |
| | | if (!trimmedRecord.startsWith(",")) { |
| | | trimmedRecord = "," + trimmedRecord; |
| | | } |
| | | |
| | | String[] fields = trimmedRecord.split(","); |
| | | if (fields.length < 10) { // 检查字段数量,需要包含高程字段 |
| | | continue; |
| | | } |
| | | |
| | | String deviceId = fields.length > 15 ? sanitizeDeviceId(fields[15]) : null; |
| | | if (!isDeviceAccepted(deviceId)) { |
| | | continue; |
| | | } |
| | | |
| | | // 检查定位质量 |
| | | String fixQualityStr = fields[6]; |
| | | if (fixQualityStr.isEmpty()) continue; |
| | | |
| | | int fixQuality; |
| | | try { |
| | | fixQuality = Integer.parseInt(fixQualityStr); |
| | | } catch (NumberFormatException e) { |
| | | continue; |
| | | } |
| | | |
| | | if (fixQuality != 4) continue; |
| | | |
| | | // 提取坐标数据 |
| | | String latitudeStr = fields[2]; |
| | | String latDirection = fields[3]; |
| | | String longitudeStr = fields[4]; |
| | | String lonDirection = fields[5]; |
| | | |
| | | // 提取海拔高度(第10个字段,索引9) |
| | | double elevation = 0.0; |
| | | try { |
| | | String elevationStr = fields[9]; |
| | | if (elevationStr != null && !elevationStr.isEmpty()) { |
| | | elevation = Double.parseDouble(elevationStr); |
| | | } |
| | | } catch (NumberFormatException e) { |
| | | // 高程解析失败,使用默认值0 |
| | | System.err.println("高程解析失败,使用默认值0: " + fields[9]); |
| | | } |
| | | |
| | | if (latitudeStr.isEmpty() || longitudeStr.isEmpty() || |
| | | latDirection.isEmpty() || lonDirection.isEmpty()) { |
| | | continue; |
| | | } |
| | | |
| | | // 创建Coordinate对象并添加到列表(包含高程数据) |
| | | Coordinate coord = new Coordinate(latitudeStr, latDirection, longitudeStr, lonDirection, elevation); |
| | | if (record == null || record.trim().isEmpty()) { |
| | | continue; // 跳过空字符串(split产生的第一个元素可能是空的) |
| | | } |
| | | Coordinate coord = parseSingleGnggaRecord(record, false); |
| | | if (coord != null) { |
| | | coordinates.add(coord); |
| | | |
| | | } catch (Exception e) { |
| | | System.err.println("解析GNGGA记录失败: " + record); |
| | | } |
| | | } |
| | | } |
| | | } |
| | | } |
| | | |
| | | /** |
| | | * 串口实时数据直接解析入口。 |
| | | */ |
| | | public static Coordinate dellchuankougngga(String gnggaData) { |
| | | if (!isStartSaveGngga || gnggaData == null) { |
| | | return null; |
| | | } |
| | | |
| | | String cleaned = gnggaData.trim(); |
| | | if (cleaned.isEmpty()) { |
| | | return null; |
| | | } |
| | | |
| | | int markerIndex = cleaned.indexOf("$GNGGA"); |
| | | String record = markerIndex >= 0 |
| | | ? cleaned.substring(markerIndex + "$GNGGA".length()) |
| | | : cleaned; |
| | | |
| | | Coordinate coordinate = parseSingleGnggaRecord(record, true); |
| | | if (coordinate != null) { |
| | | coordinates.add(coordinate); |
| | | } |
| | | return coordinate; |
| | | } |
| | | |
| | | private static Coordinate parseSingleGnggaRecord(String record, boolean skipDeviceFilter) { |
| | | try { |
| | | String trimmedRecord = record == null ? "" : record.trim(); |
| | | if (trimmedRecord.isEmpty()) { |
| | | return null; |
| | | } |
| | | |
| | | if (!trimmedRecord.startsWith(",")) { |
| | | trimmedRecord = "," + trimmedRecord; |
| | | } |
| | | |
| | | String[] fields = trimmedRecord.split(","); |
| | | if (fields.length < 10) { |
| | | return null; |
| | | } |
| | | |
| | | String deviceId = fields.length > 15 ? sanitizeDeviceId(fields[15]) : null; |
| | | if (!skipDeviceFilter && !isDeviceAccepted(deviceId)) { |
| | | return null; |
| | | } |
| | | |
| | | String fixQualityStr = fields[6]; |
| | | if (fixQualityStr.isEmpty()) { |
| | | return null; |
| | | } |
| | | |
| | | int fixQuality; |
| | | try { |
| | | fixQuality = Integer.parseInt(fixQualityStr); |
| | | } catch (NumberFormatException e) { |
| | | return null; |
| | | } |
| | | |
| | | if (fixQuality != 4) { |
| | | return null; |
| | | } |
| | | |
| | | String latitudeStr = fields[2]; |
| | | String latDirection = fields[3]; |
| | | String longitudeStr = fields[4]; |
| | | String lonDirection = fields[5]; |
| | | |
| | | if (latitudeStr.isEmpty() || longitudeStr.isEmpty() || |
| | | latDirection.isEmpty() || lonDirection.isEmpty()) { |
| | | return null; |
| | | } |
| | | |
| | | double elevation = 0.0; |
| | | try { |
| | | String elevationStr = fields[9]; |
| | | if (elevationStr != null && !elevationStr.isEmpty()) { |
| | | elevation = Double.parseDouble(elevationStr); |
| | | } |
| | | } catch (NumberFormatException e) { |
| | | System.err.println("高程解析失败,使用默认值0: " + fields[9]); |
| | | } |
| | | |
| | | return new Coordinate(latitudeStr, latDirection, longitudeStr, lonDirection, elevation); |
| | | } catch (Exception e) { |
| | | System.err.println("解析GNGGA记录失败: " + record); |
| | | return null; |
| | | } |
| | | } |
| | | |
| | | private static boolean isDeviceAccepted(String deviceId) { |