diff options
-rw-r--r-- | src/org/traccar/Server.java | 48 | ||||
-rw-r--r-- | src/org/traccar/helper/Crc.java | 116 | ||||
-rw-r--r-- | src/org/traccar/protocol/Gt02ProtocolDecoder.java | 4 | ||||
-rw-r--r-- | src/org/traccar/protocol/Gt06ProtocolDecoder.java | 171 | ||||
-rw-r--r-- | src/org/traccar/protocol/MeiligaoProtocolDecoder.java | 4 | ||||
-rw-r--r-- | test/org/traccar/protocol/Gt06ProtocolDecoderTest.java | 23 |
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))); + + } + +} |