/*
* Copyright 2014 - 2017 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.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.traccar;
import org.traccar.helper.DistanceCalculator;
import org.traccar.helper.Log;
import org.traccar.helper.UnitsConverter;
import org.traccar.model.Position;
public class FilterHandler extends BaseDataHandler {
private boolean filterInvalid;
private boolean filterZero;
private boolean filterDuplicate;
private long filterFuture;
private boolean filterApproximate;
private boolean filterStatic;
private int filterDistance;
private int filterMaxSpeed;
private long filterLimit;
public void setFilterInvalid(boolean filterInvalid) {
this.filterInvalid = filterInvalid;
}
public void setFilterZero(boolean filterZero) {
this.filterZero = filterZero;
}
public void setFilterDuplicate(boolean filterDuplicate) {
this.filterDuplicate = filterDuplicate;
}
public void setFilterFuture(long filterFuture) {
this.filterFuture = filterFuture;
}
public void setFilterApproximate(boolean filterApproximate) {
this.filterApproximate = filterApproximate;
}
public void setFilterStatic(boolean filterStatic) {
this.filterStatic = filterStatic;
}
public void setFilterDistance(int filterDistance) {
this.filterDistance = filterDistance;
}
public void setFilterMaxSpeed(int filterMaxSpeed) {
this.filterMaxSpeed = filterMaxSpeed;
}
public void setFilterLimit(long filterLimit) {
this.filterLimit = filterLimit;
}
public FilterHandler() {
Config config = Context.getConfig();
if (config != null) {
filterInvalid = config.getBoolean("filter.invalid");
filterZero = config.getBoolean("filter.zero");
filterDuplicate = config.getBoolean("filter.duplicate");
filterFuture = config.getLong("filter.future") * 1000;
filterApproximate = config.getBoolean("filter.approximate");
filterStatic = config.getBoolean("filter.static");
filterDistance = config.getInteger("filter.distance");
filterMaxSpeed = config.getInteger("filter.maxSpeed");
filterLimit = config.getLong("filter.limit") * 1000;
}
}
private boolean filterInvalid(Position position) {
return filterInvalid && !position.getValid();
}
private boolean filterZero(Position position) {
return filterZero && position.getLatitude() == 0.0 && position.getLongitude() == 0.0;
}
private boolean filterDuplicate(Position position, Position last) {
return filterDuplicate && last != null && position.getFixTime().equals(last.getFixTime());
}
private boolean filterFuture(Position position) {
return filterFuture != 0 && position.getFixTime().getTime() > System.currentTimeMillis() + filterFuture;
}
private boolean filterApproximate(Position position) {
return filterApproximate && position.getBoolean(Position.KEY_APPROXIMATE);
}
private boolean filterStatic(Position position) {
return filterStatic && position.getSpeed() == 0.0;
}
private boolean filterDistance(Position position, Position last) {
if (filterDistance != 0 && last != null) {
double distance = DistanceCalculator.distance(
position.getLatitude(), position.getLongitude(),
last.getLatitude(), last.getLongitude());
return distance < filterDistance;
}
return false;
}
private boolean filterMaxSpeed(Position position, Position last) {
if (filterMaxSpeed != 0 && last != null) {
double distance = DistanceCalculator.distance(
position.getLatitude(), position.getLongitude(),
last.getLatitude(), last.getLongitude());
long time = position.getFixTime().getTime() - last.getFixTime().getTime();
return UnitsConverter.knotsFromMps(distance / time) > filterMaxSpeed;
}
return false;
}
private boolean filterLimit(Position position, Position last) {
if (filterLimit != 0) {
if (last != null) {
return (position.getFixTime().getTime() - last.getFixTime().getTime()) > filterLimit;
} else {
return false;
}
} else {
return false;
}
}
private boolean filter(Position position) {
StringBuilder filterType = new StringBuilder();
Position last = null;
if (Context.getIdentityManager() != null) {
last = Context.getIdentityManager().getLastPosition(position.getDeviceId());
}
if (filterInvalid(position)) {
filterType.append("Invalid ");
}
if (filterZero(position)) {
filterType.append("Zero ");
}
if (filterDuplicate(position, last)) {
filterType.append("Duplicate ");
}
if (filterFuture(position)) {
filterType.append("Future ");
}
if (filterApproximate(position)) {
filterType.append("Approximate ");
}
if (filterStatic(position)) {
filterType.append("Static ");
}
if (filterDistance(position, last)) {
filterType.append("Distance ");
}
if (filterMaxSpeed(position, last)) {
filterType.append("MaxSpeed ");
}
if (filterType.length() > 0 && !filterLimit(position, last)) {
StringBuilder message = new StringBuilder();
message.append("Position filtered by ");
message.append(filterType.toString());
message.append("filters from device: ");
message.append(Context.getIdentityManager().getDeviceById(position.getDeviceId()).getUniqueId());
message.append(" with id: ");
message.append(position.getDeviceId());
Log.info(message.toString());
return true;
}
return false;
}
@Override
protected Position handlePosition(Position position) {
if (filter(position)) {
return null;
}
return position;
}
}