aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--src/main/java/org/traccar/reports/common/ReportUtils.java83
-rw-r--r--src/test/java/org/traccar/reports/ReportUtilsTest.java26
2 files changed, 82 insertions, 27 deletions
diff --git a/src/main/java/org/traccar/reports/common/ReportUtils.java b/src/main/java/org/traccar/reports/common/ReportUtils.java
index a930f9439..28e3d2ae5 100644
--- a/src/main/java/org/traccar/reports/common/ReportUtils.java
+++ b/src/main/java/org/traccar/reports/common/ReportUtils.java
@@ -37,6 +37,7 @@ import org.traccar.helper.model.UserUtil;
import org.traccar.model.BaseModel;
import org.traccar.model.Device;
import org.traccar.model.Driver;
+import org.traccar.model.Event;
import org.traccar.model.Position;
import org.traccar.model.User;
import org.traccar.reports.model.BaseReportItem;
@@ -48,6 +49,7 @@ import org.traccar.storage.Storage;
import org.traccar.storage.StorageException;
import org.traccar.storage.query.Columns;
import org.traccar.storage.query.Condition;
+import org.traccar.storage.query.Order;
import org.traccar.storage.query.Request;
import javax.annotation.Nullable;
@@ -57,10 +59,13 @@ import java.io.InputStream;
import java.io.OutputStream;
import java.math.BigDecimal;
import java.math.RoundingMode;
+import java.time.Duration;
import java.util.ArrayList;
import java.util.Date;
import java.util.List;
import java.util.Locale;
+import java.util.Set;
+import java.util.stream.Collectors;
public class ReportUtils {
@@ -161,7 +166,8 @@ public class ReportUtils {
}
private TripReportItem calculateTrip(
- Device device, Position startTrip, Position endTrip, boolean ignoreOdometer) throws StorageException {
+ Device device, Position startTrip, Position endTrip, double maxSpeed,
+ boolean ignoreOdometer) throws StorageException {
TripReportItem trip = new TripReportItem();
@@ -195,6 +201,7 @@ public class ReportUtils {
if (tripDuration > 0) {
trip.setAverageSpeed(UnitsConverter.knotsFromMps(trip.getDistance() * 1000 / tripDuration));
}
+ trip.setMaxSpeed(maxSpeed);
trip.setSpentFuel(calculateFuel(startTrip, endTrip));
trip.setDriverUniqueId(findDriver(startTrip, endTrip));
@@ -258,20 +265,13 @@ public class ReportUtils {
@SuppressWarnings("unchecked")
private <T extends BaseReportItem> T calculateTripOrStop(
- Device device, List<Position> positions, int startIndex, int endIndex,
+ Device device, Position startPosition, Position endPosition, double maxSpeed,
boolean ignoreOdometer, Class<T> reportClass) throws StorageException {
if (reportClass.equals(TripReportItem.class)) {
- var result = calculateTrip(device, positions.get(startIndex), positions.get(endIndex), ignoreOdometer);
- for (int i = startIndex; i <= endIndex; i++) {
- double speed = positions.get(i).getSpeed();
- if (speed > result.getMaxSpeed()) {
- result.setMaxSpeed(speed);
- }
- }
- return (T) result;
+ return (T) calculateTrip(device, startPosition, endPosition, maxSpeed, ignoreOdometer);
} else {
- return (T) calculateStop(device, positions.get(startIndex), positions.get(endIndex), ignoreOdometer);
+ return (T) calculateStop(device, startPosition, endPosition, ignoreOdometer);
}
}
@@ -293,6 +293,17 @@ public class ReportUtils {
public <T extends BaseReportItem> List<T> detectTripsAndStops(
Device device, Date from, Date to, Class<T> reportClass) throws StorageException {
+ long threshold = config.getLong(Keys.REPORT_FAST_THRESHOLD);
+ if (Duration.between(from.toInstant(), to.toInstant()).toSeconds() > threshold) {
+ return fastTripsAndStops(device, from, to, reportClass);
+ } else {
+ return slowTripsAndStops(device, from, to, reportClass);
+ }
+ }
+
+ public <T extends BaseReportItem> List<T> slowTripsAndStops(
+ Device device, Date from, Date to, Class<T> reportClass) throws StorageException {
+
List<T> result = new ArrayList<>();
TripsConfig tripsConfig = new TripsConfig(
new AttributeUtil.StorageProvider(config, storage, permissionsService, device));
@@ -308,17 +319,23 @@ public class ReportUtils {
motionState.setMotionState(initialValue);
boolean detected = trips == motionState.getMotionState();
+ double maxSpeed = 0;
int startEventIndex = detected ? 0 : -1;
int startNoEventIndex = -1;
for (int i = 0; i < positions.size(); i++) {
boolean motion = isMoving(positions, i, tripsConfig);
if (motionState.getMotionState() != motion) {
if (motion == trips) {
- startEventIndex = detected ? startEventIndex : i;
+ if (!detected) {
+ startEventIndex = i;
+ maxSpeed = positions.get(i).getSpeed();
+ }
startNoEventIndex = -1;
} else {
startNoEventIndex = i;
}
+ } else {
+ maxSpeed = Math.max(maxSpeed, positions.get(i).getSpeed());
}
MotionProcessor.updateState(motionState, positions.get(i), motion, tripsConfig);
@@ -328,7 +345,8 @@ public class ReportUtils {
startNoEventIndex = -1;
} else if (startEventIndex >= 0 && startNoEventIndex >= 0) {
result.add(calculateTripOrStop(
- device, positions, startEventIndex, startNoEventIndex, ignoreOdometer, reportClass));
+ device, positions.get(startEventIndex), positions.get(startNoEventIndex),
+ maxSpeed, ignoreOdometer, reportClass));
detected = false;
startEventIndex = -1;
startNoEventIndex = -1;
@@ -338,7 +356,44 @@ public class ReportUtils {
if (detected & startEventIndex >= 0 && startEventIndex < positions.size() - 1) {
int endIndex = startNoEventIndex >= 0 ? startNoEventIndex : positions.size() - 1;
result.add(calculateTripOrStop(
- device, positions, startEventIndex, endIndex, ignoreOdometer, reportClass));
+ device, positions.get(startEventIndex), positions.get(endIndex),
+ maxSpeed, ignoreOdometer, reportClass));
+ }
+ }
+
+ return result;
+ }
+
+ public <T extends BaseReportItem> List<T> fastTripsAndStops(
+ Device device, Date from, Date to, Class<T> reportClass) throws StorageException {
+
+ List<T> result = new ArrayList<>();
+ boolean ignoreOdometer = config.getBoolean(Keys.REPORT_IGNORE_ODOMETER);
+ boolean trips = reportClass.equals(TripReportItem.class);
+ Set<String> filter = Set.of(Event.TYPE_DEVICE_MOVING, Event.TYPE_DEVICE_STOPPED);
+
+ var events = storage.getObjects(Event.class, new Request(
+ new Columns.All(),
+ new Condition.And(
+ new Condition.Equals("deviceId", device.getId()),
+ new Condition.Between("eventTime", "from", from, "to", to)),
+ new Order("eventTime")));
+ var filteredEvents = events.stream()
+ .filter(event -> filter.contains(event.getType()))
+ .collect(Collectors.toList());
+
+ Event startEvent = null;
+ for (Event event : filteredEvents) {
+ boolean motion = event.getType().equals(Event.TYPE_DEVICE_MOVING);
+ if (motion == trips) {
+ startEvent = event;
+ } else if (startEvent != null) {
+ Position startPosition = storage.getObject(Position.class, new Request(
+ new Columns.All(), new Condition.Equals("id", startEvent.getPositionId())));
+ Position endPosition = storage.getObject(Position.class, new Request(
+ new Columns.All(), new Condition.Equals("id", event.getPositionId())));
+ result.add(calculateTripOrStop(device, startPosition, endPosition, 0, ignoreOdometer, reportClass));
+ startEvent = null;
}
}
diff --git a/src/test/java/org/traccar/reports/ReportUtilsTest.java b/src/test/java/org/traccar/reports/ReportUtilsTest.java
index d11d2b2e1..0f14577fd 100644
--- a/src/test/java/org/traccar/reports/ReportUtilsTest.java
+++ b/src/test/java/org/traccar/reports/ReportUtilsTest.java
@@ -119,7 +119,7 @@ public class ReportUtilsTest extends BaseTest {
ReportUtils reportUtils = new ReportUtils(
mock(Config.class), storage, mock(PermissionsService.class), mock(VelocityEngine.class), null);
- var trips = reportUtils.detectTripsAndStops(device, new Date(), new Date(), TripReportItem.class);
+ var trips = reportUtils.slowTripsAndStops(device, new Date(), new Date(), TripReportItem.class);
assertNotNull(trips);
assertFalse(trips.isEmpty());
@@ -133,7 +133,7 @@ public class ReportUtilsTest extends BaseTest {
assertEquals(10, itemTrip.getMaxSpeed(), 0.01);
assertEquals(3000, itemTrip.getDistance(), 0.01);
- var stops = reportUtils.detectTripsAndStops(device, new Date(), new Date(), StopReportItem.class);
+ var stops = reportUtils.slowTripsAndStops(device, new Date(), new Date(), StopReportItem.class);
assertNotNull(stops);
assertFalse(stops.isEmpty());
@@ -174,7 +174,7 @@ public class ReportUtilsTest extends BaseTest {
ReportUtils reportUtils = new ReportUtils(
mock(Config.class), storage, mock(PermissionsService.class), mock(VelocityEngine.class), null);
- var trips = reportUtils.detectTripsAndStops(device, new Date(), new Date(), TripReportItem.class);
+ var trips = reportUtils.slowTripsAndStops(device, new Date(), new Date(), TripReportItem.class);
assertNotNull(trips);
assertFalse(trips.isEmpty());
@@ -188,7 +188,7 @@ public class ReportUtilsTest extends BaseTest {
assertEquals(10, itemTrip.getMaxSpeed(), 0.01);
assertEquals(3000, itemTrip.getDistance(), 0.01);
- trips = reportUtils.detectTripsAndStops(device, new Date(), new Date(), TripReportItem.class);
+ trips = reportUtils.slowTripsAndStops(device, new Date(), new Date(), TripReportItem.class);
assertNotNull(trips);
assertFalse(trips.isEmpty());
@@ -202,7 +202,7 @@ public class ReportUtilsTest extends BaseTest {
assertEquals(10, itemTrip.getMaxSpeed(), 0.01);
assertEquals(3000, itemTrip.getDistance(), 0.01);
- var stops = reportUtils.detectTripsAndStops(device, new Date(), new Date(), StopReportItem.class);
+ var stops = reportUtils.slowTripsAndStops(device, new Date(), new Date(), StopReportItem.class);
assertNotNull(stops);
assertFalse(stops.isEmpty());
@@ -245,7 +245,7 @@ public class ReportUtilsTest extends BaseTest {
ReportUtils reportUtils = new ReportUtils(
mock(Config.class), storage, mock(PermissionsService.class), mock(VelocityEngine.class), null);
- var trips = reportUtils.detectTripsAndStops(device, new Date(), new Date(), TripReportItem.class);
+ var trips = reportUtils.slowTripsAndStops(device, new Date(), new Date(), TripReportItem.class);
assertNotNull(trips);
assertFalse(trips.isEmpty());
@@ -259,7 +259,7 @@ public class ReportUtilsTest extends BaseTest {
assertEquals(10, itemTrip.getMaxSpeed(), 0.01);
assertEquals(7000, itemTrip.getDistance(), 0.01);
- var stops = reportUtils.detectTripsAndStops(device, new Date(), new Date(), StopReportItem.class);
+ var stops = reportUtils.slowTripsAndStops(device, new Date(), new Date(), StopReportItem.class);
assertNotNull(stops);
assertFalse(stops.isEmpty());
@@ -296,7 +296,7 @@ public class ReportUtilsTest extends BaseTest {
ReportUtils reportUtils = new ReportUtils(
mock(Config.class), storage, mock(PermissionsService.class), mock(VelocityEngine.class), null);
- var result = reportUtils.detectTripsAndStops(device, new Date(), new Date(), StopReportItem.class);
+ var result = reportUtils.slowTripsAndStops(device, new Date(), new Date(), StopReportItem.class);
assertNotNull(result);
assertFalse(result.isEmpty());
@@ -325,7 +325,7 @@ public class ReportUtilsTest extends BaseTest {
ReportUtils reportUtils = new ReportUtils(
mock(Config.class), storage, mock(PermissionsService.class), mock(VelocityEngine.class), null);
- var result = reportUtils.detectTripsAndStops(device, new Date(), new Date(), StopReportItem.class);
+ var result = reportUtils.slowTripsAndStops(device, new Date(), new Date(), StopReportItem.class);
assertNotNull(result);
assertFalse(result.isEmpty());
@@ -354,7 +354,7 @@ public class ReportUtilsTest extends BaseTest {
ReportUtils reportUtils = new ReportUtils(
mock(Config.class), storage, mock(PermissionsService.class), mock(VelocityEngine.class), null);
- var result = reportUtils.detectTripsAndStops(device, new Date(), new Date(), StopReportItem.class);
+ var result = reportUtils.slowTripsAndStops(device, new Date(), new Date(), StopReportItem.class);
assertNotNull(result);
assertFalse(result.isEmpty());
@@ -383,7 +383,7 @@ public class ReportUtilsTest extends BaseTest {
ReportUtils reportUtils = new ReportUtils(
mock(Config.class), storage, mock(PermissionsService.class), mock(VelocityEngine.class), null);
- var result = reportUtils.detectTripsAndStops(device, new Date(), new Date(), StopReportItem.class);
+ var result = reportUtils.slowTripsAndStops(device, new Date(), new Date(), StopReportItem.class);
assertNotNull(result);
assertTrue(result.isEmpty());
@@ -408,7 +408,7 @@ public class ReportUtilsTest extends BaseTest {
ReportUtils reportUtils = new ReportUtils(
mock(Config.class), storage, mock(PermissionsService.class), mock(VelocityEngine.class), null);
- var trips = reportUtils.detectTripsAndStops(device, new Date(), new Date(), TripReportItem.class);
+ var trips = reportUtils.slowTripsAndStops(device, new Date(), new Date(), TripReportItem.class);
assertNotNull(trips);
assertFalse(trips.isEmpty());
@@ -422,7 +422,7 @@ public class ReportUtilsTest extends BaseTest {
assertEquals(7, itemTrip.getMaxSpeed(), 0.01);
assertEquals(600, itemTrip.getDistance(), 0.01);
- var stops = reportUtils.detectTripsAndStops(device, new Date(), new Date(), StopReportItem.class);
+ var stops = reportUtils.slowTripsAndStops(device, new Date(), new Date(), StopReportItem.class);
assertNotNull(stops);
assertFalse(stops.isEmpty());