diff options
author | Anton Tananaev <anton@traccar.org> | 2022-09-19 19:07:26 -0700 |
---|---|---|
committer | Anton Tananaev <anton@traccar.org> | 2022-09-19 19:07:26 -0700 |
commit | 561647947118a86256dbb584f6da450334462739 (patch) | |
tree | 288f205d70cb066593a81db3aee75dab893a6074 | |
parent | 18513d7949a2be933541c45728a1d466be2b50a2 (diff) | |
download | trackermap-server-561647947118a86256dbb584f6da450334462739.tar.gz trackermap-server-561647947118a86256dbb584f6da450334462739.tar.bz2 trackermap-server-561647947118a86256dbb584f6da450334462739.zip |
Refactor overspeed handling
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); } } |