From fe9f9b034713cb98531d73698a65bd03d18a771c Mon Sep 17 00:00:00 2001 From: Anton Tananaev Date: Fri, 21 Dec 2012 22:04:03 +1300 Subject: Added GT06 protocol (fix #100) --- src/org/traccar/Server.java | 48 +++++++++- src/org/traccar/helper/Crc.java | 20 ++-- src/org/traccar/protocol/Gt02ProtocolDecoder.java | 4 +- src/org/traccar/protocol/Gt06ProtocolDecoder.java | 103 ++++++++++++++------- .../traccar/protocol/MeiligaoProtocolDecoder.java | 4 +- 5 files changed, 123 insertions(+), 56 deletions(-) (limited to 'src/org/traccar') 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 5da774d65..cef0cc482 100644 --- a/src/org/traccar/helper/Crc.java +++ b/src/org/traccar/helper/Crc.java @@ -15,6 +15,8 @@ */ package org.traccar.helper; +import java.nio.ByteBuffer; + /** * CRC functions */ @@ -93,35 +95,35 @@ public class Crc { private static final int crc16CcittStart = 0xFFFF; private static final int crc16CcittXorout = 0xFFFF; - private static int crc16Unreflected(byte[] buf, int crc_in, int[] table) { + private static int crc16Unreflected(ByteBuffer buf, int crc_in, int[] table) { int crc16 = crc_in; - for (int i = 0; i < buf.length; i++) { - crc16 = table[((crc16 >> 8) ^ buf[i]) & 0xff] ^ (crc16 << 8); + 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(byte[] buf, int crc_in, int[] table) { + private static int crc16Reflected(ByteBuffer buf, int crc_in, int[] table) { int crc16 = crc_in; - for (int i = 0; i < buf.length; i++) { - crc16 = table[(crc16 ^ buf[i]) & 0xff] ^ (crc16 >> 8); + for (int i = 0; i < buf.remaining(); i++) { + crc16 = table[(crc16 ^ buf.get(i)) & 0xff] ^ (crc16 >> 8); } return crc16 & 0xFFFF; } - public static int crc16Ccitt(byte[] buf) { + public static int crc16Ccitt(ByteBuffer buf) { return crc16Reflected(buf, crc16CcittStart, crc16CcittTableReverse) ^ crc16CcittXorout; } - public static int crc16X25Ccitt(byte[] buf) { + public static int crc16X25Ccitt(ByteBuffer buf) { return crc16Unreflected(buf, crc16CcittStart, crc16CcittTable); } - public static int crc16CcittSeed(byte[] buf, int seed) { + 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 index f6d6d576b..1daf6c4ec 100644 --- a/src/org/traccar/protocol/Gt06ProtocolDecoder.java +++ b/src/org/traccar/protocol/Gt06ProtocolDecoder.java @@ -17,13 +17,12 @@ 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; 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; @@ -31,12 +30,14 @@ import org.traccar.model.Position; /** * T55 tracker protocol decoder */ -public class Gt02ProtocolDecoder extends GenericProtocolDecoder { +public class Gt06ProtocolDecoder extends GenericProtocolDecoder { + + private Long deviceId; /** * Initialize */ - public Gt02ProtocolDecoder(DataManager dataManager) { + public Gt06ProtocolDecoder(DataManager dataManager) { super(dataManager); } @@ -52,8 +53,24 @@ public class Gt02ProtocolDecoder extends GenericProtocolDecoder { return imei.toString(); } - private static final int MSG_HEARTBEAT = 0x1A; - private static final int MSG_DATA = 0x10; + 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 @@ -68,33 +85,28 @@ public class Gt02ProtocolDecoder extends GenericProtocolDecoder { buf.skipBytes(2); // header buf.readByte(); // size - // Zero for location messages - buf.readByte(); // voltage - buf.readByte(); // gsm signal - - String imei = readImei(buf); - long index = buf.readUnsignedShort(); int type = buf.readUnsignedByte(); - if (type == MSG_HEARTBEAT) { - if (channel != null) { - byte[] response = {0x54, 0x68, 0x1A, 0x0D, 0x0A}; - channel.write(ChannelBuffers.wrappedBuffer(response)); + 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.setId(index); - - // Get device id - try { - position.setDeviceId(getDataManager().getDeviceByImei(imei).getId()); - } catch(Exception error) { - Log.warning("Unknown device - " + imei); - } + position.setDeviceId(deviceId); + StringBuilder extendedInfo = new StringBuilder("gt06"); // Date and time Calendar time = Calendar.getInstance(TimeZone.getTimeZone("UTC")); @@ -107,6 +119,11 @@ public class Gt02ProtocolDecoder extends GenericProtocolDecoder { time.set(Calendar.SECOND, buf.readUnsignedByte()); position.setTime(time.getTime()); + // Satellites count + extendedInfo.append(""); + extendedInfo.append(buf.readUnsignedByte()); + extendedInfo.append(""); + // Latitude double latitude = buf.readUnsignedInt() / (60.0 * 30000.0); @@ -115,22 +132,36 @@ public class Gt02ProtocolDecoder extends GenericProtocolDecoder { // Speed position.setSpeed((double) buf.readUnsignedByte()); - - // Speed - position.setCourse((double) buf.readUnsignedShort()); - - buf.skipBytes(3); // reserved - - // Flags - long flags = buf.readUnsignedInt(); - position.setValid((flags & 0x1) == 0x1); - if ((flags & 0x2) == 0) latitude = -latitude; - if ((flags & 0x4) == 0) longitude = -longitude; + + // 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(""); + extendedInfo.append(buf.readUnsignedShort()); + extendedInfo.append(""); + extendedInfo.append(""); + extendedInfo.append(buf.readUnsignedByte()); + extendedInfo.append(""); + extendedInfo.append(""); + extendedInfo.append(buf.readUnsignedShort()); + extendedInfo.append(""); + extendedInfo.append(""); + extendedInfo.append(buf.readUnsignedShort() << 8 + buf.readUnsignedByte()); + extendedInfo.append(""); + + // Index + position.setId((long) buf.readUnsignedShort()); + position.setExtendedInfo(extendedInfo.toString()); return position; } diff --git a/src/org/traccar/protocol/MeiligaoProtocolDecoder.java b/src/org/traccar/protocol/MeiligaoProtocolDecoder.java index f1332ddf9..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.crc16X25Ccitt(array)); + sendBuf.writeShort(Crc.crc16X25Ccitt(sendBuf.toByteBuffer())); sendBuf.writeByte('\r'); sendBuf.writeByte('\n'); if (channel != null) { -- cgit v1.2.3