aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--debug.xml1
-rw-r--r--src/org/traccar/MainEventHandler.java4
-rw-r--r--src/org/traccar/model/Position.java11
-rw-r--r--src/org/traccar/notification/NotificationFormatter.java4
-rw-r--r--src/org/traccar/protocol/AutoFonProtocolDecoder.java4
-rw-r--r--src/org/traccar/protocol/Avl301ProtocolDecoder.java2
-rw-r--r--src/org/traccar/protocol/BlackKiteProtocolDecoder.java4
-rw-r--r--src/org/traccar/protocol/CarTrackProtocolDecoder.java2
-rw-r--r--src/org/traccar/protocol/CarcellProtocolDecoder.java4
-rw-r--r--src/org/traccar/protocol/CastelProtocolDecoder.java221
-rw-r--r--src/org/traccar/protocol/Gps103ProtocolDecoder.java21
-rw-r--r--src/org/traccar/protocol/GranitProtocolDecoder.java4
-rw-r--r--src/org/traccar/protocol/Gt06ProtocolDecoder.java2
-rw-r--r--src/org/traccar/protocol/H02ProtocolDecoder.java13
-rw-r--r--src/org/traccar/protocol/Jt600ProtocolDecoder.java2
-rw-r--r--src/org/traccar/protocol/MeiligaoProtocolDecoder.java23
-rw-r--r--src/org/traccar/protocol/MxtProtocolDecoder.java4
-rw-r--r--src/org/traccar/protocol/NavisProtocolDecoder.java6
-rw-r--r--src/org/traccar/protocol/NoranProtocolDecoder.java18
-rw-r--r--src/org/traccar/protocol/ObdDongleProtocol.java43
-rw-r--r--src/org/traccar/protocol/ObdDongleProtocolDecoder.java128
-rw-r--r--src/org/traccar/protocol/ProgressProtocolDecoder.java2
-rw-r--r--src/org/traccar/protocol/SuntechProtocolDecoder.java2
-rw-r--r--src/org/traccar/protocol/TeltonikaProtocolDecoder.java39
-rw-r--r--src/org/traccar/protocol/Tk103ProtocolDecoder.java28
-rw-r--r--src/org/traccar/protocol/TotemProtocolDecoder.java31
-rw-r--r--src/org/traccar/protocol/UlbotechProtocolDecoder.java21
-rw-r--r--test/org/traccar/protocol/CastelProtocolDecoderTest.java6
-rw-r--r--test/org/traccar/protocol/ObdDongleProtocolDecoderTest.java22
-rw-r--r--test/org/traccar/protocol/Tk103ProtocolDecoderTest.java6
-rwxr-xr-xtools/test-generator.py4
-rw-r--r--web/app/view/Login.js4
-rw-r--r--web/l10n/en.json2
33 files changed, 538 insertions, 150 deletions
diff --git a/debug.xml b/debug.xml
index 70bd0e80f..3f875aae7 100644
--- a/debug.xml
+++ b/debug.xml
@@ -448,5 +448,6 @@
<entry key='l100.port'>5112</entry>
<entry key='granit.port'>5113</entry>
<entry key='carcell.port'>5114</entry>
+ <entry key='obddongle.port'>5115</entry>
</properties>
diff --git a/src/org/traccar/MainEventHandler.java b/src/org/traccar/MainEventHandler.java
index c01760283..3f7e68b2a 100644
--- a/src/org/traccar/MainEventHandler.java
+++ b/src/org/traccar/MainEventHandler.java
@@ -25,6 +25,7 @@ import org.jboss.netty.handler.timeout.IdleStateAwareChannelHandler;
import org.jboss.netty.handler.timeout.IdleStateEvent;
import org.traccar.helper.Log;
import org.traccar.model.Position;
+import org.traccar.protocol.TeltonikaProtocolDecoder;
import java.sql.SQLException;
import java.text.SimpleDateFormat;
@@ -78,7 +79,8 @@ public class MainEventHandler extends IdleStateAwareChannelHandler {
Log.info(formatChannel(e.getChannel()) + " disconnected");
closeChannel(e.getChannel());
- if (ctx.getPipeline().get("httpDecoder") == null) {
+ if (ctx.getPipeline().get("httpDecoder") == null
+ && !(ctx.getPipeline().get("objectDecoder") instanceof TeltonikaProtocolDecoder)) {
Context.getConnectionManager().removeActiveDevice(e.getChannel());
}
}
diff --git a/src/org/traccar/model/Position.java b/src/org/traccar/model/Position.java
index e667f097d..d2409a75d 100644
--- a/src/org/traccar/model/Position.java
+++ b/src/org/traccar/model/Position.java
@@ -54,6 +54,7 @@ public class Position extends Message {
public static final String KEY_APPROXIMATE = "approximate";
public static final String KEY_THROTTLE = "throttle";
public static final String KEY_MOTION = "motion";
+ public static final String KEY_ARMED = "armed";
public static final String KEY_OBD_SPEED = "obd-speed";
public static final String KEY_OBD_ODOMETER = "obd-odometer";
@@ -65,15 +66,25 @@ public class Position extends Message {
public static final String PREFIX_ADC = "adc";
public static final String PREFIX_IO = "io";
public static final String PREFIX_COUNT = "count";
+ public static final String PREFIX_BUTTON = "button";
+ public static final String ALARM_GENERAL = "general";
public static final String ALARM_SOS = "sos";
public static final String ALARM_VIBRATION = "vibration";
public static final String ALARM_MOVEMENT = "movement";
+ public static final String ALARM_LOW_SPEED = "lowspeed";
public static final String ALARM_OVERSPEED = "overspeed";
public static final String ALARM_FALL_DOWN = "fallDown";
public static final String ALARM_LOW_BATTERY = "lowBattery";
public static final String ALARM_MOTION = "motion";
public static final String ALARM_FAULT = "fault";
+ public static final String ALARM_POWER_OFF = "powerOff";
+ public static final String ALARM_GEOFENCE = "geofence";
+ public static final String ALARM_GEOFENCE_ENTER = "geofenceEnter";
+ public static final String ALARM_GEOFENCE_EXIT = "geofenceExit";
+ public static final String ALARM_GPS_ANTENNA_CUT = "gpsAntennaCut";
+ public static final String ALARM_ACCIDENT = "accident";
+
private String protocol;
diff --git a/src/org/traccar/notification/NotificationFormatter.java b/src/org/traccar/notification/NotificationFormatter.java
index 37bd7848c..449426df0 100644
--- a/src/org/traccar/notification/NotificationFormatter.java
+++ b/src/org/traccar/notification/NotificationFormatter.java
@@ -53,9 +53,9 @@ public final class NotificationFormatter {
+ "Point: http://www.openstreetmap.org/?mlat=%3$f&mlon=%4$f#map=16/%3$f/%4$f%n"
+ "Time: %2$tc%n";
- public static final String TITLE_TEMPLATE_TYPE_DEVICE_OVERSPEED = "%1$s: exeeds the speed";
+ public static final String TITLE_TEMPLATE_TYPE_DEVICE_OVERSPEED = "%1$s: exceeds the speed";
public static final String MESSAGE_TEMPLATE_TYPE_DEVICE_OVERSPEED = "Device: %1$s%n"
- + "Exeeds the speed: %5$f%n"
+ + "Exceeds the speed: %5$f%n"
+ "Point: http://www.openstreetmap.org/?mlat=%3$f&mlon=%4$f#map=16/%3$f/%4$f%n"
+ "Time: %2$tc%n";
diff --git a/src/org/traccar/protocol/AutoFonProtocolDecoder.java b/src/org/traccar/protocol/AutoFonProtocolDecoder.java
index dd0f54af0..90e8ca103 100644
--- a/src/org/traccar/protocol/AutoFonProtocolDecoder.java
+++ b/src/org/traccar/protocol/AutoFonProtocolDecoder.java
@@ -169,7 +169,9 @@ public class AutoFonProtocolDecoder extends BaseProtocolDecoder {
position.setDeviceId(deviceSession.getDeviceId());
short status = buf.readUnsignedByte();
- position.set(Position.KEY_ALARM, BitUtil.check(status, 7));
+ if (BitUtil.check(status, 7)) {
+ position.set(Position.KEY_ALARM, Position.ALARM_GENERAL);
+ }
position.set(Position.KEY_BATTERY, BitUtil.to(status, 7));
buf.skipBytes(2); // remaining time
diff --git a/src/org/traccar/protocol/Avl301ProtocolDecoder.java b/src/org/traccar/protocol/Avl301ProtocolDecoder.java
index 4d2dfe126..818dd94df 100644
--- a/src/org/traccar/protocol/Avl301ProtocolDecoder.java
+++ b/src/org/traccar/protocol/Avl301ProtocolDecoder.java
@@ -123,7 +123,7 @@ public class Avl301ProtocolDecoder extends BaseProtocolDecoder {
position.set(Position.KEY_LAC, buf.readUnsignedShort());
position.set(Position.KEY_CID, buf.readUnsignedMedium());
- position.set(Position.KEY_ALARM, true);
+ position.set(Position.KEY_ALARM, Position.ALARM_GENERAL);
int flags = buf.readUnsignedByte();
position.set("acc", (flags & 0x2) != 0);
diff --git a/src/org/traccar/protocol/BlackKiteProtocolDecoder.java b/src/org/traccar/protocol/BlackKiteProtocolDecoder.java
index 92179072a..c2c051884 100644
--- a/src/org/traccar/protocol/BlackKiteProtocolDecoder.java
+++ b/src/org/traccar/protocol/BlackKiteProtocolDecoder.java
@@ -122,7 +122,9 @@ public class BlackKiteProtocolDecoder extends BaseProtocolDecoder {
case TAG_STATUS:
int status = buf.readUnsignedShort();
position.set(Position.KEY_IGNITION, BitUtil.check(status, 9));
- position.set(Position.KEY_ALARM, BitUtil.check(status, 15));
+ if (BitUtil.check(status, 15)) {
+ position.set(Position.KEY_ALARM, Position.ALARM_GENERAL);
+ }
position.set(Position.KEY_POWER, BitUtil.check(status, 2));
break;
diff --git a/src/org/traccar/protocol/CarTrackProtocolDecoder.java b/src/org/traccar/protocol/CarTrackProtocolDecoder.java
index e0fd60b15..0d21e77e6 100644
--- a/src/org/traccar/protocol/CarTrackProtocolDecoder.java
+++ b/src/org/traccar/protocol/CarTrackProtocolDecoder.java
@@ -99,7 +99,7 @@ public class CarTrackProtocolDecoder extends BaseProtocolDecoder {
odometer = odometer.replace("?", "F");
position.set(Position.KEY_ODOMETER, Integer.parseInt(odometer, 16));
- position.set(Position.KEY_ALARM, parser.next());
+ parser.next(); // there is no meaningful alarms
position.set(Position.PREFIX_ADC + 1, parser.next());
return position;
diff --git a/src/org/traccar/protocol/CarcellProtocolDecoder.java b/src/org/traccar/protocol/CarcellProtocolDecoder.java
index 7aacfa4d0..e9b6cdf28 100644
--- a/src/org/traccar/protocol/CarcellProtocolDecoder.java
+++ b/src/org/traccar/protocol/CarcellProtocolDecoder.java
@@ -143,7 +143,9 @@ public class CarcellProtocolDecoder extends BaseProtocolDecoder {
parser.next(); // panic button status
String painelStatus = parser.next();
- position.set(Position.KEY_ALARM, painelStatus.equals("1"));
+ if (painelStatus.equals("1")) {
+ position.set(Position.KEY_ALARM, Position.ALARM_GENERAL);
+ }
position.set("painel", painelStatus.equals("2"));
Double mainVoltage = parser.nextDouble() / 100d;
diff --git a/src/org/traccar/protocol/CastelProtocolDecoder.java b/src/org/traccar/protocol/CastelProtocolDecoder.java
index 212096018..994c66ea6 100644
--- a/src/org/traccar/protocol/CastelProtocolDecoder.java
+++ b/src/org/traccar/protocol/CastelProtocolDecoder.java
@@ -1,5 +1,5 @@
/*
- * Copyright 2015 Anton Tananaev (anton.tananaev@gmail.com)
+ * Copyright 2015 - 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.
@@ -132,150 +132,175 @@ public class CastelProtocolDecoder extends BaseProtocolDecoder {
}
}
- @Override
- protected Object decode(
- Channel channel, SocketAddress remoteAddress, Object msg) throws Exception {
+ private Object decodeSc(
+ Channel channel, SocketAddress remoteAddress, ChannelBuffer buf,
+ int version, ChannelBuffer id, int type, DeviceSession deviceSession) {
- ChannelBuffer buf = (ChannelBuffer) msg;
+ if (type == MSG_SC_HEARTBEAT) {
- int header = buf.readUnsignedShort();
- buf.readUnsignedShort(); // length
+ sendResponse(channel, remoteAddress, version, id, MSG_SC_HEARTBEAT_RESPONSE, null);
- int version = -1;
- if (header == 0x4040) {
- version = buf.readUnsignedByte();
- }
+ } else if (type == MSG_SC_LOGIN || type == MSG_SC_LOGOUT || type == MSG_SC_GPS
+ || type == MSG_SC_ALARM || type == MSG_SC_CURRENT_LOCATION) {
- ChannelBuffer id = buf.readBytes(20);
- int type = ChannelBuffers.swapShort(buf.readShort());
-
- DeviceSession deviceSession = getDeviceSession(
- channel, remoteAddress, id.toString(StandardCharsets.US_ASCII).trim());
- if (deviceSession == null) {
- return null;
- }
+ if (type == MSG_SC_LOGIN) {
+ ChannelBuffer response = ChannelBuffers.directBuffer(ByteOrder.LITTLE_ENDIAN, 10);
+ response.writeInt(0xFFFFFFFF);
+ response.writeShort(0);
+ response.writeInt((int) (System.currentTimeMillis() / 1000));
+ sendResponse(channel, remoteAddress, version, id, MSG_SC_LOGIN_RESPONSE, response);
+ }
- if (version == -1) {
+ if (type == MSG_SC_GPS) {
+ buf.readUnsignedByte(); // historical
+ } else if (type == MSG_SC_ALARM) {
+ buf.readUnsignedInt(); // alarm
+ } else if (type == MSG_SC_CURRENT_LOCATION) {
+ buf.readUnsignedShort();
+ }
- if (type == 0x2001) {
+ buf.readUnsignedInt(); // ACC ON time
+ buf.readUnsignedInt(); // UTC time
+ long odometer = buf.readUnsignedInt();
+ buf.readUnsignedInt(); // trip odometer
+ buf.readUnsignedInt(); // total fuel consumption
+ buf.readUnsignedShort(); // current fuel consumption
+ long status = buf.readUnsignedInt();
+ buf.skipBytes(8);
- sendResponse(channel, remoteAddress, id, (short) 0x1001);
+ int count = buf.readUnsignedByte();
- buf.readUnsignedInt(); // index
- buf.readUnsignedInt(); // unix time
- buf.readUnsignedByte();
+ List<Position> positions = new LinkedList<>();
- return readPosition(deviceSession, buf);
+ for (int i = 0; i < count; i++) {
+ Position position = readPosition(deviceSession, buf);
+ position.set(Position.KEY_ODOMETER, odometer);
+ position.set(Position.KEY_STATUS, status);
+ positions.add(position);
+ }
+ if (!positions.isEmpty()) {
+ return positions;
}
- } else if (version == 4) {
+ } else if (type == MSG_SC_GPS_SLEEP) {
- if (type == MSG_SC_HEARTBEAT) {
+ buf.readUnsignedInt(); // device time
- sendResponse(channel, remoteAddress, version, id, MSG_SC_HEARTBEAT_RESPONSE, null);
+ return readPosition(deviceSession, buf);
- } else if (type == MSG_SC_LOGIN || type == MSG_SC_LOGOUT || type == MSG_SC_GPS
- || type == MSG_SC_ALARM || type == MSG_SC_CURRENT_LOCATION) {
+ } else if (type == MSG_SC_AGPS_REQUEST) {
- if (type == MSG_SC_LOGIN) {
- ChannelBuffer response = ChannelBuffers.directBuffer(ByteOrder.LITTLE_ENDIAN, 10);
- response.writeInt(0xFFFFFFFF);
- response.writeShort(0);
- response.writeInt((int) (System.currentTimeMillis() / 1000));
- sendResponse(channel, remoteAddress, version, id, MSG_SC_LOGIN_RESPONSE, response);
- }
+ return readPosition(deviceSession, buf);
- if (type == MSG_SC_GPS) {
- buf.readUnsignedByte(); // historical
- } else if (type == MSG_SC_ALARM) {
- buf.readUnsignedInt(); // alarm
- } else if (type == MSG_SC_CURRENT_LOCATION) {
- buf.readUnsignedShort();
- }
+ }
- buf.readUnsignedInt(); // ACC ON time
- buf.readUnsignedInt(); // UTC time
- long odometer = buf.readUnsignedInt();
- buf.readUnsignedInt(); // trip odometer
- buf.readUnsignedInt(); // total fuel consumption
- buf.readUnsignedShort(); // current fuel consumption
- long status = buf.readUnsignedInt();
- buf.skipBytes(8);
+ return null;
+ }
- int count = buf.readUnsignedByte();
- List<Position> positions = new LinkedList<>();
+ private Object decodeCc(
+ Channel channel, SocketAddress remoteAddress, ChannelBuffer buf,
+ int version, ChannelBuffer id, int type, DeviceSession deviceSession) {
- for (int i = 0; i < count; i++) {
- Position position = readPosition(deviceSession, buf);
- position.set(Position.KEY_ODOMETER, odometer);
- position.set(Position.KEY_STATUS, status);
- positions.add(position);
- }
+ if (type == MSG_CC_HEARTBEAT) {
- if (!positions.isEmpty()) {
- return positions;
- }
+ sendResponse(channel, remoteAddress, version, id, MSG_CC_HEARTBEAT_RESPONSE, null);
- } else if (type == MSG_SC_GPS_SLEEP || type == MSG_SC_AGPS_REQUEST) {
+ buf.readUnsignedByte(); // 0x01 for history
+ int count = buf.readUnsignedByte();
- return readPosition(deviceSession, buf);
+ List<Position> positions = new LinkedList<>();
+
+ for (int i = 0; i < count; i++) {
+ Position position = readPosition(deviceSession, buf);
+
+ position.set(Position.KEY_STATUS, buf.readUnsignedInt());
+ position.set(Position.KEY_BATTERY, buf.readUnsignedByte());
+ position.set(Position.KEY_ODOMETER, buf.readUnsignedInt());
+
+ buf.readUnsignedByte(); // geo-fencing id
+ buf.readUnsignedByte(); // geo-fencing flags
+ buf.readUnsignedByte(); // additional flags
+
+ position.set(Position.KEY_LAC, buf.readUnsignedShort());
+ position.set(Position.KEY_CID, buf.readUnsignedShort());
+ positions.add(position);
}
- } else {
+ return positions;
- if (type == MSG_CC_HEARTBEAT) {
+ } else if (type == MSG_CC_LOGIN) {
- sendResponse(channel, remoteAddress, version, id, MSG_CC_HEARTBEAT_RESPONSE, null);
+ sendResponse(channel, remoteAddress, version, id, MSG_CC_LOGIN_RESPONSE, null);
- buf.readUnsignedByte(); // 0x01 for history
- int count = buf.readUnsignedByte();
+ Position position = readPosition(deviceSession, buf);
- List<Position> positions = new LinkedList<>();
+ position.set(Position.KEY_STATUS, buf.readUnsignedInt());
+ position.set(Position.KEY_BATTERY, buf.readUnsignedByte());
+ position.set(Position.KEY_ODOMETER, buf.readUnsignedInt());
- for (int i = 0; i < count; i++) {
- Position position = readPosition(deviceSession, buf);
+ buf.readUnsignedByte(); // geo-fencing id
+ buf.readUnsignedByte(); // geo-fencing flags
+ buf.readUnsignedByte(); // additional flags
- position.set(Position.KEY_STATUS, buf.readUnsignedInt());
- position.set(Position.KEY_BATTERY, buf.readUnsignedByte());
- position.set(Position.KEY_ODOMETER, buf.readUnsignedInt());
+ // GSM_CELL_CODE
+ // STR_Z - firmware version
+ // STR_Z - hardware version
- buf.readUnsignedByte(); // geo-fencing id
- buf.readUnsignedByte(); // geo-fencing flags
- buf.readUnsignedByte(); // additional flags
+ return position;
- position.set(Position.KEY_LAC, buf.readUnsignedShort());
- position.set(Position.KEY_CID, buf.readUnsignedShort());
+ }
- positions.add(position);
- }
+ return null;
+ }
- return positions;
+ @Override
+ protected Object decode(
+ Channel channel, SocketAddress remoteAddress, Object msg) throws Exception {
- } else if (type == MSG_CC_LOGIN) {
+ ChannelBuffer buf = (ChannelBuffer) msg;
- sendResponse(channel, remoteAddress, version, id, MSG_CC_LOGIN_RESPONSE, null);
+ int header = buf.readUnsignedShort();
+ buf.readUnsignedShort(); // length
- Position position = readPosition(deviceSession, buf);
+ int version = -1;
+ if (header == 0x4040) {
+ version = buf.readUnsignedByte();
+ }
- position.set(Position.KEY_STATUS, buf.readUnsignedInt());
- position.set(Position.KEY_BATTERY, buf.readUnsignedByte());
- position.set(Position.KEY_ODOMETER, buf.readUnsignedInt());
+ ChannelBuffer id = buf.readBytes(20);
+ int type = ChannelBuffers.swapShort(buf.readShort());
- buf.readUnsignedByte(); // geo-fencing id
- buf.readUnsignedByte(); // geo-fencing flags
- buf.readUnsignedByte(); // additional flags
+ DeviceSession deviceSession = getDeviceSession(
+ channel, remoteAddress, id.toString(StandardCharsets.US_ASCII).trim());
+ if (deviceSession == null) {
+ return null;
+ }
+
+ if (version == -1) {
+
+ if (type == 0x2001) {
+
+ sendResponse(channel, remoteAddress, id, (short) 0x1001);
- // GSM_CELL_CODE
- // STR_Z - firmware version
- // STR_Z - hardware version
+ buf.readUnsignedInt(); // index
+ buf.readUnsignedInt(); // unix time
+ buf.readUnsignedByte();
- return position;
+ return readPosition(deviceSession, buf);
}
+ } else if (version == 4) {
+
+ return decodeSc(channel, remoteAddress, buf, version, id, type, deviceSession);
+
+ } else {
+
+ return decodeCc(channel, remoteAddress, buf, version, id, type, deviceSession);
+
}
return null;
diff --git a/src/org/traccar/protocol/Gps103ProtocolDecoder.java b/src/org/traccar/protocol/Gps103ProtocolDecoder.java
index 821cf2d21..b153984cb 100644
--- a/src/org/traccar/protocol/Gps103ProtocolDecoder.java
+++ b/src/org/traccar/protocol/Gps103ProtocolDecoder.java
@@ -102,6 +102,25 @@ public class Gps103ProtocolDecoder extends BaseProtocolDecoder {
.any()
.compile();
+ private String decodeAlarm(String value) {
+ switch (value) {
+ case "tracker":
+ return null;
+ case "help me":
+ return Position.ALARM_SOS;
+ case "low battery":
+ return Position.ALARM_LOW_BATTERY;
+ case "stockade":
+ return Position.ALARM_GEOFENCE;
+ case "move":
+ return Position.ALARM_MOVEMENT;
+ case "speed":
+ return Position.ALARM_OVERSPEED;
+ default:
+ return null;
+ }
+ }
+
@Override
protected Object decode(
Channel channel, SocketAddress remoteAddress, Object msg) throws Exception {
@@ -195,7 +214,7 @@ public class Gps103ProtocolDecoder extends BaseProtocolDecoder {
position.setDeviceId(deviceSession.getDeviceId());
String alarm = parser.next();
- position.set(Position.KEY_ALARM, alarm);
+ position.set(Position.KEY_ALARM, decodeAlarm(alarm));
if (channel != null && alarm.equals("help me")) {
channel.write("**,imei:" + imei + ",E;", remoteAddress);
}
diff --git a/src/org/traccar/protocol/GranitProtocolDecoder.java b/src/org/traccar/protocol/GranitProtocolDecoder.java
index 0c7ea4d1d..3a2d24fa2 100644
--- a/src/org/traccar/protocol/GranitProtocolDecoder.java
+++ b/src/org/traccar/protocol/GranitProtocolDecoder.java
@@ -71,7 +71,9 @@ public class GranitProtocolDecoder extends BaseProtocolDecoder {
private static void decodeStructure(ChannelBuffer buf, Position position) {
short flags = buf.readUnsignedByte();
position.setValid(BitUtil.check(flags, 7));
- position.set(Position.KEY_ALARM, BitUtil.check(flags, 1));
+ if (BitUtil.check(flags, 1)) {
+ position.set(Position.KEY_ALARM, Position.ALARM_GENERAL);
+ }
short satDel = buf.readUnsignedByte();
position.set(Position.KEY_SATELLITES, BitUtil.from(satDel, 4));
diff --git a/src/org/traccar/protocol/Gt06ProtocolDecoder.java b/src/org/traccar/protocol/Gt06ProtocolDecoder.java
index 3e875086e..d69f425ab 100644
--- a/src/org/traccar/protocol/Gt06ProtocolDecoder.java
+++ b/src/org/traccar/protocol/Gt06ProtocolDecoder.java
@@ -154,7 +154,7 @@ public class Gt06ProtocolDecoder extends BaseProtocolDecoder {
private void decodeStatus(Position position, ChannelBuffer buf) {
- position.set(Position.KEY_ALARM, true);
+ position.set(Position.KEY_ALARM, Position.ALARM_GENERAL);
int flags = buf.readUnsignedByte();
diff --git a/src/org/traccar/protocol/H02ProtocolDecoder.java b/src/org/traccar/protocol/H02ProtocolDecoder.java
index bb18a68e2..fc6c9f17c 100644
--- a/src/org/traccar/protocol/H02ProtocolDecoder.java
+++ b/src/org/traccar/protocol/H02ProtocolDecoder.java
@@ -65,20 +65,15 @@ public class H02ProtocolDecoder extends BaseProtocolDecoder {
private void processStatus(Position position, long status) {
if (!BitUtil.check(status, 0) || !BitUtil.check(status, 1)
- || !BitUtil.check(status, 3) || !BitUtil.check(status, 4) || !BitUtil.check(status, 7)) {
+ || !BitUtil.check(status, 2)) {
if (!BitUtil.check(status, 0)) {
position.set(Position.KEY_ALARM, Position.ALARM_VIBRATION);
} else if (!BitUtil.check(status, 1)) {
- position.set(Position.KEY_ALARM, "robbery");
- } else if (!BitUtil.check(status, 3)) {
- position.set(Position.KEY_ALARM, "illegal ignition");
- } else if (!BitUtil.check(status, 4)) {
- position.set(Position.KEY_ALARM, "entering");
- } else if (!BitUtil.check(status, 7)) {
- position.set(Position.KEY_ALARM, "out");
+ position.set(Position.KEY_ALARM, Position.ALARM_SOS);
+ } else if (!BitUtil.check(status, 2)) {
+ position.set(Position.KEY_ALARM, Position.ALARM_OVERSPEED);
}
-
}
position.set(Position.KEY_IGNITION, BitUtil.check(status, 10));
position.set(Position.KEY_STATUS, status);
diff --git a/src/org/traccar/protocol/Jt600ProtocolDecoder.java b/src/org/traccar/protocol/Jt600ProtocolDecoder.java
index 7e0b54456..372b4cac1 100644
--- a/src/org/traccar/protocol/Jt600ProtocolDecoder.java
+++ b/src/org/traccar/protocol/Jt600ProtocolDecoder.java
@@ -151,7 +151,7 @@ public class Jt600ProtocolDecoder extends BaseProtocolDecoder {
Position position = new Position();
position.setProtocol(getProtocolName());
- position.set(Position.KEY_ALARM, true);
+ position.set(Position.KEY_ALARM, Position.ALARM_GENERAL);
DeviceSession deviceSession = getDeviceSession(channel, remoteAddress, parser.next());
if (deviceSession == null) {
diff --git a/src/org/traccar/protocol/MeiligaoProtocolDecoder.java b/src/org/traccar/protocol/MeiligaoProtocolDecoder.java
index 9c7e9ea23..41e248791 100644
--- a/src/org/traccar/protocol/MeiligaoProtocolDecoder.java
+++ b/src/org/traccar/protocol/MeiligaoProtocolDecoder.java
@@ -151,6 +151,27 @@ public class MeiligaoProtocolDecoder extends BaseProtocolDecoder {
return server;
}
+ private String decodeAlarm(short value) {
+ switch (value) {
+ case 0x01:
+ return Position.ALARM_SOS;
+ case 0x10:
+ return Position.ALARM_LOW_BATTERY;
+ case 0x11:
+ return Position.ALARM_OVERSPEED;
+ case 0x12:
+ return Position.ALARM_MOVEMENT;
+ case 0x13:
+ return Position.ALARM_GEOFENCE_ENTER;
+ case 0x50:
+ return Position.ALARM_POWER_OFF;
+ case 0x53:
+ return Position.ALARM_GPS_ANTENNA_CUT;
+ default:
+ return null;
+ }
+ }
+
@Override
protected Object decode(
Channel channel, SocketAddress remoteAddress, Object msg) throws Exception {
@@ -196,7 +217,7 @@ public class MeiligaoProtocolDecoder extends BaseProtocolDecoder {
// Custom data
if (command == MSG_ALARM) {
- position.set(Position.KEY_ALARM, buf.readUnsignedByte());
+ position.set(Position.KEY_ALARM, decodeAlarm(buf.readUnsignedByte()));
} else if (command == MSG_POSITION_LOGGED) {
buf.skipBytes(6);
}
diff --git a/src/org/traccar/protocol/MxtProtocolDecoder.java b/src/org/traccar/protocol/MxtProtocolDecoder.java
index 56024057e..1dbfc3696 100644
--- a/src/org/traccar/protocol/MxtProtocolDecoder.java
+++ b/src/org/traccar/protocol/MxtProtocolDecoder.java
@@ -82,7 +82,9 @@ public class MxtProtocolDecoder extends BaseProtocolDecoder {
long flags = buf.readUnsignedInt();
position.set(Position.KEY_IGNITION, BitUtil.check(flags, 0));
- position.set(Position.KEY_ALARM, BitUtil.check(flags, 1));
+ if (BitUtil.check(flags, 1)) {
+ position.set(Position.KEY_ALARM, Position.ALARM_GENERAL);
+ }
position.set(Position.KEY_INPUT, BitUtil.between(flags, 2, 7));
position.set(Position.KEY_OUTPUT, BitUtil.between(flags, 7, 10));
position.setCourse(BitUtil.between(flags, 10, 13) * 45);
diff --git a/src/org/traccar/protocol/NavisProtocolDecoder.java b/src/org/traccar/protocol/NavisProtocolDecoder.java
index fad24301c..72c5f53c3 100644
--- a/src/org/traccar/protocol/NavisProtocolDecoder.java
+++ b/src/org/traccar/protocol/NavisProtocolDecoder.java
@@ -95,7 +95,11 @@ public class NavisProtocolDecoder extends BaseProtocolDecoder {
buf.skipBytes(6); // event time
- position.set(Position.KEY_ALARM, buf.readUnsignedByte());
+ short armedStatus = buf.readUnsignedByte();
+ position.set(Position.KEY_ARMED, armedStatus & 0x7F);
+ if (BitUtil.check(armedStatus, 7)) {
+ position.set(Position.KEY_ALARM, Position.ALARM_GENERAL);
+ }
position.set(Position.KEY_STATUS, buf.readUnsignedByte());
position.set(Position.KEY_GSM, buf.readUnsignedByte());
diff --git a/src/org/traccar/protocol/NoranProtocolDecoder.java b/src/org/traccar/protocol/NoranProtocolDecoder.java
index c2161d9c9..aaecfc1db 100644
--- a/src/org/traccar/protocol/NoranProtocolDecoder.java
+++ b/src/org/traccar/protocol/NoranProtocolDecoder.java
@@ -90,7 +90,23 @@ public class NoranProtocolDecoder extends BaseProtocolDecoder {
position.setValid(BitUtil.check(buf.readUnsignedByte(), 0));
- position.set(Position.KEY_ALARM, buf.readUnsignedByte());
+ short alarm = buf.readUnsignedByte();
+ switch (alarm) {
+ case 1:
+ position.set(Position.KEY_ALARM, Position.ALARM_SOS);
+ break;
+ case 2:
+ position.set(Position.KEY_ALARM, Position.ALARM_OVERSPEED);
+ break;
+ case 3:
+ position.set(Position.KEY_ALARM, Position.ALARM_GEOFENCE_EXIT);
+ break;
+ case 9:
+ position.set(Position.KEY_ALARM, Position.ALARM_POWER_OFF);
+ break;
+ default:
+ break;
+ }
if (newFormat) {
position.setSpeed(UnitsConverter.knotsFromKph(buf.readUnsignedInt()));
diff --git a/src/org/traccar/protocol/ObdDongleProtocol.java b/src/org/traccar/protocol/ObdDongleProtocol.java
new file mode 100644
index 000000000..e87f9a99a
--- /dev/null
+++ b/src/org/traccar/protocol/ObdDongleProtocol.java
@@ -0,0 +1,43 @@
+/*
+ * Copyright 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.
+ * 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.protocol;
+
+import org.jboss.netty.bootstrap.ServerBootstrap;
+import org.jboss.netty.channel.ChannelPipeline;
+import org.jboss.netty.handler.codec.frame.LengthFieldBasedFrameDecoder;
+import org.traccar.BaseProtocol;
+import org.traccar.TrackerServer;
+
+import java.util.List;
+
+public class ObdDongleProtocol extends BaseProtocol {
+
+ public ObdDongleProtocol() {
+ super("obddongle");
+ }
+
+ @Override
+ public void initTrackerServers(List<TrackerServer> serverList) {
+ serverList.add(new TrackerServer(new ServerBootstrap(), this.getName()) {
+ @Override
+ protected void addSpecificHandlers(ChannelPipeline pipeline) {
+ pipeline.addLast("frameDecoder", new LengthFieldBasedFrameDecoder(1099, 20, 2, 3, 0));
+ pipeline.addLast("objectDecoder", new ObdDongleProtocolDecoder(ObdDongleProtocol.this));
+ }
+ });
+ }
+
+}
diff --git a/src/org/traccar/protocol/ObdDongleProtocolDecoder.java b/src/org/traccar/protocol/ObdDongleProtocolDecoder.java
new file mode 100644
index 000000000..84ff1450a
--- /dev/null
+++ b/src/org/traccar/protocol/ObdDongleProtocolDecoder.java
@@ -0,0 +1,128 @@
+/*
+ * Copyright 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.
+ * 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.protocol;
+
+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.DeviceSession;
+import org.traccar.helper.BitUtil;
+import org.traccar.helper.UnitsConverter;
+import org.traccar.model.Position;
+
+import java.net.SocketAddress;
+import java.nio.charset.StandardCharsets;
+import java.util.Date;
+
+public class ObdDongleProtocolDecoder extends BaseProtocolDecoder {
+
+ public ObdDongleProtocolDecoder(ObdDongleProtocol protocol) {
+ super(protocol);
+ }
+
+ public static final int MSG_TYPE_CONNECT = 0x01;
+ public static final int MSG_TYPE_CONNACK = 0x02;
+ public static final int MSG_TYPE_PUBLISH = 0x03;
+ public static final int MSG_TYPE_PUBACK = 0x04;
+ public static final int MSG_TYPE_PINGREQ = 0x0C;
+ public static final int MSG_TYPE_PINGRESP = 0x0D;
+ public static final int MSG_TYPE_DISCONNECT = 0x0E;
+
+ private static void sendResponse(Channel channel, int type, int index, String imei, ChannelBuffer content) {
+ if (channel != null) {
+ ChannelBuffer response = ChannelBuffers.dynamicBuffer();
+ response.writeShort(0x5555); // header
+ response.writeShort(index);
+ response.writeBytes(imei.getBytes(StandardCharsets.US_ASCII));
+ response.writeByte(type);
+ response.writeShort(content.readableBytes());
+ response.writeBytes(content);
+ response.writeByte(0); // checksum
+ response.writeShort(0xAAAA);
+ channel.write(response);
+ }
+ }
+
+ @Override
+ protected Object decode(
+ Channel channel, SocketAddress remoteAddress, Object msg) throws Exception {
+
+ ChannelBuffer buf = (ChannelBuffer) msg;
+
+ buf.skipBytes(2); // header
+ int index = buf.readUnsignedShort();
+
+ String imei = buf.readBytes(15).toString(StandardCharsets.US_ASCII);
+ DeviceSession deviceSession = getDeviceSession(channel, remoteAddress, imei);
+ if (deviceSession == null) {
+ return null;
+ }
+
+ int type = buf.readUnsignedByte();
+
+ buf.readUnsignedShort(); // data length
+
+ if (type == MSG_TYPE_CONNECT) {
+
+ ChannelBuffer response = ChannelBuffers.dynamicBuffer();
+ response.writeByte(1);
+ response.writeShort(0);
+ response.writeInt(0);
+ sendResponse(channel, MSG_TYPE_CONNACK, index, imei, response);
+
+ } else if (type == MSG_TYPE_PUBLISH) {
+
+ int typeMajor = buf.readUnsignedByte();
+ int typeMinor = buf.readUnsignedByte();
+
+ buf.readUnsignedByte(); // event id
+
+ Position position = new Position();
+ position.setProtocol(getProtocolName());
+ position.setDeviceId(deviceSession.getDeviceId());
+
+ position.setTime(new Date(buf.readUnsignedInt() * 1000));
+
+ int flags = buf.readUnsignedByte();
+
+ position.setValid(!BitUtil.check(flags, 6));
+
+ position.set(Position.KEY_SATELLITES, BitUtil.to(flags, 4));
+
+ double longitude = ((BitUtil.to(buf.readUnsignedShort(), 1) << 24) + buf.readUnsignedMedium()) * 0.00001;
+ position.setLongitude(BitUtil.check(flags, 5) ? longitude : -longitude);
+
+ double latitude = buf.readUnsignedMedium() * 0.00001;
+ position.setLatitude(BitUtil.check(flags, 4) ? latitude : -latitude);
+
+ int speedCourse = buf.readUnsignedMedium();
+ position.setSpeed(UnitsConverter.knotsFromMph(BitUtil.from(speedCourse, 10) * 0.1));
+ position.setCourse(BitUtil.to(speedCourse, 10));
+
+ ChannelBuffer response = ChannelBuffers.dynamicBuffer();
+ response.writeByte(typeMajor);
+ response.writeByte(typeMinor);
+ sendResponse(channel, MSG_TYPE_PUBACK, index, imei, response);
+
+ return position;
+
+ }
+
+ return null;
+ }
+
+}
diff --git a/src/org/traccar/protocol/ProgressProtocolDecoder.java b/src/org/traccar/protocol/ProgressProtocolDecoder.java
index e524626fa..0032a9a1b 100644
--- a/src/org/traccar/protocol/ProgressProtocolDecoder.java
+++ b/src/org/traccar/protocol/ProgressProtocolDecoder.java
@@ -104,7 +104,7 @@ public class ProgressProtocolDecoder extends BaseProtocolDecoder {
position.set(Position.KEY_ARCHIVE, true);
int subtype = buf.readUnsignedShort();
if (subtype == MSG_ALARM) {
- position.set(Position.KEY_ALARM, true);
+ position.set(Position.KEY_ALARM, Position.ALARM_GENERAL);
}
if (buf.readUnsignedShort() > buf.readableBytes()) {
lastIndex += 1;
diff --git a/src/org/traccar/protocol/SuntechProtocolDecoder.java b/src/org/traccar/protocol/SuntechProtocolDecoder.java
index 5169e7c67..503f4d6f8 100644
--- a/src/org/traccar/protocol/SuntechProtocolDecoder.java
+++ b/src/org/traccar/protocol/SuntechProtocolDecoder.java
@@ -68,7 +68,7 @@ public class SuntechProtocolDecoder extends BaseProtocolDecoder {
if (parser.hasNext()) {
String type = parser.next();
if (type.equals("Alert") || type.equals("Emergency")) {
- position.set(Position.KEY_ALARM, true);
+ position.set(Position.KEY_ALARM, Position.ALARM_GENERAL);
}
}
diff --git a/src/org/traccar/protocol/TeltonikaProtocolDecoder.java b/src/org/traccar/protocol/TeltonikaProtocolDecoder.java
index d982b07b3..00ab90ce0 100644
--- a/src/org/traccar/protocol/TeltonikaProtocolDecoder.java
+++ b/src/org/traccar/protocol/TeltonikaProtocolDecoder.java
@@ -67,6 +67,32 @@ public class TeltonikaProtocolDecoder extends BaseProtocolDecoder {
}
+ private void decodeParameter(Position position, int id, long value) {
+ switch (id) {
+ case 9:
+ position.set(Position.PREFIX_ADC + 1, value);
+ break;
+ case 66:
+ position.set(Position.KEY_POWER, value);
+ break;
+ case 68:
+ position.set(Position.KEY_BATTERY, value);
+ break;
+ case 85:
+ position.set(Position.KEY_RPM, value);
+ break;
+ case 182:
+ position.set(Position.KEY_HDOP, value);
+ break;
+ case 239:
+ position.set(Position.KEY_IGNITION, value == 1);
+ break;
+ default:
+ position.set(Position.PREFIX_IO + id, value);
+ break;
+ }
+ }
+
private void decodeLocation(Position position, ChannelBuffer buf, int codec) {
int globalMask = 0x0f;
@@ -153,12 +179,7 @@ public class TeltonikaProtocolDecoder extends BaseProtocolDecoder {
if (BitUtil.check(globalMask, 1)) {
int cnt = buf.readUnsignedByte();
for (int j = 0; j < cnt; j++) {
- int id = buf.readUnsignedByte();
- if (id == 1) {
- position.set(Position.KEY_POWER, buf.readUnsignedByte());
- } else {
- position.set(Position.PREFIX_IO + id, buf.readUnsignedByte());
- }
+ decodeParameter(position, buf.readUnsignedByte(), buf.readUnsignedByte());
}
}
@@ -166,7 +187,7 @@ public class TeltonikaProtocolDecoder extends BaseProtocolDecoder {
if (BitUtil.check(globalMask, 2)) {
int cnt = buf.readUnsignedByte();
for (int j = 0; j < cnt; j++) {
- position.set(Position.PREFIX_IO + buf.readUnsignedByte(), buf.readUnsignedShort());
+ decodeParameter(position, buf.readUnsignedByte(), buf.readUnsignedShort());
}
}
@@ -174,7 +195,7 @@ public class TeltonikaProtocolDecoder extends BaseProtocolDecoder {
if (BitUtil.check(globalMask, 3)) {
int cnt = buf.readUnsignedByte();
for (int j = 0; j < cnt; j++) {
- position.set(Position.PREFIX_IO + buf.readUnsignedByte(), buf.readUnsignedInt());
+ decodeParameter(position, buf.readUnsignedByte(), buf.readUnsignedInt());
}
}
@@ -182,7 +203,7 @@ public class TeltonikaProtocolDecoder extends BaseProtocolDecoder {
if (codec == CODEC_FM4X00) {
int cnt = buf.readUnsignedByte();
for (int j = 0; j < cnt; j++) {
- position.set(Position.PREFIX_IO + buf.readUnsignedByte(), buf.readLong());
+ decodeParameter(position, buf.readUnsignedByte(), buf.readLong());
}
}
diff --git a/src/org/traccar/protocol/Tk103ProtocolDecoder.java b/src/org/traccar/protocol/Tk103ProtocolDecoder.java
index a76c208b5..ac99a1440 100644
--- a/src/org/traccar/protocol/Tk103ProtocolDecoder.java
+++ b/src/org/traccar/protocol/Tk103ProtocolDecoder.java
@@ -1,5 +1,5 @@
/*
- * Copyright 2012 - 2015 Anton Tananaev (anton.tananaev@gmail.com)
+ * Copyright 2012 - 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.
@@ -51,6 +51,7 @@ public class Tk103ProtocolDecoder extends BaseProtocolDecoder {
.number("(?:([01]{8})|(x{8}))?,?") // state
.number("(?:L(x+))?") // odometer
.any()
+ .number("([+-]ddd.d)?") // temperature
.text(")").optional()
.compile();
@@ -75,6 +76,25 @@ public class Tk103ProtocolDecoder extends BaseProtocolDecoder {
.any()
.compile();
+ private String decodeAlarm(int value) {
+ switch (value) {
+ case 1:
+ return Position.ALARM_ACCIDENT;
+ case 2:
+ return Position.ALARM_SOS;
+ case 3:
+ return Position.ALARM_VIBRATION;
+ case 4:
+ return Position.ALARM_LOW_SPEED;
+ case 5:
+ return Position.ALARM_OVERSPEED;
+ case 6:
+ return Position.ALARM_GEOFENCE_EXIT;
+ default:
+ return null;
+ }
+ }
+
@Override
protected Object decode(
Channel channel, SocketAddress remoteAddress, Object msg) throws Exception {
@@ -160,7 +180,7 @@ public class Tk103ProtocolDecoder extends BaseProtocolDecoder {
int alarm = sentence.indexOf("BO01");
if (alarm != -1) {
- position.set(Position.KEY_ALARM, Integer.parseInt(sentence.substring(alarm + 4, alarm + 5)));
+ position.set(Position.KEY_ALARM, decodeAlarm(Integer.parseInt(sentence.substring(alarm + 4, alarm + 5))));
}
DateBuilder dateBuilder = new DateBuilder();
@@ -206,6 +226,10 @@ public class Tk103ProtocolDecoder extends BaseProtocolDecoder {
position.set(Position.KEY_ODOMETER, parser.nextLong(16));
}
+ if (parser.hasNext()) {
+ position.set(Position.PREFIX_TEMP + 1, parser.nextDouble());
+ }
+
return position;
}
diff --git a/src/org/traccar/protocol/TotemProtocolDecoder.java b/src/org/traccar/protocol/TotemProtocolDecoder.java
index 7b196f5ad..72c0f6306 100644
--- a/src/org/traccar/protocol/TotemProtocolDecoder.java
+++ b/src/org/traccar/protocol/TotemProtocolDecoder.java
@@ -159,6 +159,23 @@ public class TotemProtocolDecoder extends BaseProtocolDecoder {
.any()
.compile();
+ private String decodeAlarm(Short value) {
+ switch (value) {
+ case 0x01:
+ return Position.ALARM_SOS;
+ case 0x10:
+ return Position.ALARM_LOW_BATTERY;
+ case 0x11:
+ return Position.ALARM_OVERSPEED;
+ case 0x42:
+ return Position.ALARM_GEOFENCE_EXIT;
+ case 0x43:
+ return Position.ALARM_GEOFENCE_ENTER;
+ default:
+ return null;
+ }
+ }
+
@Override
protected Object decode(
Channel channel, SocketAddress remoteAddress, Object msg) throws Exception {
@@ -193,9 +210,9 @@ public class TotemProtocolDecoder extends BaseProtocolDecoder {
position.setDeviceId(deviceSession.getDeviceId());
if (pattern == PATTERN1 || pattern == PATTERN2) {
-
- position.set(Position.KEY_ALARM, parser.next());
-
+ if (parser.hasNext()) {
+ position.set(Position.KEY_ALARM, decodeAlarm(Short.parseShort(parser.next(), 16)));
+ }
DateBuilder dateBuilder = new DateBuilder();
int year = 0;
if (pattern == PATTERN2) {
@@ -238,9 +255,9 @@ public class TotemProtocolDecoder extends BaseProtocolDecoder {
position.set(Position.KEY_ODOMETER, parser.next());
} else if (pattern == PATTERN3) {
-
- position.set(Position.KEY_ALARM, parser.next());
-
+ if (parser.hasNext()) {
+ position.set(Position.KEY_ALARM, decodeAlarm(Short.parseShort(parser.next(), 16)));
+ }
DateBuilder dateBuilder = new DateBuilder()
.setDateReverse(parser.nextInt(), parser.nextInt(), parser.nextInt())
.setTime(parser.nextInt(), parser.nextInt(), parser.nextInt());
@@ -304,11 +321,9 @@ public class TotemProtocolDecoder extends BaseProtocolDecoder {
position.setLongitude(parser.nextCoordinate());
}
-
if (channel != null) {
channel.write("ACK OK\r\n");
}
-
return position;
}
diff --git a/src/org/traccar/protocol/UlbotechProtocolDecoder.java b/src/org/traccar/protocol/UlbotechProtocolDecoder.java
index c17341b5f..36fb23f9a 100644
--- a/src/org/traccar/protocol/UlbotechProtocolDecoder.java
+++ b/src/org/traccar/protocol/UlbotechProtocolDecoder.java
@@ -115,6 +115,25 @@ public class UlbotechProtocolDecoder extends BaseProtocolDecoder {
}
}
+ private String decodeAlarm(int alarm) {
+ if (BitUtil.check(alarm, 0)) {
+ return Position.ALARM_POWER_OFF;
+ }
+ if (BitUtil.check(alarm, 1)) {
+ return Position.ALARM_MOTION;
+ }
+ if (BitUtil.check(alarm, 2)) {
+ return Position.ALARM_OVERSPEED;
+ }
+ if (BitUtil.check(alarm, 4)) {
+ return Position.ALARM_GEOFENCE;
+ }
+ if (BitUtil.check(alarm, 10)) {
+ return Position.ALARM_SOS;
+ }
+ return null;
+ }
+
@Override
protected Object decode(
Channel channel, SocketAddress remoteAddress, Object msg) throws Exception {
@@ -181,7 +200,7 @@ public class UlbotechProtocolDecoder extends BaseProtocolDecoder {
int status = buf.readUnsignedShort();
position.set(Position.KEY_IGNITION, BitUtil.check(status, 9));
position.set(Position.KEY_STATUS, status);
- position.set(Position.KEY_ALARM, buf.readUnsignedShort());
+ position.set(Position.KEY_ALARM, decodeAlarm(buf.readUnsignedShort()));
break;
case DATA_ODOMETER:
diff --git a/test/org/traccar/protocol/CastelProtocolDecoderTest.java b/test/org/traccar/protocol/CastelProtocolDecoderTest.java
index eafe80748..feba9386e 100644
--- a/test/org/traccar/protocol/CastelProtocolDecoderTest.java
+++ b/test/org/traccar/protocol/CastelProtocolDecoderTest.java
@@ -13,6 +13,12 @@ public class CastelProtocolDecoderTest extends ProtocolTest {
CastelProtocolDecoder decoder = new CastelProtocolDecoder(new CastelProtocol());
verifyPosition(decoder, binary(ByteOrder.LITTLE_ENDIAN,
+ "40403600043231334e583230313630303033343600000000004009ad31a457050810061a35b29bf80ae6da83180300320bbe32580d0a40403600043231334e583230313630303033343600000000004009ad31a457050810061a35b29bf80ae6da83180300320bbe32580d0a"));
+
+ verifyNothing(decoder, binary(ByteOrder.LITTLE_ENDIAN,
+ "4040d400043535333133350000000000000000000000000000100196d499574bd899570000000000000000010000000000000000000000002410000000004944445f3231334730325f532056322e332e345f4e004944445f3231334730325f482056322e332e345f4e0032000110021003100410051006100710081009100a100b100c100d100e1011100111021103110411051106110711011202120312041201130213031301160216011701180218011b011c011d011e011f021f031f041f051f061f071f012102210126012701285b410d0a"));
+
+ verifyPosition(decoder, binary(ByteOrder.LITTLE_ENDIAN,
"24243f00676e6768656636313031313132393030313734002001840d0000d2deb556020602100b35360456cf09e6ebac0200000000030000000001abc10d0a"));
verifyPosition(decoder, binary(ByteOrder.LITTLE_ENDIAN,
diff --git a/test/org/traccar/protocol/ObdDongleProtocolDecoderTest.java b/test/org/traccar/protocol/ObdDongleProtocolDecoderTest.java
new file mode 100644
index 000000000..19e3a4ff2
--- /dev/null
+++ b/test/org/traccar/protocol/ObdDongleProtocolDecoderTest.java
@@ -0,0 +1,22 @@
+package org.traccar.protocol;
+
+import org.junit.Test;
+import org.traccar.ProtocolTest;
+
+public class ObdDongleProtocolDecoderTest extends ProtocolTest {
+
+ @Test
+ public void testDecode() throws Exception {
+
+ ObdDongleProtocolDecoder decoder = new ObdDongleProtocolDecoder(new ObdDongleProtocol());
+
+ verifyNothing(decoder, binary(
+ "55550003383634383637303232353131303135010009010011023402010201ABAAAA"));
+
+ verifyPosition(decoder, binary(
+ "5555000338363438363730323235313130313503000100010355AABBCC184F1ABC614E21C1FA08712A84ABAAAA"),
+ position("2015-07-18 20:49:16.000", true, 22.12346, -123.45678));
+
+ }
+
+}
diff --git a/test/org/traccar/protocol/Tk103ProtocolDecoderTest.java b/test/org/traccar/protocol/Tk103ProtocolDecoderTest.java
index b15d7894e..c1bf148bc 100644
--- a/test/org/traccar/protocol/Tk103ProtocolDecoderTest.java
+++ b/test/org/traccar/protocol/Tk103ProtocolDecoderTest.java
@@ -10,6 +10,12 @@ public class Tk103ProtocolDecoderTest extends ProtocolTest {
Tk103ProtocolDecoder decoder = new Tk103ProtocolDecoder(new Tk103Protocol());
+ verifyPosition(decoder, text(
+ "(088046338039BR00160727A3354.7768N03540.7258E000.0140832068.4700000000L00BEB0D4+017.7)"));
+
+ verifyPosition(decoder, text(
+ "(088046338039BP05000088046338039160727A3354.7768N03540.7258E000.0140309065.1000000000L00BEB0D4+017.3)"));
+
verifyAttributes(decoder, text(
"(013632651491,ZC20,180716,144222,6,392,65535,255"));
diff --git a/tools/test-generator.py b/tools/test-generator.py
index b4edbfbaf..41a32a565 100755
--- a/tools/test-generator.py
+++ b/tools/test-generator.py
@@ -37,7 +37,7 @@ def send(conn, lat, lon, course, alarm):
if alarm:
params = params + (('alarm', 'sos'),)
conn.request('GET', '?' + urllib.urlencode(params))
- conn.getresponse()
+ conn.getresponse().read()
def course(lat1, lon1, lat2, lon2):
lat1 = lat1 * math.pi / 180
@@ -58,4 +58,4 @@ while True:
alarm = ((index % 10) == 0)
send(conn, lat1, lon1, course(lat1, lon1, lat2, lon2), alarm)
time.sleep(period)
- index += 1 \ No newline at end of file
+ index += 1
diff --git a/web/app/view/Login.js b/web/app/view/Login.js
index 259086854..db3c55261 100644
--- a/web/app/view/Login.js
+++ b/web/app/view/Login.js
@@ -77,8 +77,8 @@ Ext.define('Traccar.view.Login', {
inputAttrTpl: ['autocomplete="on"']
}, {
xtype: 'checkboxfield',
- reference: 'rememberMeField',
- fieldLabel: Strings.rememberMe
+ reference: 'rememberField',
+ fieldLabel: Strings.userRemember
}, {
xtype: 'component',
html: '<iframe id="submitTarget" name="submitTarget" style="display:none"></iframe>'
diff --git a/web/l10n/en.json b/web/l10n/en.json
index c64d06b45..37e4537f2 100644
--- a/web/l10n/en.json
+++ b/web/l10n/en.json
@@ -30,7 +30,7 @@
"userEmail": "Email",
"userPassword": "Password",
"userAdmin": "Admin",
- "rememberMe": "Remember Me",
+ "userRemember": "Remember",
"loginTitle": "Login",
"loginLanguage": "Language",
"loginRegister": "Register",