diff options
author | Anton Tananaev <anton.tananaev@gmail.com> | 2017-08-11 23:37:16 +1200 |
---|---|---|
committer | GitHub <noreply@github.com> | 2017-08-11 23:37:16 +1200 |
commit | 30e8409375f9992a5248f7e2597691c0ee08188c (patch) | |
tree | ea51b7d111cfae849d23941ad82045139e87520b /src/org | |
parent | 3562e0d927d539a1e9730c48ed376ee84ebc2b25 (diff) | |
parent | 26db3ccc2ed5d43a0e791a29d5cc4afca192e4b7 (diff) | |
download | trackermap-server-30e8409375f9992a5248f7e2597691c0ee08188c.tar.gz trackermap-server-30e8409375f9992a5248f7e2597691c0ee08188c.tar.bz2 trackermap-server-30e8409375f9992a5248f7e2597691c0ee08188c.zip |
Merge pull request #3431 from Abyss777/delayed_overspeed
Implement delayed overspeed events
Diffstat (limited to 'src/org')
-rw-r--r-- | src/org/traccar/BasePipelineFactory.java | 4 | ||||
-rw-r--r-- | src/org/traccar/Context.java | 37 | ||||
-rw-r--r-- | src/org/traccar/database/ConnectionManager.java | 52 | ||||
-rw-r--r-- | src/org/traccar/database/DeviceManager.java | 7 | ||||
-rw-r--r-- | src/org/traccar/events/MotionEventHandler.java | 52 | ||||
-rw-r--r-- | src/org/traccar/events/OverspeedEventHandler.java | 88 | ||||
-rw-r--r-- | src/org/traccar/model/DeviceState.java | 20 | ||||
-rw-r--r-- | src/org/traccar/reports/ReportUtils.java | 9 | ||||
-rw-r--r-- | src/org/traccar/reports/Stops.java | 7 | ||||
-rw-r--r-- | src/org/traccar/reports/Trips.java | 7 |
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; |