aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorAbyss777 <abyss@fox5.ru>2017-08-10 13:31:18 +0500
committerAbyss777 <abyss@fox5.ru>2017-08-10 13:31:18 +0500
commit532e0a98d469573a575dc595554792cbbd4cd953 (patch)
treef05220655a2df11cbdbe57f8da7e1d86ef27f491
parentb82be4f9f3b4d1d6c345bc41d5c26aca03e369cb (diff)
downloadtraccar-server-532e0a98d469573a575dc595554792cbbd4cd953.tar.gz
traccar-server-532e0a98d469573a575dc595554792cbbd4cd953.tar.bz2
traccar-server-532e0a98d469573a575dc595554792cbbd4cd953.zip
Implement delayed overspeed events
-rw-r--r--src/org/traccar/database/ConnectionManager.java58
-rw-r--r--src/org/traccar/database/DeviceManager.java7
-rw-r--r--src/org/traccar/events/MotionEventHandler.java10
-rw-r--r--src/org/traccar/events/OverspeedEventHandler.java66
-rw-r--r--src/org/traccar/model/DeviceState.java20
-rw-r--r--test/org/traccar/events/OverspeedEventHandlerTest.java85
6 files changed, 203 insertions, 43 deletions
diff --git a/src/org/traccar/database/ConnectionManager.java b/src/org/traccar/database/ConnectionManager.java
index 1c5d4428a..ee2a7bb47 100644
--- a/src/org/traccar/database/ConnectionManager.java
+++ b/src/org/traccar/database/ConnectionManager.java
@@ -21,6 +21,7 @@ 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;
@@ -44,7 +45,10 @@ public class ConnectionManager {
private final long deviceTimeout;
private final boolean enableStatusEvents;
+ private final boolean updateDeviceState;
private TripsConfig tripsConfig = null;
+ private long minimalOverspeedDuration;
+ private boolean overspeedNotRepeat;
private final Map<Long, ActiveDevice> activeDevices = new ConcurrentHashMap<>();
private final Map<Long, Set<UpdateListener>> listeners = new ConcurrentHashMap<>();
@@ -53,8 +57,11 @@ 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")) {
+ updateDeviceState = Context.getConfig().getBoolean("status.updateDeviceState");
+ if (updateDeviceState) {
tripsConfig = ReportUtils.initTripsConfig();
+ minimalOverspeedDuration = Context.getConfig().getLong("event.overspeed.minimalDuration") * 1000;
+ overspeedNotRepeat = Context.getConfig().getBoolean("event.overspeed.notRepeat");
}
}
@@ -87,28 +94,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 +145,41 @@ 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;
- }
- Event result = null;
- Boolean oldMotion = deviceState.getMotionState();
+ Set<Event> result = new HashSet<>();
long currentTime = System.currentTimeMillis();
- boolean newMotion = !oldMotion;
- Position motionPosition = deviceState.getMotionPosition();
- if (motionPosition != null) {
+ if (deviceState.getMotionState() != null && deviceState.getMotionPosition() != null) {
+ boolean newMotion = !deviceState.getMotionState();
+ Position motionPosition = deviceState.getMotionPosition();
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());
+ result.add(new Event(eventType, motionPosition.getDeviceId(), motionPosition.getId()));
deviceState.setMotionState(newMotion);
deviceState.setMotionPosition(null);
}
}
+ if (deviceState.getOverspeedState() != null && !deviceState.getOverspeedState()
+ && deviceState.getOverspeedPosition() != null) {
+ double speedLimit = Context.getDeviceManager().lookupAttributeDouble(deviceId,
+ OverspeedEventHandler.ATTRIBUTE_SPEED_LIMIT, 0, false);
+ if (speedLimit != 0) {
+ Position overspeedPosition = deviceState.getOverspeedPosition();
+ long overspeedTime = overspeedPosition.getFixTime().getTime();
+ if (overspeedTime + minimalOverspeedDuration <= currentTime) {
+ Event event = new Event(Event.TYPE_DEVICE_OVERSPEED, overspeedPosition.getDeviceId(),
+ overspeedPosition.getId());
+ event.set("speed", overspeedPosition.getSpeed());
+ event.set(OverspeedEventHandler.ATTRIBUTE_SPEED_LIMIT, speedLimit);
+ result.add(event);
+ deviceState.setOverspeedState(overspeedNotRepeat);
+ deviceState.setOverspeedPosition(null);
+ }
+ }
+ }
+
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..ed21d7b83 100644
--- a/src/org/traccar/events/MotionEventHandler.java
+++ b/src/org/traccar/events/MotionEventHandler.java
@@ -77,7 +77,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,14 +87,9 @@ 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);
diff --git a/src/org/traccar/events/OverspeedEventHandler.java b/src/org/traccar/events/OverspeedEventHandler.java
index 795892f40..3b91fed4d 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,51 @@ 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");
+ minimalDuration = Context.getConfig().getLong("event.overspeed.minimalDuration") * 1000;
+ }
+
+ public static Event updateOverspeedState(DeviceState deviceState, Position position, double speedLimit,
+ long minimalOverspeedDuration, boolean notRepeat) {
+ 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 + minimalOverspeedDuration <= currentTime) {
+ result = new Event(Event.TYPE_DEVICE_OVERSPEED, overspeedPosition.getDeviceId(),
+ overspeedPosition.getId());
+ result.set("speed", overspeedPosition.getSpeed());
+ result.set(ATTRIBUTE_SPEED_LIMIT, speedLimit);
+ deviceState.setOverspeedState(notRepeat);
+ deviceState.setOverspeedPosition(null);
+ }
+ }
+ 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 +82,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, minimalDuration, notRepeat);
}
- 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/test/org/traccar/events/OverspeedEventHandlerTest.java b/test/org/traccar/events/OverspeedEventHandlerTest.java
new file mode 100644
index 000000000..25bbb4319
--- /dev/null
+++ b/test/org/traccar/events/OverspeedEventHandlerTest.java
@@ -0,0 +1,85 @@
+package org.traccar.events;
+
+import static org.junit.Assert.assertEquals;
+import static org.junit.Assert.assertFalse;
+import static org.junit.Assert.assertTrue;
+import static org.junit.Assert.assertNotNull;
+import static org.junit.Assert.assertNull;
+
+import java.text.DateFormat;
+import java.text.ParseException;
+import java.text.SimpleDateFormat;
+import java.util.Date;
+import java.util.TimeZone;
+
+import org.junit.Test;
+import org.traccar.BaseTest;
+import org.traccar.model.DeviceState;
+import org.traccar.model.Event;
+import org.traccar.model.Position;
+
+public class OverspeedEventHandlerTest extends BaseTest {
+
+ private Date date(String time) throws ParseException {
+ DateFormat dateFormat = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
+ dateFormat.setTimeZone(TimeZone.getTimeZone("UTC"));
+ return dateFormat.parse(time);
+ }
+
+ private void testOverspeed(boolean notRepeat) throws Exception {
+ Position position = new Position();
+ position.setTime(date("2017-01-01 00:00:00"));
+ position.setSpeed(50);
+ DeviceState deviceState = new DeviceState();
+ deviceState.setOverspeedState(false);
+
+ Event event = OverspeedEventHandler.updateOverspeedState(deviceState, position, 40, 15000, notRepeat);
+ assertNull(event);
+ assertFalse(deviceState.getOverspeedState());
+ assertEquals(position, deviceState.getOverspeedPosition());
+
+ Position nextPosition = new Position();
+ nextPosition.setTime(date("2017-01-01 00:00:10"));
+ nextPosition.setSpeed(55);
+
+ event = OverspeedEventHandler.updateOverspeedState(deviceState, nextPosition, 40, 15000, notRepeat);
+ assertNull(event);
+
+ nextPosition.setTime(date("2017-01-01 00:00:20"));
+
+ event = OverspeedEventHandler.updateOverspeedState(deviceState, nextPosition, 40, 15000, notRepeat);
+ assertNotNull(event);
+ 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(notRepeat, deviceState.getOverspeedState());
+ assertNull(deviceState.getOverspeedPosition());
+
+ nextPosition.setTime(date("2017-01-01 00:00:30"));
+ event = OverspeedEventHandler.updateOverspeedState(deviceState, nextPosition, 40, 15000, notRepeat);
+ assertNull(event);
+ assertEquals(notRepeat, deviceState.getOverspeedState());
+
+ if (notRepeat) {
+ assertNull(deviceState.getOverspeedPosition());
+ } else {
+ assertNotNull(deviceState.getOverspeedPosition());
+ }
+
+ nextPosition.setTime(date("2017-01-01 00:00:40"));
+ nextPosition.setSpeed(30);
+
+ event = OverspeedEventHandler.updateOverspeedState(deviceState, nextPosition, 40, 15000, notRepeat);
+ assertNull(event);
+ assertFalse(deviceState.getOverspeedState());
+ assertNull(deviceState.getOverspeedPosition());
+ }
+
+ @Test
+ public void testOverspeedEventHandler() throws Exception {
+ testOverspeed(false);
+ testOverspeed(true);
+ }
+
+}