diff options
Diffstat (limited to 'src/main')
10 files changed, 266 insertions, 35 deletions
diff --git a/src/main/java/org/traccar/web/client/Traccar.java b/src/main/java/org/traccar/web/client/Traccar.java index 6da9e011..5ea75cf9 100644 --- a/src/main/java/org/traccar/web/client/Traccar.java +++ b/src/main/java/org/traccar/web/client/Traccar.java @@ -1,5 +1,7 @@ package org.traccar.web.client; +import java.util.List; + import org.traccar.web.client.controller.ArchiveController; import org.traccar.web.client.controller.DeviceController; import org.traccar.web.client.controller.LoginController; @@ -7,6 +9,7 @@ import org.traccar.web.client.controller.MapController; import org.traccar.web.client.database.DatabaseService; import org.traccar.web.client.database.DatabaseServiceAsync; import org.traccar.web.client.i18n.ApplicationConstants; +import org.traccar.web.shared.model.Device; import com.google.gwt.core.client.EntryPoint; import com.google.gwt.core.client.GWT; @@ -54,6 +57,7 @@ public class Traccar implements EntryPoint, LoginController.LoginHandler { private void createLayout() { mapController = new MapController(); deviceController = new DeviceController(); + deviceController.setHandler(deviceHandler); archiveController = new ArchiveController(); Canvas mainPanel = mapController.getView(); @@ -89,4 +93,18 @@ public class Traccar implements EntryPoint, LoginController.LoginHandler { mainLayout.draw(); } + DeviceController.DeviceHandler deviceHandler = new DeviceController.DeviceHandler() { + + @Override + public void onChanged(List<Device> devices) { + mapController.update(); + } + + @Override + public void onSelected(Device device) { + mapController.select(device); + } + + }; + } diff --git a/src/main/java/org/traccar/web/client/controller/DeviceController.java b/src/main/java/org/traccar/web/client/controller/DeviceController.java index 6bf73b01..0c42e8a2 100644 --- a/src/main/java/org/traccar/web/client/controller/DeviceController.java +++ b/src/main/java/org/traccar/web/client/controller/DeviceController.java @@ -15,7 +15,8 @@ import com.smartgwt.client.widgets.events.ClickHandler; public class DeviceController implements PanelController, DevicePanel.DeviceHandler, DeviceDialog.SaveHandler { public interface DeviceHandler { - public void onChanged(); + public void onChanged(List<Device> devices); + public void onSelected(Device device); } private DeviceHandler deviceHandler; @@ -65,6 +66,13 @@ public class DeviceController implements PanelController, DevicePanel.DeviceHand } @Override + public void onSelected(Device device) { + if (deviceHandler != null) { + deviceHandler.onSelected(device); + } + } + + @Override public void onSave(Device device) { Traccar.getDatabaseService().storeDevice(device, saveCallback); } @@ -87,7 +95,7 @@ public class DeviceController implements PanelController, DevicePanel.DeviceHand public void onSuccess(List<Device> result) { devicePanel.updateDevices(result); if (deviceHandler != null) { - deviceHandler.onChanged(); + deviceHandler.onChanged(result); } } }; diff --git a/src/main/java/org/traccar/web/client/controller/MapController.java b/src/main/java/org/traccar/web/client/controller/MapController.java index 64938830..89320500 100644 --- a/src/main/java/org/traccar/web/client/controller/MapController.java +++ b/src/main/java/org/traccar/web/client/controller/MapController.java @@ -1,14 +1,57 @@ package org.traccar.web.client.controller; +import java.util.List; + +import org.traccar.web.client.Traccar; import org.traccar.web.client.view.MapPanel; +import org.traccar.web.shared.model.Device; +import org.traccar.web.shared.model.Position; +import com.google.gwt.user.client.Timer; +import com.google.gwt.user.client.rpc.AsyncCallback; import com.smartgwt.client.widgets.Canvas; public class MapController implements PanelController { + private static final int UPDATE_INTERVAL = 10000; + + private final MapPanel mapPanel; + + private final Timer updateTimer; + + public MapController() { + mapPanel = new MapPanel(); + updateTimer = new Timer() { + @Override + public void run() { + update(); + } + }; + update(); + } + @Override public Canvas getView() { - return new MapPanel(); + return mapPanel; + } + + public void select(Device device) { + mapPanel.select(device, true); + } + + public void update() { + updateTimer.cancel(); + Traccar.getDatabaseService().getLatestPositions(new AsyncCallback<List<Position>>() { + @Override + public void onSuccess(List<Position> result) { + mapPanel.showPositions(result); + updateTimer.schedule(UPDATE_INTERVAL); + } + @Override + public void onFailure(Throwable caught) { + updateTimer.schedule(UPDATE_INTERVAL); + } + }); } } diff --git a/src/main/java/org/traccar/web/client/database/DatabaseService.java b/src/main/java/org/traccar/web/client/database/DatabaseService.java index 646f7a62..4e68181f 100644 --- a/src/main/java/org/traccar/web/client/database/DatabaseService.java +++ b/src/main/java/org/traccar/web/client/database/DatabaseService.java @@ -26,4 +26,6 @@ public interface DatabaseService extends RemoteService { List<Position> getPositions(Device device, Date from, Date to); + List<Position> getLatestPositions(); + } diff --git a/src/main/java/org/traccar/web/client/database/DatabaseServiceAsync.java b/src/main/java/org/traccar/web/client/database/DatabaseServiceAsync.java index 7a700beb..809574db 100644 --- a/src/main/java/org/traccar/web/client/database/DatabaseServiceAsync.java +++ b/src/main/java/org/traccar/web/client/database/DatabaseServiceAsync.java @@ -24,4 +24,6 @@ public interface DatabaseServiceAsync { void getPositions(Device device, Date from, Date to, AsyncCallback<List<Position>> callback); + void getLatestPositions(AsyncCallback<List<Position>> callback); + } diff --git a/src/main/java/org/traccar/web/client/i18n/ApplicationConstants.java b/src/main/java/org/traccar/web/client/i18n/ApplicationConstants.java index 2e7c0067..41f37643 100644 --- a/src/main/java/org/traccar/web/client/i18n/ApplicationConstants.java +++ b/src/main/java/org/traccar/web/client/i18n/ApplicationConstants.java @@ -64,4 +64,13 @@ public interface ApplicationConstants extends Constants { @DefaultStringValue("Cancel") String cancel(); + @DefaultStringValue("Mapnik") + String mapnik(); + + @DefaultStringValue("Markers") + String markers(); + + @DefaultStringValue("Map") + String map(); + } diff --git a/src/main/java/org/traccar/web/client/view/DevicePanel.java b/src/main/java/org/traccar/web/client/view/DevicePanel.java index 2052c996..11a3bc38 100644 --- a/src/main/java/org/traccar/web/client/view/DevicePanel.java +++ b/src/main/java/org/traccar/web/client/view/DevicePanel.java @@ -34,6 +34,7 @@ public class DevicePanel extends SectionStack { public void onAdd(); public void onEdit(Device device); public void onRemove(Device device); + public void onSelected(Device device); } private DeviceHandler deviceHandler; @@ -124,6 +125,13 @@ public class DevicePanel extends SectionStack { public void onSelectionChanged(SelectionEvent event) { removeButton.setVisible(list.anySelected()); editButton.setVisible(list.anySelected()); + if (deviceHandler != null) { + if (list.anySelected()) { + deviceHandler.onSelected(deviceMap.get(list.getSelectedRecord().getAttributeAsLong(COLUMN_ID))); + } else { + deviceHandler.onSelected(null); + } + } } }); diff --git a/src/main/java/org/traccar/web/client/view/MapPanel.java b/src/main/java/org/traccar/web/client/view/MapPanel.java index 06bf45cc..4a2ea944 100644 --- a/src/main/java/org/traccar/web/client/view/MapPanel.java +++ b/src/main/java/org/traccar/web/client/view/MapPanel.java @@ -1,12 +1,24 @@ package org.traccar.web.client.view; +import java.util.AbstractMap; +import java.util.HashMap; +import java.util.List; + +import org.gwtopenmaps.openlayers.client.Icon; import org.gwtopenmaps.openlayers.client.LonLat; import org.gwtopenmaps.openlayers.client.Map; import org.gwtopenmaps.openlayers.client.MapOptions; import org.gwtopenmaps.openlayers.client.MapWidget; +import org.gwtopenmaps.openlayers.client.Marker; +import org.gwtopenmaps.openlayers.client.Pixel; import org.gwtopenmaps.openlayers.client.Projection; +import org.gwtopenmaps.openlayers.client.Size; import org.gwtopenmaps.openlayers.client.control.ScaleLine; +import org.gwtopenmaps.openlayers.client.layer.Markers; import org.gwtopenmaps.openlayers.client.layer.OSM; +import org.traccar.web.client.Traccar; +import org.traccar.web.shared.model.Device; +import org.traccar.web.shared.model.Position; import com.google.gwt.user.client.DOM; import com.google.gwt.user.client.Element; @@ -18,50 +30,80 @@ import com.smartgwt.client.widgets.events.ResizedHandler; import com.smartgwt.client.widgets.layout.SectionStack; import com.smartgwt.client.widgets.layout.SectionStackSection; + +class MarkerIconFactory { + + private static final Size iconSize = new Size(21, 25); + private static final Pixel iconOffset = new Pixel(-10.5f, -25.0f); + + private static final String iconUrl = "http://www.openlayers.org/api/img/"; + private static final String iconRed = iconUrl + "marker.png"; + private static final String iconBlue = iconUrl + "marker-blue.png"; + private static final String iconGreen = iconUrl + "marker-green.png"; + private static final String iconGold = iconUrl + "marker-gold.png"; + + public static Icon getLocationIcon() { + return new Icon(iconRed, iconSize, iconOffset); + } + + public static Icon getSelectedLocationIcon() { + return new Icon(iconGreen, iconSize, iconOffset); + } + + public static Icon getArchiveIcon() { + return new Icon(iconBlue, iconSize, iconOffset); + } + + public static Icon getSelectedArchiveIcon() { + return new Icon(iconGold, iconSize, iconOffset); + } + +} + /** * Map panel widget */ public class MapPanel extends SectionStack { - //private final static int BORDER_SIZE = 1; - private MapWidget mapWidget; + private Map map; private WidgetCanvas mapWrapper; + private Markers markerLayer; + + private LonLat createPoint(double longitude, double latitude) { + LonLat point = new LonLat(longitude, latitude); + point.transform(new Projection("EPSG:4326").getProjectionCode(), map.getProjection()); + return point; + } - private MapWidget createMapWidget() { + private void createMapWidget() { MapOptions defaultMapOptions = new MapOptions(); defaultMapOptions.setNumZoomLevels(16); - MapWidget mapWidget = new MapWidget("100%", "100%", defaultMapOptions); + mapWidget = new MapWidget("100%", "100%", defaultMapOptions); + map = mapWidget.getMap(); - // Google layer - /*GoogleV3Options layerOptions = new GoogleV3Options(); - layerOptions.setIsBaseLayer(true); - layerOptions.setType(GoogleV3MapType.G_NORMAL_MAP); - GoogleV3 layer = new GoogleV3("Google", layerOptions);*/ + OSM mapLayer = OSM.Mapnik(Traccar.getConstants().mapnik()); + mapLayer.setIsBaseLayer(true); - // Open Street Map layer - OSM layer = OSM.Mapnik("Mapnik"); - layer.setIsBaseLayer(true); + markerLayer = new Markers(Traccar.getConstants().markers()); - Map map = mapWidget.getMap(); - map.addLayer(layer); + map.addLayer(mapLayer); + map.addLayer(markerLayer); map.addControl(new ScaleLine()); - // Default center - LonLat lonLat = new LonLat(12.5, 41.9); - lonLat.transform(new Projection("EPSG:4326").getProjectionCode(), map.getProjection()); - map.setCenter(lonLat, 1); - - return mapWidget; + map.setCenter(createPoint(12.5, 41.9), 1); } + public SectionStackSection section; + public MapPanel() { - SectionStackSection section = new SectionStackSection("Map"); + section = new SectionStackSection(Traccar.getConstants().map()); + section.setShowHeader(false); section.setCanCollapse(false); section.setExpanded(true); - mapWidget = createMapWidget(); + createMapWidget(); mapWrapper = new WidgetCanvas(mapWidget); mapWrapper.setStyleName("defaultBorder"); @@ -84,7 +126,7 @@ public class MapPanel extends SectionStack { mapWrapper.addResizedHandler(new ResizedHandler() { @Override public void onResized(ResizedEvent event) { - mapWidget.getMap().updateSize(); + map.updateSize(); } }); @@ -92,4 +134,44 @@ public class MapPanel extends SectionStack { setSections(section); } + private AbstractMap<Device, Position> positionMap = new HashMap<Device, Position>(); + private AbstractMap<Device, Marker> markerMap = new HashMap<Device, Marker>(); + private Device selectedDevice; + + public void showPositions(List<Position> positions) { + positionMap.clear(); + markerMap.clear(); + markerLayer.clearMarkers(); + for (Position position : positions) { + positionMap.put(position.getDevice(), position); + Marker marker = new Marker( + createPoint(position.getLongitude(), position.getLatitude()), MarkerIconFactory.getLocationIcon()); + markerMap.put(position.getDevice(), marker); + markerLayer.addMarker(marker); + } + if (selectedDevice != null) { + select(selectedDevice, false); + } + } + + private void changeMarkerIcon(Marker marker, Icon icon) { + Marker newMarker = new Marker(marker.getLonLat(), icon); + markerLayer.removeMarker(marker); + markerLayer.addMarker(newMarker); + } + + public void select(Device device, boolean center) { + if (selectedDevice != null) { + changeMarkerIcon(markerMap.get(selectedDevice), MarkerIconFactory.getLocationIcon()); + } + if (device != null) { + Marker marker = markerMap.get(device); + if (center) { + map.panTo(marker.getLonLat()); + } + changeMarkerIcon(marker, MarkerIconFactory.getSelectedLocationIcon()); + } + selectedDevice = device; + } + } diff --git a/src/main/java/org/traccar/web/server/database/DatabaseServiceImpl.java b/src/main/java/org/traccar/web/server/database/DatabaseServiceImpl.java index 335cc171..d466262d 100644 --- a/src/main/java/org/traccar/web/server/database/DatabaseServiceImpl.java +++ b/src/main/java/org/traccar/web/server/database/DatabaseServiceImpl.java @@ -131,4 +131,19 @@ public class DatabaseServiceImpl extends RemoteServiceServlet implements Databas return positions; } + @Override + public List<Position> getLatestPositions() { + User user = getUser(); + TypedQuery<Position> query = entityManager.createQuery( + "SELECT x FROM Position x WHERE (x.device, x.time) IN (" + + "SELECT y.device, MAX(y.time) FROM Position y WHERE y.device IN :devices GROUP BY y.device)", Position.class); + query.setParameter("devices", user.getDevices()); + + List<Position> positions = new LinkedList<Position>(); + for (Position position : query.getResultList()) { + positions.add(position); + } + return positions; + } + } diff --git a/src/main/java/org/traccar/web/shared/model/Position.java b/src/main/java/org/traccar/web/shared/model/Position.java index 5a918cfc..69181df2 100644 --- a/src/main/java/org/traccar/web/shared/model/Position.java +++ b/src/main/java/org/traccar/web/shared/model/Position.java @@ -28,10 +28,6 @@ public class Position implements Serializable { @Index(name = "positionsIndex") private Device device; - public void setDevice(Device device) { - this.device = device; - } - public Device getDevice() { return device; } @@ -39,14 +35,62 @@ public class Position implements Serializable { @Index(name = "positionsIndex") private Date time; - public void setTime(Date time) { - this.time = time; - } - public Date getTime() { return time; } - // TODO: other + private boolean valid; + + public boolean getValid() { + return valid; + } + + private double latitude; + + public double getLatitude() { + return latitude; + } + + private double longitude; + + public double getLongitude() { + return longitude; + } + + private double altitude; + + public double getAltitude() { + return altitude; + } + + private double speed; + + public double getSpeed() { + return speed; + } + + private double course; + + public double getCourse() { + return course; + } + + private double power; + + public double getPower() { + return power; + } + + private String address; + + public String getAddress() { + return address; + } + + private String other; + + public String getOther() { + return other; + } } |