From ce26a0768ace197cc9afdfc3ee04f970699d3c5e Mon Sep 17 00:00:00 2001 From: Abyss777 Date: Mon, 7 May 2018 15:00:21 +0500 Subject: Add basic support of overspeeding inside geofences. --- src/org/traccar/Context.java | 3 +- src/org/traccar/events/OverspeedEventHandler.java | 41 +++++++++++++++++++--- src/org/traccar/model/DeviceState.java | 10 ++++++ templates/mail/deviceOverspeed.vm | 2 +- templates/sms/deviceOverspeed.vm | 2 +- .../traccar/events/OverspeedEventHandlerTest.java | 29 +++++++++------ 6 files changed, 70 insertions(+), 17 deletions(-) diff --git a/src/org/traccar/Context.java b/src/org/traccar/Context.java index ee14eb1f7..b7cfd27b0 100644 --- a/src/org/traccar/Context.java +++ b/src/org/traccar/Context.java @@ -464,7 +464,8 @@ public final class Context { motionEventHandler = new MotionEventHandler(tripsConfig); overspeedEventHandler = new OverspeedEventHandler( Context.getConfig().getLong("event.overspeed.minimalDuration") * 1000, - Context.getConfig().getBoolean("event.overspeed.notRepeat")); + Context.getConfig().getBoolean("event.overspeed.notRepeat"), + Context.getConfig().getBoolean("event.overspeed.geofenceMinimal")); } public static void init(IdentityManager testIdentityManager) { diff --git a/src/org/traccar/events/OverspeedEventHandler.java b/src/org/traccar/events/OverspeedEventHandler.java index cb658415c..223a117ad 100644 --- a/src/org/traccar/events/OverspeedEventHandler.java +++ b/src/org/traccar/events/OverspeedEventHandler.java @@ -1,5 +1,6 @@ /* - * Copyright 2016 Anton Tananaev (anton@traccar.org) + * Copyright 2016 - 2018 Anton Tananaev (anton@traccar.org) + * Copyright 2018 Andrey Kunitsyn (andrey@traccar.org) * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -23,6 +24,7 @@ import org.traccar.Context; import org.traccar.model.Device; import org.traccar.model.DeviceState; import org.traccar.model.Event; +import org.traccar.model.Geofence; import org.traccar.model.Position; public class OverspeedEventHandler extends BaseEventHandler { @@ -30,11 +32,13 @@ public class OverspeedEventHandler extends BaseEventHandler { public static final String ATTRIBUTE_SPEED_LIMIT = "speedLimit"; private boolean notRepeat; + private boolean geofenceMinimal; private long minimalDuration; - public OverspeedEventHandler(long minimalDuration, boolean notRepeat) { + public OverspeedEventHandler(long minimalDuration, boolean notRepeat, boolean geofenceMinimal) { this.notRepeat = notRepeat; this.minimalDuration = minimalDuration; + this.geofenceMinimal = geofenceMinimal; } private Map newEvent(DeviceState deviceState, double speedLimit) { @@ -42,8 +46,10 @@ public class OverspeedEventHandler extends BaseEventHandler { Event event = new Event(Event.TYPE_DEVICE_OVERSPEED, position.getDeviceId(), position.getId()); event.set("speed", deviceState.getOverspeedPosition().getSpeed()); event.set(ATTRIBUTE_SPEED_LIMIT, speedLimit); + event.setGeofenceId(deviceState.getOverspeedGeofenceId()); deviceState.setOverspeedState(notRepeat); deviceState.setOverspeedPosition(null); + deviceState.setOverspeedGeofenceId(0); return Collections.singletonMap(event, position); } @@ -61,7 +67,8 @@ public class OverspeedEventHandler extends BaseEventHandler { return result; } - public Map updateOverspeedState(DeviceState deviceState, Position position, double speedLimit) { + public Map updateOverspeedState( + DeviceState deviceState, Position position, double speedLimit, long geofenceId) { Map result = null; Boolean oldOverspeed = deviceState.getOverspeedState(); @@ -71,12 +78,15 @@ public class OverspeedEventHandler extends BaseEventHandler { if (newOverspeed && !oldOverspeed) { if (deviceState.getOverspeedPosition() == null) { deviceState.setOverspeedPosition(position); + deviceState.setOverspeedGeofenceId(geofenceId); } } else if (oldOverspeed && !newOverspeed) { deviceState.setOverspeedState(false); deviceState.setOverspeedPosition(null); + deviceState.setOverspeedGeofenceId(0); } else { deviceState.setOverspeedPosition(null); + deviceState.setOverspeedGeofenceId(0); } Position overspeedPosition = deviceState.getOverspeedPosition(); if (overspeedPosition != null) { @@ -101,6 +111,28 @@ public class OverspeedEventHandler extends BaseEventHandler { } double speedLimit = Context.getDeviceManager().lookupAttributeDouble(deviceId, ATTRIBUTE_SPEED_LIMIT, 0, false); + + double geofenceSpeedLimit = 0; + long overspeedGeofenceId = 0; + + if (Context.getGeofenceManager() != null) { + for (long geofenceId : device.getGeofenceIds()) { + Geofence geofence = Context.getGeofenceManager().getById(geofenceId); + if (geofence != null) { + double currentSpeedLimit = geofence.getDouble(ATTRIBUTE_SPEED_LIMIT); + if (currentSpeedLimit > 0 && geofenceSpeedLimit == 0 + || geofenceMinimal && currentSpeedLimit < geofenceSpeedLimit + || !geofenceMinimal && currentSpeedLimit > geofenceSpeedLimit) { + geofenceSpeedLimit = currentSpeedLimit; + overspeedGeofenceId = geofenceId; + } + } + } + } + if (geofenceSpeedLimit > 0) { + speedLimit = geofenceSpeedLimit; + } + if (speedLimit == 0) { return null; } @@ -110,8 +142,9 @@ public class OverspeedEventHandler extends BaseEventHandler { if (deviceState.getOverspeedState() == null) { deviceState.setOverspeedState(position.getSpeed() > speedLimit); + deviceState.setOverspeedGeofenceId(position.getSpeed() > speedLimit ? overspeedGeofenceId : 0); } else { - result = updateOverspeedState(deviceState, position, speedLimit); + result = updateOverspeedState(deviceState, position, speedLimit, overspeedGeofenceId); } Context.getDeviceManager().setDeviceState(deviceId, deviceState); diff --git a/src/org/traccar/model/DeviceState.java b/src/org/traccar/model/DeviceState.java index f2d0ff614..75d6726ee 100644 --- a/src/org/traccar/model/DeviceState.java +++ b/src/org/traccar/model/DeviceState.java @@ -58,4 +58,14 @@ public class DeviceState { return overspeedPosition; } + private long overspeedGeofenceId; + + public void setOverspeedGeofenceId(long overspeedGeofenceId) { + this.overspeedGeofenceId = overspeedGeofenceId; + } + + public long getOverspeedGeofenceId() { + return overspeedGeofenceId; + } + } diff --git a/templates/mail/deviceOverspeed.vm b/templates/mail/deviceOverspeed.vm index b1f0a6734..e5e576f3a 100644 --- a/templates/mail/deviceOverspeed.vm +++ b/templates/mail/deviceOverspeed.vm @@ -12,7 +12,7 @@ Device: $device.name
-Exceeds the speed: $speedString
+Exceeds the speed: $speedString#{if}($geofence) in $geofence.name#{else}#{end}
Time: $dateTool.format("YYYY-MM-dd HH:mm:ss", $event.serverTime, $locale, $timezone)
Point: #{if}($position.address)$position.address#{else}$position.latitude°, $position.longitude°#{end}
diff --git a/templates/sms/deviceOverspeed.vm b/templates/sms/deviceOverspeed.vm index f0b03c9e7..5e92f662c 100644 --- a/templates/sms/deviceOverspeed.vm +++ b/templates/sms/deviceOverspeed.vm @@ -7,4 +7,4 @@ #else #set($speedString = $numberTool.format("0.0 kn", $position.speed)) #end -$device.name exceeds the speed $speedString at $dateTool.format("YYYY-MM-dd HH:mm:ss", $event.serverTime, $locale, $timezone) +$device.name exceeds the speed $speedString#{if}($geofence) in $geofence.name#{else}#{end} at $dateTool.format("YYYY-MM-dd HH:mm:ss", $event.serverTime, $locale, $timezone) diff --git a/test/org/traccar/events/OverspeedEventHandlerTest.java b/test/org/traccar/events/OverspeedEventHandlerTest.java index d38367cd9..98fd0f87a 100644 --- a/test/org/traccar/events/OverspeedEventHandlerTest.java +++ b/test/org/traccar/events/OverspeedEventHandlerTest.java @@ -26,8 +26,8 @@ public class OverspeedEventHandlerTest extends BaseTest { return dateFormat.parse(time); } - private void testOverspeedWithPosition(boolean notRepeat) throws Exception { - OverspeedEventHandler overspeedEventHandler = new OverspeedEventHandler(15000, notRepeat); + private void testOverspeedWithPosition(boolean notRepeat, long geofenceId) throws Exception { + OverspeedEventHandler overspeedEventHandler = new OverspeedEventHandler(15000, notRepeat, false); Position position = new Position(); position.setTime(date("2017-01-01 00:00:00")); @@ -35,52 +35,58 @@ public class OverspeedEventHandlerTest extends BaseTest { DeviceState deviceState = new DeviceState(); deviceState.setOverspeedState(false); - Map events = overspeedEventHandler.updateOverspeedState(deviceState, position, 40); + Map events = overspeedEventHandler.updateOverspeedState(deviceState, position, 40, geofenceId); assertNull(events); assertFalse(deviceState.getOverspeedState()); assertEquals(position, deviceState.getOverspeedPosition()); + assertEquals(geofenceId, deviceState.getOverspeedGeofenceId()); Position nextPosition = new Position(); nextPosition.setTime(date("2017-01-01 00:00:10")); nextPosition.setSpeed(55); - events = overspeedEventHandler.updateOverspeedState(deviceState, nextPosition, 40); + events = overspeedEventHandler.updateOverspeedState(deviceState, nextPosition, 40, geofenceId); assertNull(events); nextPosition.setTime(date("2017-01-01 00:00:20")); - events = overspeedEventHandler.updateOverspeedState(deviceState, nextPosition, 40); + events = overspeedEventHandler.updateOverspeedState(deviceState, nextPosition, 40, geofenceId); assertNotNull(events); Event event = events.keySet().iterator().next(); assertEquals(Event.TYPE_DEVICE_OVERSPEED, event.getType()); assertEquals(50, event.getDouble("speed"), 0.1); assertEquals(40, event.getDouble(OverspeedEventHandler.ATTRIBUTE_SPEED_LIMIT), 0.1); + assertEquals(geofenceId, event.getGeofenceId()); assertEquals(notRepeat, deviceState.getOverspeedState()); assertNull(deviceState.getOverspeedPosition()); + assertEquals(0, deviceState.getOverspeedGeofenceId()); nextPosition.setTime(date("2017-01-01 00:00:30")); - events = overspeedEventHandler.updateOverspeedState(deviceState, nextPosition, 40); + events = overspeedEventHandler.updateOverspeedState(deviceState, nextPosition, 40, geofenceId); assertNull(events); assertEquals(notRepeat, deviceState.getOverspeedState()); if (notRepeat) { assertNull(deviceState.getOverspeedPosition()); + assertEquals(0, deviceState.getOverspeedGeofenceId()); } else { assertNotNull(deviceState.getOverspeedPosition()); + assertEquals(geofenceId, deviceState.getOverspeedGeofenceId()); } nextPosition.setTime(date("2017-01-01 00:00:40")); nextPosition.setSpeed(30); - events = overspeedEventHandler.updateOverspeedState(deviceState, nextPosition, 40); + events = overspeedEventHandler.updateOverspeedState(deviceState, nextPosition, 40, geofenceId); assertNull(events); assertFalse(deviceState.getOverspeedState()); assertNull(deviceState.getOverspeedPosition()); + assertEquals(0, deviceState.getOverspeedGeofenceId()); } private void testOverspeedWithStatus(boolean notRepeat) throws Exception { - OverspeedEventHandler overspeedEventHandler = new OverspeedEventHandler(15000, notRepeat); + OverspeedEventHandler overspeedEventHandler = new OverspeedEventHandler(15000, notRepeat, false); Position position = new Position(); position.setTime(new Date(System.currentTimeMillis() - 30000)); @@ -99,8 +105,11 @@ public class OverspeedEventHandlerTest extends BaseTest { @Test public void testOverspeedEventHandler() throws Exception { - testOverspeedWithPosition(false); - testOverspeedWithPosition(true); + testOverspeedWithPosition(false, 0); + testOverspeedWithPosition(true, 0); + + testOverspeedWithPosition(false, 1); + testOverspeedWithPosition(true, 1); testOverspeedWithStatus(false); testOverspeedWithStatus(true); -- cgit v1.2.3 From 3639bc6d289fa137d5dc7aaa47b67cd6a6bcc47d Mon Sep 17 00:00:00 2001 From: Abyss777 Date: Thu, 10 May 2018 09:04:43 +0500 Subject: Rename config switch --- src/org/traccar/Context.java | 2 +- src/org/traccar/events/OverspeedEventHandler.java | 10 +++++----- 2 files changed, 6 insertions(+), 6 deletions(-) diff --git a/src/org/traccar/Context.java b/src/org/traccar/Context.java index b7cfd27b0..23d0a983e 100644 --- a/src/org/traccar/Context.java +++ b/src/org/traccar/Context.java @@ -465,7 +465,7 @@ public final class Context { overspeedEventHandler = new OverspeedEventHandler( Context.getConfig().getLong("event.overspeed.minimalDuration") * 1000, Context.getConfig().getBoolean("event.overspeed.notRepeat"), - Context.getConfig().getBoolean("event.overspeed.geofenceMinimal")); + Context.getConfig().getBoolean("event.overspeed.preferLowest")); } public static void init(IdentityManager testIdentityManager) { diff --git a/src/org/traccar/events/OverspeedEventHandler.java b/src/org/traccar/events/OverspeedEventHandler.java index 223a117ad..4ebe43fda 100644 --- a/src/org/traccar/events/OverspeedEventHandler.java +++ b/src/org/traccar/events/OverspeedEventHandler.java @@ -32,13 +32,13 @@ public class OverspeedEventHandler extends BaseEventHandler { public static final String ATTRIBUTE_SPEED_LIMIT = "speedLimit"; private boolean notRepeat; - private boolean geofenceMinimal; + private boolean preferLowest; private long minimalDuration; - public OverspeedEventHandler(long minimalDuration, boolean notRepeat, boolean geofenceMinimal) { + public OverspeedEventHandler(long minimalDuration, boolean notRepeat, boolean preferLowest) { this.notRepeat = notRepeat; this.minimalDuration = minimalDuration; - this.geofenceMinimal = geofenceMinimal; + this.preferLowest = preferLowest; } private Map newEvent(DeviceState deviceState, double speedLimit) { @@ -121,8 +121,8 @@ public class OverspeedEventHandler extends BaseEventHandler { if (geofence != null) { double currentSpeedLimit = geofence.getDouble(ATTRIBUTE_SPEED_LIMIT); if (currentSpeedLimit > 0 && geofenceSpeedLimit == 0 - || geofenceMinimal && currentSpeedLimit < geofenceSpeedLimit - || !geofenceMinimal && currentSpeedLimit > geofenceSpeedLimit) { + || preferLowest && currentSpeedLimit < geofenceSpeedLimit + || !preferLowest && currentSpeedLimit > geofenceSpeedLimit) { geofenceSpeedLimit = currentSpeedLimit; overspeedGeofenceId = geofenceId; } -- cgit v1.2.3