diff options
Diffstat (limited to 'src/main/java/org/traccar/handler/FilterHandler.java')
-rw-r--r-- | src/main/java/org/traccar/handler/FilterHandler.java | 153 |
1 files changed, 100 insertions, 53 deletions
diff --git a/src/main/java/org/traccar/handler/FilterHandler.java b/src/main/java/org/traccar/handler/FilterHandler.java index 7cd9153c1..994276bb6 100644 --- a/src/main/java/org/traccar/handler/FilterHandler.java +++ b/src/main/java/org/traccar/handler/FilterHandler.java @@ -1,5 +1,5 @@ /* - * Copyright 2014 - 2018 Anton Tananaev (anton@traccar.org) + * Copyright 2014 - 2022 Anton Tananaev (anton@traccar.org) * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -19,49 +19,83 @@ import io.netty.channel.ChannelHandler; import org.slf4j.Logger; import org.slf4j.LoggerFactory; import org.traccar.BaseDataHandler; -import org.traccar.Context; import org.traccar.config.Config; import org.traccar.config.Keys; import org.traccar.helper.UnitsConverter; +import org.traccar.helper.model.AttributeUtil; +import org.traccar.model.Device; import org.traccar.model.Position; - +import org.traccar.session.cache.CacheManager; +import org.traccar.storage.Storage; +import org.traccar.storage.StorageException; +import org.traccar.storage.query.Columns; +import org.traccar.storage.query.Condition; +import org.traccar.storage.query.Order; +import org.traccar.storage.query.Request; + +import javax.inject.Inject; +import javax.inject.Singleton; +import java.util.Date; + +@Singleton @ChannelHandler.Sharable public class FilterHandler extends BaseDataHandler { private static final Logger LOGGER = LoggerFactory.getLogger(FilterHandler.class); - private boolean filterInvalid; - private boolean filterZero; - private boolean filterDuplicate; - private long filterFuture; - private boolean filterApproximate; - private int filterAccuracy; - private boolean filterStatic; - private int filterDistance; - private int filterMaxSpeed; - private long filterMinPeriod; - private long skipLimit; - private boolean skipAttributes; - - public FilterHandler(Config config) { + private final boolean enabled; + private final boolean filterInvalid; + private final boolean filterZero; + private final boolean filterDuplicate; + private final long filterFuture; + private final long filterPast; + private final boolean filterApproximate; + private final int filterAccuracy; + private final boolean filterStatic; + private final int filterDistance; + private final int filterMaxSpeed; + private final long filterMinPeriod; + private final boolean filterRelative; + private final long skipLimit; + private final boolean skipAttributes; + + private final CacheManager cacheManager; + private final Storage storage; + + @Inject + public FilterHandler(Config config, CacheManager cacheManager, Storage storage) { + enabled = config.getBoolean(Keys.FILTER_ENABLE); filterInvalid = config.getBoolean(Keys.FILTER_INVALID); filterZero = config.getBoolean(Keys.FILTER_ZERO); filterDuplicate = config.getBoolean(Keys.FILTER_DUPLICATE); filterFuture = config.getLong(Keys.FILTER_FUTURE) * 1000; + filterPast = config.getLong(Keys.FILTER_PAST) * 1000; filterAccuracy = config.getInteger(Keys.FILTER_ACCURACY); filterApproximate = config.getBoolean(Keys.FILTER_APPROXIMATE); filterStatic = config.getBoolean(Keys.FILTER_STATIC); filterDistance = config.getInteger(Keys.FILTER_DISTANCE); filterMaxSpeed = config.getInteger(Keys.FILTER_MAX_SPEED); - filterMinPeriod = config.getInteger(Keys.FILTER_MIN_PERIOD) * 1000; + filterMinPeriod = config.getInteger(Keys.FILTER_MIN_PERIOD) * 1000L; + filterRelative = config.getBoolean(Keys.FILTER_RELATIVE); skipLimit = config.getLong(Keys.FILTER_SKIP_LIMIT) * 1000; skipAttributes = config.getBoolean(Keys.FILTER_SKIP_ATTRIBUTES_ENABLE); + this.cacheManager = cacheManager; + this.storage = storage; + } + + private Position getPrecedingPosition(long deviceId, Date date) throws StorageException { + return storage.getObject(Position.class, new Request( + new Columns.All(), + new Condition.And( + new Condition.Equals("deviceId", deviceId), + new Condition.Compare("fixTime", "<=", "time", date)), + new Order("fixTime", true, 1))); } private boolean filterInvalid(Position position) { return filterInvalid && (!position.getValid() - || position.getLatitude() > 90 || position.getLongitude() > 180 - || position.getLatitude() < -90 || position.getLongitude() < -180); + || position.getLatitude() > 90 || position.getLongitude() > 180 + || position.getLatitude() < -90 || position.getLongitude() < -180); } private boolean filterZero(Position position) { @@ -71,7 +105,7 @@ public class FilterHandler extends BaseDataHandler { private boolean filterDuplicate(Position position, Position last) { if (filterDuplicate && last != null && position.getFixTime().equals(last.getFixTime())) { for (String key : position.getAttributes().keySet()) { - if (!last.getAttributes().containsKey(key)) { + if (!last.hasAttribute(key)) { return false; } } @@ -84,6 +118,10 @@ public class FilterHandler extends BaseDataHandler { return filterFuture != 0 && position.getFixTime().getTime() > System.currentTimeMillis() + filterFuture; } + private boolean filterPast(Position position) { + return filterPast != 0 && position.getFixTime().getTime() < System.currentTimeMillis() - filterPast; + } + private boolean filterAccuracy(Position position) { return filterAccuracy != 0 && position.getAccuracy() > filterAccuracy; } @@ -129,10 +167,9 @@ public class FilterHandler extends BaseDataHandler { private boolean skipAttributes(Position position) { if (skipAttributes) { - String attributesString = Context.getIdentityManager().lookupAttributeString( - position.getDeviceId(), "filter.skipAttributes", "", false, true); - for (String attribute : attributesString.split("[ ,]")) { - if (position.getAttributes().containsKey(attribute)) { + String string = AttributeUtil.lookup(cacheManager, Keys.FILTER_SKIP_ATTRIBUTES, position.getDeviceId()); + for (String attribute : string.split("[ ,]")) { + if (position.hasAttribute(attribute)) { return true; } } @@ -144,51 +181,61 @@ public class FilterHandler extends BaseDataHandler { StringBuilder filterType = new StringBuilder(); - Position last = null; - if (Context.getIdentityManager() != null) { - last = Context.getIdentityManager().getLastPosition(position.getDeviceId()); - } - + // filter out invalid data if (filterInvalid(position)) { filterType.append("Invalid "); } if (filterZero(position)) { filterType.append("Zero "); } - if (filterDuplicate(position, last) && !skipLimit(position, last) && !skipAttributes(position)) { - filterType.append("Duplicate "); - } if (filterFuture(position)) { filterType.append("Future "); } + if (filterPast(position)) { + filterType.append("Past "); + } if (filterAccuracy(position)) { filterType.append("Accuracy "); } if (filterApproximate(position)) { filterType.append("Approximate "); } - if (filterStatic(position) && !skipLimit(position, last) && !skipAttributes(position)) { - filterType.append("Static "); - } - if (filterDistance(position, last) && !skipLimit(position, last) && !skipAttributes(position)) { - filterType.append("Distance "); - } - if (filterMaxSpeed(position, last)) { - filterType.append("MaxSpeed "); - } - if (filterMinPeriod(position, last)) { - filterType.append("MinPeriod "); + + // filter out excessive data + long deviceId = position.getDeviceId(); + if (filterDuplicate || filterStatic || filterDistance > 0 || filterMaxSpeed > 0 || filterMinPeriod > 0) { + Position preceding = null; + if (filterRelative) { + try { + Date newFixTime = position.getFixTime(); + preceding = getPrecedingPosition(deviceId, newFixTime); + } catch (StorageException e) { + LOGGER.warn("Error retrieving preceding position; fallbacking to last received position.", e); + preceding = cacheManager.getPosition(deviceId); + } + } else { + preceding = cacheManager.getPosition(deviceId); + } + if (filterDuplicate(position, preceding) && !skipLimit(position, preceding) && !skipAttributes(position)) { + filterType.append("Duplicate "); + } + if (filterStatic(position) && !skipLimit(position, preceding) && !skipAttributes(position)) { + filterType.append("Static "); + } + if (filterDistance(position, preceding) && !skipLimit(position, preceding) && !skipAttributes(position)) { + filterType.append("Distance "); + } + if (filterMaxSpeed(position, preceding)) { + filterType.append("MaxSpeed "); + } + 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()); - - LOGGER.info(message.toString()); + String uniqueId = cacheManager.getObject(Device.class, deviceId).getUniqueId(); + LOGGER.info("Position filtered by {}filters from device: {}", filterType, uniqueId); return true; } @@ -197,7 +244,7 @@ public class FilterHandler extends BaseDataHandler { @Override protected Position handlePosition(Position position) { - if (filter(position)) { + if (enabled && filter(position)) { return null; } return position; |