diff options
Diffstat (limited to 'src/org')
-rw-r--r-- | src/org/traccar/api/resource/ReportResource.java | 27 | ||||
-rw-r--r-- | src/org/traccar/model/Position.java | 1 | ||||
-rw-r--r-- | src/org/traccar/protocol/OwnTracksProtocolDecoder.java | 27 | ||||
-rw-r--r-- | src/org/traccar/protocol/WatchProtocolDecoder.java | 4 | ||||
-rw-r--r-- | src/org/traccar/reports/ReportUtils.java | 200 | ||||
-rw-r--r-- | src/org/traccar/reports/Stops.java | 101 | ||||
-rw-r--r-- | src/org/traccar/reports/Trips.java | 136 | ||||
-rw-r--r-- | src/org/traccar/reports/model/BaseReport.java | 10 | ||||
-rw-r--r-- | src/org/traccar/reports/model/StopReport.java | 122 | ||||
-rw-r--r-- | src/org/traccar/reports/model/SummaryReport.java | 15 | ||||
-rw-r--r-- | src/org/traccar/reports/model/TripReport.java | 11 | ||||
-rw-r--r-- | src/org/traccar/reports/model/TripsConfig.java | 83 |
12 files changed, 575 insertions, 162 deletions
diff --git a/src/org/traccar/api/resource/ReportResource.java b/src/org/traccar/api/resource/ReportResource.java index a0f686e80..7c472e84d 100644 --- a/src/org/traccar/api/resource/ReportResource.java +++ b/src/org/traccar/api/resource/ReportResource.java @@ -22,9 +22,11 @@ import org.traccar.model.Position; import org.traccar.reports.Events; import org.traccar.reports.Summary; import org.traccar.reports.Trips; +import org.traccar.reports.model.StopReport; import org.traccar.reports.model.SummaryReport; import org.traccar.reports.model.TripReport; import org.traccar.reports.Route; +import org.traccar.reports.Stops; @Path("reports") @Produces(MediaType.APPLICATION_JSON) @@ -129,4 +131,29 @@ public class ReportResource extends BaseResource { .header(HttpHeaders.CONTENT_DISPOSITION, CONTENT_DISPOSITION_VALUE_XLSX).build(); } + @Path("stops") + @GET + @Produces(MediaType.APPLICATION_JSON) + public Collection<StopReport> getStops( + @QueryParam("deviceId") final List<Long> deviceIds, @QueryParam("groupId") final List<Long> groupIds, + @QueryParam("from") String from, @QueryParam("to") String to) throws SQLException { + return Stops.getObjects(getUserId(), deviceIds, groupIds, + DateUtil.parseDate(from), DateUtil.parseDate(to)); + } + + @Path("stops") + @GET + @Produces(XLSX) + public Response getStopsExcel( + @QueryParam("deviceId") final List<Long> deviceIds, @QueryParam("groupId") final List<Long> groupIds, + @QueryParam("from") String from, @QueryParam("to") String to) throws SQLException, IOException { + ByteArrayOutputStream stream = new ByteArrayOutputStream(); + Stops.getExcel(stream, getUserId(), deviceIds, groupIds, + DateUtil.parseDate(from), DateUtil.parseDate(to)); + + return Response.ok(stream.toByteArray()) + .header(HttpHeaders.CONTENT_DISPOSITION, CONTENT_DISPOSITION_VALUE_XLSX).build(); + } + + } diff --git a/src/org/traccar/model/Position.java b/src/org/traccar/model/Position.java index c6420c17b..bf2518c3c 100644 --- a/src/org/traccar/model/Position.java +++ b/src/org/traccar/model/Position.java @@ -119,6 +119,7 @@ public class Position extends Message { public static final String ALARM_FOOT_BRAKE = "footBrake"; public static final String ALARM_OIL_LEAK = "oilLeak"; public static final String ALARM_TAMPERING = "tampering"; + public static final String ALARM_REMOVING = "removing"; private String protocol; diff --git a/src/org/traccar/protocol/OwnTracksProtocolDecoder.java b/src/org/traccar/protocol/OwnTracksProtocolDecoder.java index a5a9efbb4..ea604f4ac 100644 --- a/src/org/traccar/protocol/OwnTracksProtocolDecoder.java +++ b/src/org/traccar/protocol/OwnTracksProtocolDecoder.java @@ -1,6 +1,6 @@ /* * Copyright 2017 Jan-Piet Mens (jpmens@gmail.com) - * Copyright 2013 - 2017 Anton Tananaev (anton@traccar.org) + * Copyright 2017 Anton Tananaev (anton@traccar.org) * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -58,6 +58,11 @@ public class OwnTracksProtocolDecoder extends BaseProtocolDecoder { JsonObject root = Json.createReader( new StringReader(request.getContent().toString(StandardCharsets.US_ASCII))).readObject(); + if (!root.containsKey("_type") || !root.getString("_type").equals("location")) { + sendResponse(channel, HttpResponseStatus.BAD_REQUEST); + return null; + } + Position position = new Position(); position.setProtocol(getProtocolName()); position.setValid(true); @@ -83,17 +88,21 @@ public class OwnTracksProtocolDecoder extends BaseProtocolDecoder { if (root.containsKey("batt")) { position.set(Position.KEY_BATTERY, root.getInt("batt")); } - if (root.containsKey("topic")) { - position.set("topic", root.getString("topic")); - } - long timestamp = root.getJsonNumber("tst").longValue(); - if (timestamp < Integer.MAX_VALUE) { - timestamp *= 1000; + position.setTime(new Date(root.getJsonNumber("tst").longValue() * 1000)); + + String uniqueId; + + if (root.containsKey("topic")) { + uniqueId = root.getString("topic"); + if (root.containsKey("tid")) { + position.set("tid", root.getString("tid")); + } + } else { + uniqueId = root.getString("tid"); } - position.setTime(new Date(timestamp)); - DeviceSession deviceSession = getDeviceSession(channel, remoteAddress, root.getString("tid")); + DeviceSession deviceSession = getDeviceSession(channel, remoteAddress, uniqueId); if (deviceSession == null) { sendResponse(channel, HttpResponseStatus.BAD_REQUEST); return null; diff --git a/src/org/traccar/protocol/WatchProtocolDecoder.java b/src/org/traccar/protocol/WatchProtocolDecoder.java index 7af856a9c..d55c307da 100644 --- a/src/org/traccar/protocol/WatchProtocolDecoder.java +++ b/src/org/traccar/protocol/WatchProtocolDecoder.java @@ -76,6 +76,8 @@ public class WatchProtocolDecoder extends BaseProtocolDecoder { return Position.ALARM_GEOFENCE_ENTER; } else if (BitUtil.check(status, 3)) { return Position.ALARM_OVERSPEED; + } else if (BitUtil.check(status, 4)) { + return Position.ALARM_MOVEMENT; } else if (BitUtil.check(status, 16)) { return Position.ALARM_SOS; } else if (BitUtil.check(status, 17)) { @@ -84,6 +86,8 @@ public class WatchProtocolDecoder extends BaseProtocolDecoder { return Position.ALARM_GEOFENCE_EXIT; } else if (BitUtil.check(status, 19)) { return Position.ALARM_GEOFENCE_ENTER; + } else if (BitUtil.check(status, 20)) { + return Position.ALARM_REMOVING; } return null; } diff --git a/src/org/traccar/reports/ReportUtils.java b/src/org/traccar/reports/ReportUtils.java index 84d3b3a77..1e004beae 100644 --- a/src/org/traccar/reports/ReportUtils.java +++ b/src/org/traccar/reports/ReportUtils.java @@ -1,6 +1,6 @@ /* - * Copyright 2016 Anton Tananaev (anton@traccar.org) - * Copyright 2016 Andrey Kunitsyn (andrey@traccar.org) + * Copyright 2016 - 2017 Anton Tananaev (anton@traccar.org) + * Copyright 2016 - 2017 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. @@ -27,6 +27,10 @@ import org.jxls.transform.poi.PoiTransformer; import org.jxls.util.TransformerFactory; import org.traccar.Context; import org.traccar.model.Position; +import org.traccar.reports.model.BaseReport; +import org.traccar.reports.model.StopReport; +import org.traccar.reports.model.TripReport; +import org.traccar.reports.model.TripsConfig; import java.io.IOException; import java.io.InputStream; @@ -123,4 +127,196 @@ public final class ReportUtils { transformer.write(); } + public static TripsConfig initTripsConfig() { + return new TripsConfig( + Context.getConfig().getLong("report.trip.minimalTripDuration", 300) * 1000, + Context.getConfig().getLong("report.trip.minimalTripDistance", 500), + Context.getConfig().getLong("report.trip.minimalParkingDuration", 300) * 1000, + Context.getConfig().getBoolean("report.trip.greedyParking"), + Context.getConfig().getLong("report.trip.minimalNoDataDuration", 3600) * 1000); + } + + private static TripReport calculateTrip( + ArrayList<Position> positions, int startIndex, int endIndex, boolean ignoreOdometer) { + Position startTrip = positions.get(startIndex); + Position endTrip = positions.get(endIndex); + + double speedMax = 0.0; + double speedSum = 0.0; + for (int i = startIndex; i <= endIndex; i++) { + double speed = positions.get(i).getSpeed(); + speedSum += speed; + if (speed > speedMax) { + speedMax = speed; + } + } + + TripReport trip = new TripReport(); + + long tripDuration = endTrip.getFixTime().getTime() - startTrip.getFixTime().getTime(); + long deviceId = startTrip.getDeviceId(); + trip.setDeviceId(deviceId); + trip.setDeviceName(Context.getIdentityManager().getDeviceById(deviceId).getName()); + + trip.setStartPositionId(startTrip.getId()); + trip.setStartLat(startTrip.getLatitude()); + trip.setStartLon(startTrip.getLongitude()); + trip.setStartTime(startTrip.getFixTime()); + trip.setStartAddress(startTrip.getAddress()); + + trip.setEndPositionId(endTrip.getId()); + trip.setEndLat(endTrip.getLatitude()); + trip.setEndLon(endTrip.getLongitude()); + trip.setEndTime(endTrip.getFixTime()); + trip.setEndAddress(endTrip.getAddress()); + + trip.setDistance(calculateDistance(startTrip, endTrip, !ignoreOdometer)); + trip.setDuration(tripDuration); + trip.setAverageSpeed(speedSum / (endIndex - startIndex)); + trip.setMaxSpeed(speedMax); + trip.setSpentFuel(calculateFuel(startTrip, endTrip)); + + return trip; + } + + private static StopReport calculateStop(ArrayList<Position> positions, int startIndex, int endIndex) { + Position startStop = positions.get(startIndex); + Position endStop = positions.get(endIndex); + + StopReport stop = new StopReport(); + + long deviceId = startStop.getDeviceId(); + stop.setDeviceId(deviceId); + stop.setDeviceName(Context.getIdentityManager().getDeviceById(deviceId).getName()); + + stop.setPositionId(startStop.getId()); + stop.setLatitude(startStop.getLatitude()); + stop.setLongitude(startStop.getLongitude()); + stop.setStartTime(startStop.getFixTime()); + stop.setAddress(startStop.getAddress()); + stop.setEndTime(endStop.getFixTime()); + + long stopDuration = endStop.getFixTime().getTime() - startStop.getFixTime().getTime(); + stop.setDuration(stopDuration); + stop.setSpentFuel(calculateFuel(startStop, endStop)); + + long engineHours = 0; + for (int i = startIndex + 1; i <= endIndex; i++) { + if (positions.get(i).getBoolean(Position.KEY_IGNITION) + && positions.get(i - 1).getBoolean(Position.KEY_IGNITION)) { + engineHours += positions.get(i).getFixTime().getTime() - positions.get(i - 1).getFixTime().getTime(); + } + } + stop.setEngineHours(engineHours); + + return stop; + + } + + private static boolean isMoving(ArrayList<Position> positions, int index, + TripsConfig tripsConfig, double speedThreshold) { + if (tripsConfig.getMinimalNoDataDuration() > 0 && index < positions.size() - 1 + && positions.get(index + 1).getFixTime().getTime() - positions.get(index).getFixTime().getTime() + >= tripsConfig.getMinimalNoDataDuration()) { + return false; + } + return positions.get(index).getSpeed() > speedThreshold; + } + + public static Collection<BaseReport> detectTripsAndStops(TripsConfig tripsConfig, boolean ignoreOdometer, + double speedThreshold, Collection<Position> positionCollection, boolean trips) { + + Collection<BaseReport> result = new ArrayList<>(); + + ArrayList<Position> positions = new ArrayList<>(positionCollection); + if (positions != null && !positions.isEmpty()) { + int previousStartParkingIndex = 0; + int startParkingIndex = -1; + int previousEndParkingIndex = 0; + int endParkingIndex = 0; + + boolean isMoving = false; + boolean isLast = false; + boolean skipped = false; + boolean tripFiltered = false; + + for (int i = 0; i < positions.size(); i++) { + isMoving = isMoving(positions, i, tripsConfig, speedThreshold); + isLast = i == positions.size() - 1; + + if ((isMoving || isLast) && startParkingIndex != -1) { + if (!skipped || previousEndParkingIndex == 0) { + previousEndParkingIndex = endParkingIndex; + } + endParkingIndex = i; + } + if (!isMoving && startParkingIndex == -1) { + if (tripsConfig.getGreedyParking()) { + long tripDuration = positions.get(i).getFixTime().getTime() + - positions.get(endParkingIndex).getFixTime().getTime(); + double tripDistance = ReportUtils.calculateDistance(positions.get(endParkingIndex), + positions.get(i), false); + tripFiltered = tripDuration < tripsConfig.getMinimalTripDuration() + && tripDistance < tripsConfig.getMinimalTripDistance(); + if (tripFiltered) { + startParkingIndex = previousStartParkingIndex; + endParkingIndex = previousEndParkingIndex; + tripFiltered = false; + } else { + previousStartParkingIndex = i; + startParkingIndex = i; + } + } else { + long tripDuration = positions.get(i).getFixTime().getTime() + - positions.get(previousEndParkingIndex).getFixTime().getTime(); + double tripDistance = ReportUtils.calculateDistance(positions.get(previousEndParkingIndex), + positions.get(i), false); + tripFiltered = tripDuration < tripsConfig.getMinimalTripDuration() + && tripDistance < tripsConfig.getMinimalTripDistance(); + startParkingIndex = i; + } + } + if (startParkingIndex != -1 && (endParkingIndex > startParkingIndex || isLast)) { + long parkingDuration = positions.get(endParkingIndex).getFixTime().getTime() + - positions.get(startParkingIndex).getFixTime().getTime(); + if ((parkingDuration >= tripsConfig.getMinimalParkingDuration() || isLast) + && previousEndParkingIndex < startParkingIndex) { + if (!tripFiltered) { + if (trips) { + result.add(calculateTrip( + positions, previousEndParkingIndex, startParkingIndex, ignoreOdometer)); + } else { + if (result.isEmpty() && previousEndParkingIndex > previousStartParkingIndex) { + long previousParkingDuration = positions.get(previousEndParkingIndex) + .getFixTime().getTime() - positions.get(previousStartParkingIndex) + .getFixTime().getTime(); + if (previousParkingDuration >= tripsConfig.getMinimalParkingDuration()) { + result.add(calculateStop(positions, previousStartParkingIndex, + previousEndParkingIndex)); + } + } + result.add(calculateStop(positions, startParkingIndex, endParkingIndex)); + } + } + previousEndParkingIndex = endParkingIndex; + skipped = false; + } else { + skipped = true; + } + startParkingIndex = -1; + } + } + if (result.isEmpty() && !trips) { + int end = isMoving && !tripsConfig.getGreedyParking() + ? Math.max(endParkingIndex, previousEndParkingIndex) : positions.size() - 1; + long parkingDuration = positions.get(end).getFixTime().getTime() + - positions.get(previousStartParkingIndex).getFixTime().getTime(); + if (parkingDuration >= tripsConfig.getMinimalParkingDuration()) { + result.add(calculateStop(positions, previousStartParkingIndex, end)); + } + } + } + + return result; + } } diff --git a/src/org/traccar/reports/Stops.java b/src/org/traccar/reports/Stops.java new file mode 100644 index 000000000..64e589be1 --- /dev/null +++ b/src/org/traccar/reports/Stops.java @@ -0,0 +1,101 @@ +/* + * Copyright 2017 Anton Tananaev (anton@traccar.org) + * Copyright 2017 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. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package org.traccar.reports; + +import java.io.FileInputStream; +import java.io.IOException; +import java.io.InputStream; +import java.io.OutputStream; +import java.sql.SQLException; +import java.util.ArrayList; +import java.util.Collection; +import java.util.Date; + +import org.apache.poi.ss.util.WorkbookUtil; +import org.traccar.Context; +import org.traccar.model.Device; +import org.traccar.model.Group; +import org.traccar.reports.model.BaseReport; +import org.traccar.reports.model.DeviceReport; +import org.traccar.reports.model.StopReport; +import org.traccar.reports.model.TripsConfig; + +public final class Stops { + + private Stops() { + } + + private static Collection<StopReport> detectStops(long deviceId, Date from, Date to) throws SQLException { + double speedThreshold = Context.getConfig().getDouble("event.motion.speedThreshold", 0.01); + + TripsConfig tripsConfig = ReportUtils.initTripsConfig(); + + boolean ignoreOdometer = Context.getDeviceManager() + .lookupAttributeBoolean(deviceId, "report.ignoreOdometer", false, true); + + Collection<? extends BaseReport> result = ReportUtils.detectTripsAndStops(tripsConfig, + ignoreOdometer, speedThreshold, + Context.getDataManager().getPositions(deviceId, from, to), false); + + return (Collection<StopReport>) result; + } + + public static Collection<StopReport> getObjects(long userId, Collection<Long> deviceIds, Collection<Long> groupIds, + Date from, Date to) throws SQLException { + ArrayList<StopReport> result = new ArrayList<>(); + for (long deviceId: ReportUtils.getDeviceList(deviceIds, groupIds)) { + Context.getPermissionsManager().checkDevice(userId, deviceId); + result.addAll(detectStops(deviceId, from, to)); + } + return result; + } + + public static void getExcel(OutputStream outputStream, + long userId, Collection<Long> deviceIds, Collection<Long> groupIds, + Date from, Date to) throws SQLException, IOException { + ArrayList<DeviceReport> devicesStops = new ArrayList<>(); + ArrayList<String> sheetNames = new ArrayList<>(); + for (long deviceId: ReportUtils.getDeviceList(deviceIds, groupIds)) { + Context.getPermissionsManager().checkDevice(userId, deviceId); + Collection<StopReport> stops = detectStops(deviceId, from, to); + DeviceReport deviceStops = new DeviceReport(); + Device device = Context.getIdentityManager().getDeviceById(deviceId); + deviceStops.setDeviceName(device.getName()); + sheetNames.add(WorkbookUtil.createSafeSheetName(deviceStops.getDeviceName())); + if (device.getGroupId() != 0) { + Group group = Context.getDeviceManager().getGroupById(device.getGroupId()); + if (group != null) { + deviceStops.setGroupName(group.getName()); + } + } + deviceStops.setObjects(stops); + devicesStops.add(deviceStops); + } + String templatePath = Context.getConfig().getString("report.templatesPath", + "templates/export/"); + try (InputStream inputStream = new FileInputStream(templatePath + "/stops.xlsx")) { + org.jxls.common.Context jxlsContext = ReportUtils.initializeContext(userId); + jxlsContext.putVar("devices", devicesStops); + jxlsContext.putVar("sheetNames", sheetNames); + jxlsContext.putVar("from", from); + jxlsContext.putVar("to", to); + ReportUtils.processTemplateWithSheets(inputStream, outputStream, jxlsContext); + } + } + +} diff --git a/src/org/traccar/reports/Trips.java b/src/org/traccar/reports/Trips.java index 966c3a817..5c26bea54 100644 --- a/src/org/traccar/reports/Trips.java +++ b/src/org/traccar/reports/Trips.java @@ -29,147 +29,29 @@ import org.apache.poi.ss.util.WorkbookUtil; import org.traccar.Context; import org.traccar.model.Device; import org.traccar.model.Group; -import org.traccar.model.Position; +import org.traccar.reports.model.BaseReport; import org.traccar.reports.model.DeviceReport; import org.traccar.reports.model.TripReport; +import org.traccar.reports.model.TripsConfig; public final class Trips { private Trips() { } - private static TripReport calculateTrip( - ArrayList<Position> positions, int startIndex, int endIndex, boolean ignoreOdometer) { - Position startTrip = positions.get(startIndex); - Position endTrip = positions.get(endIndex); - - double speedMax = 0.0; - double speedSum = 0.0; - for (int i = startIndex; i <= endIndex; i++) { - double speed = positions.get(i).getSpeed(); - speedSum += speed; - if (speed > speedMax) { - speedMax = speed; - } - } - - TripReport trip = new TripReport(); - - long tripDuration = endTrip.getFixTime().getTime() - startTrip.getFixTime().getTime(); - long deviceId = startTrip.getDeviceId(); - trip.setDeviceId(deviceId); - trip.setDeviceName(Context.getIdentityManager().getDeviceById(deviceId).getName()); - - trip.setStartPositionId(startTrip.getId()); - trip.setStartLat(startTrip.getLatitude()); - trip.setStartLon(startTrip.getLongitude()); - trip.setStartTime(startTrip.getFixTime()); - trip.setStartAddress(startTrip.getAddress()); - - trip.setEndPositionId(endTrip.getId()); - trip.setEndLat(endTrip.getLatitude()); - trip.setEndLon(endTrip.getLongitude()); - trip.setEndTime(endTrip.getFixTime()); - trip.setEndAddress(endTrip.getAddress()); - - trip.setDistance(ReportUtils.calculateDistance(startTrip, endTrip, !ignoreOdometer)); - trip.setDuration(tripDuration); - trip.setAverageSpeed(speedSum / (endIndex - startIndex)); - trip.setMaxSpeed(speedMax); - trip.setSpentFuel(ReportUtils.calculateFuel(startTrip, endTrip)); - - return trip; - } - - protected static Collection<TripReport> detectTrips( - double speedThreshold, double minimalTripDistance, - long minimalTripDuration, long minimalParkingDuration, boolean greedyParking, boolean ignoreOdometer, - Collection<Position> positionCollection) { - - Collection<TripReport> result = new ArrayList<>(); - - ArrayList<Position> positions = new ArrayList<>(positionCollection); - if (positions != null && !positions.isEmpty()) { - int previousStartParkingIndex = 0; - int startParkingIndex = -1; - int previousEndParkingIndex = 0; - int endParkingIndex = 0; - - boolean isMoving = false; - boolean isLast = false; - boolean skipped = false; - boolean tripFiltered = false; - - for (int i = 0; i < positions.size(); i++) { - isMoving = positions.get(i).getSpeed() > speedThreshold; - isLast = i == positions.size() - 1; - - if ((isMoving || isLast) && startParkingIndex != -1) { - if (!skipped || previousEndParkingIndex == 0) { - previousEndParkingIndex = endParkingIndex; - } - endParkingIndex = i; - } - if (!isMoving && startParkingIndex == -1) { - if (greedyParking) { - long tripDuration = positions.get(i).getFixTime().getTime() - - positions.get(endParkingIndex).getFixTime().getTime(); - double tripDistance = ReportUtils.calculateDistance(positions.get(endParkingIndex), - positions.get(i), false); - tripFiltered = tripDuration < minimalTripDuration && tripDistance < minimalTripDistance; - if (tripFiltered) { - startParkingIndex = previousStartParkingIndex; - endParkingIndex = previousEndParkingIndex; - tripFiltered = false; - } else { - previousStartParkingIndex = i; - startParkingIndex = i; - } - } else { - long tripDuration = positions.get(i).getFixTime().getTime() - - positions.get(previousEndParkingIndex).getFixTime().getTime(); - double tripDistance = ReportUtils.calculateDistance(positions.get(previousEndParkingIndex), - positions.get(i), false); - tripFiltered = tripDuration < minimalTripDuration && tripDistance < minimalTripDistance; - startParkingIndex = i; - } - } - if (startParkingIndex != -1 && (endParkingIndex > startParkingIndex || isLast)) { - long parkingDuration = positions.get(endParkingIndex).getFixTime().getTime() - - positions.get(startParkingIndex).getFixTime().getTime(); - if ((parkingDuration >= minimalParkingDuration || isLast) - && previousEndParkingIndex < startParkingIndex) { - if (!tripFiltered) { - result.add(calculateTrip( - positions, previousEndParkingIndex, startParkingIndex, ignoreOdometer)); - } - previousEndParkingIndex = endParkingIndex; - skipped = false; - } else { - skipped = true; - } - startParkingIndex = -1; - } - } - } - - return result; - } - private static Collection<TripReport> detectTrips(long deviceId, Date from, Date to) throws SQLException { double speedThreshold = Context.getConfig().getDouble("event.motion.speedThreshold", 0.01); - long minimalTripDuration = Context.getConfig().getLong("report.trip.minimalTripDuration", 300) * 1000; - double minimalTripDistance = Context.getConfig().getLong("report.trip.minimalTripDistance", 500); - long minimalParkingDuration = Context.getConfig().getLong("report.trip.minimalParkingDuration", 300) * 1000; - boolean greedyParking = Context.getConfig().getBoolean("report.trip.greedyParking"); + + TripsConfig tripsConfig = ReportUtils.initTripsConfig(); boolean ignoreOdometer = Context.getDeviceManager() .lookupAttributeBoolean(deviceId, "report.ignoreOdometer", false, true); - return detectTrips( - speedThreshold, minimalTripDistance, minimalTripDuration, - minimalParkingDuration, greedyParking, ignoreOdometer, - Context.getDataManager().getPositions(deviceId, from, to)); + Collection<? extends BaseReport> result = ReportUtils.detectTripsAndStops(tripsConfig, + ignoreOdometer, speedThreshold, + Context.getDataManager().getPositions(deviceId, from, to), true); + + return (Collection<TripReport>) result; } public static Collection<TripReport> getObjects(long userId, Collection<Long> deviceIds, Collection<Long> groupIds, diff --git a/src/org/traccar/reports/model/BaseReport.java b/src/org/traccar/reports/model/BaseReport.java index 13c67cbb7..e1dec1407 100644 --- a/src/org/traccar/reports/model/BaseReport.java +++ b/src/org/traccar/reports/model/BaseReport.java @@ -74,4 +74,14 @@ public class BaseReport { } } + private String spentFuel; + + public String getSpentFuel() { + return spentFuel; + } + + public void setSpentFuel(String spentFuel) { + this.spentFuel = spentFuel; + } + } diff --git a/src/org/traccar/reports/model/StopReport.java b/src/org/traccar/reports/model/StopReport.java new file mode 100644 index 000000000..6b2e86299 --- /dev/null +++ b/src/org/traccar/reports/model/StopReport.java @@ -0,0 +1,122 @@ +/* + * Copyright 2017 Anton Tananaev (anton@traccar.org) + * Copyright 2017 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. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package org.traccar.reports.model; + +import java.util.Date; + +public class StopReport extends BaseReport { + + private long positionId; + + public long getPositionId() { + return positionId; + } + + public void setPositionId(long positionId) { + this.positionId = positionId; + } + + private double latitude; + + public double getLatitude() { + return latitude; + } + + public void setLatitude(double latitude) { + this.latitude = latitude; + } + + private double longitude; + + public double getLongitude() { + return longitude; + } + + public void setLongitude(double longitude) { + this.longitude = longitude; + } + + private Date startTime; + + public Date getStartTime() { + if (startTime != null) { + return new Date(startTime.getTime()); + } else { + return null; + } + } + + public void setStartTime(Date startTime) { + if (startTime != null) { + this.startTime = new Date(startTime.getTime()); + } else { + this.startTime = null; + } + } + + private Date endTime; + + public Date getEndTime() { + if (endTime != null) { + return new Date(endTime.getTime()); + } else { + return null; + } + } + + public void setEndTime(Date endTime) { + if (endTime != null) { + this.endTime = new Date(endTime.getTime()); + } else { + this.endTime = null; + } + } + + private String address; + + public String getAddress() { + return address; + } + + public void setAddress(String address) { + this.address = address; + } + + private long duration; + + public long getDuration() { + return duration; + } + + public void setDuration(long duration) { + this.duration = duration; + } + + private long engineHours; // milliseconds + + public long getEngineHours() { + return engineHours; + } + + public void setEngineHours(long engineHours) { + this.engineHours = engineHours; + } + + public void addEngineHours(long engineHours) { + this.engineHours += engineHours; + } +} diff --git a/src/org/traccar/reports/model/SummaryReport.java b/src/org/traccar/reports/model/SummaryReport.java index 85ba6bc54..6f9e9459f 100644 --- a/src/org/traccar/reports/model/SummaryReport.java +++ b/src/org/traccar/reports/model/SummaryReport.java @@ -1,6 +1,6 @@ /* - * Copyright 2016 Anton Tananaev (anton@traccar.org) - * Copyright 2016 Andrey Kunitsyn (andrey@traccar.org) + * Copyright 2016 - 2017 Anton Tananaev (anton@traccar.org) + * Copyright 2016 - 2017 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. @@ -31,15 +31,4 @@ public class SummaryReport extends BaseReport { public void addEngineHours(long engineHours) { this.engineHours += engineHours; } - - private String spentFuel; - - public String getSpentFuel() { - return spentFuel; - } - - public void setSpentFuel(String spentFuel) { - this.spentFuel = spentFuel; - } - } diff --git a/src/org/traccar/reports/model/TripReport.java b/src/org/traccar/reports/model/TripReport.java index fce805ad6..efe556f79 100644 --- a/src/org/traccar/reports/model/TripReport.java +++ b/src/org/traccar/reports/model/TripReport.java @@ -145,15 +145,4 @@ public class TripReport extends BaseReport { public void setDuration(long duration) { this.duration = duration; } - - private String spentFuel; - - public String getSpentFuel() { - return spentFuel; - } - - public void setSpentFuel(String spentFuel) { - this.spentFuel = spentFuel; - } - } diff --git a/src/org/traccar/reports/model/TripsConfig.java b/src/org/traccar/reports/model/TripsConfig.java new file mode 100644 index 000000000..7067781d7 --- /dev/null +++ b/src/org/traccar/reports/model/TripsConfig.java @@ -0,0 +1,83 @@ +/* + * Copyright 2017 Anton Tananaev (anton@traccar.org) + * Copyright 2017 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. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package org.traccar.reports.model; + +public class TripsConfig { + + public TripsConfig() { + } + + public TripsConfig(double minimalTripDistance, long minimalTripDuration, + long minimalParkingDuration, boolean greedyParking, long minimalNoDataDuration) { + this.minimalTripDistance = minimalTripDistance; + this.minimalTripDuration = minimalTripDuration; + this.minimalParkingDuration = minimalParkingDuration; + this.greedyParking = greedyParking; + this.minimalNoDataDuration = minimalNoDataDuration; + } + + private double minimalTripDistance; + + public double getMinimalTripDistance() { + return minimalTripDistance; + } + + public void setMinimalTripDistance(double minimalTripDistance) { + this.minimalTripDistance = minimalTripDistance; + } + + private long minimalTripDuration; + + public long getMinimalTripDuration() { + return minimalTripDuration; + } + + public void setMinimalTripDuration(long minimalTripDuration) { + this.minimalTripDuration = minimalTripDuration; + } + + private long minimalParkingDuration; + + public long getMinimalParkingDuration() { + return minimalParkingDuration; + } + + public void setMinimalParkingDuration(long minimalParkingDuration) { + this.minimalParkingDuration = minimalParkingDuration; + } + + private boolean greedyParking; + + public boolean getGreedyParking() { + return greedyParking; + } + + public void setGreedyParking(boolean greedyParking) { + this.greedyParking = greedyParking; + } + + private long minimalNoDataDuration; + + public long getMinimalNoDataDuration() { + return minimalNoDataDuration; + } + + public void setMinimalNoDataDuration(long minimalNoDataDuration) { + this.minimalNoDataDuration = minimalNoDataDuration; + } + +} |