aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorAnton Tananaev <anton.tananaev@gmail.com>2013-06-02 22:51:54 +1200
committerAnton Tananaev <anton.tananaev@gmail.com>2013-06-02 22:51:54 +1200
commitb16593f062d304e000899085b22d1232b055639b (patch)
tree2a25f5162d46aa6261416c4859beca4b691a24e0
parent78585a5d92c3c6ab7aed275ffad5e412a6efd707 (diff)
downloadtraccar-server-b16593f062d304e000899085b22d1232b055639b.tar.gz
traccar-server-b16593f062d304e000899085b22d1232b055639b.tar.bz2
traccar-server-b16593f062d304e000899085b22d1232b055639b.zip
Update Apel decoder
-rw-r--r--src/org/traccar/helper/Crc.java9
-rw-r--r--src/org/traccar/protocol/ApelProtocolDecoder.java188
2 files changed, 88 insertions, 109 deletions
diff --git a/src/org/traccar/helper/Crc.java b/src/org/traccar/helper/Crc.java
index a7adca874..84224a781 100644
--- a/src/org/traccar/helper/Crc.java
+++ b/src/org/traccar/helper/Crc.java
@@ -17,6 +17,7 @@ package org.traccar.helper;
import java.nio.ByteBuffer;
import java.nio.charset.Charset;
+import java.util.zip.CRC32;
/**
* CRC functions
@@ -127,6 +128,14 @@ public class Crc {
public static int crc16CcittSeed(ByteBuffer buf, int seed) {
return crc16Reflected(buf, seed, crc16CcittTableReverse) ^ crc16CcittXorout;
}
+
+ public static int crc32(ByteBuffer buf) {
+ CRC32 checksum = new CRC32();
+ for (int i = 0; i < buf.remaining(); i++) {
+ checksum.update(buf.get(i));
+ }
+ return (int) checksum.getValue();
+ }
public static String nmeaChecksum(String msg) {
int checksum = 0;
diff --git a/src/org/traccar/protocol/ApelProtocolDecoder.java b/src/org/traccar/protocol/ApelProtocolDecoder.java
index fec92b33e..4a4596591 100644
--- a/src/org/traccar/protocol/ApelProtocolDecoder.java
+++ b/src/org/traccar/protocol/ApelProtocolDecoder.java
@@ -30,6 +30,7 @@ import org.jboss.netty.channel.ChannelHandlerContext;
import org.traccar.BaseProtocolDecoder;
import org.traccar.ServerManager;
import org.traccar.helper.AdvancedConnection;
+import org.traccar.helper.Crc;
import org.traccar.helper.Log;
import org.traccar.helper.NamedParameterStatement;
import org.traccar.model.ExtendedInfoFormatter;
@@ -48,43 +49,34 @@ public class ApelProtocolDecoder extends BaseProtocolDecoder {
/*
* Message types
*/
- /*private static final int MSG_NULL = 0;
- private static final int MSG_IDENT = 1;
- private static final int MSG_IDENT_FULL = 2;
- private static final int MSG_POINT = 10;
- private static final int MSG_LOG_SYNC = 100;
- private static final int MSG_LOGMSG = 101;
- private static final int MSG_TEXT = 102;
- private static final int MSG_ALARM = 200;
- private static final int MSG_ALARM_RECIEVED = 201;*/
- private static final int MSG_TYPE_NULL = 0;
- private static final int MSG_TYPE_REQUEST_TRACKER_ID = 10;
- private static final int MSG_TYPE_TRACKER_ID = 11;
- private static final int MSG_TYPE_TRACKER_ID_EXT = 12;
- private static final int MSG_TYPE_DISCONNECT = 20;
- private static final int MSG_TYPE_REQUEST_PASSWORD = 30;
- private static final int MSG_TYPE_PASSWORD = 31;
- private static final int MSG_TYPE_REQUEST_STATE_FULL_INFO = 90;
- private static final int MSG_TYPE_STATE_FULL_INFO_T104 = 92;
- private static final int MSG_TYPE_REQUEST_CURRENT_GPS_DATA = 100;
- private static final int MSG_TYPE_CURRENT_GPS_DATA = 101;
- private static final int MSG_TYPE_REQUEST_SENSORS_STATE = 110;
- private static final int MSG_TYPE_SENSORS_STATE = 111;
- private static final int MSG_TYPE_SENSORS_STATE_T100 = 112;
- private static final int MSG_TYPE_SENSORS_STATE_T100_4 = 113;
- private static final int MSG_TYPE_REQUEST_LAST_LOG_INDEX = 120;
- private static final int MSG_TYPE_LAST_LOG_INDEX = 121;
- private static final int MSG_TYPE_REQUEST_LOG_RECORDS = 130;
- private static final int MSG_TYPE_LOG_RECORDS = 131;
- private static final int MSG_TYPE_EVENT = 141;
- private static final int MSG_TYPE_TEXT = 150;
- private static final int MSG_TYPE_ACK_ALARM = 160;
- private static final int MSG_TYPE_SET_TRACKER_MODE = 170;
- private static final int MSG_TYPE_GPRS_COMMAND = 180;
+ private static final short MSG_TYPE_NULL = 0;
+ private static final short MSG_TYPE_REQUEST_TRACKER_ID = 10;
+ private static final short MSG_TYPE_TRACKER_ID = 11;
+ private static final short MSG_TYPE_TRACKER_ID_EXT = 12;
+ private static final short MSG_TYPE_DISCONNECT = 20;
+ private static final short MSG_TYPE_REQUEST_PASSWORD = 30;
+ private static final short MSG_TYPE_PASSWORD = 31;
+ private static final short MSG_TYPE_REQUEST_STATE_FULL_INFO = 90;
+ private static final short MSG_TYPE_STATE_FULL_INFO_T104 = 92;
+ private static final short MSG_TYPE_REQUEST_CURRENT_GPS_DATA = 100;
+ private static final short MSG_TYPE_CURRENT_GPS_DATA = 101;
+ private static final short MSG_TYPE_REQUEST_SENSORS_STATE = 110;
+ private static final short MSG_TYPE_SENSORS_STATE = 111;
+ private static final short MSG_TYPE_SENSORS_STATE_T100 = 112;
+ private static final short MSG_TYPE_SENSORS_STATE_T100_4 = 113;
+ private static final short MSG_TYPE_REQUEST_LAST_LOG_INDEX = 120;
+ private static final short MSG_TYPE_LAST_LOG_INDEX = 121;
+ private static final short MSG_TYPE_REQUEST_LOG_RECORDS = 130;
+ private static final short MSG_TYPE_LOG_RECORDS = 131;
+ private static final short MSG_TYPE_EVENT = 141;
+ private static final short MSG_TYPE_TEXT = 150;
+ private static final short MSG_TYPE_ACK_ALARM = 160;
+ private static final short MSG_TYPE_SET_TRACKER_MODE = 170;
+ private static final short MSG_TYPE_GPRS_COMMAND = 180;
private static final String HEX_CHARS = "0123456789ABCDEF";
- /*private void loadLastIndex() {
+ private void loadLastIndex() {
try {
Properties p = getServerManager().getProperties();
if (p.contains("database.selectLastIndex")) {
@@ -100,20 +92,29 @@ public class ApelProtocolDecoder extends BaseProtocolDecoder {
}
} catch(Exception error) {
}
- }*/
+ }
+
+ private void sendSimpleMessage(Channel channel, short type) {
+ ChannelBuffer request = ChannelBuffers.directBuffer(ByteOrder.LITTLE_ENDIAN, 8);
+ request.writeShort(type);
+ request.writeShort(0);
+ request.writeInt(Crc.crc32(request.toByteBuffer(0, 4)));
+ channel.write(request);
+ }
- /*private void requestArchive(Channel channel) {
+ private void requestArchive(Channel channel) {
if (lastIndex == 0) {
lastIndex = newIndex;
} else if (newIndex > lastIndex) {
- ChannelBuffer request = ChannelBuffers.directBuffer(ByteOrder.LITTLE_ENDIAN, 12);
- request.writeShort(MSG_LOG_SYNC);
- request.writeShort(4);
+ ChannelBuffer request = ChannelBuffers.directBuffer(ByteOrder.LITTLE_ENDIAN, 14);
+ request.writeShort(MSG_TYPE_REQUEST_LOG_RECORDS);
+ request.writeShort(6);
request.writeInt((int) lastIndex);
- request.writeInt(0);
+ request.writeShort(512);
+ request.writeInt(Crc.crc32(request.toByteBuffer(0, 10)));
channel.write(request);
}
- }*/
+ }
@Override
protected Object decode(
@@ -126,6 +127,10 @@ public class ApelProtocolDecoder extends BaseProtocolDecoder {
type = type & 0x7FFF;
buf.readUnsignedShort(); // length
+ if (alarm) {
+ sendSimpleMessage(channel, MSG_TYPE_ACK_ALARM);
+ }
+
if (type == MSG_TYPE_TRACKER_ID) {
Log.warning("Unsupported authentication type");
return null;
@@ -139,20 +144,28 @@ public class ApelProtocolDecoder extends BaseProtocolDecoder {
String imei = buf.readBytes(length).toString(Charset.defaultCharset());
try {
deviceId = getDataManager().getDeviceByImei(imei).getId();
- //loadLastIndex();
+ loadLastIndex();
} catch(Exception error) {
Log.warning("Unknown device - " + imei + " (id - " + id + ")");
}
}
+
+ else if (type == MSG_TYPE_LAST_LOG_INDEX) {
+ long index = buf.readUnsignedInt();
+ if (index > 0) {
+ newIndex = index - 1;
+ requestArchive(channel);
+ }
+ }
// Position
- else if (deviceId != 0 && (type == MSG_TYPE_CURRENT_GPS_DATA || type == MSG_TYPE_STATE_FULL_INFO_T104)) {
+ else if (deviceId != 0 && (type == MSG_TYPE_CURRENT_GPS_DATA || type == MSG_TYPE_STATE_FULL_INFO_T104 || type == MSG_TYPE_LOG_RECORDS)) {
List<Position> positions = new LinkedList<Position>();
int recordCount = 1;
- /*if (type == MSG_LOGMSG) {
+ if (type == MSG_TYPE_LOG_RECORDS) {
recordCount = buf.readUnsignedShort();
- }*/
+ }
for (int j = 0; j < recordCount; j++) {
Position position = new Position();
@@ -160,21 +173,17 @@ public class ApelProtocolDecoder extends BaseProtocolDecoder {
position.setDeviceId(deviceId);
// Message index
- /*if (type == MSG_LOGMSG) {
+ if (type == MSG_TYPE_LOG_RECORDS) {
extendedInfo.set("archive", true);
- int subtype = buf.readUnsignedShort();
- if (subtype == MSG_ALARM) {
- extendedInfo.set("alarm", true);
- }
- if (buf.readUnsignedShort() > buf.readableBytes()) {
- lastIndex += 1;
- break; // workaround for device bug
- }
lastIndex = buf.readUnsignedInt();
position.setId(lastIndex);
- } else {
- newIndex = buf.readUnsignedInt();
- }*/
+
+ int subtype = buf.readUnsignedShort();
+ if (subtype != MSG_TYPE_CURRENT_GPS_DATA) {
+ buf.skipBytes(buf.readUnsignedShort());
+ continue;
+ }
+ }
// Time
Calendar time = Calendar.getInstance(TimeZone.getTimeZone("UTC"));
@@ -189,15 +198,15 @@ public class ApelProtocolDecoder extends BaseProtocolDecoder {
position.setLongitude(buf.readInt() * 180.0 / 0x7FFFFFFF);
// Speed and Validity
- if (type == MSG_TYPE_CURRENT_GPS_DATA) {
- int speed = buf.readShort();
- position.setValid(speed != -1);
- position.setSpeed(speed / 100.0 * 0.539957);
- } else if (type == MSG_TYPE_STATE_FULL_INFO_T104) {
+ if (type == MSG_TYPE_STATE_FULL_INFO_T104) {
int speed = buf.readUnsignedByte();
position.setValid(speed != 255);
position.setSpeed(speed * 0.539957);
extendedInfo.set("hdop", buf.readByte());
+ } else {
+ int speed = buf.readShort();
+ position.setValid(speed != -1);
+ position.setSpeed(speed / 100.0 * 0.539957);
}
// Course
@@ -233,61 +242,22 @@ public class ApelProtocolDecoder extends BaseProtocolDecoder {
extendedInfo.set("c0", buf.readUnsignedInt());
extendedInfo.set("c1", buf.readUnsignedInt());
extendedInfo.set("c2", buf.readUnsignedInt());
-
- /*long extraFlags = buf.readLong();
-
- // Analog inputs
- if ((extraFlags & 0x1) == 0x1) {
- int count = buf.readUnsignedShort();
- for (int i = 1; i <= count; i++) {
- extendedInfo.set("adc" + i, buf.readUnsignedShort());
- }
-
- }
-
- // CAN adapter
- if ((extraFlags & 0x2) == 0x2) {
- int size = buf.readUnsignedShort();
- extendedInfo.set("can", buf.toString(buf.readerIndex(), size, Charset.defaultCharset()));
- buf.skipBytes(size);
- }
-
- // Passenger sensor
- if ((extraFlags & 0x4) == 0x4) {
- int size = buf.readUnsignedShort();
-
- // Convert binary data to hex
- StringBuilder hex = new StringBuilder();
- for (int i = buf.readerIndex(); i < buf.readerIndex() + size; i++) {
- byte b = buf.getByte(i);
- hex.append(HEX_CHARS.charAt((b & 0xf0) >> 4));
- hex.append(HEX_CHARS.charAt((b & 0x0F)));
- }
-
- extendedInfo.set("passenger", hex);
-
- buf.skipBytes(size);
- }
-
- // Send response for alarm message
- if (type == MSG_ALARM) {
- byte[] response = {(byte)0xC9,0x00,0x00,0x00,0x00,0x00,0x00,0x00};
- channel.write(ChannelBuffers.wrappedBuffer(response));
-
- extendedInfo.set("alarm", true);
- }*/
}
- // Skip CRC
- buf.readUnsignedInt();
-
// Extended info
position.setExtendedInfo(extendedInfo.toString());
positions.add(position);
}
- //requestArchive(channel);
+ // Skip CRC
+ buf.readUnsignedInt();
+
+ if (type == MSG_TYPE_LOG_RECORDS) {
+ requestArchive(channel);
+ } else {
+ sendSimpleMessage(channel, MSG_TYPE_REQUEST_LAST_LOG_INDEX);
+ }
return positions;
}