aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--src/org/traccar/Server.java48
-rw-r--r--src/org/traccar/helper/Crc.java116
-rw-r--r--src/org/traccar/protocol/Gt02ProtocolDecoder.java4
-rw-r--r--src/org/traccar/protocol/Gt06ProtocolDecoder.java171
-rw-r--r--src/org/traccar/protocol/MeiligaoProtocolDecoder.java4
-rw-r--r--test/org/traccar/protocol/Gt06ProtocolDecoderTest.java23
6 files changed, 342 insertions, 24 deletions
diff --git a/src/org/traccar/Server.java b/src/org/traccar/Server.java
index 3b22e8f2d..d4e4a94cb 100644
--- a/src/org/traccar/Server.java
+++ b/src/org/traccar/Server.java
@@ -28,10 +28,7 @@ import java.util.List;
import java.util.Properties;
import java.util.logging.FileHandler;
import java.util.logging.Formatter;
-import java.util.logging.Handler;
-import java.util.logging.Level;
import java.util.logging.LogRecord;
-import java.util.logging.Logger;
import org.jboss.netty.bootstrap.ServerBootstrap;
import org.jboss.netty.buffer.ChannelBuffers;
import org.jboss.netty.channel.ChannelPipeline;
@@ -255,6 +252,7 @@ public class Server {
final Integer resetDelay = getProtocolResetDelay(properties, protocol);
server.setPipelineFactory(new GenericPipelineFactory(server, dataManager, isLoggerEnabled(), resetDelay, geocoder) {
+ @Override
protected void addSpecificHandlers(ChannelPipeline pipeline) {
pipeline.addLast("frameDecoder", new XexunFrameDecoder());
pipeline.addLast("stringDecoder", new StringDecoder());
@@ -280,6 +278,7 @@ public class Server {
final Integer resetDelay = getProtocolResetDelay(properties, protocol);
server.setPipelineFactory(new GenericPipelineFactory(server, dataManager, isLoggerEnabled(), resetDelay, geocoder) {
+ @Override
protected void addSpecificHandlers(ChannelPipeline pipeline) {
byte delimiter[] = { (byte) ';' };
pipeline.addLast("frameDecoder",
@@ -308,6 +307,7 @@ public class Server {
final Integer resetDelay = getProtocolResetDelay(properties, protocol);
server.setPipelineFactory(new GenericPipelineFactory(server, dataManager, isLoggerEnabled(), resetDelay, geocoder) {
+ @Override
protected void addSpecificHandlers(ChannelPipeline pipeline) {
byte delimiter[] = { (byte) ')' };
pipeline.addLast("frameDecoder",
@@ -336,6 +336,7 @@ public class Server {
final Integer resetDelay = getProtocolResetDelay(properties, protocol);
server.setPipelineFactory(new GenericPipelineFactory(server, dataManager, isLoggerEnabled(), resetDelay, geocoder) {
+ @Override
protected void addSpecificHandlers(ChannelPipeline pipeline) {
byte delimiter[] = { (byte) 0x0 };
pipeline.addLast("frameDecoder",
@@ -364,6 +365,7 @@ public class Server {
final Integer resetDelay = getProtocolResetDelay(properties, protocol);
server.setPipelineFactory(new GenericPipelineFactory(server, dataManager, isLoggerEnabled(), resetDelay, geocoder) {
+ @Override
protected void addSpecificHandlers(ChannelPipeline pipeline) {
byte delimiter[] = { (byte) '$' };
pipeline.addLast("frameDecoder",
@@ -392,6 +394,7 @@ public class Server {
final Integer resetDelay = getProtocolResetDelay(properties, protocol);
server.setPipelineFactory(new GenericPipelineFactory(server, dataManager, isLoggerEnabled(), resetDelay, geocoder) {
+ @Override
protected void addSpecificHandlers(ChannelPipeline pipeline) {
byte delimiter[] = { (byte) '\r', (byte) '\n' };
pipeline.addLast("frameDecoder",
@@ -420,6 +423,7 @@ public class Server {
final Integer resetDelay = getProtocolResetDelay(properties, protocol);
server.setPipelineFactory(new GenericPipelineFactory(server, dataManager, isLoggerEnabled(), resetDelay, geocoder) {
+ @Override
protected void addSpecificHandlers(ChannelPipeline pipeline) {
byte delimiter[] = { (byte) '\n' }; // tracker bug \n\r
pipeline.addLast("frameDecoder",
@@ -447,6 +451,7 @@ public class Server {
final Integer resetDelay = getProtocolResetDelay(properties, protocol);
server.setPipelineFactory(new GenericPipelineFactory(server, dataManager, isLoggerEnabled(), resetDelay, geocoder) {
+ @Override
protected void addSpecificHandlers(ChannelPipeline pipeline) {
byte delimiter[] = { (byte) '\r', (byte) '\n' };
pipeline.addLast("frameDecoder",
@@ -474,6 +479,7 @@ public class Server {
final Integer resetDelay = getProtocolResetDelay(properties, protocol);
server.setPipelineFactory(new GenericPipelineFactory(server, dataManager, isLoggerEnabled(), resetDelay, geocoder) {
+ @Override
protected void addSpecificHandlers(ChannelPipeline pipeline) {
pipeline.addLast("frameDecoder", new LengthFieldBasedFrameDecoder(1024, 0, 2, -2, 2));
pipeline.addLast("objectDecoder", new EnforaProtocolDecoder(getDataManager()));
@@ -498,6 +504,7 @@ public class Server {
final Integer resetDelay = getProtocolResetDelay(properties, protocol);
server.setPipelineFactory(new GenericPipelineFactory(server, dataManager, isLoggerEnabled(), resetDelay, geocoder) {
+ @Override
protected void addSpecificHandlers(ChannelPipeline pipeline) {
pipeline.addLast("frameDecoder", new LengthFieldBasedFrameDecoder(1024, 2, 2, -4, 4));
pipeline.addLast("objectDecoder", new MeiligaoProtocolDecoder(getDataManager()));
@@ -518,6 +525,7 @@ public class Server {
final Integer resetDelay = getProtocolResetDelay(properties, protocol);
server.setPipelineFactory(new GenericPipelineFactory(server, dataManager, isLoggerEnabled(), resetDelay, geocoder) {
+ @Override
protected void addSpecificHandlers(ChannelPipeline pipeline) {
byte delimiter[] = { (byte) '\r', (byte) '\n' };
pipeline.addLast("frameDecoder",
@@ -542,6 +550,7 @@ public class Server {
final Integer resetDelay = getProtocolResetDelay(properties, protocol);
server.setPipelineFactory(new GenericPipelineFactory(server, dataManager, isLoggerEnabled(), resetDelay, geocoder) {
+ @Override
protected void addSpecificHandlers(ChannelPipeline pipeline) {
byte delimiter[] = { (byte) '\r' };
pipeline.addLast("frameDecoder",
@@ -566,6 +575,7 @@ public class Server {
final Integer resetDelay = getProtocolResetDelay(properties, protocol);
server.setPipelineFactory(new GenericPipelineFactory(server, dataManager, isLoggerEnabled(), resetDelay, geocoder) {
+ @Override
protected void addSpecificHandlers(ChannelPipeline pipeline) {
pipeline.addLast("frameDecoder", new LengthFieldBasedFrameDecoder(1024, 2, 2, 0, 0));
pipeline.addLast("objectDecoder", new ProgressProtocolDecoder(getDataManager()));
@@ -590,6 +600,7 @@ public class Server {
final Integer resetDelay = getProtocolResetDelay(properties, protocol);
server.setPipelineFactory(new GenericPipelineFactory(server, dataManager, isLoggerEnabled(), resetDelay, geocoder) {
+ @Override
protected void addSpecificHandlers(ChannelPipeline pipeline) {
byte delimiter[] = { (byte) '#' };
pipeline.addLast("frameDecoder",
@@ -617,6 +628,7 @@ public class Server {
final Integer resetDelay = getProtocolResetDelay(properties, protocol);
server.setPipelineFactory(new GenericPipelineFactory(server, dataManager, isLoggerEnabled(), resetDelay, geocoder) {
+ @Override
protected void addSpecificHandlers(ChannelPipeline pipeline) {
pipeline.addLast("frameDecoder", new Jt600FrameDecoder());
pipeline.addLast("objectDecoder", new Jt600ProtocolDecoder(getDataManager()));
@@ -641,6 +653,7 @@ public class Server {
final Integer resetDelay = getProtocolResetDelay(properties, protocol);
server.setPipelineFactory(new GenericPipelineFactory(server, dataManager, isLoggerEnabled(), resetDelay, geocoder) {
+ @Override
protected void addSpecificHandlers(ChannelPipeline pipeline) {
byte delimiter[] = { (byte) ';' };
pipeline.addLast("frameDecoder",
@@ -668,6 +681,7 @@ public class Server {
final Integer resetDelay = getProtocolResetDelay(properties, protocol);
server.setPipelineFactory(new GenericPipelineFactory(server, dataManager, isLoggerEnabled(), resetDelay, geocoder) {
+ @Override
protected void addSpecificHandlers(ChannelPipeline pipeline) {
byte delimiter[] = { (byte) '#', (byte) '#' };
pipeline.addLast("frameDecoder",
@@ -695,6 +709,7 @@ public class Server {
final Integer resetDelay = getProtocolResetDelay(properties, protocol);
server.setPipelineFactory(new GenericPipelineFactory(server, dataManager, isLoggerEnabled(), resetDelay, geocoder) {
+ @Override
protected void addSpecificHandlers(ChannelPipeline pipeline) {
byte delimiter[] = { (byte) '\r', (byte) '\n' };
pipeline.addLast("frameDecoder",
@@ -723,6 +738,7 @@ public class Server {
final Integer resetDelay = getProtocolResetDelay(properties, protocol);
server.setPipelineFactory(new GenericPipelineFactory(server, dataManager, isLoggerEnabled(), resetDelay, geocoder) {
+ @Override
protected void addSpecificHandlers(ChannelPipeline pipeline) {
byte delimiter[] = { (byte) '\r', (byte) '\n' };
pipeline.addLast("frameDecoder",
@@ -752,6 +768,7 @@ public class Server {
final Integer resetDelay = getProtocolResetDelay(properties, protocol);
server.setPipelineFactory(new GenericPipelineFactory(server, dataManager, isLoggerEnabled(), resetDelay, geocoder) {
+ @Override
protected void addSpecificHandlers(ChannelPipeline pipeline) {
pipeline.addLast("frameDecoder", new LengthFieldBasedFrameDecoder(4 * 1024, 12, 2, 2, 0));
pipeline.addLast("objectDecoder", new NavisProtocolDecoder(getDataManager()));
@@ -776,6 +793,7 @@ public class Server {
final Integer resetDelay = getProtocolResetDelay(properties, protocol);
server.setPipelineFactory(new GenericPipelineFactory(server, dataManager, isLoggerEnabled(), resetDelay, geocoder) {
+ @Override
protected void addSpecificHandlers(ChannelPipeline pipeline) {
byte delimiter[] = { (byte) '\r', (byte) '\n' };
pipeline.addLast("frameDecoder",
@@ -804,6 +822,7 @@ public class Server {
final Integer resetDelay = getProtocolResetDelay(properties, protocol);
server.setPipelineFactory(new GenericPipelineFactory(server, dataManager, isLoggerEnabled(), resetDelay, geocoder) {
+ @Override
protected void addSpecificHandlers(ChannelPipeline pipeline) {
pipeline.addLast("objectDecoder", new SkypatrolProtocolDecoder(getDataManager()));
}
@@ -824,12 +843,12 @@ public class Server {
TrackerServer server = new TrackerServer(new ServerBootstrap());
server.setPort(getProtocolPort(properties, protocol));
server.setAddress(getProtocolInterface(properties, protocol));
- //server.setEndianness(ByteOrder.LITTLE_ENDIAN);
final Integer resetDelay = getProtocolResetDelay(properties, protocol);
server.setPipelineFactory(new GenericPipelineFactory(server, dataManager, isLoggerEnabled(), resetDelay, geocoder) {
+ @Override
protected void addSpecificHandlers(ChannelPipeline pipeline) {
- pipeline.addLast("frameDecoder", new LengthFieldBasedFrameDecoder(1024, 2, 1, 2, 0));
+ pipeline.addLast("frameDecoder", new LengthFieldBasedFrameDecoder(256, 2, 1, 2, 0));
pipeline.addLast("objectDecoder", new Gt02ProtocolDecoder(getDataManager()));
}
});
@@ -842,6 +861,25 @@ public class Server {
* Init GT06 server
*/
private void initGt06Server(Properties properties) throws SQLException {
+
+ String protocol = "gt06";
+ if (isProtocolEnabled(properties, protocol)) {
+
+ TrackerServer server = new TrackerServer(new ServerBootstrap());
+ server.setPort(getProtocolPort(properties, protocol));
+ server.setAddress(getProtocolInterface(properties, protocol));
+ final Integer resetDelay = getProtocolResetDelay(properties, protocol);
+
+ server.setPipelineFactory(new GenericPipelineFactory(server, dataManager, isLoggerEnabled(), resetDelay, geocoder) {
+ @Override
+ protected void addSpecificHandlers(ChannelPipeline pipeline) {
+ pipeline.addLast("frameDecoder", new LengthFieldBasedFrameDecoder(256, 2, 1, 2, 0));
+ pipeline.addLast("objectDecoder", new Gt06ProtocolDecoder(getDataManager()));
+ }
+ });
+
+ serverList.add(server);
+ }
}
}
diff --git a/src/org/traccar/helper/Crc.java b/src/org/traccar/helper/Crc.java
index a0ad83e72..cef0cc482 100644
--- a/src/org/traccar/helper/Crc.java
+++ b/src/org/traccar/helper/Crc.java
@@ -15,26 +15,116 @@
*/
package org.traccar.helper;
+import java.nio.ByteBuffer;
+
/**
* CRC functions
*/
public class Crc {
- public static int crc16Ccitt(byte[] bytes) {
- int crc = 0xFFFF; // initial value
- int polynomial = 0x1021; // 0001 0000 0010 0001 (0, 5, 12)
-
- for (byte b : bytes) {
- for (int i = 0; i < 8; i++) {
- boolean bit = ((b >> (7-i) & 1) == 1);
- boolean c15 = ((crc >> 15 & 1) == 1);
- crc <<= 1;
- if (c15 ^ bit) crc ^= polynomial;
- }
+ private static final int crc16CcittTableReverse[] = {
+ 0x0000, 0x1189, 0x2312, 0x329B, 0x4624, 0x57AD, 0x6536, 0x74BF,
+ 0x8C48, 0x9DC1, 0xAF5A, 0xBED3, 0xCA6C, 0xDBE5, 0xE97E, 0xF8F7,
+ 0x1081, 0x0108, 0x3393, 0x221A, 0x56A5, 0x472C, 0x75B7, 0x643E,
+ 0x9CC9, 0x8D40, 0xBFDB, 0xAE52, 0xDAED, 0xCB64, 0xF9FF, 0xE876,
+ 0x2102, 0x308B, 0x0210, 0x1399, 0x6726, 0x76AF, 0x4434, 0x55BD,
+ 0xAD4A, 0xBCC3, 0x8E58, 0x9FD1, 0xEB6E, 0xFAE7, 0xC87C, 0xD9F5,
+ 0x3183, 0x200A, 0x1291, 0x0318, 0x77A7, 0x662E, 0x54B5, 0x453C,
+ 0xBDCB, 0xAC42, 0x9ED9, 0x8F50, 0xFBEF, 0xEA66, 0xD8FD, 0xC974,
+ 0x4204, 0x538D, 0x6116, 0x709F, 0x0420, 0x15A9, 0x2732, 0x36BB,
+ 0xCE4C, 0xDFC5, 0xED5E, 0xFCD7, 0x8868, 0x99E1, 0xAB7A, 0xBAF3,
+ 0x5285, 0x430C, 0x7197, 0x601E, 0x14A1, 0x0528, 0x37B3, 0x263A,
+ 0xDECD, 0xCF44, 0xFDDF, 0xEC56, 0x98E9, 0x8960, 0xBBFB, 0xAA72,
+ 0x6306, 0x728F, 0x4014, 0x519D, 0x2522, 0x34AB, 0x0630, 0x17B9,
+ 0xEF4E, 0xFEC7, 0xCC5C, 0xDDD5, 0xA96A, 0xB8E3, 0x8A78, 0x9BF1,
+ 0x7387, 0x620E, 0x5095, 0x411C, 0x35A3, 0x242A, 0x16B1, 0x0738,
+ 0xFFCF, 0xEE46, 0xDCDD, 0xCD54, 0xB9EB, 0xA862, 0x9AF9, 0x8B70,
+ 0x8408, 0x9581, 0xA71A, 0xB693, 0xC22C, 0xD3A5, 0xE13E, 0xF0B7,
+ 0x0840, 0x19C9, 0x2B52, 0x3ADB, 0x4E64, 0x5FED, 0x6D76, 0x7CFF,
+ 0x9489, 0x8500, 0xB79B, 0xA612, 0xD2AD, 0xC324, 0xF1BF, 0xE036,
+ 0x18C1, 0x0948, 0x3BD3, 0x2A5A, 0x5EE5, 0x4F6C, 0x7DF7, 0x6C7E,
+ 0xA50A, 0xB483, 0x8618, 0x9791, 0xE32E, 0xF2A7, 0xC03C, 0xD1B5,
+ 0x2942, 0x38CB, 0x0A50, 0x1BD9, 0x6F66, 0x7EEF, 0x4C74, 0x5DFD,
+ 0xB58B, 0xA402, 0x9699, 0x8710, 0xF3AF, 0xE226, 0xD0BD, 0xC134,
+ 0x39C3, 0x284A, 0x1AD1, 0x0B58, 0x7FE7, 0x6E6E, 0x5CF5, 0x4D7C,
+ 0xC60C, 0xD785, 0xE51E, 0xF497, 0x8028, 0x91A1, 0xA33A, 0xB2B3,
+ 0x4A44, 0x5BCD, 0x6956, 0x78DF, 0x0C60, 0x1DE9, 0x2F72, 0x3EFB,
+ 0xD68D, 0xC704, 0xF59F, 0xE416, 0x90A9, 0x8120, 0xB3BB, 0xA232,
+ 0x5AC5, 0x4B4C, 0x79D7, 0x685E, 0x1CE1, 0x0D68, 0x3FF3, 0x2E7A,
+ 0xE70E, 0xF687, 0xC41C, 0xD595, 0xA12A, 0xB0A3, 0x8238, 0x93B1,
+ 0x6B46, 0x7ACF, 0x4854, 0x59DD, 0x2D62, 0x3CEB, 0x0E70, 0x1FF9,
+ 0xF78F, 0xE606, 0xD49D, 0xC514, 0xB1AB, 0xA022, 0x92B9, 0x8330,
+ 0x7BC7, 0x6A4E, 0x58D5, 0x495C, 0x3DE3, 0x2C6A, 0x1EF1, 0x0F78
+ };
+
+ private static final int crc16CcittTable[] = {
+ 0x0000, 0x1021, 0x2042, 0x3063, 0x4084, 0x50A5, 0x60C6, 0x70E7,
+ 0x8108, 0x9129, 0xA14A, 0xB16B, 0xC18C, 0xD1AD, 0xE1CE, 0xF1EF,
+ 0x1231, 0x0210, 0x3273, 0x2252, 0x52B5, 0x4294, 0x72F7, 0x62D6,
+ 0x9339, 0x8318, 0xB37B, 0xA35A, 0xD3BD, 0xC39C, 0xF3FF, 0xE3DE,
+ 0x2462, 0x3443, 0x0420, 0x1401, 0x64E6, 0x74C7, 0x44A4, 0x5485,
+ 0xA56A, 0xB54B, 0x8528, 0x9509, 0xE5EE, 0xF5CF, 0xC5AC, 0xD58D,
+ 0x3653, 0x2672, 0x1611, 0x0630, 0x76D7, 0x66F6, 0x5695, 0x46B4,
+ 0xB75B, 0xA77A, 0x9719, 0x8738, 0xF7DF, 0xE7FE, 0xD79D, 0xC7BC,
+ 0x48C4, 0x58E5, 0x6886, 0x78A7, 0x0840, 0x1861, 0x2802, 0x3823,
+ 0xC9CC, 0xD9ED, 0xE98E, 0xF9AF, 0x8948, 0x9969, 0xA90A, 0xB92B,
+ 0x5AF5, 0x4AD4, 0x7AB7, 0x6A96, 0x1A71, 0x0A50, 0x3A33, 0x2A12,
+ 0xDBFD, 0xCBDC, 0xFBBF, 0xEB9E, 0x9B79, 0x8B58, 0xBB3B, 0xAB1A,
+ 0x6CA6, 0x7C87, 0x4CE4, 0x5CC5, 0x2C22, 0x3C03, 0x0C60, 0x1C41,
+ 0xEDAE, 0xFD8F, 0xCDEC, 0xDDCD, 0xAD2A, 0xBD0B, 0x8D68, 0x9D49,
+ 0x7E97, 0x6EB6, 0x5ED5, 0x4EF4, 0x3E13, 0x2E32, 0x1E51, 0x0E70,
+ 0xFF9F, 0xEFBE, 0xDFDD, 0xCFFC, 0xBF1B, 0xAF3A, 0x9F59, 0x8F78,
+ 0x9188, 0x81A9, 0xB1CA, 0xA1EB, 0xD10C, 0xC12D, 0xF14E, 0xE16F,
+ 0x1080, 0x00A1, 0x30C2, 0x20E3, 0x5004, 0x4025, 0x7046, 0x6067,
+ 0x83B9, 0x9398, 0xA3FB, 0xB3DA, 0xC33D, 0xD31C, 0xE37F, 0xF35E,
+ 0x02B1, 0x1290, 0x22F3, 0x32D2, 0x4235, 0x5214, 0x6277, 0x7256,
+ 0xB5EA, 0xA5CB, 0x95A8, 0x8589, 0xF56E, 0xE54F, 0xD52C, 0xC50D,
+ 0x34E2, 0x24C3, 0x14A0, 0x0481, 0x7466, 0x6447, 0x5424, 0x4405,
+ 0xA7DB, 0xB7FA, 0x8799, 0x97B8, 0xE75F, 0xF77E, 0xC71D, 0xD73C,
+ 0x26D3, 0x36F2, 0x0691, 0x16B0, 0x6657, 0x7676, 0x4615, 0x5634,
+ 0xD94C, 0xC96D, 0xF90E, 0xE92F, 0x99C8, 0x89E9, 0xB98A, 0xA9AB,
+ 0x5844, 0x4865, 0x7806, 0x6827, 0x18C0, 0x08E1, 0x3882, 0x28A3,
+ 0xCB7D, 0xDB5C, 0xEB3F, 0xFB1E, 0x8BF9, 0x9BD8, 0xABBB, 0xBB9A,
+ 0x4A75, 0x5A54, 0x6A37, 0x7A16, 0x0AF1, 0x1AD0, 0x2AB3, 0x3A92,
+ 0xFD2E, 0xED0F, 0xDD6C, 0xCD4D, 0xBDAA, 0xAD8B, 0x9DE8, 0x8DC9,
+ 0x7C26, 0x6C07, 0x5C64, 0x4C45, 0x3CA2, 0x2C83, 0x1CE0, 0x0CC1,
+ 0xEF1F, 0xFF3E, 0xCF5D, 0xDF7C, 0xAF9B, 0xBFBA, 0x8FD9, 0x9FF8,
+ 0x6E17, 0x7E36, 0x4E55, 0x5E74, 0x2E93, 0x3EB2, 0x0ED1, 0x1EF0
+ };
+
+ private static final int crc16CcittStart = 0xFFFF;
+ private static final int crc16CcittXorout = 0xFFFF;
+
+ private static int crc16Unreflected(ByteBuffer buf, int crc_in, int[] table) {
+ int crc16 = crc_in;
+
+ for (int i = 0; i < buf.remaining(); i++) {
+ crc16 = table[((crc16 >> 8) ^ buf.get(i)) & 0xff] ^ (crc16 << 8);
+ }
+
+ return crc16 & 0xFFFF;
+ }
+
+ private static int crc16Reflected(ByteBuffer buf, int crc_in, int[] table) {
+ int crc16 = crc_in;
+
+ for (int i = 0; i < buf.remaining(); i++) {
+ crc16 = table[(crc16 ^ buf.get(i)) & 0xff] ^ (crc16 >> 8);
}
- crc &= 0xffff;
- return crc;
+ return crc16 & 0xFFFF;
+ }
+
+ public static int crc16Ccitt(ByteBuffer buf) {
+ return crc16Reflected(buf, crc16CcittStart, crc16CcittTableReverse) ^ crc16CcittXorout;
+ }
+
+ public static int crc16X25Ccitt(ByteBuffer buf) {
+ return crc16Unreflected(buf, crc16CcittStart, crc16CcittTable);
+ }
+
+ public static int crc16CcittSeed(ByteBuffer buf, int seed) {
+ return crc16Reflected(buf, seed, crc16CcittTableReverse) ^ crc16CcittXorout;
}
}
diff --git a/src/org/traccar/protocol/Gt02ProtocolDecoder.java b/src/org/traccar/protocol/Gt02ProtocolDecoder.java
index f6d6d576b..69d54cb5b 100644
--- a/src/org/traccar/protocol/Gt02ProtocolDecoder.java
+++ b/src/org/traccar/protocol/Gt02ProtocolDecoder.java
@@ -17,8 +17,6 @@ package org.traccar.protocol;
import java.util.Calendar;
import java.util.TimeZone;
-import java.util.regex.Matcher;
-import java.util.regex.Pattern;
import org.jboss.netty.buffer.ChannelBuffer;
import org.jboss.netty.buffer.ChannelBuffers;
import org.jboss.netty.channel.Channel;
@@ -116,7 +114,7 @@ public class Gt02ProtocolDecoder extends GenericProtocolDecoder {
// Speed
position.setSpeed((double) buf.readUnsignedByte());
- // Speed
+ // Course
position.setCourse((double) buf.readUnsignedShort());
buf.skipBytes(3); // reserved
diff --git a/src/org/traccar/protocol/Gt06ProtocolDecoder.java b/src/org/traccar/protocol/Gt06ProtocolDecoder.java
new file mode 100644
index 000000000..1daf6c4ec
--- /dev/null
+++ b/src/org/traccar/protocol/Gt06ProtocolDecoder.java
@@ -0,0 +1,171 @@
+/*
+ * Copyright 2012 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 java.util.Calendar;
+import java.util.TimeZone;
+import org.jboss.netty.buffer.ChannelBuffer;
+import org.jboss.netty.buffer.ChannelBuffers;
+import org.jboss.netty.channel.Channel;
+import org.jboss.netty.channel.ChannelHandlerContext;
+import org.traccar.GenericProtocolDecoder;
+import org.traccar.helper.Crc;
+import org.traccar.helper.Log;
+import org.traccar.model.DataManager;
+import org.traccar.model.Position;
+
+/**
+ * T55 tracker protocol decoder
+ */
+public class Gt06ProtocolDecoder extends GenericProtocolDecoder {
+
+ private Long deviceId;
+
+ /**
+ * Initialize
+ */
+ public Gt06ProtocolDecoder(DataManager dataManager) {
+ super(dataManager);
+ }
+
+ private String readImei(ChannelBuffer buf) {
+ int b = buf.readUnsignedByte();
+ StringBuilder imei = new StringBuilder();
+ imei.append(b & 0x0F);
+ for (int i = 0; i < 7; i++) {
+ b = buf.readUnsignedByte();
+ imei.append((b & 0xF0) >> 4);
+ imei.append(b & 0x0F);
+ }
+ return imei.toString();
+ }
+
+ private static final int MSG_LOGIN = 0x01;
+ private static final int MSG_DATA = 0x12;
+ private static final int MSG_HEARTBEAT = 0x13;
+ private static final int MSG_STRING = 0x15;
+ private static final int MSG_ALARM = 0x16;
+
+ private static void sendResponse(Channel channel, int type, int index) {
+ if (channel == null) {
+ ChannelBuffer response = ChannelBuffers.directBuffer(10);
+ response.writeByte(0x78); response.writeByte(0x78); // header
+ response.writeByte(0x05); // size
+ response.writeByte(type);
+ response.writeShort(index);
+ response.writeShort(Crc.crc16Ccitt(response.toByteBuffer(2, 4)));
+ response.writeByte(0x0D); response.writeByte(0x0A); // ending
+ channel.write(response);
+ }
+ }
+
+ /**
+ * Decode message
+ */
+ @Override
+ protected Object decode(
+ ChannelHandlerContext ctx, Channel channel, Object msg)
+ throws Exception {
+
+ ChannelBuffer buf = (ChannelBuffer) msg;
+
+ buf.skipBytes(2); // header
+ buf.readByte(); // size
+
+ int type = buf.readUnsignedByte();
+
+ if (type == MSG_LOGIN) {
+ String imei = readImei(buf);
+ try {
+ deviceId = getDataManager().getDeviceByImei(imei).getId();
+ sendResponse(channel, type, buf.readUnsignedShort());
+ } catch(Exception error) {
+ Log.warning("Unknown device - " + imei);
+ }
+ }
+
+ else if (type == MSG_HEARTBEAT) {
+ buf.skipBytes(5);
+ sendResponse(channel, type, buf.readUnsignedShort());
+ }
+
+ else if (type == MSG_DATA) {
+ // Create new position
+ Position position = new Position();
+ position.setDeviceId(deviceId);
+ StringBuilder extendedInfo = new StringBuilder("<protocol>gt06</protocol>");
+
+ // Date and time
+ Calendar time = Calendar.getInstance(TimeZone.getTimeZone("UTC"));
+ time.clear();
+ time.set(Calendar.YEAR, 2000 + buf.readUnsignedByte());
+ time.set(Calendar.MONTH, buf.readUnsignedByte() - 1);
+ time.set(Calendar.DAY_OF_MONTH, buf.readUnsignedByte());
+ time.set(Calendar.HOUR, buf.readUnsignedByte());
+ time.set(Calendar.MINUTE, buf.readUnsignedByte());
+ time.set(Calendar.SECOND, buf.readUnsignedByte());
+ position.setTime(time.getTime());
+
+ // Satellites count
+ extendedInfo.append("<satellites>");
+ extendedInfo.append(buf.readUnsignedByte());
+ extendedInfo.append("</satellites>");
+
+ // Latitude
+ double latitude = buf.readUnsignedInt() / (60.0 * 30000.0);
+
+ // Longitude
+ double longitude = buf.readUnsignedInt() / (60.0 * 30000.0);
+
+ // Speed
+ position.setSpeed((double) buf.readUnsignedByte());
+
+ // Course and flags
+ int union = buf.readUnsignedShort();
+ position.setCourse((double) (union & 0x03FF));
+ position.setValid((union & 0x1000) != 0);
+ if ((union & 0x0400) == 0) latitude = -latitude;
+ if ((union & 0x0800) == 0) longitude = -longitude;
+
+ position.setLatitude(latitude);
+ position.setLongitude(longitude);
+ position.setAltitude(0.0);
+
+ // Cell information
+ extendedInfo.append("<mcc>");
+ extendedInfo.append(buf.readUnsignedShort());
+ extendedInfo.append("</mcc>");
+ extendedInfo.append("<mnc>");
+ extendedInfo.append(buf.readUnsignedByte());
+ extendedInfo.append("</mnc>");
+ extendedInfo.append("<lac>");
+ extendedInfo.append(buf.readUnsignedShort());
+ extendedInfo.append("</lac>");
+ extendedInfo.append("<cell>");
+ extendedInfo.append(buf.readUnsignedShort() << 8 + buf.readUnsignedByte());
+ extendedInfo.append("</cell>");
+
+ // Index
+ position.setId((long) buf.readUnsignedShort());
+
+ position.setExtendedInfo(extendedInfo.toString());
+ return position;
+ }
+
+ return null;
+ }
+
+}
diff --git a/src/org/traccar/protocol/MeiligaoProtocolDecoder.java b/src/org/traccar/protocol/MeiligaoProtocolDecoder.java
index 4696343d6..3d8fbef75 100644
--- a/src/org/traccar/protocol/MeiligaoProtocolDecoder.java
+++ b/src/org/traccar/protocol/MeiligaoProtocolDecoder.java
@@ -106,9 +106,7 @@ public class MeiligaoProtocolDecoder extends GenericProtocolDecoder {
sendBuf.writeBytes(array);
sendBuf.writeShort(0x4000);
sendBuf.writeByte(0x01);
- array = new byte[sendBuf.readableBytes()];
- sendBuf.getBytes(0, array);
- sendBuf.writeShort(Crc.crc16Ccitt(array));
+ sendBuf.writeShort(Crc.crc16X25Ccitt(sendBuf.toByteBuffer()));
sendBuf.writeByte('\r');
sendBuf.writeByte('\n');
if (channel != null) {
diff --git a/test/org/traccar/protocol/Gt06ProtocolDecoderTest.java b/test/org/traccar/protocol/Gt06ProtocolDecoderTest.java
new file mode 100644
index 000000000..f20618061
--- /dev/null
+++ b/test/org/traccar/protocol/Gt06ProtocolDecoderTest.java
@@ -0,0 +1,23 @@
+package org.traccar.protocol;
+
+import org.jboss.netty.buffer.ChannelBuffers;
+import static org.junit.Assert.assertNotNull;
+import static org.junit.Assert.assertNull;
+import org.junit.Test;
+
+public class Gt06ProtocolDecoderTest {
+
+ @Test
+ public void testDecode() throws Exception {
+
+ Gt06ProtocolDecoder decoder = new Gt06ProtocolDecoder(new TestDataManager());
+
+ byte[] buf1 = {0x78,0x78,0x1F,0x12,0x0B,0x08,0x1D,0x11,0x2E,0x10,(byte)0xCC,0x02,0x7A,(byte)0xC7,(byte)0xEB,0x0C,0x46,0x58,0x49,0x00,0x14,(byte)0x8F,0x01,(byte)0xCC,0x00,0x28,0x7D,0x00,0x1F,(byte)0xB8,0x00,0x03,(byte)0x80,(byte)0x81,0x0D,0x0A};
+ assertNotNull(decoder.decode(null, null, ChannelBuffers.wrappedBuffer(buf1)));
+
+ byte[] buf2 = {0x78,0x78,0x0D,0x01,0x08,0x64,0x71,0x70,0x03,0x28,0x35,(byte)0x81,0x00,0x09,0x3F,0x04,0x0D,0x0A};
+ assertNull(decoder.decode(null, null, ChannelBuffers.wrappedBuffer(buf2)));
+
+ }
+
+}