From 2e0ed3ccfde8f779111de2b722a94224faa65c99 Mon Sep 17 00:00:00 2001 From: Ivan Muratov Date: Tue, 11 Jul 2017 15:57:20 +0300 Subject: Create duplicate of ARNAVI3 protocol implementation. Add an entry with ARNAVI4 port to the properties in default.xml. --- src/org/traccar/protocol/Arnavi4Protocol.java | 35 +++++++++ .../traccar/protocol/Arnavi4ProtocolDecoder.java | 87 ++++++++++++++++++++++ 2 files changed, 122 insertions(+) create mode 100644 src/org/traccar/protocol/Arnavi4Protocol.java create mode 100644 src/org/traccar/protocol/Arnavi4ProtocolDecoder.java (limited to 'src') diff --git a/src/org/traccar/protocol/Arnavi4Protocol.java b/src/org/traccar/protocol/Arnavi4Protocol.java new file mode 100644 index 000000000..622051fbd --- /dev/null +++ b/src/org/traccar/protocol/Arnavi4Protocol.java @@ -0,0 +1,35 @@ +package org.traccar.protocol; + +import org.jboss.netty.bootstrap.ServerBootstrap; +import org.jboss.netty.channel.ChannelPipeline; +import org.jboss.netty.handler.codec.frame.LineBasedFrameDecoder; +import org.jboss.netty.handler.codec.string.StringDecoder; +import org.jboss.netty.handler.codec.string.StringEncoder; +import org.traccar.BaseProtocol; +import org.traccar.TrackerServer; + +import java.util.List; + +/** + * Created by Ivan Muratov @binakot on 11.07.2017. + */ +public class Arnavi4Protocol extends BaseProtocol { + + public Arnavi4Protocol() { + super("arnavi4"); + } + + @Override + public void initTrackerServers(List serverList) { + serverList.add(new TrackerServer(new ServerBootstrap(), getName()) { + @Override + protected void addSpecificHandlers(ChannelPipeline pipeline) { + pipeline.addLast("frameDecoder", new LineBasedFrameDecoder(1024)); + pipeline.addLast("stringDecoder", new StringDecoder()); + pipeline.addLast("stringEncoder", new StringEncoder()); + pipeline.addLast("objectDecoder", new Arnavi4ProtocolDecoder(Arnavi4Protocol.this)); + } + }); + } + +} diff --git a/src/org/traccar/protocol/Arnavi4ProtocolDecoder.java b/src/org/traccar/protocol/Arnavi4ProtocolDecoder.java new file mode 100644 index 000000000..dbedff9a1 --- /dev/null +++ b/src/org/traccar/protocol/Arnavi4ProtocolDecoder.java @@ -0,0 +1,87 @@ +package org.traccar.protocol; + +import org.jboss.netty.channel.Channel; +import org.traccar.BaseProtocolDecoder; +import org.traccar.DeviceSession; +import org.traccar.helper.DateBuilder; +import org.traccar.helper.Parser; +import org.traccar.helper.PatternBuilder; +import org.traccar.model.Position; + +import java.net.SocketAddress; +import java.util.regex.Pattern; + +/** + * Created by Ivan Muratov @binakot on 11.07.2017. + */ +public class Arnavi4ProtocolDecoder extends BaseProtocolDecoder { + + public Arnavi4ProtocolDecoder(Arnavi4Protocol protocol) { + super(protocol); + } + + private static final Pattern PATTERN = new PatternBuilder() + .text("$AV,") + .number("Vd,") // type + .number("(d+),") // device id + .number("(d+),") // index + .number("(d+),") // power + .number("(d+),") // battery + .number("-?d+,") + .expression("[01],") // movement + .expression("([01]),") // ignition + .number("(d+),") // input + .number("d+,d+,") // input 1 + .number("d+,d+,").optional() // input 2 + .expression("[01],") // fix type + .number("(d+),") // satellites + .number("(dd)(dd)(dd),") // time (hhmmss) + .number("(dd)(dd.d+)([NS]),") // latitude + .number("(ddd)(dd.d+)([EW]),") // longitude + .number("(d+.d+),") // speed + .number("(d+.d+),") // course + .number("(dd)(dd)(dd)") // date (ddmmyy) + .any() + .compile(); + + @Override + protected Object decode( + Channel channel, SocketAddress remoteAddress, Object msg) throws Exception { + + Parser parser = new Parser(PATTERN, (String) msg); + if (!parser.matches()) { + return null; + } + + Position position = new Position(); + position.setProtocol(getProtocolName()); + + DeviceSession deviceSession = getDeviceSession(channel, remoteAddress, parser.next()); + if (deviceSession == null) { + return null; + } + position.setDeviceId(deviceSession.getDeviceId()); + + position.set(Position.KEY_INDEX, parser.nextInt(0)); + position.set(Position.KEY_POWER, parser.nextInt(0) * 0.01); + position.set(Position.KEY_BATTERY, parser.nextInt(0) * 0.01); + position.set(Position.KEY_IGNITION, parser.nextInt(0) == 1); + position.set(Position.KEY_INPUT, parser.nextInt(0)); + position.set(Position.KEY_SATELLITES, parser.nextInt(0)); + + DateBuilder dateBuilder = new DateBuilder() + .setTime(parser.nextInt(0), parser.nextInt(0), parser.nextInt(0)); + + position.setValid(true); + position.setLatitude(parser.nextCoordinate()); + position.setLongitude(parser.nextCoordinate()); + position.setSpeed(parser.nextDouble(0)); + position.setCourse(parser.nextDouble(0)); + + dateBuilder.setDateReverse(parser.nextInt(0), parser.nextInt(0), parser.nextInt(0)); + position.setTime(dateBuilder.getDate()); + + return position; + } + +} -- cgit v1.2.3 From 6e70a873886b366980423e448808b60c624e4047 Mon Sep 17 00:00:00 2001 From: Ivan Muratov Date: Thu, 13 Jul 2017 08:30:35 +0300 Subject: Basic ARNAVI4 binary protocol implementation is done. Supported 2 types of HEADER packets (v1, v2). Supported 3 types of PACKAGE DATA records: latitude, longitude and additional data (speed, satellites, altitude, course). --- src/org/traccar/protocol/Arnavi4FrameDecoder.java | 51 ++++++ src/org/traccar/protocol/Arnavi4Protocol.java | 14 +- .../traccar/protocol/Arnavi4ProtocolDecoder.java | 188 +++++++++++++++------ .../traccar/protocol/Arnavi4FrameDecoderTest.java | 37 ++++ .../protocol/Arnavi4ProtocolDecoderTest.java | 23 ++- 5 files changed, 249 insertions(+), 64 deletions(-) create mode 100644 src/org/traccar/protocol/Arnavi4FrameDecoder.java create mode 100644 test/org/traccar/protocol/Arnavi4FrameDecoderTest.java (limited to 'src') diff --git a/src/org/traccar/protocol/Arnavi4FrameDecoder.java b/src/org/traccar/protocol/Arnavi4FrameDecoder.java new file mode 100644 index 000000000..eaf829cc3 --- /dev/null +++ b/src/org/traccar/protocol/Arnavi4FrameDecoder.java @@ -0,0 +1,51 @@ +package org.traccar.protocol; + +import org.jboss.netty.buffer.ChannelBuffer; +import org.jboss.netty.channel.Channel; +import org.jboss.netty.channel.ChannelHandlerContext; +import org.jboss.netty.handler.codec.frame.FrameDecoder; + +/** + * Created by Ivan Muratov @binakot on 12.07.2017. + */ +public class Arnavi4FrameDecoder extends FrameDecoder { + + static final byte HEADER_START_SIGN = (byte)0xFF; + static final byte HEADER_VERSION_1 = 0x22; + static final byte HEADER_VERSION_2 = 0x23; + static final int HEADER_LENGTH = 10; + + static final byte PACKAGE_START_SIGN = 0x5B; + static final byte PACKAGE_END_SIGN = 0x5D; + static final int PACKAGE_MIN_PARCEL_NUMBER = 0x01; + static final int PACKAGE_MAX_PARCEL_NUMBER = 0xFB; + + @Override + protected Object decode( + ChannelHandlerContext ctx, + Channel channel, + ChannelBuffer buf) throws Exception { + + if (buf.readableBytes() == 0) { + return null; + } + + byte[] bytes = new byte[buf.readableBytes()]; + buf.getBytes(0, bytes); + + if (bytes[0] == HEADER_START_SIGN + && bytes.length == HEADER_LENGTH + && (bytes[1] == HEADER_VERSION_1 || bytes[1] == HEADER_VERSION_2)) { + return buf.readBytes(HEADER_LENGTH); + } + + int parcelNumber = bytes[1] & 0xFF; + if (bytes[0] == PACKAGE_START_SIGN && bytes[bytes.length - 1] == PACKAGE_END_SIGN + && parcelNumber >= PACKAGE_MIN_PARCEL_NUMBER && parcelNumber <= PACKAGE_MAX_PARCEL_NUMBER) { + return buf.readBytes(bytes.length); + } + + return null; + } + +} diff --git a/src/org/traccar/protocol/Arnavi4Protocol.java b/src/org/traccar/protocol/Arnavi4Protocol.java index 622051fbd..227397980 100644 --- a/src/org/traccar/protocol/Arnavi4Protocol.java +++ b/src/org/traccar/protocol/Arnavi4Protocol.java @@ -2,12 +2,10 @@ package org.traccar.protocol; import org.jboss.netty.bootstrap.ServerBootstrap; import org.jboss.netty.channel.ChannelPipeline; -import org.jboss.netty.handler.codec.frame.LineBasedFrameDecoder; -import org.jboss.netty.handler.codec.string.StringDecoder; -import org.jboss.netty.handler.codec.string.StringEncoder; import org.traccar.BaseProtocol; import org.traccar.TrackerServer; +import java.nio.ByteOrder; import java.util.List; /** @@ -21,15 +19,15 @@ public class Arnavi4Protocol extends BaseProtocol { @Override public void initTrackerServers(List serverList) { - serverList.add(new TrackerServer(new ServerBootstrap(), getName()) { + TrackerServer server = new TrackerServer(new ServerBootstrap(), getName()) { @Override protected void addSpecificHandlers(ChannelPipeline pipeline) { - pipeline.addLast("frameDecoder", new LineBasedFrameDecoder(1024)); - pipeline.addLast("stringDecoder", new StringDecoder()); - pipeline.addLast("stringEncoder", new StringEncoder()); + pipeline.addLast("frameDecoder", new Arnavi4FrameDecoder()); pipeline.addLast("objectDecoder", new Arnavi4ProtocolDecoder(Arnavi4Protocol.this)); } - }); + }; + server.setEndianness(ByteOrder.LITTLE_ENDIAN); + serverList.add(server); } } diff --git a/src/org/traccar/protocol/Arnavi4ProtocolDecoder.java b/src/org/traccar/protocol/Arnavi4ProtocolDecoder.java index dbedff9a1..caa8dd28f 100644 --- a/src/org/traccar/protocol/Arnavi4ProtocolDecoder.java +++ b/src/org/traccar/protocol/Arnavi4ProtocolDecoder.java @@ -1,87 +1,175 @@ package org.traccar.protocol; +import org.jboss.netty.buffer.ChannelBuffer; +import org.jboss.netty.buffer.ChannelBuffers; import org.jboss.netty.channel.Channel; import org.traccar.BaseProtocolDecoder; import org.traccar.DeviceSession; -import org.traccar.helper.DateBuilder; -import org.traccar.helper.Parser; -import org.traccar.helper.PatternBuilder; import org.traccar.model.Position; import java.net.SocketAddress; -import java.util.regex.Pattern; +import java.nio.ByteBuffer; +import java.nio.ByteOrder; +import java.util.Date; +import java.util.LinkedList; +import java.util.List; + +import static org.traccar.protocol.Arnavi4FrameDecoder.*; /** * Created by Ivan Muratov @binakot on 11.07.2017. */ public class Arnavi4ProtocolDecoder extends BaseProtocolDecoder { + private static final byte RECORD_PING = 0x00; + private static final byte RECORD_DATA = 0x01; + private static final byte RECORD_TEXT = 0x03; + private static final byte RECORD_FILE = 0x04; + private static final byte RECORD_BINARY = 0x06; + + private static final byte TAG_LATITUDE = 3; + private static final byte TAG_LONGITUDE = 4; + private static final byte TAG_COORD_PARAMS = 5; + public Arnavi4ProtocolDecoder(Arnavi4Protocol protocol) { super(protocol); } - private static final Pattern PATTERN = new PatternBuilder() - .text("$AV,") - .number("Vd,") // type - .number("(d+),") // device id - .number("(d+),") // index - .number("(d+),") // power - .number("(d+),") // battery - .number("-?d+,") - .expression("[01],") // movement - .expression("([01]),") // ignition - .number("(d+),") // input - .number("d+,d+,") // input 1 - .number("d+,d+,").optional() // input 2 - .expression("[01],") // fix type - .number("(d+),") // satellites - .number("(dd)(dd)(dd),") // time (hhmmss) - .number("(dd)(dd.d+)([NS]),") // latitude - .number("(ddd)(dd.d+)([EW]),") // longitude - .number("(d+.d+),") // speed - .number("(d+.d+),") // course - .number("(dd)(dd)(dd)") // date (ddmmyy) - .any() - .compile(); + private static int modulo256Checksum(byte[] bytes) { + int sum = 0; + for (byte b : bytes) { + sum = (sum + b) & 0xFF; + } + return sum; + } + + private Position decodePosition(DeviceSession deviceSession, ChannelBuffer buf, long timestamp) { + + final Position position = new Position(); + position.setProtocol(getProtocolName()); + position.setDeviceId(deviceSession.getDeviceId()); + + position.setTime(new Date(timestamp)); + + while (buf.readableBytes() > 0) { + short tagId = buf.readUnsignedByte(); + int tagValue = buf.readInt(); + switch (tagId) { + case TAG_LATITUDE: + position.setLatitude(Float.intBitsToFloat(tagValue)); + position.setValid(true); + break; + + case TAG_LONGITUDE: + position.setLongitude(Float.intBitsToFloat(tagValue)); + position.setValid(true); + break; + + case TAG_COORD_PARAMS: + position.setSpeed((tagValue >> 24) * 1.852); + position.set(Position.KEY_SATELLITES, (tagValue >> 16 & 0x0F) + (tagValue >> 20 & 0x0F)); + position.setAltitude((tagValue >> 8 & 0xFF) * 10.0); + position.setCourse((tagValue & 0xFF) * 2.0); + break; + + default: + break; // Skip other tags + } + } + + return position; + } @Override protected Object decode( Channel channel, SocketAddress remoteAddress, Object msg) throws Exception { - Parser parser = new Parser(PATTERN, (String) msg); - if (!parser.matches()) { + ChannelBuffer buf = (ChannelBuffer) msg; + + byte startSign = buf.readByte(); + + if (startSign == HEADER_START_SIGN) { + + byte version = buf.readByte(); + + 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[] timestampBytes = ByteBuffer.allocate(4).putInt((int) (System.currentTimeMillis() / 1000)).array(); + response.writeByte(modulo256Checksum(timestampBytes)); + response.writeBytes(timestampBytes); + response.writeByte(0x7D); + + } else { + throw new IllegalArgumentException("unsupported header version"); + } + + channel.write(response); + } + return null; } - Position position = new Position(); - position.setProtocol(getProtocolName()); - - DeviceSession deviceSession = getDeviceSession(channel, remoteAddress, parser.next()); + DeviceSession deviceSession = getDeviceSession(channel, remoteAddress); if (deviceSession == null) { return null; } - position.setDeviceId(deviceSession.getDeviceId()); - position.set(Position.KEY_INDEX, parser.nextInt(0)); - position.set(Position.KEY_POWER, parser.nextInt(0) * 0.01); - position.set(Position.KEY_BATTERY, parser.nextInt(0) * 0.01); - position.set(Position.KEY_IGNITION, parser.nextInt(0) == 1); - position.set(Position.KEY_INPUT, parser.nextInt(0)); - position.set(Position.KEY_SATELLITES, parser.nextInt(0)); + if (startSign == PACKAGE_START_SIGN) { - DateBuilder dateBuilder = new DateBuilder() - .setTime(parser.nextInt(0), parser.nextInt(0), parser.nextInt(0)); + List positions = new LinkedList<>(); - position.setValid(true); - position.setLatitude(parser.nextCoordinate()); - position.setLongitude(parser.nextCoordinate()); - position.setSpeed(parser.nextDouble(0)); - position.setCourse(parser.nextDouble(0)); + int parcelNumber = buf.readUnsignedByte(); - dateBuilder.setDateReverse(parser.nextInt(0), parser.nextInt(0), parser.nextInt(0)); - position.setTime(dateBuilder.getDate()); + byte recordStartSign = buf.readByte(); + while (recordStartSign != PACKAGE_END_SIGN) { + switch (recordStartSign) { + case RECORD_PING: + case RECORD_DATA: + case RECORD_TEXT: + case RECORD_FILE: + case RECORD_BINARY: { + int length = buf.readUnsignedShort(); + long timestamp = buf.readUnsignedInt() * 1000; + ChannelBuffer recordBuf = buf.readBytes(length); - return position; + if (recordStartSign == RECORD_DATA) { + positions.add(decodePosition(deviceSession, recordBuf, timestamp)); + } + + buf.readUnsignedByte(); // crc + + break; + } + + default: + throw new IllegalArgumentException("unsupported record type"); + } + + recordStartSign = buf.readByte(); + } + + if (channel != null) { + final ChannelBuffer response = ChannelBuffers.dynamicBuffer(ByteOrder.LITTLE_ENDIAN, 4); + response.writeBytes(new byte[]{0x7B, 0x00, (byte) parcelNumber, 0x7D}); + channel.write(response); + } + + return positions; + } + + return null; } } diff --git a/test/org/traccar/protocol/Arnavi4FrameDecoderTest.java b/test/org/traccar/protocol/Arnavi4FrameDecoderTest.java new file mode 100644 index 000000000..08abd3835 --- /dev/null +++ b/test/org/traccar/protocol/Arnavi4FrameDecoderTest.java @@ -0,0 +1,37 @@ +package org.traccar.protocol; + +import org.junit.Assert; +import org.junit.Test; +import org.traccar.ProtocolTest; + +import java.nio.ByteOrder; + +/** + * Created by Ivan Muratov @binakot on 13.07.2017. + */ +public class Arnavi4FrameDecoderTest extends ProtocolTest { + + @Test + public void testDecode() throws Exception { + + Arnavi4FrameDecoder decoder = new Arnavi4FrameDecoder(); + + Assert.assertEquals( // Valid HEADER v1 packet with IMEI + binary(ByteOrder.LITTLE_ENDIAN, "ff22f30c45f5c90f0300"), + decoder.decode(null, null, binary(ByteOrder.LITTLE_ENDIAN, "ff22f30c45f5c90f0300"))); + + Assert.assertEquals( // Valid HEADER v2 packet with IMEI + binary(ByteOrder.LITTLE_ENDIAN, "ff23f30c45f5c90f0300"), + decoder.decode(null, null, binary(ByteOrder.LITTLE_ENDIAN, "ff23f30c45f5c90f0300"))); + + Assert.assertEquals( // Valid PACKAGE packet 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 + binary(ByteOrder.LITTLE_ENDIAN, "5b01012800a3175f5903513934420447221c42055402781E0900f0c5215b4e0084005c00007c005d0000a300fa3701000029012800a3175f5903513934420447221c42055402781E0900f0c5215b4e0084005c00007c005d0000a300fa37010000295d"), + decoder.decode(null, null, binary(ByteOrder.LITTLE_ENDIAN, "5b01012800a3175f5903513934420447221c42055402781E0900f0c5215b4e0084005c00007c005d0000a300fa3701000029012800a3175f5903513934420447221c42055402781E0900f0c5215b4e0084005c00007c005d0000a300fa37010000295d"))); + + } + +} \ No newline at end of file diff --git a/test/org/traccar/protocol/Arnavi4ProtocolDecoderTest.java b/test/org/traccar/protocol/Arnavi4ProtocolDecoderTest.java index b199fe565..2395572a1 100644 --- a/test/org/traccar/protocol/Arnavi4ProtocolDecoderTest.java +++ b/test/org/traccar/protocol/Arnavi4ProtocolDecoderTest.java @@ -3,7 +3,7 @@ package org.traccar.protocol; import org.junit.Test; import org.traccar.ProtocolTest; -import static org.junit.Assert.*; +import java.nio.ByteOrder; /** * Created by Ivan Muratov @binakot on 11.07.2017. @@ -13,14 +13,25 @@ public class Arnavi4ProtocolDecoderTest extends ProtocolTest { @Test public void testDecode() throws Exception { - Arnavi4ProtocolDecoder decoder = new Arnavi4ProtocolDecoder(new Arnavi4Protocol()); + Arnavi4ProtocolDecoder decoder; - verifyPosition(decoder, text( - "$AV,V2,32768,12487,2277,203,-1,0,0,193,0,0,1,13,200741,5950.6773N,03029.1043E,0.0,0.0,121012,*6E")); + decoder = new Arnavi4ProtocolDecoder(new Arnavi4Protocol()); - verifyPosition(decoder, text( - "$AV,V3,999999,12487,2277,203,65534,0,0,193,65535,65535,65535,65535,1,13,200741,5950.6773N,03029.1043E,300.0,360.0,121012,65535,65535,65535,SF*6E")); + verifyNull(decoder, binary(ByteOrder.LITTLE_ENDIAN, // Valid HEADER v1 packet with IMEI + "ff22f30c45f5c90f0300")); + verifyPositions(decoder, binary(ByteOrder.LITTLE_ENDIAN, // Valid PACKAGE packet with one DATA packet + "5b01012800a3175f5903513934420447221c42055402781E0900f0c5215b4e0084005c00007c005d0000a300fa37010000295d"), + position("2017-07-07 05:09:55.000", true, 45.05597, 39.03347)); + + decoder = new Arnavi4ProtocolDecoder(new Arnavi4Protocol()); + + verifyNull(decoder, binary(ByteOrder.LITTLE_ENDIAN, // Valid HEADER v2 packet with IMEI + "ff23f30c45f5c90f0300")); + + verifyPositions(decoder, binary(ByteOrder.LITTLE_ENDIAN, // Valid PACKAGE packet with two DATA packet + "5b01012800a3175f5903513934420447221c42055402781E0900f0c5215b4e0084005c00007c005d0000a300fa3701000029012800a3175f5903513934420447221c42055402781E0900f0c5215b4e0084005c00007c005d0000a300fa37010000295d"), + position("2017-07-07 05:09:55.000", true, 45.05597, 39.03347)); } } -- cgit v1.2.3 From 358b591bc457786927ac1466e10181bbffbcf56b Mon Sep 17 00:00:00 2001 From: Ivan Muratov Date: Thu, 13 Jul 2017 08:42:17 +0300 Subject: Replace MODULO256 checksum method. Added covering tests. --- src/org/traccar/helper/Checksum.java | 8 ++++++++ src/org/traccar/protocol/Arnavi4ProtocolDecoder.java | 11 ++--------- test/org/traccar/helper/ChecksumTest.java | 8 ++++++++ 3 files changed, 18 insertions(+), 9 deletions(-) (limited to 'src') diff --git a/src/org/traccar/helper/Checksum.java b/src/org/traccar/helper/Checksum.java index 43ba6a689..7a0151d36 100644 --- a/src/org/traccar/helper/Checksum.java +++ b/src/org/traccar/helper/Checksum.java @@ -243,4 +243,12 @@ public final class Checksum { return (10 - (checksum % 10)) % 10; } + public static int modulo256(byte... bytes) { + int sum = 0; + for (byte b : bytes) { + sum = (sum + b) & 0xFF; + } + return sum; + } + } diff --git a/src/org/traccar/protocol/Arnavi4ProtocolDecoder.java b/src/org/traccar/protocol/Arnavi4ProtocolDecoder.java index caa8dd28f..46caebb71 100644 --- a/src/org/traccar/protocol/Arnavi4ProtocolDecoder.java +++ b/src/org/traccar/protocol/Arnavi4ProtocolDecoder.java @@ -5,6 +5,7 @@ import org.jboss.netty.buffer.ChannelBuffers; import org.jboss.netty.channel.Channel; import org.traccar.BaseProtocolDecoder; import org.traccar.DeviceSession; +import org.traccar.helper.Checksum; import org.traccar.model.Position; import java.net.SocketAddress; @@ -35,14 +36,6 @@ public class Arnavi4ProtocolDecoder extends BaseProtocolDecoder { super(protocol); } - private static int modulo256Checksum(byte[] bytes) { - int sum = 0; - for (byte b : bytes) { - sum = (sum + b) & 0xFF; - } - return sum; - } - private Position decodePosition(DeviceSession deviceSession, ChannelBuffer buf, long timestamp) { final Position position = new Position(); @@ -107,7 +100,7 @@ public class Arnavi4ProtocolDecoder extends BaseProtocolDecoder { response = ChannelBuffers.dynamicBuffer(ByteOrder.LITTLE_ENDIAN, 9); response.writeBytes(new byte[]{0x7B, 0x04, 0x00}); byte[] timestampBytes = ByteBuffer.allocate(4).putInt((int) (System.currentTimeMillis() / 1000)).array(); - response.writeByte(modulo256Checksum(timestampBytes)); + response.writeByte(Checksum.modulo256(timestampBytes)); response.writeBytes(timestampBytes); response.writeByte(0x7D); diff --git a/test/org/traccar/helper/ChecksumTest.java b/test/org/traccar/helper/ChecksumTest.java index c37eda88d..737b65c62 100644 --- a/test/org/traccar/helper/ChecksumTest.java +++ b/test/org/traccar/helper/ChecksumTest.java @@ -4,6 +4,7 @@ import org.jboss.netty.buffer.ChannelBuffer; import org.jboss.netty.buffer.ChannelBuffers; import org.junit.Assert; import org.junit.Test; +import org.traccar.protocol.Arnavi4ProtocolDecoder; import java.nio.charset.StandardCharsets; @@ -28,4 +29,11 @@ public class ChecksumTest { Assert.assertEquals(0, Checksum.luhn(63070019470771L)); } + @Test + public void testModulo256() { + Assert.assertEquals(0x00, Checksum.modulo256((byte)0x00)); + Assert.assertEquals(0x00, Checksum.modulo256((byte)0x00, (byte)0x00, (byte)0x00)); + Assert.assertEquals(0x06, Checksum.modulo256((byte)0x01, (byte)0x02, (byte)0x03)); + } + } -- cgit v1.2.3 From f643173b6b2c52a3896d6ee13578edd86f9eb3e7 Mon Sep 17 00:00:00 2001 From: Ivan Muratov Date: Thu, 13 Jul 2017 09:10:57 +0300 Subject: Fix build issues. [ERROR] src/org/traccar/protocol/Arnavi4FrameDecoder.java:[13,49] (whitespace) WhitespaceAfter: 'typecast' is not followed by whitespace. [ERROR] src/org/traccar/protocol/Arnavi4ProtocolDecoder.java:[18] (imports) AvoidStarImport: Using the '.*' form of import should be avoided - org.traccar.protocol.Arnavi4FrameDecoder.*. [ERROR] src/org/traccar/protocol/Arnavi4ProtocolDecoder.java:[102] (sizes) LineLength: Line is longer than 120 characters (found 125). [ERROR] src/org/traccar/protocol/Arnavi4ProtocolDecoder.java:[135,41] (blocks) AvoidNestedBlocks: Avoid nested blocks. --- src/org/traccar/protocol/Arnavi4FrameDecoder.java | 2 +- src/org/traccar/protocol/Arnavi4ProtocolDecoder.java | 16 +++++++++------- 2 files changed, 10 insertions(+), 8 deletions(-) (limited to 'src') diff --git a/src/org/traccar/protocol/Arnavi4FrameDecoder.java b/src/org/traccar/protocol/Arnavi4FrameDecoder.java index eaf829cc3..97bf75a20 100644 --- a/src/org/traccar/protocol/Arnavi4FrameDecoder.java +++ b/src/org/traccar/protocol/Arnavi4FrameDecoder.java @@ -10,7 +10,7 @@ import org.jboss.netty.handler.codec.frame.FrameDecoder; */ public class Arnavi4FrameDecoder extends FrameDecoder { - static final byte HEADER_START_SIGN = (byte)0xFF; + static final byte HEADER_START_SIGN = (byte) 0xFF; static final byte HEADER_VERSION_1 = 0x22; static final byte HEADER_VERSION_2 = 0x23; static final int HEADER_LENGTH = 10; diff --git a/src/org/traccar/protocol/Arnavi4ProtocolDecoder.java b/src/org/traccar/protocol/Arnavi4ProtocolDecoder.java index 46caebb71..c5ec3f31f 100644 --- a/src/org/traccar/protocol/Arnavi4ProtocolDecoder.java +++ b/src/org/traccar/protocol/Arnavi4ProtocolDecoder.java @@ -15,7 +15,11 @@ import java.util.Date; import java.util.LinkedList; import java.util.List; -import static org.traccar.protocol.Arnavi4FrameDecoder.*; +import static org.traccar.protocol.Arnavi4FrameDecoder.HEADER_START_SIGN; +import static org.traccar.protocol.Arnavi4FrameDecoder.HEADER_VERSION_1; +import static org.traccar.protocol.Arnavi4FrameDecoder.HEADER_VERSION_2; +import static org.traccar.protocol.Arnavi4FrameDecoder.PACKAGE_START_SIGN; +import static org.traccar.protocol.Arnavi4FrameDecoder.PACKAGE_END_SIGN; /** * Created by Ivan Muratov @binakot on 11.07.2017. @@ -99,9 +103,9 @@ public class Arnavi4ProtocolDecoder extends BaseProtocolDecoder { } else if (version == HEADER_VERSION_2) { response = ChannelBuffers.dynamicBuffer(ByteOrder.LITTLE_ENDIAN, 9); response.writeBytes(new byte[]{0x7B, 0x04, 0x00}); - byte[] timestampBytes = ByteBuffer.allocate(4).putInt((int) (System.currentTimeMillis() / 1000)).array(); - response.writeByte(Checksum.modulo256(timestampBytes)); - response.writeBytes(timestampBytes); + byte[] timeBytes = ByteBuffer.allocate(4).putInt((int) (System.currentTimeMillis() / 1000)).array(); + response.writeByte(Checksum.modulo256(timeBytes)); + response.writeBytes(timeBytes); response.writeByte(0x7D); } else { @@ -132,7 +136,7 @@ public class Arnavi4ProtocolDecoder extends BaseProtocolDecoder { case RECORD_DATA: case RECORD_TEXT: case RECORD_FILE: - case RECORD_BINARY: { + case RECORD_BINARY: int length = buf.readUnsignedShort(); long timestamp = buf.readUnsignedInt() * 1000; ChannelBuffer recordBuf = buf.readBytes(length); @@ -142,9 +146,7 @@ public class Arnavi4ProtocolDecoder extends BaseProtocolDecoder { } buf.readUnsignedByte(); // crc - break; - } default: throw new IllegalArgumentException("unsupported record type"); -- cgit v1.2.3 From 50d45d27beb423c1689f83401d0adb88b7fafb65 Mon Sep 17 00:00:00 2001 From: Ivan Muratov Date: Fri, 14 Jul 2017 08:48:27 +0300 Subject: Correction based on comments. Re-write modulo256 checksum's parameter to byte array, not varargs. Split the tests to two methods for HEADER ver1 and ver2. Remove above-class copyrights, added top-file copyrights. Rename parcelNumber to index. Rename recordStartSign to recordType. Remove crearing additional buffer for record data, use origin buffer instead. Added check on minimal length of packet to avoid the out-of-range exceptions. --- src/org/traccar/helper/Checksum.java | 2 +- src/org/traccar/protocol/Arnavi4FrameDecoder.java | 22 +++++++-- src/org/traccar/protocol/Arnavi4Protocol.java | 18 ++++++-- .../traccar/protocol/Arnavi4ProtocolDecoder.java | 52 ++++++++++++++-------- test/org/traccar/helper/ChecksumTest.java | 7 ++- .../traccar/protocol/Arnavi4FrameDecoderTest.java | 3 -- .../protocol/Arnavi4ProtocolDecoderTest.java | 11 +++-- 7 files changed, 77 insertions(+), 38 deletions(-) (limited to 'src') diff --git a/src/org/traccar/helper/Checksum.java b/src/org/traccar/helper/Checksum.java index 7a0151d36..44cef9635 100644 --- a/src/org/traccar/helper/Checksum.java +++ b/src/org/traccar/helper/Checksum.java @@ -243,7 +243,7 @@ public final class Checksum { return (10 - (checksum % 10)) % 10; } - public static int modulo256(byte... bytes) { + public static int modulo256(byte[] bytes) { int sum = 0; for (byte b : bytes) { sum = (sum + b) & 0xFF; diff --git a/src/org/traccar/protocol/Arnavi4FrameDecoder.java b/src/org/traccar/protocol/Arnavi4FrameDecoder.java index 97bf75a20..2587420c9 100644 --- a/src/org/traccar/protocol/Arnavi4FrameDecoder.java +++ b/src/org/traccar/protocol/Arnavi4FrameDecoder.java @@ -1,3 +1,18 @@ +/* + * Copyright 2017 Ivan Muratov (binakot@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 org.jboss.netty.buffer.ChannelBuffer; @@ -5,11 +20,10 @@ import org.jboss.netty.channel.Channel; import org.jboss.netty.channel.ChannelHandlerContext; import org.jboss.netty.handler.codec.frame.FrameDecoder; -/** - * Created by Ivan Muratov @binakot on 12.07.2017. - */ public class Arnavi4FrameDecoder extends FrameDecoder { + static final int PACKET_MIN_LENGTH = 4; + static final byte HEADER_START_SIGN = (byte) 0xFF; static final byte HEADER_VERSION_1 = 0x22; static final byte HEADER_VERSION_2 = 0x23; @@ -26,7 +40,7 @@ public class Arnavi4FrameDecoder extends FrameDecoder { Channel channel, ChannelBuffer buf) throws Exception { - if (buf.readableBytes() == 0) { + if (buf.readableBytes() < PACKET_MIN_LENGTH) { return null; } diff --git a/src/org/traccar/protocol/Arnavi4Protocol.java b/src/org/traccar/protocol/Arnavi4Protocol.java index 227397980..381a9b457 100644 --- a/src/org/traccar/protocol/Arnavi4Protocol.java +++ b/src/org/traccar/protocol/Arnavi4Protocol.java @@ -1,3 +1,18 @@ +/* + * Copyright 2017 Ivan Muratov (binakot@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 org.jboss.netty.bootstrap.ServerBootstrap; @@ -8,9 +23,6 @@ import org.traccar.TrackerServer; import java.nio.ByteOrder; import java.util.List; -/** - * Created by Ivan Muratov @binakot on 11.07.2017. - */ public class Arnavi4Protocol extends BaseProtocol { public Arnavi4Protocol() { diff --git a/src/org/traccar/protocol/Arnavi4ProtocolDecoder.java b/src/org/traccar/protocol/Arnavi4ProtocolDecoder.java index c5ec3f31f..232e8f053 100644 --- a/src/org/traccar/protocol/Arnavi4ProtocolDecoder.java +++ b/src/org/traccar/protocol/Arnavi4ProtocolDecoder.java @@ -1,3 +1,18 @@ +/* + * Copyright 2017 Ivan Muratov (binakot@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 org.jboss.netty.buffer.ChannelBuffer; @@ -21,9 +36,6 @@ import static org.traccar.protocol.Arnavi4FrameDecoder.HEADER_VERSION_2; import static org.traccar.protocol.Arnavi4FrameDecoder.PACKAGE_START_SIGN; import static org.traccar.protocol.Arnavi4FrameDecoder.PACKAGE_END_SIGN; -/** - * Created by Ivan Muratov @binakot on 11.07.2017. - */ public class Arnavi4ProtocolDecoder extends BaseProtocolDecoder { private static final byte RECORD_PING = 0x00; @@ -40,18 +52,19 @@ public class Arnavi4ProtocolDecoder extends BaseProtocolDecoder { super(protocol); } - private Position decodePosition(DeviceSession deviceSession, ChannelBuffer buf, long timestamp) { + private Position decodePosition(DeviceSession deviceSession, ChannelBuffer buf, int length, Date time) { final Position position = new Position(); position.setProtocol(getProtocolName()); position.setDeviceId(deviceSession.getDeviceId()); - position.setTime(new Date(timestamp)); + position.setTime(time); - while (buf.readableBytes() > 0) { - short tagId = buf.readUnsignedByte(); + int readBytes = 0; + while (readBytes < length) { + short tag = buf.readUnsignedByte(); int tagValue = buf.readInt(); - switch (tagId) { + switch (tag) { case TAG_LATITUDE: position.setLatitude(Float.intBitsToFloat(tagValue)); position.setValid(true); @@ -72,6 +85,8 @@ public class Arnavi4ProtocolDecoder extends BaseProtocolDecoder { default: break; // Skip other tags } + + readBytes += 5; // 1 byte tag + 4 bytes value } return position; @@ -127,37 +142,36 @@ public class Arnavi4ProtocolDecoder extends BaseProtocolDecoder { List positions = new LinkedList<>(); - int parcelNumber = buf.readUnsignedByte(); + int index = buf.readUnsignedByte(); - byte recordStartSign = buf.readByte(); - while (recordStartSign != PACKAGE_END_SIGN) { - switch (recordStartSign) { + 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(); - long timestamp = buf.readUnsignedInt() * 1000; - ChannelBuffer recordBuf = buf.readBytes(length); + Date time = new Date(buf.readUnsignedInt() * 1000); - if (recordStartSign == RECORD_DATA) { - positions.add(decodePosition(deviceSession, recordBuf, timestamp)); + if (recordType == RECORD_DATA) { + positions.add(decodePosition(deviceSession, buf, length, time)); } buf.readUnsignedByte(); // crc break; default: - throw new IllegalArgumentException("unsupported record type"); + return null; // Unsupported types of package } - recordStartSign = buf.readByte(); + recordType = buf.readByte(); } if (channel != null) { final ChannelBuffer response = ChannelBuffers.dynamicBuffer(ByteOrder.LITTLE_ENDIAN, 4); - response.writeBytes(new byte[]{0x7B, 0x00, (byte) parcelNumber, 0x7D}); + response.writeBytes(new byte[]{0x7B, 0x00, (byte) index, 0x7D}); channel.write(response); } diff --git a/test/org/traccar/helper/ChecksumTest.java b/test/org/traccar/helper/ChecksumTest.java index 737b65c62..c7c5031df 100644 --- a/test/org/traccar/helper/ChecksumTest.java +++ b/test/org/traccar/helper/ChecksumTest.java @@ -4,7 +4,6 @@ import org.jboss.netty.buffer.ChannelBuffer; import org.jboss.netty.buffer.ChannelBuffers; import org.junit.Assert; import org.junit.Test; -import org.traccar.protocol.Arnavi4ProtocolDecoder; import java.nio.charset.StandardCharsets; @@ -31,9 +30,9 @@ public class ChecksumTest { @Test public void testModulo256() { - Assert.assertEquals(0x00, Checksum.modulo256((byte)0x00)); - Assert.assertEquals(0x00, Checksum.modulo256((byte)0x00, (byte)0x00, (byte)0x00)); - Assert.assertEquals(0x06, Checksum.modulo256((byte)0x01, (byte)0x02, (byte)0x03)); + Assert.assertEquals(0x00, Checksum.modulo256(new byte[] {0x00})); + Assert.assertEquals(0x00, Checksum.modulo256(new byte[] {0x00, 0x00, 0x00})); + Assert.assertEquals(0x06, Checksum.modulo256(new byte[] {0x01, 0x02, 0x03})); } } diff --git a/test/org/traccar/protocol/Arnavi4FrameDecoderTest.java b/test/org/traccar/protocol/Arnavi4FrameDecoderTest.java index 08abd3835..0b502bc36 100644 --- a/test/org/traccar/protocol/Arnavi4FrameDecoderTest.java +++ b/test/org/traccar/protocol/Arnavi4FrameDecoderTest.java @@ -6,9 +6,6 @@ import org.traccar.ProtocolTest; import java.nio.ByteOrder; -/** - * Created by Ivan Muratov @binakot on 13.07.2017. - */ public class Arnavi4FrameDecoderTest extends ProtocolTest { @Test diff --git a/test/org/traccar/protocol/Arnavi4ProtocolDecoderTest.java b/test/org/traccar/protocol/Arnavi4ProtocolDecoderTest.java index 2395572a1..d789b1c9c 100644 --- a/test/org/traccar/protocol/Arnavi4ProtocolDecoderTest.java +++ b/test/org/traccar/protocol/Arnavi4ProtocolDecoderTest.java @@ -5,13 +5,10 @@ import org.traccar.ProtocolTest; import java.nio.ByteOrder; -/** - * Created by Ivan Muratov @binakot on 11.07.2017. - */ public class Arnavi4ProtocolDecoderTest extends ProtocolTest { @Test - public void testDecode() throws Exception { + public void testHeader1Decode() throws Exception { Arnavi4ProtocolDecoder decoder; @@ -23,6 +20,12 @@ public class Arnavi4ProtocolDecoderTest extends ProtocolTest { verifyPositions(decoder, binary(ByteOrder.LITTLE_ENDIAN, // Valid PACKAGE packet with one DATA packet "5b01012800a3175f5903513934420447221c42055402781E0900f0c5215b4e0084005c00007c005d0000a300fa37010000295d"), position("2017-07-07 05:09:55.000", true, 45.05597, 39.03347)); + } + + @Test + public void testHeader2Decode() throws Exception { + + Arnavi4ProtocolDecoder decoder; decoder = new Arnavi4ProtocolDecoder(new Arnavi4Protocol()); -- cgit v1.2.3 From a71dd10a966b491c64232180a2075450f0a258db Mon Sep 17 00:00:00 2001 From: Ivan Muratov Date: Fri, 14 Jul 2017 09:32:52 +0300 Subject: Switch from the unnecessary creating the byte array to direct working with origin buffer. Remove tag value parsing inside case block. --- src/org/traccar/protocol/Arnavi4FrameDecoder.java | 15 ++++++--------- src/org/traccar/protocol/Arnavi4ProtocolDecoder.java | 17 +++++++++-------- 2 files changed, 15 insertions(+), 17 deletions(-) (limited to 'src') diff --git a/src/org/traccar/protocol/Arnavi4FrameDecoder.java b/src/org/traccar/protocol/Arnavi4FrameDecoder.java index 2587420c9..a50ece641 100644 --- a/src/org/traccar/protocol/Arnavi4FrameDecoder.java +++ b/src/org/traccar/protocol/Arnavi4FrameDecoder.java @@ -44,19 +44,16 @@ public class Arnavi4FrameDecoder extends FrameDecoder { return null; } - byte[] bytes = new byte[buf.readableBytes()]; - buf.getBytes(0, bytes); - - if (bytes[0] == HEADER_START_SIGN - && bytes.length == HEADER_LENGTH - && (bytes[1] == HEADER_VERSION_1 || bytes[1] == HEADER_VERSION_2)) { + if (buf.getByte(0) == HEADER_START_SIGN + && buf.readableBytes() == HEADER_LENGTH + && (buf.getByte(1) == HEADER_VERSION_1 || buf.getByte(1) == HEADER_VERSION_2)) { return buf.readBytes(HEADER_LENGTH); } - int parcelNumber = bytes[1] & 0xFF; - if (bytes[0] == PACKAGE_START_SIGN && bytes[bytes.length - 1] == PACKAGE_END_SIGN + 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.readBytes(bytes.length); + return buf; } return null; diff --git a/src/org/traccar/protocol/Arnavi4ProtocolDecoder.java b/src/org/traccar/protocol/Arnavi4ProtocolDecoder.java index 232e8f053..e2a1da29f 100644 --- a/src/org/traccar/protocol/Arnavi4ProtocolDecoder.java +++ b/src/org/traccar/protocol/Arnavi4ProtocolDecoder.java @@ -63,27 +63,28 @@ public class Arnavi4ProtocolDecoder extends BaseProtocolDecoder { int readBytes = 0; while (readBytes < length) { short tag = buf.readUnsignedByte(); - int tagValue = buf.readInt(); switch (tag) { case TAG_LATITUDE: - position.setLatitude(Float.intBitsToFloat(tagValue)); + position.setLatitude(buf.readFloat()); position.setValid(true); break; case TAG_LONGITUDE: - position.setLongitude(Float.intBitsToFloat(tagValue)); + position.setLongitude(buf.readFloat()); position.setValid(true); break; case TAG_COORD_PARAMS: - position.setSpeed((tagValue >> 24) * 1.852); - position.set(Position.KEY_SATELLITES, (tagValue >> 16 & 0x0F) + (tagValue >> 20 & 0x0F)); - position.setAltitude((tagValue >> 8 & 0xFF) * 10.0); - position.setCourse((tagValue & 0xFF) * 2.0); + position.setCourse(buf.readUnsignedByte() * 2.0); + position.setAltitude(buf.readUnsignedByte() * 10.0); + byte satellites = buf.readByte(); + position.set(Position.KEY_SATELLITES, satellites & 0x0F + (satellites >> 4) & 0x0F); // gps + glonass + position.setSpeed(buf.readByte() * 1.852); break; default: - break; // Skip other tags + buf.readBytes(4); // Skip other tags + break; } readBytes += 5; // 1 byte tag + 4 bytes value -- cgit v1.2.3 From 9f2f7d21fefda741cf9e3d4d43b3195902ed0a2b Mon Sep 17 00:00:00 2001 From: Ivan Muratov Date: Fri, 14 Jul 2017 09:39:58 +0300 Subject: Fix build issues. [ERROR] src/org/traccar/protocol/Arnavi4ProtocolDecoder.java:[81] (sizes) LineLength: Line is longer than 120 characters (found 121). --- src/org/traccar/protocol/Arnavi4ProtocolDecoder.java | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'src') diff --git a/src/org/traccar/protocol/Arnavi4ProtocolDecoder.java b/src/org/traccar/protocol/Arnavi4ProtocolDecoder.java index e2a1da29f..539f6d35c 100644 --- a/src/org/traccar/protocol/Arnavi4ProtocolDecoder.java +++ b/src/org/traccar/protocol/Arnavi4ProtocolDecoder.java @@ -78,7 +78,7 @@ public class Arnavi4ProtocolDecoder extends BaseProtocolDecoder { position.setCourse(buf.readUnsignedByte() * 2.0); position.setAltitude(buf.readUnsignedByte() * 10.0); byte satellites = buf.readByte(); - position.set(Position.KEY_SATELLITES, satellites & 0x0F + (satellites >> 4) & 0x0F); // gps + glonass + position.set(Position.KEY_SATELLITES, satellites & 0x0F + (satellites >> 4) & 0x0F); // gps+glonass position.setSpeed(buf.readByte() * 1.852); break; -- cgit v1.2.3 From 8684f83d352e01effbe08cacaccb264d4d368575 Mon Sep 17 00:00:00 2001 From: Ivan Muratov Date: Fri, 14 Jul 2017 09:48:16 +0300 Subject: Change signed byte to unsidned for tag value of movement speed. --- src/org/traccar/protocol/Arnavi4ProtocolDecoder.java | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'src') diff --git a/src/org/traccar/protocol/Arnavi4ProtocolDecoder.java b/src/org/traccar/protocol/Arnavi4ProtocolDecoder.java index 539f6d35c..4422ff4a6 100644 --- a/src/org/traccar/protocol/Arnavi4ProtocolDecoder.java +++ b/src/org/traccar/protocol/Arnavi4ProtocolDecoder.java @@ -79,7 +79,7 @@ public class Arnavi4ProtocolDecoder extends BaseProtocolDecoder { position.setAltitude(buf.readUnsignedByte() * 10.0); byte satellites = buf.readByte(); position.set(Position.KEY_SATELLITES, satellites & 0x0F + (satellites >> 4) & 0x0F); // gps+glonass - position.setSpeed(buf.readByte() * 1.852); + position.setSpeed(buf.readUnsignedByte() * 1.852); break; default: -- cgit v1.2.3 From fd1d75cb1a6dd1a4af065fec66ab69fcaf359916 Mon Sep 17 00:00:00 2001 From: Ivan Muratov Date: Fri, 14 Jul 2017 10:00:05 +0300 Subject: Add reading bytes from buffer for non-data packages. --- src/org/traccar/protocol/Arnavi4ProtocolDecoder.java | 2 ++ 1 file changed, 2 insertions(+) (limited to 'src') diff --git a/src/org/traccar/protocol/Arnavi4ProtocolDecoder.java b/src/org/traccar/protocol/Arnavi4ProtocolDecoder.java index 4422ff4a6..682fc1577 100644 --- a/src/org/traccar/protocol/Arnavi4ProtocolDecoder.java +++ b/src/org/traccar/protocol/Arnavi4ProtocolDecoder.java @@ -158,6 +158,8 @@ public class Arnavi4ProtocolDecoder extends BaseProtocolDecoder { if (recordType == RECORD_DATA) { positions.add(decodePosition(deviceSession, buf, length, time)); + } else { + buf.readBytes(length); // Skip other records } buf.readUnsignedByte(); // crc -- cgit v1.2.3 From 36eeb5c4fa86f6516585819bb76ca7b73fa4d28a Mon Sep 17 00:00:00 2001 From: Ivan Muratov Date: Fri, 14 Jul 2017 12:28:41 +0300 Subject: Split responses to separate methods. Optimize math operations with course and altitude. Remove unnecessary check for package first byte. Remove exception throwing. Store speed in knots, but not in km/h. --- .../traccar/protocol/Arnavi4ProtocolDecoder.java | 118 ++++++++++----------- 1 file changed, 59 insertions(+), 59 deletions(-) (limited to 'src') diff --git a/src/org/traccar/protocol/Arnavi4ProtocolDecoder.java b/src/org/traccar/protocol/Arnavi4ProtocolDecoder.java index 682fc1577..07e4d855c 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 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 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 (recordType != PACKAGE_END_SIGN && buf.readableBytes() != 1) { // The last end sign byte + 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(); } - return null; + sendPackageResponse(channel, index); + + return positions; } } -- cgit v1.2.3 From c8f648e0261ad46e9301db35f161140aabad880a Mon Sep 17 00:00:00 2001 From: Ivan Muratov Date: Fri, 14 Jul 2017 13:29:52 +0300 Subject: Upgrade the frame decoder and remove unnecessary check for the last end sign byte in protocol decoder. Protocol decoder read the buffer until its over, because frame decoder garantee the correct package length. Added additional tests for frame decoding. --- src/org/traccar/protocol/Arnavi4FrameDecoder.java | 16 ++++++++++++---- src/org/traccar/protocol/Arnavi4ProtocolDecoder.java | 4 ++-- test/org/traccar/protocol/Arnavi4FrameDecoderTest.java | 16 ++++++++++++++-- 3 files changed, 28 insertions(+), 8 deletions(-) (limited to 'src') 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 07e4d855c..ed11e1559 100644 --- a/src/org/traccar/protocol/Arnavi4ProtocolDecoder.java +++ b/src/org/traccar/protocol/Arnavi4ProtocolDecoder.java @@ -153,7 +153,7 @@ public class Arnavi4ProtocolDecoder extends BaseProtocolDecoder { int index = buf.readUnsignedByte(); byte recordType = buf.readByte(); - while (recordType != PACKAGE_END_SIGN && buf.readableBytes() != 1) { // The last end sign byte + while (buf.readableBytes() > 0) { switch (recordType) { case RECORD_PING: case RECORD_DATA: @@ -176,7 +176,7 @@ public class Arnavi4ProtocolDecoder extends BaseProtocolDecoder { return null; // Ignore unsupported types of package } - recordType = buf.readByte(); + recordType = buf.readByte(); // The last byte in package is end sign } sendPackageResponse(channel, index); 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 -- cgit v1.2.3 From 4d4b3e92d6bc29f2d178164200f4be14a2b0ce1a Mon Sep 17 00:00:00 2001 From: Ivan Muratov Date: Fri, 14 Jul 2017 13:35:44 +0300 Subject: Fix build issues. [ERROR] src/org/traccar/protocol/Arnavi4ProtocolDecoder.java:[36,15] (imports) UnusedImports: Unused import - org.traccar.protocol.Arnavi4FrameDecoder.PACKAGE_START_SIGN. [ERROR] src/org/traccar/protocol/Arnavi4ProtocolDecoder.java:[37,15] (imports) UnusedImports: Unused import - org.traccar.protocol.Arnavi4FrameDecoder.PACKAGE_END_SIGN. --- src/org/traccar/protocol/Arnavi4ProtocolDecoder.java | 2 -- 1 file changed, 2 deletions(-) (limited to 'src') diff --git a/src/org/traccar/protocol/Arnavi4ProtocolDecoder.java b/src/org/traccar/protocol/Arnavi4ProtocolDecoder.java index ed11e1559..a1a9d2ea1 100644 --- a/src/org/traccar/protocol/Arnavi4ProtocolDecoder.java +++ b/src/org/traccar/protocol/Arnavi4ProtocolDecoder.java @@ -33,8 +33,6 @@ import java.util.List; import static org.traccar.protocol.Arnavi4FrameDecoder.HEADER_START_SIGN; import static org.traccar.protocol.Arnavi4FrameDecoder.HEADER_VERSION_1; import static org.traccar.protocol.Arnavi4FrameDecoder.HEADER_VERSION_2; -import static org.traccar.protocol.Arnavi4FrameDecoder.PACKAGE_START_SIGN; -import static org.traccar.protocol.Arnavi4FrameDecoder.PACKAGE_END_SIGN; public class Arnavi4ProtocolDecoder extends BaseProtocolDecoder { -- cgit v1.2.3 From 79147b8a6fc8a3bfe863c2e8d3c47db06af90bc8 Mon Sep 17 00:00:00 2001 From: Ivan Muratov Date: Mon, 17 Jul 2017 10:58:49 +0300 Subject: Rewrite the code of frame decoder. Added tests with invalid packets. --- src/org/traccar/protocol/Arnavi4FrameDecoder.java | 39 +++++++++++++--------- .../traccar/protocol/Arnavi4FrameDecoderTest.java | 23 +++++++++++-- 2 files changed, 44 insertions(+), 18 deletions(-) (limited to 'src') diff --git a/src/org/traccar/protocol/Arnavi4FrameDecoder.java b/src/org/traccar/protocol/Arnavi4FrameDecoder.java index bb130e6bb..ee4aee32a 100644 --- a/src/org/traccar/protocol/Arnavi4FrameDecoder.java +++ b/src/org/traccar/protocol/Arnavi4FrameDecoder.java @@ -22,17 +22,18 @@ import org.jboss.netty.handler.codec.frame.FrameDecoder; public class Arnavi4FrameDecoder extends FrameDecoder { - static final int PACKET_MIN_LENGTH = 4; + private static final int PACKET_MINIMUM_LENGTH = 4; + private static final int RECORD_MINIMUM_LENGTH = 8; - static final byte HEADER_START_SIGN = (byte) 0xFF; + static final byte HEADER_START_SIGN = (byte) 0xff; static final byte HEADER_VERSION_1 = 0x22; static final byte HEADER_VERSION_2 = 0x23; - static final int HEADER_LENGTH = 10; + private static final int HEADER_LENGTH = 10; - static final byte PACKAGE_START_SIGN = 0x5B; - static final byte PACKAGE_END_SIGN = 0x5D; - static final int PACKAGE_MIN_PARCEL_NUMBER = 0x01; - static final int PACKAGE_MAX_PARCEL_NUMBER = 0xFB; + private static final byte PACKAGE_START_SIGN = 0x5b; + private static final byte PACKAGE_END_SIGN = 0x5d; + private static final int PACKAGE_MIN_PARCEL_NUMBER = 0x01; + private static final int PACKAGE_MAX_PARCEL_NUMBER = 0xfb; @Override protected Object decode( @@ -40,31 +41,37 @@ public class Arnavi4FrameDecoder extends FrameDecoder { Channel channel, ChannelBuffer buf) throws Exception { - if (buf.readableBytes() < PACKET_MIN_LENGTH) { + if (buf.readableBytes() < PACKET_MINIMUM_LENGTH) { return null; } if (buf.getByte(0) == HEADER_START_SIGN && buf.readableBytes() == HEADER_LENGTH && (buf.getByte(1) == HEADER_VERSION_1 || buf.getByte(1) == HEADER_VERSION_2)) { + return buf.readBytes(HEADER_LENGTH); } - int index = buf.getByte(1) & 0xFF; // parcel number + int index = buf.getUnsignedByte(1); // 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; + int bufferPosition = 2; // start sign + parcel number + while (bufferPosition + RECORD_MINIMUM_LENGTH < buf.readableBytes() + && buf.getByte(bufferPosition) != PACKAGE_END_SIGN) { + + int dataLength = buf.getUnsignedShort(bufferPosition + 1); + bufferPosition += RECORD_MINIMUM_LENGTH + dataLength; // type + data length + unixtime + data + crc } - return buf.readBytes(packetStartIndex + 1); + if (bufferPosition < buf.readableBytes() + && buf.getByte(bufferPosition) == PACKAGE_END_SIGN) { + + return buf.readBytes(bufferPosition + 1); // end sign + } } return null; } -} +} \ No newline at end of file diff --git a/test/org/traccar/protocol/Arnavi4FrameDecoderTest.java b/test/org/traccar/protocol/Arnavi4FrameDecoderTest.java index 93d818f56..2203cdafc 100644 --- a/test/org/traccar/protocol/Arnavi4FrameDecoderTest.java +++ b/test/org/traccar/protocol/Arnavi4FrameDecoderTest.java @@ -9,7 +9,7 @@ import java.nio.ByteOrder; public class Arnavi4FrameDecoderTest extends ProtocolTest { @Test - public void testDecode() throws Exception { + public void testDecodeValidPackets() throws Exception { Arnavi4FrameDecoder decoder = new Arnavi4FrameDecoder(); @@ -21,7 +21,7 @@ public class Arnavi4FrameDecoderTest extends ProtocolTest { binary(ByteOrder.LITTLE_ENDIAN, "ff23f30c45f5c90f0300"), decoder.decode(null, null, binary(ByteOrder.LITTLE_ENDIAN, "ff23f30c45f5c90f0300"))); - Assert.assertEquals( // Valid PACKAGE with answer to server on file transfer. + Assert.assertEquals( // Valid PACKAGE with answer to server on file transfer null, decoder.decode(null, null, binary(ByteOrder.LITTLE_ENDIAN, "5bfd005d"))); @@ -43,4 +43,23 @@ public class Arnavi4FrameDecoderTest extends ProtocolTest { } + @Test + public void testDecodeInvalidPackets() throws Exception { + + Arnavi4FrameDecoder decoder = new Arnavi4FrameDecoder(); + + Assert.assertEquals( // Invalid PACKAGE with one DATA packet (missing last byte with end sign) + null, + decoder.decode(null, null, binary(ByteOrder.LITTLE_ENDIAN, "5b01012800a3175f5903513934420447221c42055402781E0900f0c5215b4e0084005c00007c005d0000a300fa3701000029"))); + + Assert.assertEquals( // Invalid PACKAGE with two DATA packet (missing last 10 bytes) + null, + decoder.decode(null, null, binary(ByteOrder.LITTLE_ENDIAN, "5b01012800a3175f5903513934420447221c42055402781E0900f0c5215b4e0084005c00007c005d0000a300fa3701000029012800a3175f5903513934420447221c42055402781E0900f0c5215b4e0084005c00007c005d00"))); + + Assert.assertEquals( // Valid PACKAGE with useless extra bytes at the end + binary(ByteOrder.LITTLE_ENDIAN, "5b01012800a3175f5903513934420447221c42055402781E0900f0c5215b4e0084005c00007c005d0000a300fa37010000295d"), + decoder.decode(null, null, binary(ByteOrder.LITTLE_ENDIAN, "5b01012800a3175f5903513934420447221c42055402781E0900f0c5215b4e0084005c00007c005d0000a300fa37010000295d010203040506070809"))); + + } + } \ No newline at end of file -- cgit v1.2.3 From 31e972e169acf4a517ff10f8a64f0e0cf0b8df0e Mon Sep 17 00:00:00 2001 From: Ivan Muratov Date: Mon, 17 Jul 2017 14:00:46 +0300 Subject: Refactoring of the ARNAVI4 protocol decoder. --- .../traccar/protocol/Arnavi4ProtocolDecoder.java | 35 ++++++++++------------ 1 file changed, 16 insertions(+), 19 deletions(-) (limited to 'src') diff --git a/src/org/traccar/protocol/Arnavi4ProtocolDecoder.java b/src/org/traccar/protocol/Arnavi4ProtocolDecoder.java index a1a9d2ea1..4ab929cf7 100644 --- a/src/org/traccar/protocol/Arnavi4ProtocolDecoder.java +++ b/src/org/traccar/protocol/Arnavi4ProtocolDecoder.java @@ -50,34 +50,31 @@ public class Arnavi4ProtocolDecoder extends BaseProtocolDecoder { super(protocol); } - private void sendHeaderResponse(Channel channel, byte version) { + private void sendResponse(Channel channel, byte version, int index) { 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}); + response.writeByte(0x7b); + response.writeByte(0x00); + response.writeByte((byte) index); + response.writeByte(0x7d); } else if (version == HEADER_VERSION_2) { response = ChannelBuffers.dynamicBuffer(ByteOrder.LITTLE_ENDIAN, 9); - response.writeBytes(new byte[]{0x7B, 0x04, 0x00}); + response.writeByte(0x7b); + response.writeByte(0x04); + response.writeByte(0x00); byte[] timeBytes = ByteBuffer.allocate(4).putInt((int) (System.currentTimeMillis() / 1000)).array(); response.writeByte(Checksum.modulo256(timeBytes)); response.writeBytes(timeBytes); - response.writeByte(0x7D); + response.writeByte(0x7d); } else { - return; // Ignore unsupported versions of header + return; // Ignore unsupported header's versions } 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(); @@ -135,7 +132,7 @@ public class Arnavi4ProtocolDecoder extends BaseProtocolDecoder { DeviceSession deviceSession = getDeviceSession(channel, remoteAddress, imei); if (deviceSession != null) { - sendHeaderResponse(channel, version); + sendResponse(channel, version, 0); } return null; @@ -164,20 +161,20 @@ public class Arnavi4ProtocolDecoder extends BaseProtocolDecoder { if (recordType == RECORD_DATA) { positions.add(decodePosition(deviceSession, buf, length, time)); } else { - buf.readBytes(length); // Skip other records + buf.readBytes(length); // Skip other types of record } buf.readUnsignedByte(); // crc break; default: - return null; // Ignore unsupported types of package + return null; // Ignore unsupported types of record } - recordType = buf.readByte(); // The last byte in package is end sign + recordType = buf.readByte(); } - sendPackageResponse(channel, index); + sendResponse(channel, HEADER_VERSION_1, index); return positions; } -- cgit v1.2.3 From 05bcc7359b52cad0036bcb32888b7e999a3efb25 Mon Sep 17 00:00:00 2001 From: Ivan Muratov Date: Mon, 17 Jul 2017 14:14:46 +0300 Subject: Fix build issues. --- src/org/traccar/protocol/Arnavi4FrameDecoder.java | 2 +- src/org/traccar/protocol/Arnavi4ProtocolDecoder.java | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) (limited to 'src') diff --git a/src/org/traccar/protocol/Arnavi4FrameDecoder.java b/src/org/traccar/protocol/Arnavi4FrameDecoder.java index ee4aee32a..7c60cb934 100644 --- a/src/org/traccar/protocol/Arnavi4FrameDecoder.java +++ b/src/org/traccar/protocol/Arnavi4FrameDecoder.java @@ -74,4 +74,4 @@ public class Arnavi4FrameDecoder extends FrameDecoder { return null; } -} \ No newline at end of file +} diff --git a/src/org/traccar/protocol/Arnavi4ProtocolDecoder.java b/src/org/traccar/protocol/Arnavi4ProtocolDecoder.java index 4ab929cf7..e3e027993 100644 --- a/src/org/traccar/protocol/Arnavi4ProtocolDecoder.java +++ b/src/org/traccar/protocol/Arnavi4ProtocolDecoder.java @@ -74,7 +74,7 @@ public class Arnavi4ProtocolDecoder extends BaseProtocolDecoder { channel.write(response); } } - + private Position decodePosition(DeviceSession deviceSession, ChannelBuffer buf, int length, Date time) { final Position position = new Position(); -- cgit v1.2.3 From d225018f7aadefab6381d5283347bae10e153bfa Mon Sep 17 00:00:00 2001 From: Ivan Muratov Date: Tue, 24 Oct 2017 14:45:30 +0300 Subject: Arnavi4 frame decoder's code reorganization based on traccar maintainer comments. --- setup/default.xml | 5 +- src/org/traccar/protocol/Arnavi4FrameDecoder.java | 69 +++++++++++----------- .../traccar/protocol/Arnavi4ProtocolDecoder.java | 8 +-- .../traccar/protocol/Arnavi4FrameDecoderTest.java | 43 +++++--------- 4 files changed, 55 insertions(+), 70 deletions(-) (limited to 'src') diff --git a/setup/default.xml b/setup/default.xml index 223b9a585..1e84c5218 100644 --- a/setup/default.xml +++ b/setup/default.xml @@ -579,6 +579,9 @@ 5143 5144 5145 - 5146 + 5146 + 5147 + 5148 + 5149 diff --git a/src/org/traccar/protocol/Arnavi4FrameDecoder.java b/src/org/traccar/protocol/Arnavi4FrameDecoder.java index 7c60cb934..b13f3fd7d 100644 --- a/src/org/traccar/protocol/Arnavi4FrameDecoder.java +++ b/src/org/traccar/protocol/Arnavi4FrameDecoder.java @@ -22,53 +22,50 @@ import org.jboss.netty.handler.codec.frame.FrameDecoder; public class Arnavi4FrameDecoder extends FrameDecoder { - private static final int PACKET_MINIMUM_LENGTH = 4; - private static final int RECORD_MINIMUM_LENGTH = 8; - - static final byte HEADER_START_SIGN = (byte) 0xff; - static final byte HEADER_VERSION_1 = 0x22; - static final byte HEADER_VERSION_2 = 0x23; + private static final int MIN_LENGTH = 4; private static final int HEADER_LENGTH = 10; - - private static final byte PACKAGE_START_SIGN = 0x5b; + private static final int PACKET_WRAPPER_LENGTH = 8; + private static final int COMMAND_ANSWER_PACKET_LENGTH = 4; + private static final int COMMAND_ANSWER_PARCEL_NUMBER = 0xfd; private static final byte PACKAGE_END_SIGN = 0x5d; - private static final int PACKAGE_MIN_PARCEL_NUMBER = 0x01; - private static final int PACKAGE_MAX_PARCEL_NUMBER = 0xfb; + + private boolean firstPacket = true; @Override protected Object decode( - ChannelHandlerContext ctx, - Channel channel, - ChannelBuffer buf) throws Exception { + ChannelHandlerContext ctx, Channel channel, ChannelBuffer buf) throws Exception { - if (buf.readableBytes() < PACKET_MINIMUM_LENGTH) { + if (buf.readableBytes() < MIN_LENGTH) { return null; } - if (buf.getByte(0) == HEADER_START_SIGN - && buf.readableBytes() == HEADER_LENGTH - && (buf.getByte(1) == HEADER_VERSION_1 || buf.getByte(1) == HEADER_VERSION_2)) { - - return buf.readBytes(HEADER_LENGTH); - } - - int index = buf.getUnsignedByte(1); // parcel number - if (buf.getByte(0) == PACKAGE_START_SIGN - && index >= PACKAGE_MIN_PARCEL_NUMBER && index <= PACKAGE_MAX_PARCEL_NUMBER) { - - int bufferPosition = 2; // start sign + parcel number - while (bufferPosition + RECORD_MINIMUM_LENGTH < buf.readableBytes() - && buf.getByte(bufferPosition) != PACKAGE_END_SIGN) { - - int dataLength = buf.getUnsignedShort(bufferPosition + 1); - bufferPosition += RECORD_MINIMUM_LENGTH + dataLength; // type + data length + unixtime + data + crc + int length; + if (firstPacket) { + firstPacket = false; + length = HEADER_LENGTH; + } else { + int index = buf.getUnsignedByte(1); // parcel number + if (index == COMMAND_ANSWER_PARCEL_NUMBER) { + length = COMMAND_ANSWER_PACKET_LENGTH; + } else { + int pos = 2; // start sign + parcel number + while (pos + PACKET_WRAPPER_LENGTH < buf.readableBytes() + && buf.getByte(pos) != PACKAGE_END_SIGN) { + + int dataLength = buf.getUnsignedShort(pos + 1); + pos += PACKET_WRAPPER_LENGTH + dataLength; // packet type + data length + unixtime + data + crc + } + + if (buf.getByte(pos) != PACKAGE_END_SIGN) { // end sign + return null; + } + + length = pos + 1; } + } - if (bufferPosition < buf.readableBytes() - && buf.getByte(bufferPosition) == PACKAGE_END_SIGN) { - - return buf.readBytes(bufferPosition + 1); // end sign - } + if (buf.readableBytes() >= length) { + return buf.readBytes(length); } return null; diff --git a/src/org/traccar/protocol/Arnavi4ProtocolDecoder.java b/src/org/traccar/protocol/Arnavi4ProtocolDecoder.java index e3e027993..06abb563f 100644 --- a/src/org/traccar/protocol/Arnavi4ProtocolDecoder.java +++ b/src/org/traccar/protocol/Arnavi4ProtocolDecoder.java @@ -30,12 +30,12 @@ import java.util.Date; import java.util.LinkedList; import java.util.List; -import static org.traccar.protocol.Arnavi4FrameDecoder.HEADER_START_SIGN; -import static org.traccar.protocol.Arnavi4FrameDecoder.HEADER_VERSION_1; -import static org.traccar.protocol.Arnavi4FrameDecoder.HEADER_VERSION_2; - public class Arnavi4ProtocolDecoder extends BaseProtocolDecoder { + private static final byte HEADER_START_SIGN = (byte) 0xff; + private static final byte HEADER_VERSION_1 = 0x22; + private static final byte HEADER_VERSION_2 = 0x23; + private static final byte RECORD_PING = 0x00; private static final byte RECORD_DATA = 0x01; private static final byte RECORD_TEXT = 0x03; diff --git a/test/org/traccar/protocol/Arnavi4FrameDecoderTest.java b/test/org/traccar/protocol/Arnavi4FrameDecoderTest.java index 2203cdafc..b634f0cdc 100644 --- a/test/org/traccar/protocol/Arnavi4FrameDecoderTest.java +++ b/test/org/traccar/protocol/Arnavi4FrameDecoderTest.java @@ -17,14 +17,6 @@ public class Arnavi4FrameDecoderTest extends ProtocolTest { binary(ByteOrder.LITTLE_ENDIAN, "ff22f30c45f5c90f0300"), decoder.decode(null, null, binary(ByteOrder.LITTLE_ENDIAN, "ff22f30c45f5c90f0300"))); - Assert.assertEquals( // Valid HEADER v2 packet with IMEI - binary(ByteOrder.LITTLE_ENDIAN, "ff23f30c45f5c90f0300"), - decoder.decode(null, null, binary(ByteOrder.LITTLE_ENDIAN, "ff23f30c45f5c90f0300"))); - - 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"))); @@ -34,31 +26,24 @@ public class Arnavi4FrameDecoderTest extends ProtocolTest { 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"))); + binary(ByteOrder.LITTLE_ENDIAN, "5b01030700e3f16b50747261636361721b5d"), + decoder.decode(null, null, binary(ByteOrder.LITTLE_ENDIAN, "5b01030700e3f16b50747261636361721b5d"))); - Assert.assertEquals( // Valid PACKAGE with one BINARY packet. - null, - decoder.decode(null, null, binary(ByteOrder.LITTLE_ENDIAN, "062000e3f16b5003298b5e4204cbd514420500191000080400ff021b"))); - - } + Assert.assertEquals( // Valid PACKAGE with two TEXT packet. + binary(ByteOrder.LITTLE_ENDIAN, "5b01030700e3f16b50747261636361721b030700e3f16b50747261636361721b5d"), + decoder.decode(null, null, binary(ByteOrder.LITTLE_ENDIAN, "5b01030700e3f16b50747261636361721b030700e3f16b50747261636361721b5d"))); - @Test - public void testDecodeInvalidPackets() throws Exception { - - Arnavi4FrameDecoder decoder = new Arnavi4FrameDecoder(); - - Assert.assertEquals( // Invalid PACKAGE with one DATA packet (missing last byte with end sign) - null, - decoder.decode(null, null, binary(ByteOrder.LITTLE_ENDIAN, "5b01012800a3175f5903513934420447221c42055402781E0900f0c5215b4e0084005c00007c005d0000a300fa3701000029"))); + Assert.assertEquals( // Valid PACKAGE with one BINARY packet. + binary(ByteOrder.LITTLE_ENDIAN, "5b01061400e3f16b5003298b5e4204cbd514420500191000080400ff021b5d"), + decoder.decode(null, null, binary(ByteOrder.LITTLE_ENDIAN, "5b01061400e3f16b5003298b5e4204cbd514420500191000080400ff021b5d"))); - Assert.assertEquals( // Invalid PACKAGE with two DATA packet (missing last 10 bytes) - null, - decoder.decode(null, null, binary(ByteOrder.LITTLE_ENDIAN, "5b01012800a3175f5903513934420447221c42055402781E0900f0c5215b4e0084005c00007c005d0000a300fa3701000029012800a3175f5903513934420447221c42055402781E0900f0c5215b4e0084005c00007c005d00"))); + Assert.assertEquals( // Valid PACKAGE with two BINARY packet. + binary(ByteOrder.LITTLE_ENDIAN, "5b01061400e3f16b5003298b5e4204cbd514420500191000080400ff021b061400e3f16b5003298b5e4204cbd514420500191000080400ff021b5d"), + decoder.decode(null, null, binary(ByteOrder.LITTLE_ENDIAN, "5b01061400e3f16b5003298b5e4204cbd514420500191000080400ff021b061400e3f16b5003298b5e4204cbd514420500191000080400ff021b5d"))); - Assert.assertEquals( // Valid PACKAGE with useless extra bytes at the end - binary(ByteOrder.LITTLE_ENDIAN, "5b01012800a3175f5903513934420447221c42055402781E0900f0c5215b4e0084005c00007c005d0000a300fa37010000295d"), - decoder.decode(null, null, binary(ByteOrder.LITTLE_ENDIAN, "5b01012800a3175f5903513934420447221c42055402781E0900f0c5215b4e0084005c00007c005d0000a300fa37010000295d010203040506070809"))); + Assert.assertEquals( // Valid PACKAGE with answer to server on file transfer + binary(ByteOrder.LITTLE_ENDIAN, "5bfd005d"), + decoder.decode(null, null, binary(ByteOrder.LITTLE_ENDIAN, "5bfd005d"))); } -- cgit v1.2.3