diff --git a/src/main/java/io/github/dsheirer/map/MapPanel.java b/src/main/java/io/github/dsheirer/map/MapPanel.java index e3bd1c2e6..f79fa930c 100644 --- a/src/main/java/io/github/dsheirer/map/MapPanel.java +++ b/src/main/java/io/github/dsheirer/map/MapPanel.java @@ -468,7 +468,7 @@ private JTable getPlottedTracksTable() if(mPlottedTracksTable == null) { mPlottedTracksTable = new JTable(mMapService.getPlottableEntityModel()); - + mPlottedTracksTable.setAutoCreateRowSorter(true); mMapService.getPlottableEntityModel().addTableModelListener(e -> { //Update the followed entity for DELETE/UPDATE operations diff --git a/src/main/java/io/github/dsheirer/map/PlottableEntityHistory.java b/src/main/java/io/github/dsheirer/map/PlottableEntityHistory.java index 85fdacf69..5f43074c0 100644 --- a/src/main/java/io/github/dsheirer/map/PlottableEntityHistory.java +++ b/src/main/java/io/github/dsheirer/map/PlottableEntityHistory.java @@ -87,12 +87,42 @@ public IdentifierCollection getIdentifierCollection() */ public void add(PlottableDecodeEvent event) { - mCurrentEvent = event; - mLocationHistory.add(0, new TimestampedGeoPosition(event.getLocation(), event.getTimeStart())); + TimestampedGeoPosition mostRecentPosition = getLatestPosition(); + TimestampedGeoPosition latest = new TimestampedGeoPosition(event.getLocation(), event.getTimeStart()); - while(mLocationHistory.size() > MAX_LOCATION_HISTORY) + if(isUnique(latest, mostRecentPosition)) { - mLocationHistory.remove(mLocationHistory.size() - 1); + mCurrentEvent = event; + mLocationHistory.add(0, latest); + + while(mLocationHistory.size() > MAX_LOCATION_HISTORY) + { + mLocationHistory.remove(mLocationHistory.size() - 1); + } + } + } + + /** + * Indicates if the latest time and position is at least 30 seconds newer than the previous position and either the + * latitude or longitude differs by at least 0.00001 degrees. + * @param latest location + * @param previous location + * @return indication of uniqueness. + */ + private boolean isUnique(TimestampedGeoPosition latest, TimestampedGeoPosition previous) + { + if(latest != null && previous == null) + { + return true; + } + + if(latest != null && previous != null) + { + return latest.getTimestamp() > (previous.getTimestamp() + 30_000) || + Math.abs(latest.getLatitude() - previous.getLatitude()) > 0.00001 || + Math.abs(latest.getLongitude() - previous.getLongitude()) > 0.00001; } + + return false; } } diff --git a/src/main/java/io/github/dsheirer/map/PlottableEntityModel.java b/src/main/java/io/github/dsheirer/map/PlottableEntityModel.java index 0b54ee411..50722888e 100644 --- a/src/main/java/io/github/dsheirer/map/PlottableEntityModel.java +++ b/src/main/java/io/github/dsheirer/map/PlottableEntityModel.java @@ -22,6 +22,7 @@ import io.github.dsheirer.alias.Alias; import io.github.dsheirer.alias.AliasList; import io.github.dsheirer.alias.AliasModel; +import io.github.dsheirer.identifier.Form; import io.github.dsheirer.identifier.Identifier; import io.github.dsheirer.identifier.configuration.AliasListConfigurationIdentifier; import io.github.dsheirer.module.decode.event.PlottableDecodeEvent; @@ -104,7 +105,7 @@ public void receive(PlottableDecodeEvent plottableDecodeEvent) EventQueue.invokeLater(() -> { Identifier from = plottableDecodeEvent.getIdentifierCollection().getFromIdentifier(); - if(from != null) + if(from != null && from.getForm() != Form.LOCATION) { AliasListConfigurationIdentifier aliasList = plottableDecodeEvent.getIdentifierCollection().getAliasListConfiguration(); String key = (aliasList != null ? aliasList.toString() : KEY_NO_ALIAS_LIST) + from; diff --git a/src/main/java/io/github/dsheirer/module/decode/p25/phase2/P25P2DecoderState.java b/src/main/java/io/github/dsheirer/module/decode/p25/phase2/P25P2DecoderState.java index 235cf41ec..b8cbb919c 100644 --- a/src/main/java/io/github/dsheirer/module/decode/p25/phase2/P25P2DecoderState.java +++ b/src/main/java/io/github/dsheirer/module/decode/p25/phase2/P25P2DecoderState.java @@ -40,6 +40,7 @@ import io.github.dsheirer.log.LoggingSuppressor; import io.github.dsheirer.message.IMessage; import io.github.dsheirer.module.decode.DecoderType; +import io.github.dsheirer.module.decode.event.DecodeEvent; import io.github.dsheirer.module.decode.event.DecodeEventType; import io.github.dsheirer.module.decode.event.PlottableDecodeEvent; import io.github.dsheirer.module.decode.p25.IServiceOptionsProvider; @@ -1523,13 +1524,14 @@ private void processGPS(MacMessage message, MacStructure structure) collection.update(fromRadio); } - broadcast(PlottableDecodeEvent.plottableBuilder(DecodeEventType.GPS, message.getTimestamp()) + DecodeEvent decodeEvent = PlottableDecodeEvent.plottableBuilder(DecodeEventType.GPS, message.getTimestamp()) .protocol(Protocol.APCO25) .location(gps.getGeoPosition()).channel(getCurrentChannel()).details("LOCATION: " + gps.getLocation().toString()) .identifiers(collection) - .build()); - + .build(); + broadcast(decodeEvent); + mTrafficChannelManager.broadcast(decodeEvent); mTrafficChannelManager.processP2CurrentUser(getCurrentFrequency(), getTimeslot(), gps.getLocation(), message.getTimestamp()); }