From 43ffaf8c3bb0c4937f8d9185f47a95530d118931 Mon Sep 17 00:00:00 2001 From: Anton Tananaev Date: Wed, 22 Nov 2017 08:37:20 +1300 Subject: Implement GK310 protocol extension --- src/org/traccar/protocol/Gt06ProtocolDecoder.java | 172 ++++++++++++++++----- .../traccar/protocol/Gt06ProtocolDecoderTest.java | 27 ++++ 2 files changed, 158 insertions(+), 41 deletions(-) diff --git a/src/org/traccar/protocol/Gt06ProtocolDecoder.java b/src/org/traccar/protocol/Gt06ProtocolDecoder.java index 177c0b653..7703650a4 100644 --- a/src/org/traccar/protocol/Gt06ProtocolDecoder.java +++ b/src/org/traccar/protocol/Gt06ProtocolDecoder.java @@ -36,6 +36,7 @@ import org.traccar.model.WifiAccessPoint; import java.net.SocketAddress; import java.nio.charset.StandardCharsets; +import java.util.Calendar; import java.util.HashMap; import java.util.Map; import java.util.TimeZone; @@ -78,6 +79,9 @@ public class Gt06ProtocolDecoder extends BaseProtocolDecoder { public static final int MSG_LBS_STATUS = 0x19; public static final int MSG_GPS_PHONE = 0x1A; public static final int MSG_GPS_LBS_EXTEND = 0x1E; + public static final int MSG_HEARTBEAT = 0x23; + public static final int MSG_ADDRESS_REQUEST = 0x2A; + public static final int MSG_ADDRESS_RESPONSE = 0x97; public static final int MSG_AZ735_GPS = 0x32; public static final int MSG_AZ735_ALARM = 0x33; public static final int MSG_X1_GPS = 0x34; @@ -87,27 +91,69 @@ public class Gt06ProtocolDecoder extends BaseProtocolDecoder { public static final int MSG_COMMAND_0 = 0x80; public static final int MSG_COMMAND_1 = 0x81; public static final int MSG_COMMAND_2 = 0x82; + public static final int MSG_TIME_REQUEST = 0x8A; public static final int MSG_INFO = 0x94; public static final int MSG_STRING_INFO = 0x21; + public static final int MSG_GPS_2 = 0xA0; + public static final int MSG_LBS_2 = 0xA1; + public static final int MSG_WIFI_3 = 0xA2; + public static final int MSG_FENCE_SINGLE = 0xA3; + public static final int MSG_FENCE_MULTI = 0xA4; + public static final int MSG_LBS_ALARM = 0xA5; + public static final int MSG_LBS_ADDRESS = 0xA7; private static boolean isSupported(int type) { return hasGps(type) || hasLbs(type) || hasStatus(type); } private static boolean hasGps(int type) { - return type == MSG_GPS || type == MSG_GPS_LBS_1 || type == MSG_GPS_LBS_2 - || type == MSG_GPS_LBS_STATUS_1 || type == MSG_GPS_LBS_STATUS_2 || type == MSG_GPS_LBS_STATUS_3 - || type == MSG_GPS_PHONE || type == MSG_GPS_LBS_EXTEND; + switch (type) { + case MSG_GPS: + case MSG_GPS_LBS_1: + case MSG_GPS_LBS_2: + case MSG_GPS_LBS_STATUS_1: + case MSG_GPS_LBS_STATUS_2: + case MSG_GPS_LBS_STATUS_3: + case MSG_GPS_PHONE: + case MSG_GPS_LBS_EXTEND: + case MSG_GPS_2: + case MSG_FENCE_SINGLE: + return true; + default: + return false; + } } private static boolean hasLbs(int type) { - return type == MSG_LBS || type == MSG_LBS_STATUS || type == MSG_GPS_LBS_1 || type == MSG_GPS_LBS_2 - || type == MSG_GPS_LBS_STATUS_1 || type == MSG_GPS_LBS_STATUS_2 || type == MSG_GPS_LBS_STATUS_3; + switch (type) { + case MSG_LBS: + case MSG_LBS_STATUS: + case MSG_GPS_LBS_1: + case MSG_GPS_LBS_2: + case MSG_GPS_LBS_STATUS_1: + case MSG_GPS_LBS_STATUS_2: + case MSG_GPS_LBS_STATUS_3: + case MSG_GPS_2: + case MSG_FENCE_SINGLE: + case MSG_LBS_ALARM: + case MSG_LBS_ADDRESS: + return true; + default: + return false; + } } private static boolean hasStatus(int type) { - return type == MSG_STATUS || type == MSG_LBS_STATUS - || type == MSG_GPS_LBS_STATUS_1 || type == MSG_GPS_LBS_STATUS_2 || type == MSG_GPS_LBS_STATUS_3; + switch (type) { + case MSG_STATUS: + case MSG_LBS_STATUS: + case MSG_GPS_LBS_STATUS_1: + case MSG_GPS_LBS_STATUS_2: + case MSG_GPS_LBS_STATUS_3: + return true; + default: + return false; + } } private void sendResponse(Channel channel, boolean extended, int type, ChannelBuffer content) { @@ -348,6 +394,44 @@ public class Gt06ProtocolDecoder extends BaseProtocolDecoder { sendResponse(channel, false, type, null); } + } else if (type == MSG_HEARTBEAT) { + + Position position = new Position(); + position.setDeviceId(deviceSession.getDeviceId()); + position.setProtocol(getProtocolName()); + + getLastLocation(position, null); + + int status = buf.readUnsignedByte(); + position.set(Position.KEY_ARMED, BitUtil.check(status, 0)); + position.set(Position.KEY_IGNITION, BitUtil.check(status, 1)); + position.set(Position.KEY_CHARGE, BitUtil.check(status, 2)); + + sendResponse(channel, false, type, null); + + return position; + + } else if (type == MSG_ADDRESS_REQUEST) { + + String response = "NA&&NA&&0##"; + ChannelBuffer content = ChannelBuffers.dynamicBuffer(); + content.writeByte(response.length()); + content.writeInt(0); + content.writeBytes(response.getBytes(StandardCharsets.US_ASCII)); + sendResponse(channel, true, MSG_ADDRESS_RESPONSE, content); + + } else if (type == MSG_TIME_REQUEST) { + + Calendar calendar = Calendar.getInstance(TimeZone.getTimeZone("UTC")); + ChannelBuffer content = ChannelBuffers.dynamicBuffer(); + content.writeByte(calendar.get(Calendar.YEAR) - 2000); + content.writeByte(calendar.get(Calendar.MONTH) + 1); + content.writeByte(calendar.get(Calendar.DAY_OF_MONTH)); + content.writeByte(calendar.get(Calendar.HOUR_OF_DAY)); + content.writeByte(calendar.get(Calendar.MINUTE)); + content.writeByte(calendar.get(Calendar.SECOND)); + sendResponse(channel, false, MSG_TIME_REQUEST, content); + } else if (type == MSG_X1_GPS) { Position position = new Position(); @@ -385,48 +469,53 @@ public class Gt06ProtocolDecoder extends BaseProtocolDecoder { } else if (type == MSG_WIFI || type == MSG_WIFI_2) { - Position position = new Position(); - position.setDeviceId(deviceSession.getDeviceId()); - position.setProtocol(getProtocolName()); - - DateBuilder dateBuilder = new DateBuilder() - .setYear(BcdUtil.readInteger(buf, 2)) - .setMonth(BcdUtil.readInteger(buf, 2)) - .setDay(BcdUtil.readInteger(buf, 2)) - .setHour(BcdUtil.readInteger(buf, 2)) - .setMinute(BcdUtil.readInteger(buf, 2)) - .setSecond(BcdUtil.readInteger(buf, 2)); - getLastLocation(position, dateBuilder.getDate()); + return decodeWifi(buf, deviceSession); - Network network = new Network(); + } else { - int wifiCount = buf.getByte(2); - for (int i = 0; i < wifiCount; i++) { - String mac = String.format("%02x:%02x:%02x:%02x:%02x:%02x", - buf.readUnsignedByte(), buf.readUnsignedByte(), buf.readUnsignedByte(), - buf.readUnsignedByte(), buf.readUnsignedByte(), buf.readUnsignedByte()); - network.addWifiAccessPoint(WifiAccessPoint.from(mac, buf.readUnsignedByte())); - } + return decodeBasicOther(channel, buf, deviceSession, type, dataLength); - int cellCount = buf.readUnsignedByte(); - int mcc = buf.readUnsignedShort(); - int mnc = buf.readUnsignedByte(); - for (int i = 0; i < cellCount; i++) { - network.addCellTower(CellTower.from( - mcc, mnc, buf.readUnsignedShort(), buf.readUnsignedShort(), buf.readUnsignedByte())); - } + } - position.setNetwork(network); + return null; + } - return position; + private Object decodeWifi(ChannelBuffer buf, DeviceSession deviceSession) throws Exception { - } else { + Position position = new Position(); + position.setDeviceId(deviceSession.getDeviceId()); + position.setProtocol(getProtocolName()); - return decodeBasicOther(channel, buf, deviceSession, type, dataLength); + DateBuilder dateBuilder = new DateBuilder() + .setYear(BcdUtil.readInteger(buf, 2)) + .setMonth(BcdUtil.readInteger(buf, 2)) + .setDay(BcdUtil.readInteger(buf, 2)) + .setHour(BcdUtil.readInteger(buf, 2)) + .setMinute(BcdUtil.readInteger(buf, 2)) + .setSecond(BcdUtil.readInteger(buf, 2)); + getLastLocation(position, dateBuilder.getDate()); + + Network network = new Network(); + + int wifiCount = buf.getByte(2); + for (int i = 0; i < wifiCount; i++) { + String mac = String.format("%02x:%02x:%02x:%02x:%02x:%02x", + buf.readUnsignedByte(), buf.readUnsignedByte(), buf.readUnsignedByte(), + buf.readUnsignedByte(), buf.readUnsignedByte(), buf.readUnsignedByte()); + network.addWifiAccessPoint(WifiAccessPoint.from(mac, buf.readUnsignedByte())); + } + int cellCount = buf.readUnsignedByte(); + int mcc = buf.readUnsignedShort(); + int mnc = buf.readUnsignedByte(); + for (int i = 0; i < cellCount; i++) { + network.addCellTower(CellTower.from( + mcc, mnc, buf.readUnsignedShort(), buf.readUnsignedShort(), buf.readUnsignedByte())); } - return null; + position.setNetwork(network); + + return position; } private Object decodeBasicOther(Channel channel, ChannelBuffer buf, @@ -436,7 +525,8 @@ public class Gt06ProtocolDecoder extends BaseProtocolDecoder { position.setDeviceId(deviceSession.getDeviceId()); position.setProtocol(getProtocolName()); - if (type == MSG_LBS_MULTIPLE || type == MSG_LBS_EXTEND || type == MSG_LBS_WIFI) { + if (type == MSG_LBS_MULTIPLE || type == MSG_LBS_EXTEND || type == MSG_LBS_WIFI + || type == MSG_LBS_2 || type == MSG_WIFI_3) { DateBuilder dateBuilder = new DateBuilder(timeZone) .setDate(buf.readUnsignedByte(), buf.readUnsignedByte(), buf.readUnsignedByte()) @@ -458,7 +548,7 @@ public class Gt06ProtocolDecoder extends BaseProtocolDecoder { buf.readUnsignedByte(); // time leads - if (type != MSG_LBS_MULTIPLE) { + if (type != MSG_LBS_MULTIPLE && type != MSG_LBS_2) { int wifiCount = buf.readUnsignedByte(); for (int i = 0; i < wifiCount; i++) { String mac = ChannelBuffers.hexDump(buf.readBytes(6)).replaceAll("(..)", "$1:"); diff --git a/test/org/traccar/protocol/Gt06ProtocolDecoderTest.java b/test/org/traccar/protocol/Gt06ProtocolDecoderTest.java index c9ef29791..c6a95e6fc 100644 --- a/test/org/traccar/protocol/Gt06ProtocolDecoderTest.java +++ b/test/org/traccar/protocol/Gt06ProtocolDecoderTest.java @@ -16,6 +16,27 @@ public class Gt06ProtocolDecoderTest extends ProtocolTest { verifyNull(decoder, binary( "78780D01086471700328358100093F040D0A")); + verifyAttributes(decoder, binary( + "78780B23C00122040001000818720D0A")); + + verifyNotNull(decoder, binary( + "78782ba701cc000000919100000000090617032b3836313832323038343735363200000000000000000100049fb60d0a")); + + verifyNotNull(decoder, binary( + "787819a501cc0000009191000000000906170304050400010005f44d0d0a")); + + verifyNotNull(decoder, binary( + "78782ca3110b10081336f000000000000000000004003901cc0000009191000000000906170304050400010003e0940d0a")); + + verifyNotNull(decoder, binary( + "7878A3A2110B0603201501CC010000254E000000000615F804000000254E000000000615F804000000254E000000000615F804000000254E000000000615F804000000254E000000000615F804000000254E000000000615F804000000254E000000000615F80400FF08F483CD4DF4C0D750BD5F8BC5CECFB0D59DAFB459CDA8574E8424C6CC50BD5F6C7E1CC9B0D59D8AA718C90087363040E0C83496727B4DE4C7002919670D0A")); + + verifyNotNull(decoder, binary( + "78786CA1110B0413093801CC01000025FC000000000618C10201000025FC000000000618C10201000025FC000000000618C10201000025FC000000000618C10201000025FC000000000618C10201000025FC000000000618C10201000025FC000000000618C10201FF0002000541D70D0A")); + + verifyPosition(decoder, binary( + "787822220F0C1D023305C9027AC8180C46586000140001CC00287D001F71000001000820860D0A")); + verifyAttributes(decoder, binary( "797900262100000000020043006f006d006d0061006e00640020006500720072006f0072002100236e850d0a")); @@ -206,6 +227,12 @@ public class Gt06ProtocolDecoderTest extends ProtocolTest { verifyNull(decoder, binary( "787801080d0a")); + verifyNull(decoder, binary( + "78782E2A0F0C1D071139CA027AC8000C4658000014D83132353230313335333231373730373900000000000001002A6ECE0D0A")); + + verifyNull(decoder, binary( + "7878058A000688290D0A")); + } } -- cgit v1.2.3