diff options
-rw-r--r-- | src/org/traccar/protocol/Arnavi4FrameDecoder.java | 16 | ||||
-rw-r--r-- | src/org/traccar/protocol/Arnavi4ProtocolDecoder.java | 118 | ||||
-rw-r--r-- | test/org/traccar/protocol/Arnavi4FrameDecoderTest.java | 16 |
3 files changed, 85 insertions, 65 deletions
diff --git a/src/org/traccar/protocol/Arnavi4FrameDecoder.java b/src/org/traccar/protocol/Arnavi4FrameDecoder.java index a50ece641..bb130e6bb 100644 --- a/src/org/traccar/protocol/Arnavi4FrameDecoder.java +++ b/src/org/traccar/protocol/Arnavi4FrameDecoder.java @@ -50,10 +50,18 @@ public class Arnavi4FrameDecoder extends FrameDecoder { return buf.readBytes(HEADER_LENGTH); } - int parcelNumber = buf.getByte(1) & 0xFF; - if (buf.getByte(0) == PACKAGE_START_SIGN && buf.getByte(buf.readableBytes() - 1) == PACKAGE_END_SIGN - && parcelNumber >= PACKAGE_MIN_PARCEL_NUMBER && parcelNumber <= PACKAGE_MAX_PARCEL_NUMBER) { - return buf; + int index = buf.getByte(1) & 0xFF; // parcel number + if (buf.getByte(0) == PACKAGE_START_SIGN + && index >= PACKAGE_MIN_PARCEL_NUMBER && index <= PACKAGE_MAX_PARCEL_NUMBER) { + + // package: 1 byte start sign, 1 byte parcel number, packets, 1 byte end sign + int packetStartIndex = 2; + while (packetStartIndex + 8 < buf.readableBytes() && buf.getByte(packetStartIndex) != PACKAGE_END_SIGN) { + // packet: 1 byte type, 2 bytes length, 4 bytes unixtime, length-bytes data, 1 byte crc + packetStartIndex += buf.getUnsignedShort(packetStartIndex + 1) + 8; + } + + return buf.readBytes(packetStartIndex + 1); } return null; diff --git a/src/org/traccar/protocol/Arnavi4ProtocolDecoder.java b/src/org/traccar/protocol/Arnavi4ProtocolDecoder.java index 682fc1577..ed11e1559 100644 --- a/src/org/traccar/protocol/Arnavi4ProtocolDecoder.java +++ b/src/org/traccar/protocol/Arnavi4ProtocolDecoder.java @@ -52,6 +52,34 @@ public class Arnavi4ProtocolDecoder extends BaseProtocolDecoder { super(protocol); } + private void sendHeaderResponse(Channel channel, byte version) { + if (channel != null) { + final ChannelBuffer response; + if (version == HEADER_VERSION_1) { + response = ChannelBuffers.dynamicBuffer(ByteOrder.LITTLE_ENDIAN, 4); + response.writeBytes(new byte[]{0x7B, 0x00, 0x00, 0x7D}); + } else if (version == HEADER_VERSION_2) { + response = ChannelBuffers.dynamicBuffer(ByteOrder.LITTLE_ENDIAN, 9); + response.writeBytes(new byte[]{0x7B, 0x04, 0x00}); + byte[] timeBytes = ByteBuffer.allocate(4).putInt((int) (System.currentTimeMillis() / 1000)).array(); + response.writeByte(Checksum.modulo256(timeBytes)); + response.writeBytes(timeBytes); + response.writeByte(0x7D); + } else { + return; // Ignore unsupported versions of header + } + channel.write(response); + } + } + + private void sendPackageResponse(Channel channel, int index) { + if (channel != null) { + final ChannelBuffer response = ChannelBuffers.dynamicBuffer(ByteOrder.LITTLE_ENDIAN, 4); + response.writeBytes(new byte[]{0x7B, 0x00, (byte) index, 0x7D}); + channel.write(response); + } + } + private Position decodePosition(DeviceSession deviceSession, ChannelBuffer buf, int length, Date time) { final Position position = new Position(); @@ -75,15 +103,15 @@ public class Arnavi4ProtocolDecoder extends BaseProtocolDecoder { break; case TAG_COORD_PARAMS: - position.setCourse(buf.readUnsignedByte() * 2.0); - position.setAltitude(buf.readUnsignedByte() * 10.0); + position.setCourse(buf.readUnsignedByte() * 2); + position.setAltitude(buf.readUnsignedByte() * 10); byte satellites = buf.readByte(); position.set(Position.KEY_SATELLITES, satellites & 0x0F + (satellites >> 4) & 0x0F); // gps+glonass - position.setSpeed(buf.readUnsignedByte() * 1.852); + position.setSpeed(buf.readUnsignedByte()); break; default: - buf.readBytes(4); // Skip other tags + buf.readBytes(4); // Skip unsupported tags break; } @@ -108,27 +136,8 @@ public class Arnavi4ProtocolDecoder extends BaseProtocolDecoder { String imei = String.valueOf(buf.readLong()); DeviceSession deviceSession = getDeviceSession(channel, remoteAddress, imei); - if (deviceSession != null && channel != null) { - - final ChannelBuffer response; - - if (version == HEADER_VERSION_1) { - response = ChannelBuffers.dynamicBuffer(ByteOrder.LITTLE_ENDIAN, 4); - response.writeBytes(new byte[]{0x7B, 0x00, 0x00, 0x7D}); - - } else if (version == HEADER_VERSION_2) { - response = ChannelBuffers.dynamicBuffer(ByteOrder.LITTLE_ENDIAN, 9); - response.writeBytes(new byte[]{0x7B, 0x04, 0x00}); - byte[] timeBytes = ByteBuffer.allocate(4).putInt((int) (System.currentTimeMillis() / 1000)).array(); - response.writeByte(Checksum.modulo256(timeBytes)); - response.writeBytes(timeBytes); - response.writeByte(0x7D); - - } else { - throw new IllegalArgumentException("unsupported header version"); - } - - channel.write(response); + if (deviceSession != null) { + sendHeaderResponse(channel, version); } return null; @@ -139,49 +148,40 @@ public class Arnavi4ProtocolDecoder extends BaseProtocolDecoder { return null; } - if (startSign == PACKAGE_START_SIGN) { - - List<Position> positions = new LinkedList<>(); - - int index = buf.readUnsignedByte(); - - byte recordType = buf.readByte(); - while (recordType != PACKAGE_END_SIGN) { - switch (recordType) { - case RECORD_PING: - case RECORD_DATA: - case RECORD_TEXT: - case RECORD_FILE: - case RECORD_BINARY: - int length = buf.readUnsignedShort(); - Date time = new Date(buf.readUnsignedInt() * 1000); + List<Position> positions = new LinkedList<>(); - if (recordType == RECORD_DATA) { - positions.add(decodePosition(deviceSession, buf, length, time)); - } else { - buf.readBytes(length); // Skip other records - } + int index = buf.readUnsignedByte(); - buf.readUnsignedByte(); // crc - break; + byte recordType = buf.readByte(); + while (buf.readableBytes() > 0) { + switch (recordType) { + case RECORD_PING: + case RECORD_DATA: + case RECORD_TEXT: + case RECORD_FILE: + case RECORD_BINARY: + int length = buf.readUnsignedShort(); + Date time = new Date(buf.readUnsignedInt() * 1000); - default: - return null; // Unsupported types of package - } + if (recordType == RECORD_DATA) { + positions.add(decodePosition(deviceSession, buf, length, time)); + } else { + buf.readBytes(length); // Skip other records + } - recordType = buf.readByte(); - } + buf.readUnsignedByte(); // crc + break; - if (channel != null) { - final ChannelBuffer response = ChannelBuffers.dynamicBuffer(ByteOrder.LITTLE_ENDIAN, 4); - response.writeBytes(new byte[]{0x7B, 0x00, (byte) index, 0x7D}); - channel.write(response); + default: + return null; // Ignore unsupported types of package } - return positions; + recordType = buf.readByte(); // The last byte in package is end sign } - return null; + sendPackageResponse(channel, index); + + return positions; } } diff --git a/test/org/traccar/protocol/Arnavi4FrameDecoderTest.java b/test/org/traccar/protocol/Arnavi4FrameDecoderTest.java index 0b502bc36..93d818f56 100644 --- a/test/org/traccar/protocol/Arnavi4FrameDecoderTest.java +++ b/test/org/traccar/protocol/Arnavi4FrameDecoderTest.java @@ -21,14 +21,26 @@ public class Arnavi4FrameDecoderTest extends ProtocolTest { binary(ByteOrder.LITTLE_ENDIAN, "ff23f30c45f5c90f0300"), decoder.decode(null, null, binary(ByteOrder.LITTLE_ENDIAN, "ff23f30c45f5c90f0300"))); - Assert.assertEquals( // Valid PACKAGE packet with one DATA packet + Assert.assertEquals( // Valid PACKAGE with answer to server on file transfer. + null, + decoder.decode(null, null, binary(ByteOrder.LITTLE_ENDIAN, "5bfd005d"))); + + Assert.assertEquals( // Valid PACKAGE with one DATA packet binary(ByteOrder.LITTLE_ENDIAN, "5b01012800a3175f5903513934420447221c42055402781E0900f0c5215b4e0084005c00007c005d0000a300fa37010000295d"), decoder.decode(null, null, binary(ByteOrder.LITTLE_ENDIAN, "5b01012800a3175f5903513934420447221c42055402781E0900f0c5215b4e0084005c00007c005d0000a300fa37010000295d"))); - Assert.assertEquals( // Valid PACKAGE packet with two DATA packet + Assert.assertEquals( // Valid PACKAGE with two DATA packet binary(ByteOrder.LITTLE_ENDIAN, "5b01012800a3175f5903513934420447221c42055402781E0900f0c5215b4e0084005c00007c005d0000a300fa3701000029012800a3175f5903513934420447221c42055402781E0900f0c5215b4e0084005c00007c005d0000a300fa37010000295d"), decoder.decode(null, null, binary(ByteOrder.LITTLE_ENDIAN, "5b01012800a3175f5903513934420447221c42055402781E0900f0c5215b4e0084005c00007c005d0000a300fa3701000029012800a3175f5903513934420447221c42055402781E0900f0c5215b4e0084005c00007c005d0000a300fa37010000295d"))); + Assert.assertEquals( // Valid PACKAGE with one TEXT packet. + null, + decoder.decode(null, null, binary(ByteOrder.LITTLE_ENDIAN, "030700e3f16b50747261636361721b"))); + + Assert.assertEquals( // Valid PACKAGE with one BINARY packet. + null, + decoder.decode(null, null, binary(ByteOrder.LITTLE_ENDIAN, "062000e3f16b5003298b5e4204cbd514420500191000080400ff021b"))); + } }
\ No newline at end of file |