aboutsummaryrefslogtreecommitdiff
path: root/src/org/traccar
diff options
context:
space:
mode:
authorAnton Tananaev <anton.tananaev@gmail.com>2017-08-11 23:37:16 +1200
committerGitHub <noreply@github.com>2017-08-11 23:37:16 +1200
commit30e8409375f9992a5248f7e2597691c0ee08188c (patch)
treeea51b7d111cfae849d23941ad82045139e87520b /src/org/traccar
parent3562e0d927d539a1e9730c48ed376ee84ebc2b25 (diff)
parent26db3ccc2ed5d43a0e791a29d5cc4afca192e4b7 (diff)
downloadtraccar-server-30e8409375f9992a5248f7e2597691c0ee08188c.tar.gz
traccar-server-30e8409375f9992a5248f7e2597691c0ee08188c.tar.bz2
traccar-server-30e8409375f9992a5248f7e2597691c0ee08188c.zip
Merge pull request #3431 from Abyss777/delayed_overspeed
Implement delayed overspeed events
Diffstat (limited to 'src/org/traccar')
-rw-r--r--src/org/traccar/BasePipelineFactory.java4
-rw-r--r--src/org/traccar/Context.java37
-rw-r--r--src/org/traccar/database/ConnectionManager.java52
-rw-r--r--src/org/traccar/database/DeviceManager.java7
-rw-r--r--src/org/traccar/events/MotionEventHandler.java52
-rw-r--r--src/org/traccar/events/OverspeedEventHandler.java88
-rw-r--r--src/org/traccar/model/DeviceState.java20
-rw-r--r--src/org/traccar/reports/ReportUtils.java9
-rw-r--r--src/org/traccar/reports/Stops.java7
-rw-r--r--src/org/traccar/reports/Trips.java7
10 files changed, 193 insertions, 90 deletions
diff --git a/src/org/traccar/BasePipelineFactory.java b/src/org/traccar/BasePipelineFactory.java
index b368c800d..da8060071 100644
--- a/src/org/traccar/BasePipelineFactory.java
+++ b/src/org/traccar/BasePipelineFactory.java
@@ -165,9 +165,9 @@ public abstract class BasePipelineFactory implements ChannelPipelineFactory {
if (Context.getConfig().getBoolean("event.enable")) {
commandResultEventHandler = new CommandResultEventHandler();
- overspeedEventHandler = new OverspeedEventHandler();
+ overspeedEventHandler = Context.getOverspeedEventHandler();
fuelDropEventHandler = new FuelDropEventHandler();
- motionEventHandler = new MotionEventHandler();
+ motionEventHandler = Context.getMotionEventHandler();
geofenceEventHandler = new GeofenceEventHandler();
alertEventHandler = new AlertEventHandler();
ignitionEventHandler = new IgnitionEventHandler();
diff --git a/src/org/traccar/Context.java b/src/org/traccar/Context.java
index 306a37e83..a69b1786d 100644
--- a/src/org/traccar/Context.java
+++ b/src/org/traccar/Context.java
@@ -41,6 +41,8 @@ import org.traccar.database.GeofenceManager;
import org.traccar.database.GroupsManager;
import org.traccar.database.StatisticsManager;
import org.traccar.database.UsersManager;
+import org.traccar.events.MotionEventHandler;
+import org.traccar.events.OverspeedEventHandler;
import org.traccar.geocoder.BingMapsGeocoder;
import org.traccar.geocoder.FactualGeocoder;
import org.traccar.geocoder.GeocodeFarmGeocoder;
@@ -65,6 +67,7 @@ import org.traccar.geolocation.GeolocationProvider;
import org.traccar.geolocation.MozillaGeolocationProvider;
import org.traccar.geolocation.OpenCellIdGeolocationProvider;
import org.traccar.notification.EventForwarder;
+import org.traccar.reports.model.TripsConfig;
import org.traccar.smpp.SmppClient;
import org.traccar.web.WebServer;
@@ -229,6 +232,33 @@ public final class Context {
return smppClient;
}
+ private static MotionEventHandler motionEventHandler;
+
+ public static MotionEventHandler getMotionEventHandler() {
+ return motionEventHandler;
+ }
+
+ private static OverspeedEventHandler overspeedEventHandler;
+
+ public static OverspeedEventHandler getOverspeedEventHandler() {
+ return overspeedEventHandler;
+ }
+
+ private static TripsConfig tripsConfig;
+
+ public static TripsConfig getTripsConfig() {
+ return tripsConfig;
+ }
+
+ public static TripsConfig initTripsConfig() {
+ return new TripsConfig(
+ config.getLong("report.trip.minimalTripDistance", 500),
+ config.getLong("report.trip.minimalTripDuration", 300) * 1000,
+ config.getLong("report.trip.minimalParkingDuration", 300) * 1000,
+ config.getBoolean("report.trip.greedyParking"),
+ config.getLong("report.trip.minimalNoDataDuration", 3600) * 1000);
+ }
+
public static void init(String[] arguments) throws Exception {
config = new Config();
@@ -327,6 +357,8 @@ public final class Context {
connectionManager = new ConnectionManager();
+ tripsConfig = initTripsConfig();
+
if (config.getBoolean("event.enable")) {
geofenceManager = new GeofenceManager(dataManager);
calendarManager = new CalendarManager(dataManager);
@@ -350,6 +382,11 @@ public final class Context {
velocityEngine = new VelocityEngine();
velocityEngine.init(velocityProperties);
+
+ motionEventHandler = new MotionEventHandler(tripsConfig);
+ overspeedEventHandler = new OverspeedEventHandler(
+ Context.getConfig().getLong("event.overspeed.minimalDuration") * 1000,
+ Context.getConfig().getBoolean("event.overspeed.notRepeat"));
}
serverManager = new ServerManager();
diff --git a/src/org/traccar/database/ConnectionManager.java b/src/org/traccar/database/ConnectionManager.java
index 1c5d4428a..7a0a6d30d 100644
--- a/src/org/traccar/database/ConnectionManager.java
+++ b/src/org/traccar/database/ConnectionManager.java
@@ -21,13 +21,12 @@ import org.jboss.netty.util.TimerTask;
import org.traccar.Context;
import org.traccar.GlobalTimer;
import org.traccar.Protocol;
+import org.traccar.events.OverspeedEventHandler;
import org.traccar.helper.Log;
import org.traccar.model.Device;
import org.traccar.model.DeviceState;
import org.traccar.model.Event;
import org.traccar.model.Position;
-import org.traccar.reports.ReportUtils;
-import org.traccar.reports.model.TripsConfig;
import java.net.SocketAddress;
import java.sql.SQLException;
@@ -44,7 +43,7 @@ public class ConnectionManager {
private final long deviceTimeout;
private final boolean enableStatusEvents;
- private TripsConfig tripsConfig = null;
+ private final boolean updateDeviceState;
private final Map<Long, ActiveDevice> activeDevices = new ConcurrentHashMap<>();
private final Map<Long, Set<UpdateListener>> listeners = new ConcurrentHashMap<>();
@@ -53,9 +52,7 @@ public class ConnectionManager {
public ConnectionManager() {
deviceTimeout = Context.getConfig().getLong("status.timeout", DEFAULT_TIMEOUT) * 1000;
enableStatusEvents = Context.getConfig().getBoolean("event.enable");
- if (Context.getConfig().getBoolean("status.updateDeviceState")) {
- tripsConfig = ReportUtils.initTripsConfig();
- }
+ updateDeviceState = Context.getConfig().getBoolean("status.updateDeviceState");
}
public void addActiveDevice(long deviceId, Protocol protocol, Channel channel, SocketAddress remoteAddress) {
@@ -87,28 +84,24 @@ public class ConnectionManager {
if (enableStatusEvents && !status.equals(oldStatus)) {
String eventType;
- Event stateEvent = null;
+ Set<Event> events = new HashSet<>();
switch (status) {
case Device.STATUS_ONLINE:
eventType = Event.TYPE_DEVICE_ONLINE;
break;
case Device.STATUS_UNKNOWN:
eventType = Event.TYPE_DEVICE_UNKNOWN;
- if (tripsConfig != null) {
- stateEvent = updateDeviceState(deviceId);
+ if (updateDeviceState) {
+ events.addAll(updateDeviceState(deviceId));
}
break;
default:
eventType = Event.TYPE_DEVICE_OFFLINE;
- if (tripsConfig != null) {
- stateEvent = updateDeviceState(deviceId);
+ if (updateDeviceState) {
+ events.addAll(updateDeviceState(deviceId));
}
break;
}
- Set<Event> events = new HashSet<>();
- if (stateEvent != null) {
- events.add(stateEvent);
- }
events.add(new Event(eventType, deviceId));
Context.getNotificationManager().updateEvents(events, null);
}
@@ -142,26 +135,21 @@ public class ConnectionManager {
updateDevice(device);
}
- public Event updateDeviceState(long deviceId) {
+ public Set<Event> updateDeviceState(long deviceId) {
DeviceState deviceState = Context.getDeviceManager().getDeviceState(deviceId);
- if (deviceState == null || deviceState.getMotionState() == null) {
- return null;
+ Set<Event> result = new HashSet<>();
+
+ Event event = Context.getMotionEventHandler().updateMotionState(deviceState);
+ if (event != null) {
+ result.add(event);
}
- Event result = null;
- Boolean oldMotion = deviceState.getMotionState();
- long currentTime = System.currentTimeMillis();
- boolean newMotion = !oldMotion;
- Position motionPosition = deviceState.getMotionPosition();
- if (motionPosition != null) {
- long motionTime = motionPosition.getFixTime().getTime()
- + (newMotion ? tripsConfig.getMinimalTripDuration() : tripsConfig.getMinimalParkingDuration());
- if (motionTime <= currentTime) {
- String eventType = newMotion ? Event.TYPE_DEVICE_MOVING : Event.TYPE_DEVICE_STOPPED;
- result = new Event(eventType, motionPosition.getDeviceId(), motionPosition.getId());
- deviceState.setMotionState(newMotion);
- deviceState.setMotionPosition(null);
- }
+
+ event = Context.getOverspeedEventHandler().updateOverspeedState(deviceState, Context.getDeviceManager().
+ lookupAttributeDouble(deviceId, OverspeedEventHandler.ATTRIBUTE_SPEED_LIMIT, 0, false));
+ if (event != null) {
+ result.add(event);
}
+
return result;
}
diff --git a/src/org/traccar/database/DeviceManager.java b/src/org/traccar/database/DeviceManager.java
index 3b7e5c617..a485d6dc6 100644
--- a/src/org/traccar/database/DeviceManager.java
+++ b/src/org/traccar/database/DeviceManager.java
@@ -392,7 +392,12 @@ public class DeviceManager extends BaseObjectManager<Device> implements Identity
}
public DeviceState getDeviceState(long deviceId) {
- return deviceStates.get(deviceId);
+ DeviceState deviceState = deviceStates.get(deviceId);
+ if (deviceState == null) {
+ deviceState = new DeviceState();
+ deviceStates.put(deviceId, deviceState);
+ }
+ return deviceState;
}
public void setDeviceState(long deviceId, DeviceState deviceState) {
diff --git a/src/org/traccar/events/MotionEventHandler.java b/src/org/traccar/events/MotionEventHandler.java
index 228b43c0f..b20a11999 100644
--- a/src/org/traccar/events/MotionEventHandler.java
+++ b/src/org/traccar/events/MotionEventHandler.java
@@ -32,11 +32,35 @@ public class MotionEventHandler extends BaseEventHandler {
private TripsConfig tripsConfig;
- public MotionEventHandler() {
- tripsConfig = ReportUtils.initTripsConfig();
+ public MotionEventHandler(TripsConfig tripsConfig) {
+ this.tripsConfig = tripsConfig;
}
- public static Event updateMotionState(DeviceState deviceState, Position position, TripsConfig tripsConfig) {
+ private Event newEvent(DeviceState deviceState, boolean newMotion) {
+ String eventType = newMotion ? Event.TYPE_DEVICE_MOVING : Event.TYPE_DEVICE_STOPPED;
+ Event event = new Event(eventType, deviceState.getMotionPosition().getDeviceId(),
+ deviceState.getMotionPosition().getId());
+ deviceState.setMotionState(newMotion);
+ deviceState.setMotionPosition(null);
+ return event;
+ }
+
+ public Event updateMotionState(DeviceState deviceState) {
+ Event result = null;
+ if (deviceState.getMotionState() != null && deviceState.getMotionPosition() != null) {
+ boolean newMotion = !deviceState.getMotionState();
+ Position motionPosition = deviceState.getMotionPosition();
+ long currentTime = System.currentTimeMillis();
+ long motionTime = motionPosition.getFixTime().getTime()
+ + (newMotion ? tripsConfig.getMinimalTripDuration() : tripsConfig.getMinimalParkingDuration());
+ if (motionTime <= currentTime) {
+ result = newEvent(deviceState, newMotion);
+ }
+ }
+ return result;
+ }
+
+ public Event updateMotionState(DeviceState deviceState, Position position) {
Event result = null;
Boolean oldMotion = deviceState.getMotionState();
@@ -57,17 +81,11 @@ public class MotionEventHandler extends BaseEventHandler {
if (newMotion) {
if (motionTime + tripsConfig.getMinimalTripDuration() <= currentTime
|| distance >= tripsConfig.getMinimalTripDistance()) {
- result = new Event(Event.TYPE_DEVICE_MOVING, motionPosition.getDeviceId(),
- motionPosition.getId());
- deviceState.setMotionState(true);
- deviceState.setMotionPosition(null);
+ result = newEvent(deviceState, newMotion);
}
} else {
if (motionTime + tripsConfig.getMinimalParkingDuration() <= currentTime) {
- result = new Event(Event.TYPE_DEVICE_STOPPED, motionPosition.getDeviceId(),
- motionPosition.getId());
- deviceState.setMotionState(false);
- deviceState.setMotionPosition(null);
+ result = newEvent(deviceState, newMotion);
}
}
}
@@ -77,7 +95,8 @@ public class MotionEventHandler extends BaseEventHandler {
@Override
protected Collection<Event> analyzePosition(Position position) {
- Device device = Context.getIdentityManager().getById(position.getDeviceId());
+ long deviceId = position.getDeviceId();
+ Device device = Context.getIdentityManager().getById(deviceId);
if (device == null) {
return null;
}
@@ -86,17 +105,12 @@ public class MotionEventHandler extends BaseEventHandler {
}
Event result = null;
-
- long deviceId = position.getDeviceId();
DeviceState deviceState = Context.getDeviceManager().getDeviceState(deviceId);
- if (deviceState == null) {
- deviceState = new DeviceState();
- deviceState.setMotionState(position.getBoolean(Position.KEY_MOTION));
- } else if (deviceState.getMotionState() == null) {
+ if (deviceState.getMotionState() == null) {
deviceState.setMotionState(position.getBoolean(Position.KEY_MOTION));
} else {
- result = updateMotionState(deviceState, position, tripsConfig);
+ result = updateMotionState(deviceState, position);
}
Context.getDeviceManager().setDeviceState(deviceId, deviceState);
if (result != null) {
diff --git a/src/org/traccar/events/OverspeedEventHandler.java b/src/org/traccar/events/OverspeedEventHandler.java
index 795892f40..953af6b33 100644
--- a/src/org/traccar/events/OverspeedEventHandler.java
+++ b/src/org/traccar/events/OverspeedEventHandler.java
@@ -21,6 +21,7 @@ import java.util.Collections;
import org.traccar.BaseEventHandler;
import org.traccar.Context;
import org.traccar.model.Device;
+import org.traccar.model.DeviceState;
import org.traccar.model.Event;
import org.traccar.model.Position;
@@ -29,15 +30,69 @@ public class OverspeedEventHandler extends BaseEventHandler {
public static final String ATTRIBUTE_SPEED_LIMIT = "speedLimit";
private boolean notRepeat;
+ private long minimalDuration;
- public OverspeedEventHandler() {
- notRepeat = Context.getConfig().getBoolean("event.overspeed.notRepeat");
+ public OverspeedEventHandler(long minimalDuration, boolean notRepeat) {
+ this.notRepeat = notRepeat;
+ this.minimalDuration = minimalDuration;
+ }
+
+ private Event newEvent(DeviceState deviceState, double speedLimit) {
+ Event event = new Event(Event.TYPE_DEVICE_OVERSPEED, deviceState.getOverspeedPosition().getDeviceId(),
+ deviceState.getOverspeedPosition().getId());
+ event.set("speed", deviceState.getOverspeedPosition().getSpeed());
+ event.set(ATTRIBUTE_SPEED_LIMIT, speedLimit);
+ deviceState.setOverspeedState(notRepeat);
+ deviceState.setOverspeedPosition(null);
+ return event;
+ }
+
+ public Event updateOverspeedState(DeviceState deviceState, double speedLimit) {
+ Event result = null;
+ if (deviceState.getOverspeedState() != null && !deviceState.getOverspeedState()
+ && deviceState.getOverspeedPosition() != null && speedLimit != 0) {
+ long currentTime = System.currentTimeMillis();
+ Position overspeedPosition = deviceState.getOverspeedPosition();
+ long overspeedTime = overspeedPosition.getFixTime().getTime();
+ if (overspeedTime + minimalDuration <= currentTime) {
+ result = newEvent(deviceState, speedLimit);
+ }
+ }
+ return result;
+ }
+
+ public Event updateOverspeedState(DeviceState deviceState, Position position, double speedLimit) {
+ Event result = null;
+
+ Boolean oldOverspeed = deviceState.getOverspeedState();
+
+ long currentTime = position.getFixTime().getTime();
+ boolean newOverspeed = position.getSpeed() > speedLimit;
+ if (newOverspeed && !oldOverspeed) {
+ if (deviceState.getOverspeedPosition() == null) {
+ deviceState.setOverspeedPosition(position);
+ }
+ } else if (oldOverspeed && !newOverspeed) {
+ deviceState.setOverspeedState(false);
+ deviceState.setOverspeedPosition(null);
+ } else {
+ deviceState.setOverspeedPosition(null);
+ }
+ Position overspeedPosition = deviceState.getOverspeedPosition();
+ if (overspeedPosition != null) {
+ long overspeedTime = overspeedPosition.getFixTime().getTime();
+ if (newOverspeed && overspeedTime + minimalDuration <= currentTime) {
+ result = newEvent(deviceState, speedLimit);
+ }
+ }
+ return result;
}
@Override
protected Collection<Event> analyzePosition(Position position) {
- Device device = Context.getIdentityManager().getById(position.getDeviceId());
+ long deviceId = position.getDeviceId();
+ Device device = Context.getIdentityManager().getById(deviceId);
if (device == null) {
return null;
}
@@ -45,24 +100,23 @@ public class OverspeedEventHandler extends BaseEventHandler {
return null;
}
- double speed = position.getSpeed();
- double speedLimit = Context.getDeviceManager()
- .lookupAttributeDouble(device.getId(), ATTRIBUTE_SPEED_LIMIT, 0, false);
+ double speedLimit = Context.getDeviceManager().lookupAttributeDouble(deviceId, ATTRIBUTE_SPEED_LIMIT, 0, false);
if (speedLimit == 0) {
return null;
}
- double oldSpeed = 0;
- if (notRepeat) {
- Position lastPosition = Context.getIdentityManager().getLastPosition(position.getDeviceId());
- if (lastPosition != null) {
- oldSpeed = lastPosition.getSpeed();
- }
+
+ Event result = null;
+ DeviceState deviceState = Context.getDeviceManager().getDeviceState(deviceId);
+
+ if (deviceState.getOverspeedState() == null) {
+ deviceState.setOverspeedState(position.getSpeed() > speedLimit);
+ } else {
+ result = updateOverspeedState(deviceState, position, speedLimit);
}
- if (speed > speedLimit && oldSpeed <= speedLimit) {
- Event event = new Event(Event.TYPE_DEVICE_OVERSPEED, position.getDeviceId(), position.getId());
- event.set("speed", speed);
- event.set(ATTRIBUTE_SPEED_LIMIT, speedLimit);
- return Collections.singleton(event);
+
+ Context.getDeviceManager().setDeviceState(deviceId, deviceState);
+ if (result != null) {
+ return Collections.singleton(result);
}
return null;
}
diff --git a/src/org/traccar/model/DeviceState.java b/src/org/traccar/model/DeviceState.java
index 3626b9953..f2d0ff614 100644
--- a/src/org/traccar/model/DeviceState.java
+++ b/src/org/traccar/model/DeviceState.java
@@ -38,4 +38,24 @@ public class DeviceState {
return motionPosition;
}
+ private Boolean overspeedState;
+
+ public void setOverspeedState(boolean overspeedState) {
+ this.overspeedState = overspeedState;
+ }
+
+ public Boolean getOverspeedState() {
+ return overspeedState;
+ }
+
+ private Position overspeedPosition;
+
+ public void setOverspeedPosition(Position overspeedPosition) {
+ this.overspeedPosition = overspeedPosition;
+ }
+
+ public Position getOverspeedPosition() {
+ return overspeedPosition;
+ }
+
}
diff --git a/src/org/traccar/reports/ReportUtils.java b/src/org/traccar/reports/ReportUtils.java
index e8db7e3b5..8c39bb9dc 100644
--- a/src/org/traccar/reports/ReportUtils.java
+++ b/src/org/traccar/reports/ReportUtils.java
@@ -155,15 +155,6 @@ public final class ReportUtils {
transformer.write();
}
- public static TripsConfig initTripsConfig() {
- return new TripsConfig(
- Context.getConfig().getLong("report.trip.minimalTripDistance", 500),
- Context.getConfig().getLong("report.trip.minimalTripDuration", 300) * 1000,
- Context.getConfig().getLong("report.trip.minimalParkingDuration", 300) * 1000,
- Context.getConfig().getBoolean("report.trip.greedyParking"),
- Context.getConfig().getLong("report.trip.minimalNoDataDuration", 3600) * 1000);
- }
-
private static TripReport calculateTrip(
ArrayList<Position> positions, int startIndex, int endIndex, boolean ignoreOdometer) {
Position startTrip = positions.get(startIndex);
diff --git a/src/org/traccar/reports/Stops.java b/src/org/traccar/reports/Stops.java
index ee6746e4e..3f7f674b5 100644
--- a/src/org/traccar/reports/Stops.java
+++ b/src/org/traccar/reports/Stops.java
@@ -33,7 +33,6 @@ import org.traccar.model.Group;
import org.traccar.reports.model.BaseReport;
import org.traccar.reports.model.DeviceReport;
import org.traccar.reports.model.StopReport;
-import org.traccar.reports.model.TripsConfig;
public final class Stops {
@@ -43,13 +42,11 @@ public final class Stops {
private static Collection<StopReport> detectStops(long deviceId, Date from, Date to) throws SQLException {
double speedThreshold = Context.getConfig().getDouble("event.motion.speedThreshold", 0.01);
- TripsConfig tripsConfig = ReportUtils.initTripsConfig();
-
boolean ignoreOdometer = Context.getDeviceManager()
.lookupAttributeBoolean(deviceId, "report.ignoreOdometer", false, true);
- Collection<? extends BaseReport> result = ReportUtils.detectTripsAndStops(tripsConfig,
- ignoreOdometer, speedThreshold,
+ Collection<? extends BaseReport> result = ReportUtils.detectTripsAndStops(
+ Context.getTripsConfig(), ignoreOdometer, speedThreshold,
Context.getDataManager().getPositions(deviceId, from, to), false);
return (Collection<StopReport>) result;
diff --git a/src/org/traccar/reports/Trips.java b/src/org/traccar/reports/Trips.java
index 6b97507f4..a4dcf00f1 100644
--- a/src/org/traccar/reports/Trips.java
+++ b/src/org/traccar/reports/Trips.java
@@ -32,7 +32,6 @@ import org.traccar.model.Group;
import org.traccar.reports.model.BaseReport;
import org.traccar.reports.model.DeviceReport;
import org.traccar.reports.model.TripReport;
-import org.traccar.reports.model.TripsConfig;
public final class Trips {
@@ -42,13 +41,11 @@ public final class Trips {
private static Collection<TripReport> detectTrips(long deviceId, Date from, Date to) throws SQLException {
double speedThreshold = Context.getConfig().getDouble("event.motion.speedThreshold", 0.01);
- TripsConfig tripsConfig = ReportUtils.initTripsConfig();
-
boolean ignoreOdometer = Context.getDeviceManager()
.lookupAttributeBoolean(deviceId, "report.ignoreOdometer", false, true);
- Collection<? extends BaseReport> result = ReportUtils.detectTripsAndStops(tripsConfig,
- ignoreOdometer, speedThreshold,
+ Collection<? extends BaseReport> result = ReportUtils.detectTripsAndStops(
+ Context.getTripsConfig(), ignoreOdometer, speedThreshold,
Context.getDataManager().getPositions(deviceId, from, to), true);
return (Collection<TripReport>) result;