aboutsummaryrefslogtreecommitdiff
path: root/src/org
diff options
context:
space:
mode:
Diffstat (limited to 'src/org')
-rw-r--r--src/org/traccar/Context.java11
-rw-r--r--src/org/traccar/api/resource/UserResource.java8
-rw-r--r--src/org/traccar/database/DataManager.java14
-rw-r--r--src/org/traccar/database/NotificationManager.java3
-rw-r--r--src/org/traccar/notification/EventForwarder.java75
-rw-r--r--src/org/traccar/protocol/EelinkProtocolDecoder.java129
6 files changed, 198 insertions, 42 deletions
diff --git a/src/org/traccar/Context.java b/src/org/traccar/Context.java
index ebe700221..0bb18b675 100644
--- a/src/org/traccar/Context.java
+++ b/src/org/traccar/Context.java
@@ -35,6 +35,7 @@ import org.traccar.helper.Log;
import org.traccar.location.LocationProvider;
import org.traccar.location.MozillaLocationProvider;
import org.traccar.location.OpenCellIdLocationProvider;
+import org.traccar.notification.EventForwarder;
import org.traccar.web.WebServer;
public final class Context {
@@ -120,6 +121,12 @@ public final class Context {
return ASYNC_HTTP_CLIENT;
}
+ private static EventForwarder eventForwarder;
+
+ public static EventForwarder getEventForvarder() {
+ return eventForwarder;
+ }
+
public static void init(String[] arguments) throws Exception {
config = new Config();
@@ -210,6 +217,10 @@ public final class Context {
serverManager = new ServerManager();
+ if (config.getBoolean("event.forward.enable")) {
+ eventForwarder = new EventForwarder();
+ }
+
}
public static void init(IdentityManager testIdentityManager) {
diff --git a/src/org/traccar/api/resource/UserResource.java b/src/org/traccar/api/resource/UserResource.java
index cfe338b56..da72c7f47 100644
--- a/src/org/traccar/api/resource/UserResource.java
+++ b/src/org/traccar/api/resource/UserResource.java
@@ -52,9 +52,6 @@ public class UserResource extends BaseResource {
}
Context.getDataManager().addUser(entity);
Context.getPermissionsManager().refresh();
- if (Context.getGeofenceManager() != null) {
- Context.getGeofenceManager().refresh();
- }
if (Context.getNotificationManager() != null) {
Context.getNotificationManager().refresh();
}
@@ -71,9 +68,6 @@ public class UserResource extends BaseResource {
}
Context.getDataManager().updateUser(entity);
Context.getPermissionsManager().refresh();
- if (Context.getGeofenceManager() != null) {
- Context.getGeofenceManager().refresh();
- }
if (Context.getNotificationManager() != null) {
Context.getNotificationManager().refresh();
}
@@ -87,7 +81,7 @@ public class UserResource extends BaseResource {
Context.getDataManager().removeUser(id);
Context.getPermissionsManager().refresh();
if (Context.getGeofenceManager() != null) {
- Context.getGeofenceManager().refresh();
+ Context.getGeofenceManager().refreshUserGeofences();
}
if (Context.getNotificationManager() != null) {
Context.getNotificationManager().refresh();
diff --git a/src/org/traccar/database/DataManager.java b/src/org/traccar/database/DataManager.java
index a9fc09448..239fc1930 100644
--- a/src/org/traccar/database/DataManager.java
+++ b/src/org/traccar/database/DataManager.java
@@ -401,9 +401,11 @@ public class DataManager implements IdentityManager {
QueryBuilder.create(dataSource, getQuery("database.updateDeviceStatus"))
.setObject(device)
.executeUpdate();
- Device cachedDevice = getDeviceById(device.getId());
- cachedDevice.setStatus(device.getStatus());
- cachedDevice.setMotion(device.getMotion());
+ if (devicesById.containsKey(device.getId())) {
+ Device cachedDevice = devicesById.get(device.getId());
+ cachedDevice.setStatus(device.getStatus());
+ cachedDevice.setMotion(device.getMotion());
+ }
}
public void removeDevice(long deviceId) throws SQLException {
@@ -512,8 +514,10 @@ public class DataManager implements IdentityManager {
.setDate("now", new Date())
.setObject(position)
.executeUpdate();
- Device device = getDeviceById(position.getDeviceId());
- device.setPositionId(position.getId());
+ if (devicesById.containsKey(position.getDeviceId())) {
+ Device cachedDevice = devicesById.get(position.getDeviceId());
+ cachedDevice.setPositionId(position.getId());
+ }
}
public Collection<Position> getLatestPositions() throws SQLException {
diff --git a/src/org/traccar/database/NotificationManager.java b/src/org/traccar/database/NotificationManager.java
index e618d7ed3..911c5d2dc 100644
--- a/src/org/traccar/database/NotificationManager.java
+++ b/src/org/traccar/database/NotificationManager.java
@@ -68,6 +68,9 @@ public class NotificationManager {
}
}
}
+ if (Context.getEventForvarder() != null) {
+ Context.getEventForvarder().forwardEvent(event, position);
+ }
}
public void updateEvents(Collection<Event> events, Position position) {
diff --git a/src/org/traccar/notification/EventForwarder.java b/src/org/traccar/notification/EventForwarder.java
new file mode 100644
index 000000000..096026541
--- /dev/null
+++ b/src/org/traccar/notification/EventForwarder.java
@@ -0,0 +1,75 @@
+package org.traccar.notification;
+
+import java.nio.charset.StandardCharsets;
+
+import javax.json.Json;
+import javax.json.JsonObjectBuilder;
+
+import org.traccar.Context;
+import org.traccar.model.Device;
+import org.traccar.model.Event;
+import org.traccar.model.Geofence;
+import org.traccar.model.Position;
+import org.traccar.web.JsonConverter;
+
+import com.ning.http.client.AsyncHttpClient.BoundRequestBuilder;
+
+public final class EventForwarder {
+
+ private String url;
+ private String header;
+
+ public EventForwarder() {
+ url = Context.getConfig().getString("event.forward.url", "http://localhost/");
+ header = Context.getConfig().getString("event.forward.header", "");
+ }
+
+ private static final String USER_AGENT = "Traccar Server";
+
+ private static final String KEY_POSITION = "position";
+ private static final String KEY_EVENT = "event";
+ private static final String KEY_GEOFENCE = "geofence";
+ private static final String KEY_DEVICE = "device";
+
+ public void forwardEvent(Event event, Position position) {
+
+
+ BoundRequestBuilder requestBuilder = Context.getAsyncHttpClient().preparePost(url);
+
+ requestBuilder.addHeader("Content-Type", "application/json; charset=utf-8");
+ requestBuilder.addHeader("User-Agent", USER_AGENT);
+ if (!header.equals("")) {
+ String[] headerLines = header.split("\\r?\\n");
+ for (String headerLine: headerLines) {
+ String[] splitedLine = headerLine.split(":", 2);
+ if (splitedLine.length == 2) {
+ requestBuilder.addHeader(splitedLine[0].trim(), splitedLine[1].trim());
+ }
+ }
+ }
+
+ requestBuilder.setBody(preparePayload(event, position));
+ requestBuilder.execute();
+ }
+
+ private byte[] preparePayload(Event event, Position position) {
+ JsonObjectBuilder json = Json.createObjectBuilder();
+ json.add(KEY_EVENT, JsonConverter.objectToJson(event));
+ if (position != null) {
+ json.add(KEY_POSITION, JsonConverter.objectToJson(position));
+ }
+ if (event.getDeviceId() != 0) {
+ Device device = Context.getIdentityManager().getDeviceById(event.getDeviceId());
+ if (device != null) {
+ json.add(KEY_DEVICE, JsonConverter.objectToJson(device));
+ }
+ }
+ if (event.getGeofenceId() != 0) {
+ Geofence geofence = Context.getGeofenceManager().getGeofence(event.getGeofenceId());
+ if (geofence != null) {
+ json.add(KEY_GEOFENCE, JsonConverter.objectToJson(geofence));
+ }
+ }
+ return json.build().toString().getBytes(StandardCharsets.UTF_8);
+ }
+}
diff --git a/src/org/traccar/protocol/EelinkProtocolDecoder.java b/src/org/traccar/protocol/EelinkProtocolDecoder.java
index 09cf1808f..e9de73dd5 100644
--- a/src/org/traccar/protocol/EelinkProtocolDecoder.java
+++ b/src/org/traccar/protocol/EelinkProtocolDecoder.java
@@ -1,5 +1,5 @@
/*
- * Copyright 2014 Anton Tananaev (anton.tananaev@gmail.com)
+ * Copyright 2014 - 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.
@@ -19,6 +19,7 @@ import org.jboss.netty.buffer.ChannelBuffer;
import org.jboss.netty.buffer.ChannelBuffers;
import org.jboss.netty.channel.Channel;
import org.traccar.BaseProtocolDecoder;
+import org.traccar.helper.BitUtil;
import org.traccar.helper.UnitsConverter;
import org.traccar.model.Position;
@@ -41,6 +42,16 @@ public class EelinkProtocolDecoder extends BaseProtocolDecoder {
public static final int MSG_INTERACTIVE = 0x80;
public static final int MSG_DATA = 0x81;
+ public static final int MSG_NORMAL = 0x12;
+ public static final int MSG_WARNING = 0x14;
+ public static final int MSG_REPORT = 0x15;
+ public static final int MSG_COMMAND = 0x16;
+ public static final int MSG_OBD_DATA = 0x17;
+ public static final int MSG_OBD_BODY = 0x18;
+ public static final int MSG_OBD_CODE = 0x19;
+ public static final int MSG_CAMERA_INFO = 0x1E;
+ public static final int MSG_CAMERA_DATA = 0x1F;
+
private void sendResponse(Channel channel, int type, int index) {
if (channel != null) {
ChannelBuffer response = ChannelBuffers.buffer(7);
@@ -52,57 +63,115 @@ public class EelinkProtocolDecoder extends BaseProtocolDecoder {
}
}
- @Override
- protected Object decode(
- Channel channel, SocketAddress remoteAddress, Object msg) throws Exception {
+ private Position decodeOld(ChannelBuffer buf, int type, int index) {
- ChannelBuffer buf = (ChannelBuffer) msg;
+ Position position = new Position();
+ position.setDeviceId(getDeviceId());
+ position.setProtocol(getProtocolName());
- buf.skipBytes(2); // header
- int type = buf.readUnsignedByte();
- buf.readShort(); // length
- int index = buf.readUnsignedShort();
+ position.set(Position.KEY_INDEX, index);
- if (type != MSG_GPS && type != MSG_DATA) {
- sendResponse(channel, type, index);
+ position.setTime(new Date(buf.readUnsignedInt() * 1000));
+ position.setLatitude(buf.readInt() / 1800000.0);
+ position.setLongitude(buf.readInt() / 1800000.0);
+ position.setSpeed(UnitsConverter.knotsFromKph(buf.readUnsignedByte()));
+ position.setCourse(buf.readUnsignedShort());
+
+ position.set(Position.KEY_MCC, buf.readUnsignedShort());
+ position.set(Position.KEY_MNC, buf.readUnsignedShort());
+ position.set(Position.KEY_LAC, buf.readUnsignedShort());
+ position.set(Position.KEY_CID, buf.readUnsignedMedium());
+
+ position.setValid((buf.readUnsignedByte() & 0x01) != 0);
+
+ if (type == MSG_ALARM) {
+ position.set(Position.KEY_ALARM, buf.readUnsignedByte());
}
- if (type == MSG_LOGIN) {
+ if (type == MSG_STATE) {
+ position.set(Position.KEY_STATUS, buf.readUnsignedByte());
+ }
- identify(ChannelBuffers.hexDump(buf.readBytes(8)).substring(1), channel, remoteAddress);
+ return position;
+ }
+
+ private Position decodeNew(ChannelBuffer buf, int type, int index) {
+
+ Position position = new Position();
+ position.setDeviceId(getDeviceId());
+ position.setProtocol(getProtocolName());
- } else if (hasDeviceId()
- && (type == MSG_GPS || type == MSG_ALARM || type == MSG_STATE || type == MSG_SMS)) {
+ position.set(Position.KEY_INDEX, index);
- Position position = new Position();
- position.setDeviceId(getDeviceId());
+ position.setTime(new Date(buf.readUnsignedInt() * 1000));
- position.setProtocol(getProtocolName());
- position.set(Position.KEY_INDEX, index);
+ int flags = buf.readUnsignedByte();
- position.setTime(new Date(buf.readUnsignedInt() * 1000));
+ if (BitUtil.check(flags, 0)) {
position.setLatitude(buf.readInt() / 1800000.0);
position.setLongitude(buf.readInt() / 1800000.0);
- position.setSpeed(UnitsConverter.knotsFromKph(buf.readUnsignedByte()));
+ position.setAltitude(buf.readShort());
+ position.setSpeed(UnitsConverter.knotsFromKph(buf.readUnsignedShort()));
position.setCourse(buf.readUnsignedShort());
+ position.set(Position.KEY_SATELLITES, buf.readUnsignedByte());
+ }
+ if (BitUtil.check(flags, 1)) {
position.set(Position.KEY_MCC, buf.readUnsignedShort());
position.set(Position.KEY_MNC, buf.readUnsignedShort());
position.set(Position.KEY_LAC, buf.readUnsignedShort());
- position.set(Position.KEY_CID, buf.readUnsignedMedium());
+ position.set(Position.KEY_CID, buf.readUnsignedInt());
+ position.set(Position.KEY_GSM, buf.readUnsignedByte());
+ }
- position.setValid((buf.readUnsignedByte() & 0x01) != 0);
+ if (BitUtil.check(flags, 2)) {
+ buf.skipBytes(7); // bsid1
+ }
- if (type == MSG_ALARM) {
- position.set(Position.KEY_ALARM, buf.readUnsignedByte());
- }
+ if (BitUtil.check(flags, 3)) {
+ buf.skipBytes(7); // bsid2
+ }
- if (type == MSG_STATE) {
- position.set(Position.KEY_STATUS, buf.readUnsignedByte());
- }
+ if (BitUtil.check(flags, 4)) {
+ buf.skipBytes(7); // bss0
+ }
+
+ if (BitUtil.check(flags, 5)) {
+ buf.skipBytes(7); // bss1
+ }
+
+ if (BitUtil.check(flags, 6)) {
+ buf.skipBytes(7); // bss2
+ }
+
+ return position;
+ }
+
+ @Override
+ protected Object decode(
+ Channel channel, SocketAddress remoteAddress, Object msg) throws Exception {
+
+ ChannelBuffer buf = (ChannelBuffer) msg;
- return position;
+ buf.skipBytes(2); // header
+ int type = buf.readUnsignedByte();
+ buf.readShort(); // length
+ int index = buf.readUnsignedShort();
+ if (type != MSG_GPS && type != MSG_DATA) {
+ sendResponse(channel, type, index);
+ }
+
+ if (type == MSG_LOGIN) {
+
+ identify(ChannelBuffers.hexDump(buf.readBytes(8)).substring(1), channel, remoteAddress);
+
+ } else if (hasDeviceId()) {
+ if (type == MSG_GPS || type == MSG_ALARM || type == MSG_STATE || type == MSG_SMS) {
+ return decodeOld(buf, type, index);
+ } else if (type >= MSG_NORMAL && type <= MSG_OBD_CODE) {
+ return decodeNew(buf, type, index);
+ }
}
return null;