aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--setup/default.xml7
-rw-r--r--src/main/java/org/traccar/config/Keys.java9
-rw-r--r--src/main/java/org/traccar/database/DataManager.java16
-rw-r--r--src/main/java/org/traccar/handler/FilterHandler.java35
4 files changed, 30 insertions, 37 deletions
diff --git a/setup/default.xml b/setup/default.xml
index 54677d845..7ed3e35b2 100644
--- a/setup/default.xml
+++ b/setup/default.xml
@@ -22,7 +22,6 @@
<entry key='filter.enable'>true</entry>
<entry key='filter.future'>86400</entry>
- <entry key='filter.relative'>false</entry>
<entry key='event.ignoreDuplicateAlerts'>true</entry>
<entry key='processing.computedAttributes.enable'>true</entry>
@@ -53,14 +52,10 @@
SELECT * FROM tc_positions WHERE deviceId = :deviceId AND fixTime = :time LIMIT 1
</entry>
- <entry key='database.selectPrevPosition'>
+ <entry key='database.selectPrecedingPosition'>
SELECT * FROM tc_positions WHERE deviceId = :deviceId AND fixTime lte :time ORDER BY fixTime DESC LIMIT 1
</entry>
- <entry key='database.selectNextPosition'>
- SELECT * FROM tc_positions WHERE deviceId = :deviceId AND fixTime gt :time ORDER BY fixTime ASC LIMIT 1
- </entry>
-
<entry key='database.selectLatestPositions'>
SELECT tc_positions.* FROM tc_positions INNER JOIN tc_devices ON tc_positions.id = tc_devices.positionid;
</entry>
diff --git a/src/main/java/org/traccar/config/Keys.java b/src/main/java/org/traccar/config/Keys.java
index c6a202d2f..a77204175 100644
--- a/src/main/java/org/traccar/config/Keys.java
+++ b/src/main/java/org/traccar/config/Keys.java
@@ -890,11 +890,12 @@ public final class Keys {
Collections.singletonList(KeyType.GLOBAL));
/**
- * If FALSE, then filter compares duplicates, distance or period only with the last received location.
- * Server expects all locations to come sequentially.
+ * If false, the server expects all locations to come sequentially (for each device). Filter checks for duplicates,
+ * distance, speed, or time period only against the location that was last received by server.
*
- * If TRUE, then filter compares duplicates, distance or period with Position's fixTime strictly before and after.
- * Server expects locations to come at random order, since tracking device might go offline.
+ * If true, the server expects locations to come at random order (since tracking device might go offline).
+ * Filter checks for duplicates, distance, speed, or time period against the preceding Position's.
+ * Important: setting to true can cause potential performance issues.
*/
public static final ConfigKey<Boolean> FILTER_RELATIVE = new ConfigKey<>(
"filter.relative",
diff --git a/src/main/java/org/traccar/database/DataManager.java b/src/main/java/org/traccar/database/DataManager.java
index 3f702f78a..d8401774e 100644
--- a/src/main/java/org/traccar/database/DataManager.java
+++ b/src/main/java/org/traccar/database/DataManager.java
@@ -340,20 +340,8 @@ public class DataManager {
}
}
- public Position getPrevPosition(long deviceId, Date date) throws SQLException {
- Collection<Position> positions = QueryBuilder.create(dataSource, getQuery("database.selectPrevPosition"))
- .setLong("deviceId", deviceId)
- .setDate("time", date)
- .executeQuery(Position.class);
- if (positions.isEmpty()) {
- return null;
- } else {
- return positions.iterator().next();
- }
- }
-
- public Position getNextPosition(long deviceId, Date date) throws SQLException {
- Collection<Position> positions = QueryBuilder.create(dataSource, getQuery("database.selectNextPosition"))
+ public Position getPrecedingPosition(long deviceId, Date date) throws SQLException {
+ Collection<Position> positions = QueryBuilder.create(dataSource, getQuery("database.selectPrecedingPosition"))
.setLong("deviceId", deviceId)
.setDate("time", date)
.executeQuery(Position.class);
diff --git a/src/main/java/org/traccar/handler/FilterHandler.java b/src/main/java/org/traccar/handler/FilterHandler.java
index 16e5ae2da..5287a7639 100644
--- a/src/main/java/org/traccar/handler/FilterHandler.java
+++ b/src/main/java/org/traccar/handler/FilterHandler.java
@@ -146,6 +146,7 @@ public class FilterHandler extends BaseDataHandler {
}
private boolean filter(Position position) {
+
if (skipAttributes(position)) {
return false;
}
@@ -173,43 +174,44 @@ public class FilterHandler extends BaseDataHandler {
}
// relative filtering
- if (filterDuplicate || filterDistance != 0 || filterMaxSpeed != 0 || filterMinPeriod != 0) {
- Position previous = null;
+ long deviceId = position.getDeviceId();
+ if (filterDuplicate || filterDistance > 0 || filterMaxSpeed > 0 || filterMinPeriod > 0) {
+ Position preceding = null;
if (filterRelative) {
try {
Date newFixTime = position.getFixTime();
- previous = Context.getDataManager().getPrevPosition(position.getDeviceId(), newFixTime);
+ preceding = Context.getDataManager().getPrecedingPosition(deviceId, newFixTime);
} catch (SQLException e) {
- LOGGER.warn("Error filtering position", e);
+ LOGGER.warn("Error retrieving preceding position; fallbacking to last received position.", e);
+ preceding = getLastReceivedPosition(deviceId);
}
} else {
- if (Context.getIdentityManager() != null) {
- previous = Context.getIdentityManager().getLastPosition(position.getDeviceId());
- }
+ preceding = getLastReceivedPosition(deviceId);
}
- if (skipLimit(position, previous)) {
+ if (skipLimit(position, preceding)) {
return false;
}
- if (filterDuplicate(position, previous)) {
+ if (filterDuplicate(position, preceding)) {
filterType.append("Duplicate ");
}
- if (filterDistance(position, previous)) {
+ if (filterDistance(position, preceding)) {
filterType.append("Distance ");
}
- if (filterMaxSpeed(position, previous)) {
+ if (filterMaxSpeed(position, preceding)) {
filterType.append("MaxSpeed ");
}
- if (filterMinPeriod(position, previous)) {
+ if (filterMinPeriod(position, preceding)) {
filterType.append("MinPeriod ");
}
}
if (filterType.length() > 0) {
+
StringBuilder message = new StringBuilder();
message.append("Position filtered by ");
message.append(filterType.toString());
message.append("filters from device: ");
- message.append(Context.getIdentityManager().getById(position.getDeviceId()).getUniqueId());
+ message.append(Context.getIdentityManager().getById(deviceId).getUniqueId());
LOGGER.info(message.toString());
return true;
@@ -218,6 +220,13 @@ public class FilterHandler extends BaseDataHandler {
return false;
}
+ private Position getLastReceivedPosition(long deviceId) {
+ if (Context.getIdentityManager() != null) {
+ return Context.getIdentityManager().getLastPosition(deviceId);
+ }
+ return null;
+ }
+
@Override
protected Position handlePosition(Position position) {
if (filter(position)) {