diff options
Diffstat (limited to 'src/org/traccar/database')
-rw-r--r-- | src/org/traccar/database/ConnectionManager.java | 78 | ||||
-rw-r--r-- | src/org/traccar/database/DataManager.java | 6 |
2 files changed, 69 insertions, 15 deletions
diff --git a/src/org/traccar/database/ConnectionManager.java b/src/org/traccar/database/ConnectionManager.java index 450f2f61f..e03fd1663 100644 --- a/src/org/traccar/database/ConnectionManager.java +++ b/src/org/traccar/database/ConnectionManager.java @@ -25,7 +25,13 @@ import java.util.LinkedList; import java.util.List; import java.util.Map; import java.util.Set; +import java.util.concurrent.TimeUnit; + import org.jboss.netty.channel.Channel; +import org.jboss.netty.util.Timeout; +import org.jboss.netty.util.TimerTask; +import org.traccar.Context; +import org.traccar.GlobalTimer; import org.traccar.Protocol; import org.traccar.helper.Log; import org.traccar.model.Device; @@ -33,15 +39,21 @@ import org.traccar.model.Position; public class ConnectionManager { + private static final long DEFAULT_TIMEOUT = 600; + + private final long deviceTimeout; + private final Map<Long, ActiveDevice> activeDevices = new HashMap<>(); private final Map<Long, Position> positions = new HashMap<>(); - private final Map<Long, Set<DataCacheListener>> listeners = new HashMap<>(); + private final Map<Long, Set<UpdateListener>> listeners = new HashMap<>(); + private final Map<Long, Timeout> timeouts = new HashMap<>(); public ConnectionManager(DataManager dataManager) { + deviceTimeout = Context.getConfig().getLong("status.timeout", DEFAULT_TIMEOUT) * 1000; if (dataManager != null) { try { for (Position position : dataManager.getLatestPositions()) { - this.positions.put(position.getDeviceId(), position); + positions.put(position.getDeviceId(), position); } } catch (SQLException error) { Log.warning(error); @@ -56,7 +68,7 @@ public class ConnectionManager { public void removeActiveDevice(Channel channel) { for (ActiveDevice activeDevice : activeDevices.values()) { if (activeDevice.getChannel() == channel) { - updateDevice(activeDevice.getDeviceId(), Device.STATUS_OFFLINE, new Date()); + updateDevice(activeDevice.getDeviceId(), Device.STATUS_OFFLINE, null); activeDevices.remove(activeDevice.getDeviceId()); break; } @@ -67,17 +79,52 @@ public class ConnectionManager { return activeDevices.get(deviceId); } - public synchronized void updateDevice(long deviceId, String status, Date time) { - // TODO update cache and call listener - /*Log.debug(deviceId + " " + status + " " - + new SimpleDateFormat(Log.DATE_FORMAT).format(time));*/ + public synchronized void updateDevice(final long deviceId, String status, Date time) { + Device device = Context.getIdentityManager().getDeviceById(deviceId); + if (device == null) { + return; + } + + device.setStatus(status); + if (time != null) { + device.setLastUpdate(time); + } + + Timeout timeout = timeouts.remove(deviceId); + if (timeout != null) { + timeout.cancel(); + } + + if (status.equals(Device.STATUS_ONLINE)) { + timeouts.put(deviceId, GlobalTimer.getTimer().newTimeout(new TimerTask() { + @Override + public void run(Timeout timeout) throws Exception { + if (!timeout.isCancelled()) { + updateDevice(deviceId, Device.STATUS_UNKNOWN, null); + } + } + }, deviceTimeout, TimeUnit.MILLISECONDS)); + } + + try { + Context.getDataManager().updateDeviceStatus(device); + } catch (SQLException error) { + Log.warning(error); + } + + if (listeners.containsKey(deviceId)) { + for (UpdateListener listener : listeners.get(deviceId)) { + listener.onUpdateDevice(device); + } + } } public synchronized void updatePosition(Position position) { long deviceId = position.getDeviceId(); positions.put(deviceId, position); + if (listeners.containsKey(deviceId)) { - for (DataCacheListener listener : listeners.get(deviceId)) { + for (UpdateListener listener : listeners.get(deviceId)) { listener.onUpdatePosition(position); } } @@ -100,32 +147,33 @@ public class ConnectionManager { return result; } - public interface DataCacheListener { + public interface UpdateListener { + void onUpdateDevice(Device device); void onUpdatePosition(Position position); } - public void addListener(Collection<Long> devices, DataCacheListener listener) { + public void addListener(Collection<Long> devices, UpdateListener listener) { for (long deviceId : devices) { addListener(deviceId, listener); } } - public synchronized void addListener(long deviceId, DataCacheListener listener) { + public synchronized void addListener(long deviceId, UpdateListener listener) { if (!listeners.containsKey(deviceId)) { - listeners.put(deviceId, new HashSet<DataCacheListener>()); + listeners.put(deviceId, new HashSet<UpdateListener>()); } listeners.get(deviceId).add(listener); } - public void removeListener(Collection<Long> devices, DataCacheListener listener) { + public void removeListener(Collection<Long> devices, UpdateListener listener) { for (long deviceId : devices) { removeListener(deviceId, listener); } } - public synchronized void removeListener(long deviceId, DataCacheListener listener) { + public synchronized void removeListener(long deviceId, UpdateListener listener) { if (!listeners.containsKey(deviceId)) { - listeners.put(deviceId, new HashSet<DataCacheListener>()); + listeners.put(deviceId, new HashSet<UpdateListener>()); } listeners.get(deviceId).remove(listener); } diff --git a/src/org/traccar/database/DataManager.java b/src/org/traccar/database/DataManager.java index 767582604..530ec1779 100644 --- a/src/org/traccar/database/DataManager.java +++ b/src/org/traccar/database/DataManager.java @@ -310,6 +310,12 @@ public class DataManager implements IdentityManager { .executeUpdate(); } + public void updateDeviceStatus(Device device) throws SQLException { + QueryBuilder.create(dataSource, getQuery("database.updateDeviceStatus")) + .setObject(device) + .executeUpdate(); + } + public void removeDevice(Device device) throws SQLException { QueryBuilder.create(dataSource, getQuery("database.deleteDevice")) .setObject(device) |