aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorAnton Tananaev <anton@traccar.org>2022-09-19 19:07:26 -0700
committerAnton Tananaev <anton@traccar.org>2022-09-19 19:07:26 -0700
commit561647947118a86256dbb584f6da450334462739 (patch)
tree288f205d70cb066593a81db3aee75dab893a6074
parent18513d7949a2be933541c45728a1d466be2b50a2 (diff)
downloadtrackermap-server-561647947118a86256dbb584f6da450334462739.tar.gz
trackermap-server-561647947118a86256dbb584f6da450334462739.tar.bz2
trackermap-server-561647947118a86256dbb584f6da450334462739.zip
Refactor overspeed handling
-rw-r--r--src/main/java/org/traccar/config/Keys.java14
-rw-r--r--src/main/java/org/traccar/handler/events/MotionEventHandler.java15
-rw-r--r--src/main/java/org/traccar/handler/events/OverspeedEventHandler.java91
-rw-r--r--src/main/java/org/traccar/session/ConnectionManager.java34
-rw-r--r--src/main/java/org/traccar/session/DeviceState.java18
-rw-r--r--src/test/java/org/traccar/handler/events/MotionEventHandlerTest.java21
-rw-r--r--src/test/java/org/traccar/handler/events/OverspeedEventHandlerTest.java108
7 files changed, 70 insertions, 231 deletions
diff --git a/src/main/java/org/traccar/config/Keys.java b/src/main/java/org/traccar/config/Keys.java
index e6c3656da..ea394d914 100644
--- a/src/main/java/org/traccar/config/Keys.java
+++ b/src/main/java/org/traccar/config/Keys.java
@@ -327,13 +327,6 @@ public final class Keys {
0.0);
/**
- * If true, the event is generated once at the beginning of overspeeding period.
- */
- public static final ConfigKey<Boolean> EVENT_OVERSPEED_NOT_REPEAT = new BooleanConfigKey(
- "event.overspeed.notRepeat",
- List.of(KeyType.CONFIG));
-
- /**
* Minimal over speed duration to trigger the event. Value in seconds.
*/
public static final ConfigKey<Long> EVENT_OVERSPEED_MINIMAL_DURATION = new LongConfigKey(
@@ -599,13 +592,6 @@ public final class Keys {
600L);
/**
- * Force additional state check when device status changes to 'offline' or 'unknown'. Default false.
- */
- public static final ConfigKey<Boolean> STATUS_UPDATE_DEVICE_STATE = new BooleanConfigKey(
- "status.updateDeviceState",
- List.of(KeyType.CONFIG));
-
- /**
* List of protocol names to ignore offline status. Can be useful to not trigger status change when devices are
* configured to disconnect after reporting a batch of data.
*/
diff --git a/src/main/java/org/traccar/handler/events/MotionEventHandler.java b/src/main/java/org/traccar/handler/events/MotionEventHandler.java
index 1be1896ef..7ef9ec21d 100644
--- a/src/main/java/org/traccar/handler/events/MotionEventHandler.java
+++ b/src/main/java/org/traccar/handler/events/MotionEventHandler.java
@@ -54,21 +54,6 @@ public class MotionEventHandler extends BaseEventHandler {
return Collections.singletonMap(event, position);
}
- public Map<Event, Position> updateMotionState(DeviceState deviceState) {
- Map<Event, Position> 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 Map<Event, Position> updateMotionState(DeviceState deviceState, Position position) {
return updateMotionState(deviceState, position, position.getBoolean(Position.KEY_MOTION));
}
diff --git a/src/main/java/org/traccar/handler/events/OverspeedEventHandler.java b/src/main/java/org/traccar/handler/events/OverspeedEventHandler.java
index 7f3675308..cfba56a38 100644
--- a/src/main/java/org/traccar/handler/events/OverspeedEventHandler.java
+++ b/src/main/java/org/traccar/handler/events/OverspeedEventHandler.java
@@ -42,7 +42,6 @@ public class OverspeedEventHandler extends BaseEventHandler {
private final ConnectionManager connectionManager;
private final CacheManager cacheManager;
- private final boolean notRepeat;
private final long minimalDuration;
private final boolean preferLowest;
@@ -50,66 +49,46 @@ public class OverspeedEventHandler extends BaseEventHandler {
public OverspeedEventHandler(Config config, ConnectionManager connectionManager, CacheManager cacheManager) {
this.connectionManager = connectionManager;
this.cacheManager = cacheManager;
- notRepeat = config.getBoolean(Keys.EVENT_OVERSPEED_NOT_REPEAT);
minimalDuration = config.getLong(Keys.EVENT_OVERSPEED_MINIMAL_DURATION) * 1000;
preferLowest = config.getBoolean(Keys.EVENT_OVERSPEED_PREFER_LOWEST);
}
- private Map<Event, Position> newEvent(DeviceState deviceState, double speedLimit) {
- Position position = deviceState.getOverspeedPosition();
- Event event = new Event(Event.TYPE_DEVICE_OVERSPEED, position);
- event.set(ATTRIBUTE_SPEED, deviceState.getOverspeedPosition().getSpeed());
- event.set(Position.KEY_SPEED_LIMIT, speedLimit);
- event.setGeofenceId(deviceState.getOverspeedGeofenceId());
- deviceState.setOverspeedState(notRepeat);
- deviceState.setOverspeedPosition(null);
- deviceState.setOverspeedGeofenceId(0);
- return Collections.singletonMap(event, position);
- }
-
- public Map<Event, Position> updateOverspeedState(DeviceState deviceState, double speedLimit) {
- Map<Event, Position> 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 Map<Event, Position> updateOverspeedState(
DeviceState deviceState, Position position, double speedLimit, long geofenceId) {
- Map<Event, Position> result = null;
- Boolean oldOverspeed = deviceState.getOverspeedState();
+ boolean oldState = deviceState.getOverspeedState();
+ if (oldState) {
+ boolean newState = position.getSpeed() > speedLimit;
+ if (newState) {
+ if (deviceState.getOverspeedTime() != null) {
+ long oldTime = deviceState.getOverspeedTime().getTime();
+ long newTime = position.getFixTime().getTime();
+ if (newTime - oldTime > minimalDuration) {
- long currentTime = position.getFixTime().getTime();
- boolean newOverspeed = position.getSpeed() > speedLimit;
- 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) {
- long overspeedTime = overspeedPosition.getFixTime().getTime();
- if (newOverspeed && overspeedTime + minimalDuration <= currentTime) {
- result = newEvent(deviceState, speedLimit);
+ Event event = new Event(Event.TYPE_DEVICE_OVERSPEED, position);
+ event.set(ATTRIBUTE_SPEED, position.getSpeed());
+ event.set(Position.KEY_SPEED_LIMIT, speedLimit);
+ event.setGeofenceId(deviceState.getOverspeedGeofenceId());
+
+ deviceState.setOverspeedTime(null);
+ deviceState.setOverspeedGeofenceId(0);
+
+ return Collections.singletonMap(event, position);
+
+ }
+ }
+ } else {
+ deviceState.setOverspeedState(false);
+ deviceState.setOverspeedTime(null);
+ deviceState.setOverspeedGeofenceId(0);
}
+ } else if (position != null && position.getSpeed() > speedLimit) {
+ deviceState.setOverspeedState(true);
+ deviceState.setOverspeedTime(position.getFixTime());
+ deviceState.setOverspeedGeofenceId(geofenceId);
}
- return result;
+
+ return null;
}
@Override
@@ -156,16 +135,8 @@ public class OverspeedEventHandler extends BaseEventHandler {
return null;
}
- Map<Event, Position> result = null;
DeviceState deviceState = connectionManager.getDeviceState(deviceId);
-
- if (deviceState.getOverspeedState() == null) {
- deviceState.setOverspeedState(position.getSpeed() > speedLimit);
- deviceState.setOverspeedGeofenceId(position.getSpeed() > speedLimit ? overspeedGeofenceId : 0);
- } else {
- result = updateOverspeedState(deviceState, position, speedLimit, overspeedGeofenceId);
- }
-
+ Map<Event, Position> result = updateOverspeedState(deviceState, position, speedLimit, overspeedGeofenceId);
connectionManager.setDeviceState(deviceId, deviceState);
return result;
}
diff --git a/src/main/java/org/traccar/session/ConnectionManager.java b/src/main/java/org/traccar/session/ConnectionManager.java
index 262a302af..c826b99db 100644
--- a/src/main/java/org/traccar/session/ConnectionManager.java
+++ b/src/main/java/org/traccar/session/ConnectionManager.java
@@ -15,7 +15,6 @@
*/
package org.traccar.session;
-import com.google.inject.Injector;
import io.netty.channel.Channel;
import io.netty.util.Timeout;
import io.netty.util.Timer;
@@ -28,9 +27,6 @@ import org.traccar.config.Config;
import org.traccar.config.Keys;
import org.traccar.database.DeviceLookupService;
import org.traccar.database.NotificationManager;
-import org.traccar.handler.events.MotionEventHandler;
-import org.traccar.handler.events.OverspeedEventHandler;
-import org.traccar.helper.model.AttributeUtil;
import org.traccar.model.BaseModel;
import org.traccar.model.Device;
import org.traccar.model.Event;
@@ -66,14 +62,12 @@ public class ConnectionManager implements BroadcastInterface {
private static final Logger LOGGER = LoggerFactory.getLogger(ConnectionManager.class);
private final long deviceTimeout;
- private final boolean updateDeviceState;
private final Map<Long, DeviceSession> sessionsByDeviceId = new ConcurrentHashMap<>();
private final Map<Endpoint, Map<String, DeviceSession>> sessionsByEndpoint = new ConcurrentHashMap<>();
private final Map<Long, DeviceState> deviceStates = new ConcurrentHashMap<>();
- private final Injector injector;
private final Config config;
private final CacheManager cacheManager;
private final Storage storage;
@@ -90,10 +84,9 @@ public class ConnectionManager implements BroadcastInterface {
@Inject
public ConnectionManager(
- Injector injector, Config config, CacheManager cacheManager, Storage storage,
+ Config config, CacheManager cacheManager, Storage storage,
NotificationManager notificationManager, Timer timer, BroadcastService broadcastService,
DeviceLookupService deviceLookupService) {
- this.injector = injector;
this.config = config;
this.cacheManager = cacheManager;
this.storage = storage;
@@ -102,7 +95,6 @@ public class ConnectionManager implements BroadcastInterface {
this.broadcastService = broadcastService;
this.deviceLookupService = deviceLookupService;
deviceTimeout = config.getLong(Keys.STATUS_TIMEOUT);
- updateDeviceState = config.getBoolean(Keys.STATUS_UPDATE_DEVICE_STATE);
broadcastService.registerListener(this);
}
@@ -246,15 +238,9 @@ public class ConnectionManager implements BroadcastInterface {
break;
case Device.STATUS_UNKNOWN:
eventType = Event.TYPE_DEVICE_UNKNOWN;
- if (updateDeviceState) {
- events.putAll(updateDeviceState(deviceId));
- }
break;
default:
eventType = Event.TYPE_DEVICE_OFFLINE;
- if (updateDeviceState) {
- events.putAll(updateDeviceState(deviceId));
- }
break;
}
events.put(new Event(eventType, deviceId), null);
@@ -297,24 +283,6 @@ public class ConnectionManager implements BroadcastInterface {
deviceStates.put(deviceId, deviceState);
}
- public Map<Event, Position> updateDeviceState(long deviceId) {
- DeviceState deviceState = getDeviceState(deviceId);
- Map<Event, Position> result = new HashMap<>();
-
- Map<Event, Position> event = injector.getInstance(MotionEventHandler.class).updateMotionState(deviceState);
- if (event != null) {
- result.putAll(event);
- }
-
- double speedLimit = AttributeUtil.lookup(cacheManager, Keys.EVENT_OVERSPEED_LIMIT, deviceId);
- event = injector.getInstance(OverspeedEventHandler.class).updateOverspeedState(deviceState, speedLimit);
- if (event != null) {
- result.putAll(event);
- }
-
- return result;
- }
-
public synchronized void sendKeepalive() {
for (Set<UpdateListener> userListeners : listeners.values()) {
for (UpdateListener listener : userListeners) {
diff --git a/src/main/java/org/traccar/session/DeviceState.java b/src/main/java/org/traccar/session/DeviceState.java
index b7248688a..f67b906c4 100644
--- a/src/main/java/org/traccar/session/DeviceState.java
+++ b/src/main/java/org/traccar/session/DeviceState.java
@@ -1,5 +1,5 @@
/*
- * Copyright 2017 Anton Tananaev (anton@traccar.org)
+ * Copyright 2017 - 2022 Anton Tananaev (anton@traccar.org)
* Copyright 2017 Andrey Kunitsyn (andrey@traccar.org)
*
* Licensed under the Apache License, Version 2.0 (the "License");
@@ -18,6 +18,8 @@ package org.traccar.session;
import org.traccar.model.Position;
+import java.util.Date;
+
public class DeviceState {
private Boolean motionState;
@@ -40,24 +42,24 @@ public class DeviceState {
return motionPosition;
}
- private Boolean overspeedState;
+ private boolean overspeedState;
public void setOverspeedState(boolean overspeedState) {
this.overspeedState = overspeedState;
}
- public Boolean getOverspeedState() {
+ public boolean getOverspeedState() {
return overspeedState;
}
- private Position overspeedPosition;
+ private Date overspeedTime;
- public void setOverspeedPosition(Position overspeedPosition) {
- this.overspeedPosition = overspeedPosition;
+ public Date getOverspeedTime() {
+ return overspeedTime;
}
- public Position getOverspeedPosition() {
- return overspeedPosition;
+ public void setOverspeedTime(Date overspeedTime) {
+ this.overspeedTime = overspeedTime;
}
private long overspeedGeofenceId;
diff --git a/src/test/java/org/traccar/handler/events/MotionEventHandlerTest.java b/src/test/java/org/traccar/handler/events/MotionEventHandlerTest.java
index 780d1b833..1f6212eec 100644
--- a/src/test/java/org/traccar/handler/events/MotionEventHandlerTest.java
+++ b/src/test/java/org/traccar/handler/events/MotionEventHandlerTest.java
@@ -70,27 +70,6 @@ public class MotionEventHandlerTest extends BaseTest {
}
@Test
- public void testMotionWithStatus() throws Exception {
- MotionEventHandler motionEventHandler = new MotionEventHandler(
- null, null, new TripsConfig(500, 300 * 1000, 300 * 1000, 0, false, false, 0.01));
-
- Position position = new Position();
- position.setTime(new Date(System.currentTimeMillis() - 360000));
- position.set(Position.KEY_MOTION, true);
- DeviceState deviceState = new DeviceState();
- deviceState.setMotionState(false);
- deviceState.setMotionPosition(position);
-
- Map<Event, Position> events = motionEventHandler.updateMotionState(deviceState);
-
- assertNotNull(events);
- Event event = events.keySet().iterator().next();
- assertEquals(Event.TYPE_DEVICE_MOVING, event.getType());
- assertTrue(deviceState.getMotionState());
- assertNull(deviceState.getMotionPosition());
- }
-
- @Test
public void testStopWithPositionIgnition() throws Exception {
MotionEventHandler motionEventHandler = new MotionEventHandler(
null, null, new TripsConfig(500, 300 * 1000, 300 * 1000, 0, true, false, 0.01));
diff --git a/src/test/java/org/traccar/handler/events/OverspeedEventHandlerTest.java b/src/test/java/org/traccar/handler/events/OverspeedEventHandlerTest.java
index 46e142935..bbddbae72 100644
--- a/src/test/java/org/traccar/handler/events/OverspeedEventHandlerTest.java
+++ b/src/test/java/org/traccar/handler/events/OverspeedEventHandlerTest.java
@@ -11,118 +11,66 @@ import org.traccar.session.DeviceState;
import java.text.DateFormat;
import java.text.ParseException;
import java.text.SimpleDateFormat;
-import java.util.Date;
-import java.util.Map;
import java.util.TimeZone;
import static org.junit.Assert.assertEquals;
-import static org.junit.Assert.assertFalse;
import static org.junit.Assert.assertNotNull;
import static org.junit.Assert.assertNull;
public class OverspeedEventHandlerTest extends BaseTest {
- private Date date(String time) throws ParseException {
+ private Position position(String time, double speed) throws ParseException {
+ Position position = new Position();
DateFormat dateFormat = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
dateFormat.setTimeZone(TimeZone.getTimeZone("UTC"));
- return dateFormat.parse(time);
+ position.setTime(dateFormat.parse(time));
+ position.setSpeed(speed);
+ return position;
+ }
+
+ private void verifyState(DeviceState deviceState, boolean state, long geofenceId) {
+ assertEquals(state, deviceState.getOverspeedState());
+ assertEquals(geofenceId, deviceState.getOverspeedGeofenceId());
}
- private void testOverspeedWithPosition(boolean notRepeat, long geofenceId) throws ParseException {
+ private void testOverspeedWithPosition(long geofenceId) throws ParseException {
Config config = new Config();
- config.setString(Keys.EVENT_OVERSPEED_NOT_REPEAT, String.valueOf(notRepeat));
config.setString(Keys.EVENT_OVERSPEED_MINIMAL_DURATION, String.valueOf(15));
config.setString(Keys.EVENT_OVERSPEED_PREFER_LOWEST, String.valueOf(false));
OverspeedEventHandler overspeedEventHandler = new OverspeedEventHandler(config, null, null);
- Position position = new Position();
- position.setTime(date("2017-01-01 00:00:00"));
- position.setSpeed(50);
DeviceState deviceState = new DeviceState();
- deviceState.setOverspeedState(false);
-
- Map<Event, Position> 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);
+ Position position = position("2017-01-01 00:00:00", 50);
+ assertNull(overspeedEventHandler.updateOverspeedState(deviceState, position, 40, geofenceId));
+ verifyState(deviceState, true, geofenceId);
- events = overspeedEventHandler.updateOverspeedState(deviceState, nextPosition, 40, geofenceId);
- assertNull(events);
+ position = position("2017-01-01 00:00:10", 55);
+ assertNull(overspeedEventHandler.updateOverspeedState(deviceState, position, 40, geofenceId));
- nextPosition.setTime(date("2017-01-01 00:00:20"));
-
- events = overspeedEventHandler.updateOverspeedState(deviceState, nextPosition, 40, geofenceId);
+ position = position("2017-01-01 00:00:20", 55);
+ var events = overspeedEventHandler.updateOverspeedState(deviceState, position, 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(55, event.getDouble("speed"), 0.1);
assertEquals(40, event.getDouble("speedLimit"), 0.1);
assertEquals(geofenceId, event.getGeofenceId());
+ verifyState(deviceState, true, 0);
- 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, 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, geofenceId);
- assertNull(events);
- assertFalse(deviceState.getOverspeedState());
- assertNull(deviceState.getOverspeedPosition());
- assertEquals(0, deviceState.getOverspeedGeofenceId());
- }
-
- private void testOverspeedWithStatus(boolean notRepeat) {
- Config config = new Config();
- config.setString(Keys.EVENT_OVERSPEED_NOT_REPEAT, String.valueOf(notRepeat));
- config.setString(Keys.EVENT_OVERSPEED_MINIMAL_DURATION, String.valueOf(15));
- config.setString(Keys.EVENT_OVERSPEED_PREFER_LOWEST, String.valueOf(false));
- OverspeedEventHandler overspeedEventHandler = new OverspeedEventHandler(config, null, null);
+ position = position("2017-01-01 00:00:30", 55);
+ assertNull(overspeedEventHandler.updateOverspeedState(deviceState, position, 40, geofenceId));
+ verifyState(deviceState, true, 0);
- Position position = new Position();
- position.setTime(new Date(System.currentTimeMillis() - 30000));
- position.setSpeed(50);
- DeviceState deviceState = new DeviceState();
- deviceState.setOverspeedState(false);
- deviceState.setOverspeedPosition(position);
-
- Map<Event, Position> events = overspeedEventHandler.updateOverspeedState(deviceState, 40);
-
- assertNotNull(events);
- Event event = events.keySet().iterator().next();
- assertEquals(Event.TYPE_DEVICE_OVERSPEED, event.getType());
- assertEquals(notRepeat, deviceState.getOverspeedState());
+ position = position("2017-01-01 00:00:30", 30);
+ assertNull(overspeedEventHandler.updateOverspeedState(deviceState, position, 40, geofenceId));
+ verifyState(deviceState, false, 0);
}
@Test
public void testOverspeedEventHandler() throws Exception {
- testOverspeedWithPosition(false, 0);
- testOverspeedWithPosition(true, 0);
-
- testOverspeedWithPosition(false, 1);
- testOverspeedWithPosition(true, 1);
-
- testOverspeedWithStatus(false);
- testOverspeedWithStatus(true);
+ testOverspeedWithPosition(0);
+ testOverspeedWithPosition(1);
}
}