diff options
author | Renaud Allard <renaud@allard.it> | 2016-10-20 08:31:57 +0200 |
---|---|---|
committer | Renaud Allard <renaud@allard.it> | 2016-10-20 08:31:57 +0200 |
commit | 1104c2738e19579c5865db5c030388e1e320f0b4 (patch) | |
tree | a6571455b6f5d88581c8034bd1059968d506ed01 /src | |
parent | 0d347cd7aac2ebfad01c1635f3893964be2e67ae (diff) | |
parent | 4f7356cc1c6962f46ca522246d5b63dc06a2d268 (diff) | |
download | traccar-server-1104c2738e19579c5865db5c030388e1e320f0b4.tar.gz traccar-server-1104c2738e19579c5865db5c030388e1e320f0b4.tar.bz2 traccar-server-1104c2738e19579c5865db5c030388e1e320f0b4.zip |
Merge branch 'master' of https://github.com/tananaev/traccar
Diffstat (limited to 'src')
-rw-r--r-- | src/org/traccar/api/resource/EventResource.java | 13 | ||||
-rw-r--r-- | src/org/traccar/api/resource/PositionResource.java | 24 | ||||
-rw-r--r-- | src/org/traccar/api/resource/ReportResource.java | 70 | ||||
-rw-r--r-- | src/org/traccar/database/DataManager.java | 11 | ||||
-rw-r--r-- | src/org/traccar/model/Event.java | 2 | ||||
-rw-r--r-- | src/org/traccar/model/User.java | 5 | ||||
-rw-r--r-- | src/org/traccar/protocol/H02FrameDecoder.java | 16 | ||||
-rw-r--r-- | src/org/traccar/protocol/H02Protocol.java | 2 | ||||
-rw-r--r-- | src/org/traccar/protocol/RuptelaProtocolDecoder.java | 32 | ||||
-rw-r--r-- | src/org/traccar/reports/Events.java | 95 | ||||
-rw-r--r-- | src/org/traccar/reports/Route.java | 60 | ||||
-rw-r--r-- | src/org/traccar/reports/Summary.java | 29 | ||||
-rw-r--r-- | src/org/traccar/reports/Trips.java | 66 | ||||
-rw-r--r-- | src/org/traccar/reports/model/DeviceReport.java | 49 | ||||
-rw-r--r-- | src/org/traccar/reports/model/TripReport.java | 48 |
15 files changed, 420 insertions, 102 deletions
diff --git a/src/org/traccar/api/resource/EventResource.java b/src/org/traccar/api/resource/EventResource.java index 74a748ea5..c0a8f968d 100644 --- a/src/org/traccar/api/resource/EventResource.java +++ b/src/org/traccar/api/resource/EventResource.java @@ -1,14 +1,12 @@ package org.traccar.api.resource; import java.sql.SQLException; -import java.util.Collection; import javax.ws.rs.Consumes; import javax.ws.rs.GET; import javax.ws.rs.Path; import javax.ws.rs.PathParam; import javax.ws.rs.Produces; -import javax.ws.rs.QueryParam; import javax.ws.rs.core.MediaType; import org.traccar.Context; @@ -26,14 +24,9 @@ public class EventResource extends BaseResource { public Event get(@PathParam("id") long id) throws SQLException { Event event = Context.getDataManager().getEvent(id); Context.getPermissionsManager().checkDevice(getUserId(), event.getDeviceId()); + if (event.getGeofenceId() != 0) { + Context.getPermissionsManager().checkGeofence(getUserId(), event.getGeofenceId()); + } return event; } - - @GET - public Collection<Event> get( - @QueryParam("deviceId") long deviceId, @QueryParam("type") String type, - @QueryParam("interval") int interval) throws SQLException { - Context.getPermissionsManager().checkDevice(getUserId(), deviceId); - return Context.getDataManager().getLastEvents(deviceId, type, interval); - } } diff --git a/src/org/traccar/api/resource/PositionResource.java b/src/org/traccar/api/resource/PositionResource.java index e00e06e7a..92b62c0a6 100644 --- a/src/org/traccar/api/resource/PositionResource.java +++ b/src/org/traccar/api/resource/PositionResource.java @@ -18,6 +18,7 @@ package org.traccar.api.resource; import org.traccar.Context; import org.traccar.api.BaseResource; import org.traccar.model.Position; +import org.traccar.web.CsvBuilder; import org.traccar.web.JsonConverter; import javax.ws.rs.Consumes; @@ -25,17 +26,23 @@ import javax.ws.rs.GET; import javax.ws.rs.Path; import javax.ws.rs.Produces; import javax.ws.rs.QueryParam; +import javax.ws.rs.core.HttpHeaders; import javax.ws.rs.core.MediaType; +import javax.ws.rs.core.Response; + import java.sql.SQLException; import java.util.Collection; @Path("positions") -@Produces(MediaType.APPLICATION_JSON) @Consumes(MediaType.APPLICATION_JSON) public class PositionResource extends BaseResource { + public static final String TEXT_CSV = "text/csv"; + public static final String CONTENT_DISPOSITION_VALUE_CSV = "attachment; filename=positions.csv"; + @GET - public Collection<Position> get( + @Produces(MediaType.APPLICATION_JSON) + public Collection<Position> getJson( @QueryParam("deviceId") long deviceId, @QueryParam("from") String from, @QueryParam("to") String to) throws SQLException { if (deviceId == 0) { @@ -47,4 +54,17 @@ public class PositionResource extends BaseResource { } } + @GET + @Produces(TEXT_CSV) + public Response getCsv( + @QueryParam("deviceId") long deviceId, @QueryParam("from") String from, @QueryParam("to") String to) + throws SQLException { + Context.getPermissionsManager().checkDevice(getUserId(), deviceId); + CsvBuilder csv = new CsvBuilder(); + csv.addHeaderLine(new Position()); + csv.addArray(Context.getDataManager().getPositions( + deviceId, JsonConverter.parseDate(from), JsonConverter.parseDate(to))); + return Response.ok(csv.build()).header(HttpHeaders.CONTENT_DISPOSITION, CONTENT_DISPOSITION_VALUE_CSV).build(); + } + } diff --git a/src/org/traccar/api/resource/ReportResource.java b/src/org/traccar/api/resource/ReportResource.java index 0dd0452ff..709eef377 100644 --- a/src/org/traccar/api/resource/ReportResource.java +++ b/src/org/traccar/api/resource/ReportResource.java @@ -1,5 +1,7 @@ package org.traccar.api.resource; +import java.io.ByteArrayOutputStream; +import java.io.IOException; import java.sql.SQLException; import java.util.List; @@ -23,8 +25,8 @@ import org.traccar.web.JsonConverter; @Consumes(MediaType.APPLICATION_JSON) public class ReportResource extends BaseResource { - public static final String TEXT_CSV = "text/csv"; - public static final String CONTENT_DISPOSITION_VALUE = "attachment; filename=report.csv"; + private static final String XLSX = "application/vnd.openxmlformats-officedocument.spreadsheetml.sheet"; + private static final String CONTENT_DISPOSITION_VALUE_XLSX = "attachment; filename=report.xlsx"; @Path("route") @GET @@ -38,14 +40,16 @@ public class ReportResource extends BaseResource { @Path("route") @GET - @Produces(TEXT_CSV) - public Response getRouteCsv( + @Produces(XLSX) + public Response getRouteExcel( @QueryParam("deviceId") final List<Long> deviceIds, @QueryParam("groupId") final List<Long> groupIds, - @QueryParam("from") String from, @QueryParam("to") String to) throws SQLException { - return Response.ok(Route.getCsv(getUserId(), deviceIds, groupIds, - JsonConverter.parseDate(from), JsonConverter.parseDate(to))) - .header(HttpHeaders.CONTENT_DISPOSITION, CONTENT_DISPOSITION_VALUE) - .build(); + @QueryParam("from") String from, @QueryParam("to") String to) throws SQLException, IOException { + ByteArrayOutputStream stream = new ByteArrayOutputStream(); + Route.getExcel(stream, getUserId(), deviceIds, groupIds, + JsonConverter.parseDate(from), JsonConverter.parseDate(to)); + + return Response.ok(stream.toByteArray()) + .header(HttpHeaders.CONTENT_DISPOSITION, CONTENT_DISPOSITION_VALUE_XLSX).build(); } @Path("events") @@ -61,15 +65,17 @@ public class ReportResource extends BaseResource { @Path("events") @GET - @Produces(TEXT_CSV) - public Response getEventsCsv( + @Produces(XLSX) + public Response getEventsExcel( @QueryParam("deviceId") final List<Long> deviceIds, @QueryParam("groupId") final List<Long> groupIds, @QueryParam("type") final List<String> types, - @QueryParam("from") String from, @QueryParam("to") String to) throws SQLException { - return Response.ok(Events.getCsv(getUserId(), deviceIds, groupIds, - types, JsonConverter.parseDate(from), JsonConverter.parseDate(to))) - .header(HttpHeaders.CONTENT_DISPOSITION, CONTENT_DISPOSITION_VALUE) - .build(); + @QueryParam("from") String from, @QueryParam("to") String to) throws SQLException, IOException { + ByteArrayOutputStream stream = new ByteArrayOutputStream(); + Events.getExcel(stream, getUserId(), deviceIds, groupIds, types, + JsonConverter.parseDate(from), JsonConverter.parseDate(to)); + + return Response.ok(stream.toByteArray()) + .header(HttpHeaders.CONTENT_DISPOSITION, CONTENT_DISPOSITION_VALUE_XLSX).build(); } @Path("summary") @@ -84,14 +90,16 @@ public class ReportResource extends BaseResource { @Path("summary") @GET - @Produces(TEXT_CSV) - public Response getSummaryCsv( + @Produces(XLSX) + public Response getSummaryExcel( @QueryParam("deviceId") final List<Long> deviceIds, @QueryParam("groupId") final List<Long> groupIds, - @QueryParam("from") String from, @QueryParam("to") String to) throws SQLException { - return Response.ok(Summary.getCsv(getUserId(), deviceIds, groupIds, - JsonConverter.parseDate(from), JsonConverter.parseDate(to))) - .header(HttpHeaders.CONTENT_DISPOSITION, CONTENT_DISPOSITION_VALUE) - .build(); + @QueryParam("from") String from, @QueryParam("to") String to) throws SQLException, IOException { + ByteArrayOutputStream stream = new ByteArrayOutputStream(); + Summary.getExcel(stream, getUserId(), deviceIds, groupIds, + JsonConverter.parseDate(from), JsonConverter.parseDate(to)); + + return Response.ok(stream.toByteArray()) + .header(HttpHeaders.CONTENT_DISPOSITION, CONTENT_DISPOSITION_VALUE_XLSX).build(); } @Path("trips") @@ -106,14 +114,16 @@ public class ReportResource extends BaseResource { @Path("trips") @GET - @Produces(TEXT_CSV) - public Response getTripsCsv( + @Produces(XLSX) + public Response getTripsExcel( @QueryParam("deviceId") final List<Long> deviceIds, @QueryParam("groupId") final List<Long> groupIds, - @QueryParam("from") String from, @QueryParam("to") String to) throws SQLException { - return Response.ok(Trips.getCsv(getUserId(), deviceIds, groupIds, - JsonConverter.parseDate(from), JsonConverter.parseDate(to))) - .header(HttpHeaders.CONTENT_DISPOSITION, CONTENT_DISPOSITION_VALUE) - .build(); + @QueryParam("from") String from, @QueryParam("to") String to) throws SQLException, IOException { + ByteArrayOutputStream stream = new ByteArrayOutputStream(); + Trips.getExcel(stream, getUserId(), deviceIds, groupIds, + JsonConverter.parseDate(from), JsonConverter.parseDate(to)); + + return Response.ok(stream.toByteArray()) + .header(HttpHeaders.CONTENT_DISPOSITION, CONTENT_DISPOSITION_VALUE_XLSX).build(); } } diff --git a/src/org/traccar/database/DataManager.java b/src/org/traccar/database/DataManager.java index 58d16d7f5..e98e1429c 100644 --- a/src/org/traccar/database/DataManager.java +++ b/src/org/traccar/database/DataManager.java @@ -20,7 +20,6 @@ import java.lang.reflect.Method; import java.net.URL; import java.net.URLClassLoader; import java.sql.SQLException; -import java.util.Calendar; import java.util.Collection; import java.util.Date; @@ -332,22 +331,14 @@ public class DataManager { .executeUpdate()); } - public Collection<Event> getEvents(long deviceId, String type, Date from, Date to) throws SQLException { + public Collection<Event> getEvents(long deviceId, Date from, Date to) throws SQLException { return QueryBuilder.create(dataSource, getQuery("database.selectEvents")) .setLong("deviceId", deviceId) - .setString("type", type) .setDate("from", from) .setDate("to", to) .executeQuery(Event.class); } - public Collection<Event> getLastEvents(long deviceId, String type, int interval) throws SQLException { - Calendar calendar = Calendar.getInstance(); - calendar.add(Calendar.SECOND, -interval); - Date from = calendar.getTime(); - return getEvents(deviceId, type, from, new Date()); - } - public Collection<Geofence> getGeofences() throws SQLException { return QueryBuilder.create(dataSource, getQuery("database.selectGeofencesAll")) .executeQuery(Geofence.class); diff --git a/src/org/traccar/model/Event.java b/src/org/traccar/model/Event.java index c3c8b5320..5b4b0e089 100644 --- a/src/org/traccar/model/Event.java +++ b/src/org/traccar/model/Event.java @@ -35,6 +35,8 @@ public class Event extends Message { public Event() { } + public static final String ALL_EVENTS = "allEvents"; + public static final String TYPE_COMMAND_RESULT = "commandResult"; public static final String TYPE_DEVICE_ONLINE = "deviceOnline"; diff --git a/src/org/traccar/model/User.java b/src/org/traccar/model/User.java index 59951718e..860c91629 100644 --- a/src/org/traccar/model/User.java +++ b/src/org/traccar/model/User.java @@ -140,14 +140,11 @@ public class User extends Extensible { this.coordinateFormat = coordinateFormat; } - private String password; - public String getPassword() { - return password; + return null; } public void setPassword(String password) { - this.password = password; if (password != null && !password.isEmpty()) { Hashing.HashingResult hashingResult = Hashing.createHash(password); hashedPassword = hashingResult.getHash(); diff --git a/src/org/traccar/protocol/H02FrameDecoder.java b/src/org/traccar/protocol/H02FrameDecoder.java index feba8033d..2a005e760 100644 --- a/src/org/traccar/protocol/H02FrameDecoder.java +++ b/src/org/traccar/protocol/H02FrameDecoder.java @@ -22,6 +22,9 @@ import org.jboss.netty.handler.codec.frame.FrameDecoder; public class H02FrameDecoder extends FrameDecoder { + private static final int MESSAGE_SHORT = 32; + private static final int MESSAGE_LONG = 45; + private int messageLength; public H02FrameDecoder(int messageLength) { @@ -49,10 +52,17 @@ public class H02FrameDecoder extends FrameDecoder { return buf.readBytes(index + 1 - buf.readerIndex()); } - } else if (marker == '$' && buf.readableBytes() >= messageLength) { + } else if (marker == '$') { - // Return binary message - return buf.readBytes(messageLength); + if (messageLength > 0 && buf.readableBytes() >= messageLength) { + return buf.readBytes(messageLength); + } else if (buf.readableBytes() >= MESSAGE_SHORT) { + if (buf.getUnsignedByte(buf.readerIndex() + MESSAGE_SHORT - 1) == 0) { + return buf.readBytes(MESSAGE_SHORT); + } else if (buf.readableBytes() >= MESSAGE_LONG) { + return buf.readBytes(MESSAGE_LONG); + } + } } diff --git a/src/org/traccar/protocol/H02Protocol.java b/src/org/traccar/protocol/H02Protocol.java index 06ac2a6fa..089721aed 100644 --- a/src/org/traccar/protocol/H02Protocol.java +++ b/src/org/traccar/protocol/H02Protocol.java @@ -43,7 +43,7 @@ public class H02Protocol extends BaseProtocol { serverList.add(new TrackerServer(new ServerBootstrap(), getName()) { @Override protected void addSpecificHandlers(ChannelPipeline pipeline) { - int messageLength = Context.getConfig().getInteger(getName() + ".messageLength", 32); + int messageLength = Context.getConfig().getInteger(getName() + ".messageLength"); pipeline.addLast("frameDecoder", new H02FrameDecoder(messageLength)); pipeline.addLast("stringEncoder", new StringEncoder()); pipeline.addLast("objectEncoder", new H02ProtocolEncoder()); diff --git a/src/org/traccar/protocol/RuptelaProtocolDecoder.java b/src/org/traccar/protocol/RuptelaProtocolDecoder.java index 224c027f3..84cc0e101 100644 --- a/src/org/traccar/protocol/RuptelaProtocolDecoder.java +++ b/src/org/traccar/protocol/RuptelaProtocolDecoder.java @@ -1,5 +1,5 @@ /* - * Copyright 2013 - 2014 Anton Tananaev (anton.tananaev@gmail.com) + * Copyright 2013 - 2016 Anton Tananaev (anton.tananaev@gmail.com) * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -35,6 +35,7 @@ public class RuptelaProtocolDecoder extends BaseProtocolDecoder { } public static final int MSG_RECORDS = 1; + public static final int MSG_EXTENDED_RECORDS = 68; public static final int MSG_SMS_VIA_GPRS = 108; @Override @@ -53,7 +54,7 @@ public class RuptelaProtocolDecoder extends BaseProtocolDecoder { int type = buf.readUnsignedByte(); - if (type == MSG_RECORDS) { + if (type == MSG_RECORDS || type == MSG_EXTENDED_RECORDS) { List<Position> positions = new LinkedList<>(); buf.readUnsignedByte(); // records left @@ -67,45 +68,56 @@ public class RuptelaProtocolDecoder extends BaseProtocolDecoder { position.setTime(new Date(buf.readUnsignedInt() * 1000)); buf.readUnsignedByte(); // timestamp extension + if (type == MSG_EXTENDED_RECORDS) { + buf.readUnsignedByte(); // record extension + } + buf.readUnsignedByte(); // priority (reserved) + position.setValid(true); position.setLongitude(buf.readInt() / 10000000.0); position.setLatitude(buf.readInt() / 10000000.0); position.setAltitude(buf.readUnsignedShort() / 10.0); position.setCourse(buf.readUnsignedShort() / 100.0); - int satellites = buf.readUnsignedByte(); - position.set(Position.KEY_SATELLITES, satellites); - position.setValid(satellites >= 3); + position.set(Position.KEY_SATELLITES, buf.readUnsignedByte()); position.setSpeed(UnitsConverter.knotsFromKph(buf.readUnsignedShort())); position.set(Position.KEY_HDOP, buf.readUnsignedByte() / 10.0); - buf.readUnsignedByte(); + if (type == MSG_EXTENDED_RECORDS) { + buf.readUnsignedShort(); // event + } else { + buf.readUnsignedByte(); // event + } // Read 1 byte data int cnt = buf.readUnsignedByte(); for (int j = 0; j < cnt; j++) { - position.set(Position.PREFIX_IO + buf.readUnsignedByte(), buf.readUnsignedByte()); + int id = type == MSG_EXTENDED_RECORDS ? buf.readUnsignedShort() : buf.readUnsignedByte(); + position.set(Position.PREFIX_IO + id, buf.readUnsignedByte()); } // Read 2 byte data cnt = buf.readUnsignedByte(); for (int j = 0; j < cnt; j++) { - position.set(Position.PREFIX_IO + buf.readUnsignedByte(), buf.readUnsignedShort()); + int id = type == MSG_EXTENDED_RECORDS ? buf.readUnsignedShort() : buf.readUnsignedByte(); + position.set(Position.PREFIX_IO + id, buf.readUnsignedShort()); } // Read 4 byte data cnt = buf.readUnsignedByte(); for (int j = 0; j < cnt; j++) { - position.set(Position.PREFIX_IO + buf.readUnsignedByte(), buf.readUnsignedInt()); + int id = type == MSG_EXTENDED_RECORDS ? buf.readUnsignedShort() : buf.readUnsignedByte(); + position.set(Position.PREFIX_IO + id, buf.readUnsignedInt()); } // Read 8 byte data cnt = buf.readUnsignedByte(); for (int j = 0; j < cnt; j++) { - position.set(Position.PREFIX_IO + buf.readUnsignedByte(), buf.readLong()); + int id = type == MSG_EXTENDED_RECORDS ? buf.readUnsignedShort() : buf.readUnsignedByte(); + position.set(Position.PREFIX_IO + id, buf.readLong()); } positions.add(position); diff --git a/src/org/traccar/reports/Events.java b/src/org/traccar/reports/Events.java index ed7e9e411..77d995f56 100644 --- a/src/org/traccar/reports/Events.java +++ b/src/org/traccar/reports/Events.java @@ -16,16 +16,34 @@ */ 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 java.util.HashMap; +import java.util.Iterator; +import java.util.List; import javax.json.Json; import javax.json.JsonArrayBuilder; +import org.jxls.area.Area; +import org.jxls.builder.xls.XlsCommentAreaBuilder; +import org.jxls.common.CellRef; +import org.jxls.formula.StandardFormulaProcessor; +import org.jxls.transform.Transformer; +import org.jxls.transform.poi.PoiTransformer; +import org.jxls.util.TransformerFactory; import org.traccar.Context; +import org.traccar.model.Device; import org.traccar.model.Event; -import org.traccar.web.CsvBuilder; +import org.traccar.model.Geofence; +import org.traccar.model.Group; +import org.traccar.reports.model.DeviceReport; import org.traccar.web.JsonConverter; public final class Events { @@ -38,25 +56,80 @@ public final class Events { JsonArrayBuilder json = Json.createArrayBuilder(); for (long deviceId: ReportUtils.getDeviceList(deviceIds, groupIds)) { Context.getPermissionsManager().checkDevice(userId, deviceId); - for (String type : types) { - for (Event event : Context.getDataManager().getEvents(deviceId, type, from, to)) { - json.add(JsonConverter.objectToJson(event)); + Collection<Event> events = Context.getDataManager().getEvents(deviceId, from, to); + boolean all = types.isEmpty() || types.contains(Event.ALL_EVENTS); + for (Event event : events) { + if (all || types.contains(event.getType())) { + long geofenceId = event.getGeofenceId(); + if (geofenceId == 0 || Context.getGeofenceManager().checkGeofence(userId, geofenceId)) { + json.add(JsonConverter.objectToJson(event)); + } } } } return json.build().toString(); } - public static String getCsv(long userId, Collection<Long> deviceIds, Collection<Long> groupIds, - Collection<String> types, Date from, Date to) throws SQLException { - CsvBuilder csv = new CsvBuilder(); - csv.addHeaderLine(new Event()); + public static void getExcel(OutputStream outputStream, + long userId, Collection<Long> deviceIds, Collection<Long> groupIds, + Collection<String> types, Date from, Date to) throws SQLException, IOException { + ArrayList<DeviceReport> devicesEvents = new ArrayList<>(); + ArrayList<String> sheetNames = new ArrayList<>(); + HashMap<Long, String> geofenceNames = new HashMap<>(); for (long deviceId: ReportUtils.getDeviceList(deviceIds, groupIds)) { Context.getPermissionsManager().checkDevice(userId, deviceId); - for (String type : types) { - csv.addArray(Context.getDataManager().getEvents(deviceId, type, from, to)); + Collection<Event> events = Context.getDataManager().getEvents(deviceId, from, to); + boolean all = types.isEmpty() || types.contains(Event.ALL_EVENTS); + for (Iterator<Event> iterator = events.iterator(); iterator.hasNext();) { + Event event = iterator.next(); + if (all || types.contains(event.getType())) { + long geofenceId = event.getGeofenceId(); + if (geofenceId != 0) { + if (Context.getGeofenceManager().checkGeofence(userId, geofenceId)) { + Geofence geofence = Context.getGeofenceManager().getGeofence(geofenceId); + if (geofence != null) { + geofenceNames.put(geofenceId, geofence.getName()); + } + } else { + iterator.remove(); + } + } + } else { + iterator.remove(); + } + } + DeviceReport deviceEvents = new DeviceReport(); + Device device = Context.getIdentityManager().getDeviceById(deviceId); + deviceEvents.setDeviceName(device.getName()); + sheetNames.add(deviceEvents.getDeviceName()); + if (device.getGroupId() != 0) { + Group group = Context.getDeviceManager().getGroupById(device.getGroupId()); + if (group != null) { + deviceEvents.setGroupName(group.getName()); + } + } + deviceEvents.setObjects(events); + devicesEvents.add(deviceEvents); + } + String templatePath = Context.getConfig().getString("report.templatesPath", + "templates/export/"); + try (InputStream inputStream = new FileInputStream(templatePath + "/events.xlsx")) { + org.jxls.common.Context jxlsContext = PoiTransformer.createInitialContext(); + jxlsContext.putVar("devices", devicesEvents); + jxlsContext.putVar("sheetNames", sheetNames); + jxlsContext.putVar("geofenceNames", geofenceNames); + jxlsContext.putVar("from", from); + jxlsContext.putVar("to", to); + jxlsContext.putVar("bracketsRegex", "[\\{\\}\"]"); + Transformer transformer = TransformerFactory.createTransformer(inputStream, outputStream); + List<Area> xlsAreas = new XlsCommentAreaBuilder(transformer).build(); + for (Area xlsArea : xlsAreas) { + xlsArea.applyAt(new CellRef(xlsArea.getStartCellRef().getCellName()), jxlsContext); + xlsArea.setFormulaProcessor(new StandardFormulaProcessor()); + xlsArea.processFormulas(); } + transformer.deleteSheet(xlsAreas.get(0).getStartCellRef().getSheetName()); + transformer.write(); } - return csv.build(); } } diff --git a/src/org/traccar/reports/Route.java b/src/org/traccar/reports/Route.java index 45b81cd8c..6992c89cc 100644 --- a/src/org/traccar/reports/Route.java +++ b/src/org/traccar/reports/Route.java @@ -16,16 +16,31 @@ */ 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 java.util.List; import javax.json.Json; import javax.json.JsonArrayBuilder; +import org.jxls.area.Area; +import org.jxls.builder.xls.XlsCommentAreaBuilder; +import org.jxls.common.CellRef; +import org.jxls.formula.StandardFormulaProcessor; +import org.jxls.transform.Transformer; +import org.jxls.transform.poi.PoiTransformer; +import org.jxls.util.TransformerFactory; import org.traccar.Context; +import org.traccar.model.Device; +import org.traccar.model.Group; import org.traccar.model.Position; -import org.traccar.web.CsvBuilder; +import org.traccar.reports.model.DeviceReport; import org.traccar.web.JsonConverter; public final class Route { @@ -45,14 +60,45 @@ public final class Route { return json.build().toString(); } - public static String getCsv(long userId, Collection<Long> deviceIds, Collection<Long> groupIds, - Date from, Date to) throws SQLException { - CsvBuilder csv = new CsvBuilder(); - csv.addHeaderLine(new Position()); + public static void getExcel(OutputStream outputStream, + long userId, Collection<Long> deviceIds, Collection<Long> groupIds, + Date from, Date to) throws SQLException, IOException { + ArrayList<DeviceReport> devicesRoutes = new ArrayList<>(); + ArrayList<String> sheetNames = new ArrayList<>(); for (long deviceId: ReportUtils.getDeviceList(deviceIds, groupIds)) { Context.getPermissionsManager().checkDevice(userId, deviceId); - csv.addArray(Context.getDataManager().getPositions(deviceId, from, to)); + Collection<Position> positions = Context.getDataManager().getPositions(deviceId, from, to); + DeviceReport deviceRoutes = new DeviceReport(); + Device device = Context.getIdentityManager().getDeviceById(deviceId); + deviceRoutes.setDeviceName(device.getName()); + sheetNames.add(deviceRoutes.getDeviceName()); + if (device.getGroupId() != 0) { + Group group = Context.getDeviceManager().getGroupById(device.getGroupId()); + if (group != null) { + deviceRoutes.setGroupName(group.getName()); + } + } + deviceRoutes.setObjects(positions); + devicesRoutes.add(deviceRoutes); + } + String templatePath = Context.getConfig().getString("report.templatesPath", + "templates/export/"); + try (InputStream inputStream = new FileInputStream(templatePath + "/route.xlsx")) { + org.jxls.common.Context jxlsContext = PoiTransformer.createInitialContext(); + jxlsContext.putVar("devices", devicesRoutes); + jxlsContext.putVar("sheetNames", sheetNames); + jxlsContext.putVar("from", from); + jxlsContext.putVar("to", to); + jxlsContext.putVar("bracketsRegex", "[\\{\\}\"]"); + Transformer transformer = TransformerFactory.createTransformer(inputStream, outputStream); + List<Area> xlsAreas = new XlsCommentAreaBuilder(transformer).build(); + for (Area xlsArea : xlsAreas) { + xlsArea.applyAt(new CellRef(xlsArea.getStartCellRef().getCellName()), jxlsContext); + xlsArea.setFormulaProcessor(new StandardFormulaProcessor()); + xlsArea.processFormulas(); + } + transformer.deleteSheet(xlsAreas.get(0).getStartCellRef().getSheetName()); + transformer.write(); } - return csv.build(); } } diff --git a/src/org/traccar/reports/Summary.java b/src/org/traccar/reports/Summary.java index d4171f644..14f8b7839 100644 --- a/src/org/traccar/reports/Summary.java +++ b/src/org/traccar/reports/Summary.java @@ -16,17 +16,23 @@ */ 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 javax.json.Json; import javax.json.JsonArrayBuilder; +import org.jxls.transform.poi.PoiTransformer; +import org.jxls.util.JxlsHelper; import org.traccar.Context; import org.traccar.model.Position; import org.traccar.reports.model.SummaryReport; -import org.traccar.web.CsvBuilder; import org.traccar.web.JsonConverter; public final class Summary { @@ -78,14 +84,23 @@ public final class Summary { return json.build().toString(); } - public static String getCsv(long userId, Collection<Long> deviceIds, Collection<Long> groupIds, - Date from, Date to) throws SQLException { - CsvBuilder csv = new CsvBuilder(); - csv.addHeaderLine(new SummaryReport()); + public static void getExcel(OutputStream outputStream, + long userId, Collection<Long> deviceIds, Collection<Long> groupIds, + Date from, Date to) throws SQLException, IOException { + ArrayList<SummaryReport> summaries = new ArrayList<>(); for (long deviceId: ReportUtils.getDeviceList(deviceIds, groupIds)) { Context.getPermissionsManager().checkDevice(userId, deviceId); - csv.addLine(calculateSummaryResult(deviceId, from, to)); + summaries.add(calculateSummaryResult(deviceId, from, to)); + } + String templatePath = Context.getConfig().getString("report.templatesPath", + "templates/export/"); + try (InputStream inputStream = new FileInputStream(templatePath + "/summary.xlsx")) { + org.jxls.common.Context jxlsContext = PoiTransformer.createInitialContext(); + jxlsContext.putVar("summaries", summaries); + jxlsContext.putVar("from", from); + jxlsContext.putVar("to", to); + JxlsHelper.getInstance().setUseFastFormulaProcessor(false) + .processTemplate(inputStream, outputStream, jxlsContext); } - return csv.build(); } } diff --git a/src/org/traccar/reports/Trips.java b/src/org/traccar/reports/Trips.java index f0a10edbd..705644849 100644 --- a/src/org/traccar/reports/Trips.java +++ b/src/org/traccar/reports/Trips.java @@ -16,18 +16,32 @@ */ 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 java.util.List; import javax.json.Json; import javax.json.JsonArrayBuilder; +import org.jxls.area.Area; +import org.jxls.builder.xls.XlsCommentAreaBuilder; +import org.jxls.common.CellRef; +import org.jxls.formula.StandardFormulaProcessor; +import org.jxls.transform.Transformer; +import org.jxls.transform.poi.PoiTransformer; +import org.jxls.util.TransformerFactory; import org.traccar.Context; +import org.traccar.model.Device; +import org.traccar.model.Group; import org.traccar.model.Position; +import org.traccar.reports.model.DeviceReport; import org.traccar.reports.model.TripReport; -import org.traccar.web.CsvBuilder; import org.traccar.web.JsonConverter; public final class Trips { @@ -50,16 +64,24 @@ public final class Trips { } TripReport trip = new TripReport(); + long tripDuration = endTrip.getFixTime().getTime() - positions.get(startIndex).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()); + boolean ignoreOdometer = Context.getDeviceManager() .lookupConfigBoolean(deviceId, "report.ignoreOdometer", false); trip.setDistance(ReportUtils.calculateDistance(startTrip, endTrip, !ignoreOdometer)); @@ -157,14 +179,44 @@ public final class Trips { return json.build().toString(); } - public static String getCsv(long userId, Collection<Long> deviceIds, Collection<Long> groupIds, - Date from, Date to) throws SQLException { - CsvBuilder csv = new CsvBuilder(); - csv.addHeaderLine(new TripReport()); + public static void getExcel(OutputStream outputStream, + long userId, Collection<Long> deviceIds, Collection<Long> groupIds, + Date from, Date to) throws SQLException, IOException { + ArrayList<DeviceReport> devicesTrips = new ArrayList<>(); + ArrayList<String> sheetNames = new ArrayList<>(); for (long deviceId: ReportUtils.getDeviceList(deviceIds, groupIds)) { Context.getPermissionsManager().checkDevice(userId, deviceId); - csv.addArray(detectTrips(deviceId, from, to)); + Collection<TripReport> trips = detectTrips(deviceId, from, to); + DeviceReport deviceTrips = new DeviceReport(); + Device device = Context.getIdentityManager().getDeviceById(deviceId); + deviceTrips.setDeviceName(device.getName()); + sheetNames.add(deviceTrips.getDeviceName()); + if (device.getGroupId() != 0) { + Group group = Context.getDeviceManager().getGroupById(device.getGroupId()); + if (group != null) { + deviceTrips.setGroupName(group.getName()); + } + } + deviceTrips.setObjects(trips); + devicesTrips.add(deviceTrips); + } + String templatePath = Context.getConfig().getString("report.templatesPath", + "templates/export/"); + try (InputStream inputStream = new FileInputStream(templatePath + "/trips.xlsx")) { + org.jxls.common.Context jxlsContext = PoiTransformer.createInitialContext(); + jxlsContext.putVar("devices", devicesTrips); + jxlsContext.putVar("sheetNames", sheetNames); + jxlsContext.putVar("from", from); + jxlsContext.putVar("to", to); + Transformer transformer = TransformerFactory.createTransformer(inputStream, outputStream); + List<Area> xlsAreas = new XlsCommentAreaBuilder(transformer).build(); + for (Area xlsArea : xlsAreas) { + xlsArea.applyAt(new CellRef(xlsArea.getStartCellRef().getCellName()), jxlsContext); + xlsArea.setFormulaProcessor(new StandardFormulaProcessor()); + xlsArea.processFormulas(); + } + transformer.deleteSheet(xlsAreas.get(0).getStartCellRef().getSheetName()); + transformer.write(); } - return csv.build(); } } diff --git a/src/org/traccar/reports/model/DeviceReport.java b/src/org/traccar/reports/model/DeviceReport.java new file mode 100644 index 000000000..c072de231 --- /dev/null +++ b/src/org/traccar/reports/model/DeviceReport.java @@ -0,0 +1,49 @@ +/* + * Copyright 2016 Anton Tananaev (anton.tananaev@gmail.com) + * Copyright 2016 Andrey Kunitsyn (abyss@fox5.ru) + * + * 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.ArrayList; +import java.util.Collection; +import java.util.List; + +public class DeviceReport { + + private String deviceName; + public String getDeviceName() { + return deviceName; + } + public void setDeviceName(String deviceName) { + this.deviceName = deviceName; + } + + private String groupName = ""; + public String getGroupName() { + return groupName; + } + public void setGroupName(String groupName) { + this.groupName = groupName; + } + + private List<?> objects; + public Collection<?> getObjects() { + return objects; + } + public void setObjects(Collection<?> objects) { + this.objects = new ArrayList<>(objects); + } + +} diff --git a/src/org/traccar/reports/model/TripReport.java b/src/org/traccar/reports/model/TripReport.java index 3a77b02ca..d726195cb 100644 --- a/src/org/traccar/reports/model/TripReport.java +++ b/src/org/traccar/reports/model/TripReport.java @@ -1,3 +1,19 @@ +/* + * Copyright 2016 Anton Tananaev (anton.tananaev@gmail.com) + * Copyright 2016 Andrey Kunitsyn (abyss@fox5.ru) + * + * 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; @@ -20,6 +36,38 @@ public class TripReport extends BaseReport { this.endPositionId = endPositionId; } + private double startLat; + public double getStartLat() { + return startLat; + } + public void setStartLat(double startLat) { + this.startLat = startLat; + } + + private double startLon; + public double getStartLon() { + return startLon; + } + public void setStartLon(double startLon) { + this.startLon = startLon; + } + + private double endLat; + public double getEndLat() { + return endLat; + } + public void setEndLat(double endLat) { + this.endLat = endLat; + } + + private double endLon; + public double getEndLon() { + return endLon; + } + public void setEndLon(double endLon) { + this.endLon = endLon; + } + private Date startTime; public Date getStartTime() { if (startTime != null) { |