From b16593f062d304e000899085b22d1232b055639b Mon Sep 17 00:00:00 2001 From: Anton Tananaev Date: Sun, 2 Jun 2013 22:51:54 +1200 Subject: Update Apel decoder --- src/org/traccar/helper/Crc.java | 9 ++ src/org/traccar/protocol/ApelProtocolDecoder.java | 188 +++++++++------------- 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 positions = new LinkedList(); 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; } -- cgit v1.2.3