From fc707a69c3c95223ecb8e263d7de32a72ec84af3 Mon Sep 17 00:00:00 2001 From: Evgeny S Maksimov Date: Thu, 17 Jan 2019 19:05:23 +0300 Subject: Implemented FLEX 1.0 extension support for Navis (NTCB) protocol --- src/org/traccar/protocol/NavisFrameDecoder.java | 80 ++++ src/org/traccar/protocol/NavisProtocol.java | 4 +- src/org/traccar/protocol/NavisProtocolDecoder.java | 463 +++++++++++++++++++-- 3 files changed, 499 insertions(+), 48 deletions(-) create mode 100644 src/org/traccar/protocol/NavisFrameDecoder.java (limited to 'src/org/traccar') diff --git a/src/org/traccar/protocol/NavisFrameDecoder.java b/src/org/traccar/protocol/NavisFrameDecoder.java new file mode 100644 index 000000000..2480629ac --- /dev/null +++ b/src/org/traccar/protocol/NavisFrameDecoder.java @@ -0,0 +1,80 @@ +/* + * Copyright 2019 Anton Tananaev (anton@traccar.org) + * + * 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 io.netty.buffer.ByteBuf; +import io.netty.channel.Channel; +import io.netty.channel.ChannelHandlerContext; +import io.netty.handler.codec.TooLongFrameException; +import org.traccar.BaseFrameDecoder; + +public class NavisFrameDecoder extends BaseFrameDecoder { + + private static final int NTCB_HEADER_LENGHT = 16; + private static final int NTCB_LENGHT_OFFSET = 12; + private static final int MAX_FRAME_LENGHT = 65551; + + private static byte src8Checksum(ByteBuf buf, int length) { + byte sum = (byte) 0xFF; + for (int i = 0; i < length; i++) { + sum ^= buf.getUnsignedByte(i); + for (int j = 0; j < 8; j++) { + sum = (sum & 0x80) != 0 ? (byte) ((sum << 1) ^ 0x31) : (byte) (sum << 1); + } + } + return sum; + } + + @Override + protected Object decode( + ChannelHandlerContext ctx, Channel channel, ByteBuf buf) throws Exception { + + // Check minimum length + if (buf.readableBytes() < 1) { + return null; + } + + if (buf.getByte(buf.readerIndex()) == 0x7F) { + // FLEX keep alive frame + return buf.readRetainedSlice(1); + } else if (buf.getByte(buf.readerIndex()) == 0x7E /* "~" */) { + // FLEX frame + if (buf.readableBytes() > MAX_FRAME_LENGHT) { + throw new TooLongFrameException(); + } + + if (src8Checksum(buf, buf.readableBytes() - 1) == buf.getByte(buf.readableBytes() - 1)) { + return buf.readRetainedSlice(buf.readableBytes()); + } + } else { + // NTCB frame + if (buf.readableBytes() < NTCB_HEADER_LENGHT) { + return null; + } + + int length = buf.getUnsignedShortLE(buf.readerIndex() + NTCB_LENGHT_OFFSET); + if (buf.readableBytes() >= NTCB_HEADER_LENGHT + length) { + if (buf.readableBytes() > MAX_FRAME_LENGHT) { + throw new TooLongFrameException(); + } + return buf.readRetainedSlice(NTCB_HEADER_LENGHT + length); + } + } + + return null; + } + +} diff --git a/src/org/traccar/protocol/NavisProtocol.java b/src/org/traccar/protocol/NavisProtocol.java index 83a9dc99d..4250ba4dc 100644 --- a/src/org/traccar/protocol/NavisProtocol.java +++ b/src/org/traccar/protocol/NavisProtocol.java @@ -15,19 +15,17 @@ */ package org.traccar.protocol; -import io.netty.handler.codec.LengthFieldBasedFrameDecoder; import org.traccar.BaseProtocol; import org.traccar.PipelineBuilder; import org.traccar.TrackerServer; -import java.nio.ByteOrder; public class NavisProtocol extends BaseProtocol { public NavisProtocol() { addServer(new TrackerServer(false, getName()) { @Override protected void addProtocolHandlers(PipelineBuilder pipeline) { - pipeline.addLast(new LengthFieldBasedFrameDecoder(ByteOrder.LITTLE_ENDIAN, 4096, 12, 2, 2, 0, true)); + pipeline.addLast(new NavisFrameDecoder()); pipeline.addLast(new NavisProtocolDecoder(NavisProtocol.this)); } }); diff --git a/src/org/traccar/protocol/NavisProtocolDecoder.java b/src/org/traccar/protocol/NavisProtocolDecoder.java index 83088e9f0..3c5abc2a4 100644 --- a/src/org/traccar/protocol/NavisProtocolDecoder.java +++ b/src/org/traccar/protocol/NavisProtocolDecoder.java @@ -18,6 +18,8 @@ package org.traccar.protocol; import io.netty.buffer.ByteBuf; import io.netty.buffer.Unpooled; import io.netty.channel.Channel; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; import org.traccar.BaseProtocolDecoder; import org.traccar.DeviceSession; import org.traccar.NetworkMessage; @@ -31,14 +33,20 @@ import java.net.SocketAddress; import java.nio.charset.StandardCharsets; import java.util.LinkedList; import java.util.List; +import java.util.Date; public class NavisProtocolDecoder extends BaseProtocolDecoder { private String prefix; private long deviceUniqueId, serverId; + private int flexDataSize; // bits + private final byte[] flexBitfield; + private byte flexProtocolVersion, flexStructVersion; + private static final Logger LOGGER = LoggerFactory.getLogger(NavisProtocolDecoder.class); public NavisProtocolDecoder(Protocol protocol) { super(protocol); + this.flexBitfield = new byte[16]; } public static final int F10 = 0x01; @@ -77,7 +85,7 @@ public class NavisProtocolDecoder extends BaseProtocolDecoder { } } - private ParseResult parsePosition(DeviceSession deviceSession, ByteBuf buf) { + private ParseResult parseNTCBPosition(DeviceSession deviceSession, ByteBuf buf) { Position position = new Position(getProtocolName()); position.setDeviceId(deviceSession.getDeviceId()); @@ -95,7 +103,7 @@ public class NavisProtocolDecoder extends BaseProtocolDecoder { position.set(Position.KEY_EVENT, buf.readUnsignedShortLE()); - buf.skipBytes(6); // event time + buf.skipBytes(6); // Event time short armedStatus = buf.readUnsignedByte(); if (isFormat(format, F10, F20, F30, F40, F50, F51, F52)) { @@ -114,19 +122,48 @@ public class NavisProtocolDecoder extends BaseProtocolDecoder { position.set(Position.KEY_RSSI, buf.readUnsignedByte()); if (isFormat(format, F10, F20, F30)) { - position.set(Position.KEY_OUTPUT, buf.readUnsignedShortLE()); + int output = buf.readUnsignedShortLE(); + position.set(Position.KEY_OUTPUT, output); + for (int i = 0; i < 16; i++) { + position.set(Position.PREFIX_OUT + (i + 1), BitUtil.check(output, i)); + } } else if (isFormat(format, F50, F51, F52)) { - int extField = buf.readUnsignedByte(); + short extField = buf.readUnsignedByte(); position.set(Position.KEY_OUTPUT, extField & 0x3); position.set(Position.KEY_SATELLITES, extField >> 2); + position.set(Position.PREFIX_OUT + 1, BitUtil.check(extField, 0)); + position.set(Position.PREFIX_OUT + 2, BitUtil.check(extField, 1)); } else if (isFormat(format, F40, F60)) { - position.set(Position.KEY_OUTPUT, buf.readUnsignedByte() & 0xF); + short output = buf.readUnsignedByte(); + position.set(Position.KEY_OUTPUT, output & 0xF); + for (int i = 0; i < 4; i++) { + position.set(Position.PREFIX_OUT + (i + 1), BitUtil.check(output, i)); + } } if (isFormat(format, F10, F20, F30, F40)) { - position.set(Position.KEY_INPUT, buf.readUnsignedShortLE()); + int input = buf.readUnsignedShortLE(); + position.set(Position.KEY_INPUT, input); + if (!isFormat(format, F40)) { + for (int i = 0; i < 16; i++) { + position.set(Position.PREFIX_IN + (i + 1), BitUtil.check(input, i)); + } + } else { + position.set(Position.PREFIX_IN + 1, BitUtil.check(input, 0)); + position.set(Position.PREFIX_IN + 2, BitUtil.check(input, 1)); + position.set(Position.PREFIX_IN + 3, BitUtil.check(input, 2)); + position.set(Position.PREFIX_IN + 4, BitUtil.check(input, 3)); + position.set(Position.PREFIX_IN + 5, (input & 0x70) >> 4); + position.set(Position.PREFIX_IN + 6, (input & 0x380) >> 7); + position.set(Position.PREFIX_IN + 7, (input & 0xC00) >> 10); + position.set(Position.PREFIX_IN + 8, (input & 0x3000) >> 12); + } } else if (isFormat(format, F50, F51, F52, F60)) { - position.set(Position.KEY_INPUT, buf.readUnsignedByte()); + short input = buf.readUnsignedByte(); + position.set(Position.KEY_INPUT, input); + for (int i = 0; i < 8; i++) { + position.set(Position.PREFIX_IN + (i + 1), BitUtil.check(input, i)); + } } position.set(Position.KEY_POWER, buf.readUnsignedShortLE() * 0.001); @@ -199,6 +236,7 @@ public class NavisProtocolDecoder extends BaseProtocolDecoder { position.setLatitude(buf.readFloatLE() / Math.PI * 180); position.setLongitude(buf.readFloatLE() / Math.PI * 180); } + position.setSpeed(UnitsConverter.knotsFromKph(buf.readFloatLE())); position.setCourse(buf.readUnsignedShortLE()); @@ -234,13 +272,13 @@ public class NavisProtocolDecoder extends BaseProtocolDecoder { return new ParseResult(index, position); } - private Object processSingle(DeviceSession deviceSession, Channel channel, ByteBuf buf) { - ParseResult result = parsePosition(deviceSession, buf); + private Object processNTCBSingle(DeviceSession deviceSession, Channel channel, ByteBuf buf) { + ParseResult result = parseNTCBPosition(deviceSession, buf); - ByteBuf response = Unpooled.buffer(8); + ByteBuf response = Unpooled.buffer(7); response.writeCharSequence("* positions = new LinkedList<>(); int count = buf.readUnsignedByte(); for (int i = 0; i < count; i++) { - Position position = parsePosition(deviceSession, buf).getPosition(); + Position position = parseNTCBPosition(deviceSession, buf).getPosition(); if (position.getFixTime() != null) { positions.add(position); } } - ByteBuf response = Unpooled.buffer(8); + ByteBuf response = Unpooled.buffer(7); response.writeCharSequence("*> i % 8)) == 0) { + // Skip FLEX data field + continue; + } + LOGGER.info("DEBUG: id={} parseFLEXPosition_FIELD={}", deviceSession.getDeviceId(), i + 1); + int status = 0; + short input = 0; + short output = 0; + + switch (i) { + case 0: + index = buf.readUnsignedIntLE(); + position.set(Position.KEY_INDEX, index); + break; + case 1: + position.set(Position.KEY_EVENT, buf.readUnsignedShortLE()); + break; + case 2: + buf.skipBytes(4); // Event time + break; + case 3: + short armedStatus = buf.readUnsignedByte(); + position.set(Position.KEY_ARMED, armedStatus & 0x1); + if (BitUtil.check(armedStatus, 1)) { + position.set(Position.KEY_ALARM, Position.ALARM_GENERAL); + } + break; + case 4: + status = buf.readUnsignedByte(); + position.set(Position.KEY_STATUS, status); + break; + case 5: + int status2 = buf.readUnsignedByte(); + position.set(Position.KEY_STATUS, (short) ((status & 0xFF) | (status2 << 1))); + break; + case 6: + position.set(Position.KEY_RSSI, buf.readUnsignedByte()); + break; + case 7: + int navSensorState = buf.readUnsignedByte(); + position.setValid(BitUtil.check(navSensorState, 1)); + position.set(Position.KEY_SATELLITES, navSensorState >> 2); + break; + case 8: + position.setTime(new DateBuilder(new Date(buf.readUnsignedIntLE() * 1000)).getDate()); + break; + case 9: + position.setLatitude(buf.readIntLE() / 600000.0); + break; + case 10: + position.setLongitude(buf.readIntLE() / 600000.0); + break; + case 11: + position.setAltitude(buf.readIntLE() * 0.1); + break; + case 12: + position.setSpeed(UnitsConverter.knotsFromKph(buf.readFloatLE())); + break; + case 13: + position.setCourse(buf.readUnsignedShortLE()); + break; + case 14: + position.set(Position.KEY_ODOMETER, buf.readFloatLE() * 1000); + break; + case 15: + position.set(Position.KEY_DISTANCE, buf.readFloatLE() * 1000); + break; + case 16: + case 17: + buf.skipBytes(2); + break; + case 18: + position.set(Position.KEY_POWER, buf.readUnsignedShortLE() * 0.001); + break; + case 19: + position.set(Position.KEY_BATTERY, buf.readUnsignedShortLE() * 0.001); + break; + case 20: + case 21: + case 22: + case 23: + case 24: + case 25: + case 26: + case 27: + position.set(Position.PREFIX_ADC + (i - 19), buf.readUnsignedShortLE()); + break; + case 28: + input = buf.readUnsignedByte(); + position.set(Position.KEY_INPUT, input); + for (int k = 0; k < 8; k++) { + position.set(Position.PREFIX_IN + (k + 1), BitUtil.check(input, k)); + } + break; + case 29: + short input2 = buf.readUnsignedByte(); + position.set(Position.KEY_INPUT, (short) ((input & 0xFF) | (input2 << 1))); + for (int k = 0; k < 8; k++) { + position.set(Position.PREFIX_IN + (k + 9), BitUtil.check(input2, k)); + } + break; + case 30: + output = buf.readUnsignedByte(); + position.set(Position.KEY_OUTPUT, output); + for (int k = 0; k < 8; k++) { + position.set(Position.PREFIX_OUT + (k + 1), BitUtil.check(output, k)); + } + break; + case 31: + short output2 = buf.readUnsignedByte(); + position.set(Position.KEY_OUTPUT, (short) ((output & 0xFF) | (output2 << 1))); + for (int k = 0; k < 8; k++) { + position.set(Position.PREFIX_OUT + (k + 9), BitUtil.check(output2, k)); + } + break; + case 32: + case 33: // Impulse counters + buf.skipBytes(4); + break; + case 34: + case 35: // Fuel + buf.skipBytes(2); + break; + case 36: + position.set(Position.KEY_HOURS, buf.readUnsignedIntLE() * 1000); + break; + case 37: + case 38: + case 39: + case 40: + case 41: + case 42: + case 43: // Fuel RS-485 + buf.skipBytes(2); + break; + case 44: + case 45: + case 46: + case 47: + case 48: + case 49: + case 50: + case 51: + position.set(Position.PREFIX_TEMP + (i - 43), buf.readByte()); + break; + case 52: // CAN Fuel + buf.skipBytes(2); + break; + case 53: // CAN Fuel consumption + buf.skipBytes(4); + break; + case 54: // CAN RPM + buf.skipBytes(2); + break; + case 55: // CAN Coolant temperature + buf.skipBytes(1); + break; + case 56: // CAN Kilometrage + buf.skipBytes(4); + break; + case 57: + case 58: + case 59: + case 60: + case 61: // CAN Axle weight + buf.skipBytes(2); + break; + case 62: // CAN Accelerator + buf.skipBytes(1); + break; + case 63: // CAN Brake + buf.skipBytes(1); + break; + case 64: // CAN Engine load + buf.skipBytes(1); + break; + case 65: // CAN Filter fluid level + buf.skipBytes(2); + break; + case 66: // CAN Engine time + buf.skipBytes(4); + break; + case 67: // CAN Distance to maintenance + buf.skipBytes(2); + break; + case 68: // CAN Speed + position.set("can-speed", buf.readByte()); + break; + default: + break; + } + } + + return new ParseResult(index, position); + } + + private Object processFLEXSingle(DeviceSession deviceSession, Channel channel, ByteBuf buf) { + buf.skipBytes(4); // Event index + + ParseResult result = parseFLEXPosition(deviceSession, buf); + + ByteBuf response = Unpooled.buffer(6); + response.writeCharSequence("~T", StandardCharsets.US_ASCII); + response.writeIntLE((int) result.getId()); + sendFLEXReply(channel, response); + + if (result.getPosition().getFixTime() == null) { + return null; + } + + return result.getPosition(); + } + + private Object processFLEXArray(DeviceSession deviceSession, Channel channel, ByteBuf buf) { + List positions = new LinkedList<>(); + int count = buf.readUnsignedByte(); + LOGGER.info("DEBUG: id={} processFLEXArray_COUNT={}", deviceSession.getDeviceId(), count); + for (int i = 0; i < count; i++) { + Position position = parseFLEXPosition(deviceSession, buf).getPosition(); + if (position.getFixTime() != null) { + positions.add(position); + } + } + + ByteBuf response = Unpooled.buffer(6); + response.writeCharSequence("~A", StandardCharsets.US_ASCII); + response.writeByte(count); + sendFLEXReply(channel, response); + + if (positions.isEmpty()) { + return null; + } + + return positions; + } + + private Object processFLEXNegotiation(Channel channel, ByteBuf buf) { + if (buf.readByte() != (byte) 0xB0) { + return null; + } + + flexProtocolVersion = buf.readByte(); + flexStructVersion = buf.readByte(); + if (flexProtocolVersion != (byte) 0x0A && flexProtocolVersion != (byte) 0x14) { + return null; + } + if (flexStructVersion != (byte) 0x0A && flexStructVersion != (byte) 0x14) { + return null; + } + + flexDataSize = buf.readByte(); + if (flexDataSize > 122) { + return null; + } + buf.readBytes(flexBitfield, 0, (int) Math.ceil(flexDataSize / 8)); + + ByteBuf response = Unpooled.buffer(9); + response.writeCharSequence("*S")) { - return processHandshake(channel, remoteAddress, buf); + if (buf.getByte(buf.readerIndex()) == 0x7F) { + // FLEX keep alive message + return null; + } else if (buf.getByte(buf.readerIndex()) == 0x7E) { // "~" + // FLEX message + try { + DeviceSession deviceSession = getDeviceSession(channel, remoteAddress); + if (deviceSession != null) { + switch (buf.readShortLE()) { + // FLEX 1.0 + case 0x417E: // "~A" + return processFLEXArray(deviceSession, channel, buf); + case 0x547E: // "~T" + case 0x437E: // "~C" + return processFLEXSingle(deviceSession, channel, buf); + // FLEX 2.0 + case 0x457E: // "~E" + LOGGER.info("DEBUG: id={} FLEX \"~E\"", deviceSession.getDeviceId()); + break; + case 0x587E: // "~X" + LOGGER.info("DEBUG: id={} FLEX \"~X\"", deviceSession.getDeviceId()); + break; + default: + break; + } + } + } catch (IndexOutOfBoundsException error) { + LOGGER.warn("Navis FLEX message parsing error", error); + } } else { - DeviceSession deviceSession = getDeviceSession(channel, remoteAddress); - if (deviceSession != null) { - if (type.equals("*>T")) { - return processSingle(deviceSession, channel, buf); - } else if (type.equals("*>A")) { - return processArray(deviceSession, channel, buf); + // NTCB message + prefix = buf.toString(buf.readerIndex(), 4, StandardCharsets.US_ASCII); + buf.skipBytes(prefix.length()); // Prefix @NTC by default + serverId = buf.readUnsignedIntLE(); + deviceUniqueId = buf.readUnsignedIntLE(); + int length = buf.readUnsignedShortLE(); + buf.skipBytes(2); // Header and data XOR checksum + + if (length == 0) { + return null; // Keep alive message + } + + int type = buf.getIntLE(buf.readerIndex()); + buf.skipBytes(3); + if ((type & 0xFFFFFF) == 0x533E2AL) { // "*>S" + return processHandshake(channel, remoteAddress, buf); + } else { + DeviceSession deviceSession = getDeviceSession(channel, remoteAddress); + if (deviceSession != null) { + try { + switch (type & 0xFFFFFF) { + case 0x413E2A: // "*>A" + return processNTCBArray(deviceSession, channel, buf); + case 0x543E2A: // "*>T" + return processNTCBSingle(deviceSession, channel, buf); + case 0x463E2A: // "*>F" (*>FLEX) + buf.skipBytes(3); + return processFLEXNegotiation(channel, buf); + default: + break; + } + } catch (IndexOutOfBoundsException error) { + LOGGER.warn("Navis NTCB message parsing error", error); + } } } } return null; } - } -- cgit v1.2.3 From cbe838ad644ce5e787f080e292bc332e50efa4a0 Mon Sep 17 00:00:00 2001 From: Evgeny S Maksimov Date: Fri, 18 Jan 2019 21:48:41 +0300 Subject: Added strict implementation for frame decoder --- src/org/traccar/protocol/NavisFrameDecoder.java | 55 +++++++++++++++++----- src/org/traccar/protocol/NavisProtocol.java | 6 +-- src/org/traccar/protocol/NavisProtocolDecoder.java | 48 ++++++++++++++----- 3 files changed, 82 insertions(+), 27 deletions(-) (limited to 'src/org/traccar') diff --git a/src/org/traccar/protocol/NavisFrameDecoder.java b/src/org/traccar/protocol/NavisFrameDecoder.java index 2480629ac..aa057b51f 100644 --- a/src/org/traccar/protocol/NavisFrameDecoder.java +++ b/src/org/traccar/protocol/NavisFrameDecoder.java @@ -25,17 +25,13 @@ public class NavisFrameDecoder extends BaseFrameDecoder { private static final int NTCB_HEADER_LENGHT = 16; private static final int NTCB_LENGHT_OFFSET = 12; + private static final int FLEX_HEADER_LENGHT = 2; private static final int MAX_FRAME_LENGHT = 65551; - private static byte src8Checksum(ByteBuf buf, int length) { - byte sum = (byte) 0xFF; - for (int i = 0; i < length; i++) { - sum ^= buf.getUnsignedByte(i); - for (int j = 0; j < 8; j++) { - sum = (sum & 0x80) != 0 ? (byte) ((sum << 1) ^ 0x31) : (byte) (sum << 1); - } - } - return sum; + private final NavisProtocolDecoder protocolDecoder; + + public NavisFrameDecoder(NavisProtocolDecoder protocolDecoder) { + this.protocolDecoder = protocolDecoder; } @Override @@ -52,12 +48,49 @@ public class NavisFrameDecoder extends BaseFrameDecoder { return buf.readRetainedSlice(1); } else if (buf.getByte(buf.readerIndex()) == 0x7E /* "~" */) { // FLEX frame + if (protocolDecoder.getFLEXDataSize() == 0) { + return null; + } if (buf.readableBytes() > MAX_FRAME_LENGHT) { throw new TooLongFrameException(); } - if (src8Checksum(buf, buf.readableBytes() - 1) == buf.getByte(buf.readableBytes() - 1)) { - return buf.readRetainedSlice(buf.readableBytes()); + if (buf.readableBytes() > FLEX_HEADER_LENGHT) { + int length = 0; + switch (buf.getByte(buf.readerIndex() + 1)) { + // FLEX 1.0 + case 0x41: // "A" + length = protocolDecoder.getFLEXDataSize() + * buf.getByte(buf.readerIndex() + FLEX_HEADER_LENGHT) + 2; + break; + case 0x54: // "T" + length = protocolDecoder.getFLEXDataSize() + 5; + break; + case 0x43: // "C" + length = protocolDecoder.getFLEXDataSize() + 1; + break; + // FLEX 2.0 (Extra packages) + case 0x45: // "E" + length++; + for (int i = 0; i < buf.getByte(buf.readerIndex() + FLEX_HEADER_LENGHT); i++) { + if (buf.readableBytes() > FLEX_HEADER_LENGHT + length + 1) { + length += buf.getUnsignedShort(length + FLEX_HEADER_LENGHT) + 2; + } else { + return null; + } + } + length++; + break; + case 0x58: // "X" + length = buf.getUnsignedShortLE(buf.readerIndex() + FLEX_HEADER_LENGHT) + 7; + break; + default: + break; + } + + if (buf.readableBytes() >= FLEX_HEADER_LENGHT + length) { + return buf.readRetainedSlice(buf.readableBytes()); + } } } else { // NTCB frame diff --git a/src/org/traccar/protocol/NavisProtocol.java b/src/org/traccar/protocol/NavisProtocol.java index 4250ba4dc..628b78fd4 100644 --- a/src/org/traccar/protocol/NavisProtocol.java +++ b/src/org/traccar/protocol/NavisProtocol.java @@ -25,10 +25,10 @@ public class NavisProtocol extends BaseProtocol { addServer(new TrackerServer(false, getName()) { @Override protected void addProtocolHandlers(PipelineBuilder pipeline) { - pipeline.addLast(new NavisFrameDecoder()); - pipeline.addLast(new NavisProtocolDecoder(NavisProtocol.this)); + NavisProtocolDecoder protocolDecoder = new NavisProtocolDecoder(NavisProtocol.this); + pipeline.addLast(new NavisFrameDecoder(protocolDecoder)); + pipeline.addLast(protocolDecoder); } }); } - } diff --git a/src/org/traccar/protocol/NavisProtocolDecoder.java b/src/org/traccar/protocol/NavisProtocolDecoder.java index 3c5abc2a4..71dd1bcc7 100644 --- a/src/org/traccar/protocol/NavisProtocolDecoder.java +++ b/src/org/traccar/protocol/NavisProtocolDecoder.java @@ -35,11 +35,15 @@ import java.util.LinkedList; import java.util.List; import java.util.Date; +// DEBUG: +import org.traccar.helper.DataConverter; + public class NavisProtocolDecoder extends BaseProtocolDecoder { private String prefix; private long deviceUniqueId, serverId; - private int flexDataSize; // bits + private int flexDataSize; // bytes + private int flexBitfieldDataSize; // bits private final byte[] flexBitfield; private byte flexProtocolVersion, flexStructVersion; private static final Logger LOGGER = LoggerFactory.getLogger(NavisProtocolDecoder.class); @@ -311,14 +315,15 @@ public class NavisProtocolDecoder extends BaseProtocolDecoder { } private ParseResult parseFLEXPosition(DeviceSession deviceSession, ByteBuf buf) { - LOGGER.info("DEBUG: id={} parseFLEXPosition_START", deviceSession.getDeviceId()); + LOGGER.info("DEBUG: id={} parseFLEXPosition_START, flexDataSize={}, flexBitfield[]={}", + deviceSession.getDeviceId(), flexBitfieldDataSize, DataConverter.printHex(flexBitfield)); Position position = new Position(getProtocolName()); position.setDeviceId(deviceSession.getDeviceId()); long index = 0; - for (int i = 0; i < flexDataSize; i++) { + for (int i = 0; i < flexBitfieldDataSize; i++) { if ((flexBitfield[(int) (i / 8)] & (0x80 >> i % 8)) == 0) { // Skip FLEX data field continue; @@ -505,7 +510,7 @@ public class NavisProtocolDecoder extends BaseProtocolDecoder { buf.skipBytes(2); break; case 68: // CAN Speed - position.set("can-speed", buf.readByte()); + position.set("can-speed", buf.readUnsignedByte()); break; default: break; @@ -535,7 +540,7 @@ public class NavisProtocolDecoder extends BaseProtocolDecoder { private Object processFLEXArray(DeviceSession deviceSession, Channel channel, ByteBuf buf) { List positions = new LinkedList<>(); int count = buf.readUnsignedByte(); - LOGGER.info("DEBUG: id={} processFLEXArray_COUNT={}", deviceSession.getDeviceId(), count); + for (int i = 0; i < count; i++) { Position position = parseFLEXPosition(deviceSession, buf).getPosition(); if (position.getFixTime() != null) { @@ -556,12 +561,18 @@ public class NavisProtocolDecoder extends BaseProtocolDecoder { } private Object processFLEXNegotiation(Channel channel, ByteBuf buf) { - if (buf.readByte() != (byte) 0xB0) { + int[] fieldsSizes = {4, 2, 4, 1, 1, 1, 1, 1, 4, 4, 4, 4, 4, 2, 4, 4, + 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 1, 1, 1, 1, + 4, 4, 2, 2, 4, 2, 2, 2, 2, 2, 2, 2, 1, 1, 1, 1, + 1, 1, 1, 1, 2, 4, 2, 1, 4, 2, 2, 2, 2, 2, 1, 1, + 1, 2, 4, 2, 1}; + + if ((byte) buf.readUnsignedByte() != (byte) 0xB0) { return null; } - flexProtocolVersion = buf.readByte(); - flexStructVersion = buf.readByte(); + flexProtocolVersion = (byte) buf.readUnsignedByte(); + flexStructVersion = (byte) buf.readUnsignedByte(); if (flexProtocolVersion != (byte) 0x0A && flexProtocolVersion != (byte) 0x14) { return null; } @@ -569,11 +580,18 @@ public class NavisProtocolDecoder extends BaseProtocolDecoder { return null; } - flexDataSize = buf.readByte(); - if (flexDataSize > 122) { + flexBitfieldDataSize = buf.readUnsignedByte(); + if (flexBitfieldDataSize > 122) { return null; } - buf.readBytes(flexBitfield, 0, (int) Math.ceil(flexDataSize / 8)); + buf.readBytes(flexBitfield, 0, (int) Math.ceil((double) flexBitfieldDataSize / 8)); + + flexDataSize = 0; + for (int i = 0; i < flexBitfieldDataSize; i++) { + if ((flexBitfield[(int) (i / 8)] & (0x80 >> i % 8)) != 0) { + flexDataSize += fieldsSizes[i]; + } + } ByteBuf response = Unpooled.buffer(9); response.writeCharSequence("* Date: Sat, 19 Jan 2019 15:02:46 +0300 Subject: Implemented FLEX 2.0 extension support for Navis (NTCB) protocol --- checkstyle.xml | 2 +- src/org/traccar/protocol/NavisProtocolDecoder.java | 205 ++++++++++++--------- 2 files changed, 114 insertions(+), 93 deletions(-) (limited to 'src/org/traccar') diff --git a/checkstyle.xml b/checkstyle.xml index a456428a6..d85100471 100644 --- a/checkstyle.xml +++ b/checkstyle.xml @@ -68,7 +68,7 @@ - + diff --git a/src/org/traccar/protocol/NavisProtocolDecoder.java b/src/org/traccar/protocol/NavisProtocolDecoder.java index 71dd1bcc7..e4664444e 100644 --- a/src/org/traccar/protocol/NavisProtocolDecoder.java +++ b/src/org/traccar/protocol/NavisProtocolDecoder.java @@ -35,18 +35,20 @@ import java.util.LinkedList; import java.util.List; import java.util.Date; -// DEBUG: -import org.traccar.helper.DataConverter; - public class NavisProtocolDecoder extends BaseProtocolDecoder { private String prefix; private long deviceUniqueId, serverId; - private int flexDataSize; // bytes - private int flexBitfieldDataSize; // bits + private int flexDataSize; // Bytes + private int flexBitfieldDataSize; // Bits private final byte[] flexBitfield; private byte flexProtocolVersion, flexStructVersion; private static final Logger LOGGER = LoggerFactory.getLogger(NavisProtocolDecoder.class); + private static final int[] FLEX_FIELDS_SIZES = {4, 2, 4, 1, 1, 1, 1, 1, 4, 4, 4, 4, 4, 2, 4, 4, 2, 2, + 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 1, 1, 1, 1, 4, 4, 2, 2, 4, 2, 2, 2, 2, 2, 2, 2, 1, 1, 1, 1, 1, 1, 1, + 1, 2, 4, 2, 1, 4, 2, 2, 2, 2, 2, 1, 1, 1, 2, 4, 2, 1, /* FLEX 2.0 */ 8, 2, 1, 16, 4, 2, 4, 37, 1, + 1, 1, 1, 1, 1, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 6, 12, 24, 48, 1, 1, 1, 1, 4, 4, 1, 4, 2, 6, 2, 6, 2, + 2, 2, 2, 2, 2, 2, 2, 1, 2, 2, 2, 1}; // Bytes public NavisProtocolDecoder(Protocol protocol) { super(protocol); @@ -314,9 +316,14 @@ public class NavisProtocolDecoder extends BaseProtocolDecoder { return positions; } + private void skipFLEXField(int index, ByteBuf buf) { + if (index < FLEX_FIELDS_SIZES.length) { + buf.skipBytes(FLEX_FIELDS_SIZES[index]); + } + } + private ParseResult parseFLEXPosition(DeviceSession deviceSession, ByteBuf buf) { - LOGGER.info("DEBUG: id={} parseFLEXPosition_START, flexDataSize={}, flexBitfield[]={}", - deviceSession.getDeviceId(), flexBitfieldDataSize, DataConverter.printHex(flexBitfield)); + Position position = new Position(getProtocolName()); position.setDeviceId(deviceSession.getDeviceId()); @@ -325,10 +332,10 @@ public class NavisProtocolDecoder extends BaseProtocolDecoder { for (int i = 0; i < flexBitfieldDataSize; i++) { if ((flexBitfield[(int) (i / 8)] & (0x80 >> i % 8)) == 0) { - // Skip FLEX data field + // Skip FLEX field continue; } - LOGGER.info("DEBUG: id={} parseFLEXPosition_FIELD={}", deviceSession.getDeviceId(), i + 1); + int status = 0; short input = 0; short output = 0; @@ -341,9 +348,6 @@ public class NavisProtocolDecoder extends BaseProtocolDecoder { case 1: position.set(Position.KEY_EVENT, buf.readUnsignedShortLE()); break; - case 2: - buf.skipBytes(4); // Event time - break; case 3: short armedStatus = buf.readUnsignedByte(); position.set(Position.KEY_ARMED, armedStatus & 0x1); @@ -391,10 +395,6 @@ public class NavisProtocolDecoder extends BaseProtocolDecoder { case 15: position.set(Position.KEY_DISTANCE, buf.readFloatLE() * 1000); break; - case 16: - case 17: - buf.skipBytes(2); - break; case 18: position.set(Position.KEY_POWER, buf.readUnsignedShortLE() * 0.001); break; @@ -439,26 +439,9 @@ public class NavisProtocolDecoder extends BaseProtocolDecoder { position.set(Position.PREFIX_OUT + (k + 9), BitUtil.check(output2, k)); } break; - case 32: - case 33: // Impulse counters - buf.skipBytes(4); - break; - case 34: - case 35: // Fuel - buf.skipBytes(2); - break; case 36: position.set(Position.KEY_HOURS, buf.readUnsignedIntLE() * 1000); break; - case 37: - case 38: - case 39: - case 40: - case 41: - case 42: - case 43: // Fuel RS-485 - buf.skipBytes(2); - break; case 44: case 45: case 46: @@ -469,50 +452,23 @@ public class NavisProtocolDecoder extends BaseProtocolDecoder { case 51: position.set(Position.PREFIX_TEMP + (i - 43), buf.readByte()); break; - case 52: // CAN Fuel - buf.skipBytes(2); - break; - case 53: // CAN Fuel consumption - buf.skipBytes(4); - break; - case 54: // CAN RPM - buf.skipBytes(2); - break; - case 55: // CAN Coolant temperature - buf.skipBytes(1); - break; - case 56: // CAN Kilometrage - buf.skipBytes(4); - break; - case 57: - case 58: - case 59: - case 60: - case 61: // CAN Axle weight - buf.skipBytes(2); - break; - case 62: // CAN Accelerator - buf.skipBytes(1); - break; - case 63: // CAN Brake - buf.skipBytes(1); - break; - case 64: // CAN Engine load - buf.skipBytes(1); - break; - case 65: // CAN Filter fluid level - buf.skipBytes(2); - break; - case 66: // CAN Engine time - buf.skipBytes(4); - break; - case 67: // CAN Distance to maintenance - buf.skipBytes(2); - break; case 68: // CAN Speed position.set("can-speed", buf.readUnsignedByte()); break; + // FLEX 2.0 + case 69: + int satVisible = 0; + for (int k = 0; k < 8; k++) { + satVisible += buf.readUnsignedByte(); + } + position.set(Position.KEY_SATELLITES_VISIBLE, satVisible); + break; + case 70: + position.set(Position.KEY_HDOP, buf.readUnsignedByte() * 0.1); + position.set(Position.KEY_PDOP, buf.readUnsignedByte() * 0.1); + break; default: + skipFLEXField(i, buf); break; } } @@ -520,13 +476,54 @@ public class NavisProtocolDecoder extends BaseProtocolDecoder { return new ParseResult(index, position); } - private Object processFLEXSingle(DeviceSession deviceSession, Channel channel, ByteBuf buf) { + private ParseResult parseFLEX20Position(DeviceSession deviceSession, ByteBuf buf) { + Position position = new Position(getProtocolName()); + + position.setDeviceId(deviceSession.getDeviceId()); + + long index = 0; + int length = buf.readUnsignedShort(); + + // Check buffer size and struct version + if (length <= buf.readableBytes() && buf.readUnsignedByte() == 0x0A) { + buf.skipBytes(1); // Length of static part + + index = buf.readUnsignedIntLE(); + position.set(Position.KEY_INDEX, index); + + position.set(Position.KEY_EVENT, buf.readUnsignedShortLE()); + buf.skipBytes(4); // Event time + + int navSensorState = buf.readUnsignedByte(); + position.setValid(BitUtil.check(navSensorState, 1)); + position.set(Position.KEY_SATELLITES, navSensorState >> 2); + + position.setTime(new DateBuilder(new Date(buf.readUnsignedIntLE() * 1000)).getDate()); + position.setLatitude(buf.readIntLE() / 600000.0); + position.setLongitude(buf.readIntLE() / 600000.0); + position.setAltitude(buf.readIntLE() * 0.1); + position.setSpeed(UnitsConverter.knotsFromKph(buf.readFloatLE())); + position.setCourse(buf.readUnsignedShortLE()); + position.set(Position.KEY_ODOMETER, buf.readFloatLE() * 1000); + + buf.skipBytes(length - buf.readerIndex() - 1); // Skip unused part + } + + return new ParseResult(index, position); + } + + private interface FLEXPositionParser { + ParseResult parsePosition(DeviceSession deviceSession, ByteBuf buf); + } + + private Object processFLEXSingle( + FLEXPositionParser parser, String flexHeader, DeviceSession deviceSession, Channel channel, ByteBuf buf) { buf.skipBytes(4); // Event index - ParseResult result = parseFLEXPosition(deviceSession, buf); + ParseResult result = parser.parsePosition(deviceSession, buf); ByteBuf response = Unpooled.buffer(6); - response.writeCharSequence("~T", StandardCharsets.US_ASCII); + response.writeCharSequence(flexHeader, StandardCharsets.US_ASCII); response.writeIntLE((int) result.getId()); sendFLEXReply(channel, response); @@ -537,19 +534,20 @@ public class NavisProtocolDecoder extends BaseProtocolDecoder { return result.getPosition(); } - private Object processFLEXArray(DeviceSession deviceSession, Channel channel, ByteBuf buf) { + private Object processFLEXArray( + FLEXPositionParser parser, String flexHeader, DeviceSession deviceSession, Channel channel, ByteBuf buf) { List positions = new LinkedList<>(); int count = buf.readUnsignedByte(); for (int i = 0; i < count; i++) { - Position position = parseFLEXPosition(deviceSession, buf).getPosition(); + Position position = parser.parsePosition(deviceSession, buf).getPosition(); if (position.getFixTime() != null) { positions.add(position); } } ByteBuf response = Unpooled.buffer(6); - response.writeCharSequence("~A", StandardCharsets.US_ASCII); + response.writeCharSequence(flexHeader, StandardCharsets.US_ASCII); response.writeByte(count); sendFLEXReply(channel, response); @@ -561,12 +559,6 @@ public class NavisProtocolDecoder extends BaseProtocolDecoder { } private Object processFLEXNegotiation(Channel channel, ByteBuf buf) { - int[] fieldsSizes = {4, 2, 4, 1, 1, 1, 1, 1, 4, 4, 4, 4, 4, 2, 4, 4, - 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 1, 1, 1, 1, - 4, 4, 2, 2, 4, 2, 2, 2, 2, 2, 2, 2, 1, 1, 1, 1, - 1, 1, 1, 1, 2, 4, 2, 1, 4, 2, 2, 2, 2, 2, 1, 1, - 1, 2, 4, 2, 1}; - if ((byte) buf.readUnsignedByte() != (byte) 0xB0) { return null; } @@ -589,7 +581,7 @@ public class NavisProtocolDecoder extends BaseProtocolDecoder { flexDataSize = 0; for (int i = 0; i < flexBitfieldDataSize; i++) { if ((flexBitfield[(int) (i / 8)] & (0x80 >> i % 8)) != 0) { - flexDataSize += fieldsSizes[i]; + flexDataSize += FLEX_FIELDS_SIZES[i]; } } @@ -670,17 +662,46 @@ public class NavisProtocolDecoder extends BaseProtocolDecoder { switch (buf.readShortLE()) { // FLEX 1.0 case 0x417E: // "~A" - return processFLEXArray(deviceSession, channel, buf); + return processFLEXArray(new FLEXPositionParser() { + @Override + public ParseResult parsePosition(DeviceSession deviceSession, ByteBuf buf) { + return NavisProtocolDecoder.this.parseFLEXPosition(deviceSession, buf); + } + }, + "~A", deviceSession, channel, buf); case 0x547E: // "~T" + return processFLEXSingle(new FLEXPositionParser() { + @Override + public ParseResult parsePosition(DeviceSession deviceSession, ByteBuf buf) { + return NavisProtocolDecoder.this.parseFLEXPosition(deviceSession, buf); + } + }, + "~T", deviceSession, channel, buf); case 0x437E: // "~C" - return processFLEXSingle(deviceSession, channel, buf); + return processFLEXSingle(new FLEXPositionParser() { + @Override + public ParseResult parsePosition(DeviceSession deviceSession, ByteBuf buf) { + return NavisProtocolDecoder.this.parseFLEXPosition(deviceSession, buf); + } + }, + "~C", deviceSession, channel, buf); // FLEX 2.0 (Extra packages) case 0x457E: // "~E" - LOGGER.info("DEBUG: id={} FLEX \"~E\"", deviceSession.getDeviceId()); - break; + return processFLEXArray(new FLEXPositionParser() { + @Override + public ParseResult parsePosition(DeviceSession deviceSession, ByteBuf buf) { + return NavisProtocolDecoder.this.parseFLEX20Position(deviceSession, buf); + } + }, + "~E", deviceSession, channel, buf); case 0x587E: // "~X" - LOGGER.info("DEBUG: id={} FLEX \"~X\"", deviceSession.getDeviceId()); - break; + return processFLEXSingle(new FLEXPositionParser() { + @Override + public ParseResult parsePosition(DeviceSession deviceSession, ByteBuf buf) { + return NavisProtocolDecoder.this.parseFLEX20Position(deviceSession, buf); + } + }, + "~X", deviceSession, channel, buf); default: break; } -- cgit v1.2.3 From 7b85a8fc8713d62352cacf1b6111cb08e2857e4b Mon Sep 17 00:00:00 2001 From: Evgeny S Maksimov Date: Sat, 19 Jan 2019 21:03:27 +0300 Subject: Fixed typos --- src/org/traccar/protocol/NavisFrameDecoder.java | 34 ++++++++++++------------- 1 file changed, 17 insertions(+), 17 deletions(-) (limited to 'src/org/traccar') diff --git a/src/org/traccar/protocol/NavisFrameDecoder.java b/src/org/traccar/protocol/NavisFrameDecoder.java index aa057b51f..b82a3a5fb 100644 --- a/src/org/traccar/protocol/NavisFrameDecoder.java +++ b/src/org/traccar/protocol/NavisFrameDecoder.java @@ -23,10 +23,10 @@ import org.traccar.BaseFrameDecoder; public class NavisFrameDecoder extends BaseFrameDecoder { - private static final int NTCB_HEADER_LENGHT = 16; - private static final int NTCB_LENGHT_OFFSET = 12; - private static final int FLEX_HEADER_LENGHT = 2; - private static final int MAX_FRAME_LENGHT = 65551; + private static final int NTCB_HEADER_LENGTH = 16; + private static final int NTCB_LENGTH_OFFSET = 12; + private static final int FLEX_HEADER_LENGTH = 2; + private static final int MAX_FRAME_LENGTH = 65551; private final NavisProtocolDecoder protocolDecoder; @@ -51,17 +51,17 @@ public class NavisFrameDecoder extends BaseFrameDecoder { if (protocolDecoder.getFLEXDataSize() == 0) { return null; } - if (buf.readableBytes() > MAX_FRAME_LENGHT) { + if (buf.readableBytes() > MAX_FRAME_LENGTH) { throw new TooLongFrameException(); } - if (buf.readableBytes() > FLEX_HEADER_LENGHT) { + if (buf.readableBytes() > FLEX_HEADER_LENGTH) { int length = 0; switch (buf.getByte(buf.readerIndex() + 1)) { // FLEX 1.0 case 0x41: // "A" length = protocolDecoder.getFLEXDataSize() - * buf.getByte(buf.readerIndex() + FLEX_HEADER_LENGHT) + 2; + * buf.getByte(buf.readerIndex() + FLEX_HEADER_LENGTH) + 2; break; case 0x54: // "T" length = protocolDecoder.getFLEXDataSize() + 5; @@ -72,9 +72,9 @@ public class NavisFrameDecoder extends BaseFrameDecoder { // FLEX 2.0 (Extra packages) case 0x45: // "E" length++; - for (int i = 0; i < buf.getByte(buf.readerIndex() + FLEX_HEADER_LENGHT); i++) { - if (buf.readableBytes() > FLEX_HEADER_LENGHT + length + 1) { - length += buf.getUnsignedShort(length + FLEX_HEADER_LENGHT) + 2; + for (int i = 0; i < buf.getByte(buf.readerIndex() + FLEX_HEADER_LENGTH); i++) { + if (buf.readableBytes() > FLEX_HEADER_LENGTH + length + 1) { + length += buf.getUnsignedShort(length + FLEX_HEADER_LENGTH) + 2; } else { return null; } @@ -82,28 +82,28 @@ public class NavisFrameDecoder extends BaseFrameDecoder { length++; break; case 0x58: // "X" - length = buf.getUnsignedShortLE(buf.readerIndex() + FLEX_HEADER_LENGHT) + 7; + length = buf.getUnsignedShortLE(buf.readerIndex() + FLEX_HEADER_LENGTH) + 7; break; default: break; } - if (buf.readableBytes() >= FLEX_HEADER_LENGHT + length) { + if (buf.readableBytes() >= FLEX_HEADER_LENGTH + length) { return buf.readRetainedSlice(buf.readableBytes()); } } } else { // NTCB frame - if (buf.readableBytes() < NTCB_HEADER_LENGHT) { + if (buf.readableBytes() < NTCB_HEADER_LENGTH) { return null; } - int length = buf.getUnsignedShortLE(buf.readerIndex() + NTCB_LENGHT_OFFSET); - if (buf.readableBytes() >= NTCB_HEADER_LENGHT + length) { - if (buf.readableBytes() > MAX_FRAME_LENGHT) { + int length = buf.getUnsignedShortLE(buf.readerIndex() + NTCB_LENGTH_OFFSET); + if (buf.readableBytes() >= NTCB_HEADER_LENGTH + length) { + if (buf.readableBytes() > MAX_FRAME_LENGTH) { throw new TooLongFrameException(); } - return buf.readRetainedSlice(NTCB_HEADER_LENGHT + length); + return buf.readRetainedSlice(NTCB_HEADER_LENGTH + length); } } -- cgit v1.2.3 From 3a0bcff44aba8b15d97a669dc8c959830644a8bd Mon Sep 17 00:00:00 2001 From: Evgeny S Maksimov Date: Mon, 21 Jan 2019 19:27:15 +0300 Subject: Fixed two-field parameters --- src/org/traccar/protocol/NavisProtocolDecoder.java | 13 ++++++------- traccar-web | 2 +- 2 files changed, 7 insertions(+), 8 deletions(-) (limited to 'src/org/traccar') diff --git a/src/org/traccar/protocol/NavisProtocolDecoder.java b/src/org/traccar/protocol/NavisProtocolDecoder.java index e4664444e..ec1a1324b 100644 --- a/src/org/traccar/protocol/NavisProtocolDecoder.java +++ b/src/org/traccar/protocol/NavisProtocolDecoder.java @@ -329,6 +329,9 @@ public class NavisProtocolDecoder extends BaseProtocolDecoder { position.setDeviceId(deviceSession.getDeviceId()); long index = 0; + int status = 0; + short input = 0; + short output = 0; for (int i = 0; i < flexBitfieldDataSize; i++) { if ((flexBitfield[(int) (i / 8)] & (0x80 >> i % 8)) == 0) { @@ -336,10 +339,6 @@ public class NavisProtocolDecoder extends BaseProtocolDecoder { continue; } - int status = 0; - short input = 0; - short output = 0; - switch (i) { case 0: index = buf.readUnsignedIntLE(); @@ -361,7 +360,7 @@ public class NavisProtocolDecoder extends BaseProtocolDecoder { break; case 5: int status2 = buf.readUnsignedByte(); - position.set(Position.KEY_STATUS, (short) ((status & 0xFF) | (status2 << 1))); + position.set(Position.KEY_STATUS, (short) ((status & 0xFF) | (status2 << 8))); break; case 6: position.set(Position.KEY_RSSI, buf.readUnsignedByte()); @@ -420,7 +419,7 @@ public class NavisProtocolDecoder extends BaseProtocolDecoder { break; case 29: short input2 = buf.readUnsignedByte(); - position.set(Position.KEY_INPUT, (short) ((input & 0xFF) | (input2 << 1))); + position.set(Position.KEY_INPUT, (short) ((input & 0xFF) | (input2 << 8))); for (int k = 0; k < 8; k++) { position.set(Position.PREFIX_IN + (k + 9), BitUtil.check(input2, k)); } @@ -434,7 +433,7 @@ public class NavisProtocolDecoder extends BaseProtocolDecoder { break; case 31: short output2 = buf.readUnsignedByte(); - position.set(Position.KEY_OUTPUT, (short) ((output & 0xFF) | (output2 << 1))); + position.set(Position.KEY_OUTPUT, (short) ((output & 0xFF) | (output2 << 8))); for (int k = 0; k < 8; k++) { position.set(Position.PREFIX_OUT + (k + 9), BitUtil.check(output2, k)); } diff --git a/traccar-web b/traccar-web index 689d2b691..5d0d92b9a 160000 --- a/traccar-web +++ b/traccar-web @@ -1 +1 @@ -Subproject commit 689d2b691829301014e85b5f7ce5804b0649be09 +Subproject commit 5d0d92b9a7b3170103aad0d09e21b1239444d249 -- cgit v1.2.3 From 7706648481f9687eecc070b4678cc792d7811da7 Mon Sep 17 00:00:00 2001 From: Evgeny S Maksimov Date: Mon, 21 Jan 2019 19:35:21 +0300 Subject: Used member references for the FLEXPositionParser interface --- src/org/traccar/protocol/NavisProtocolDecoder.java | 40 +++------------------- 1 file changed, 5 insertions(+), 35 deletions(-) (limited to 'src/org/traccar') diff --git a/src/org/traccar/protocol/NavisProtocolDecoder.java b/src/org/traccar/protocol/NavisProtocolDecoder.java index ec1a1324b..39e3bdc0f 100644 --- a/src/org/traccar/protocol/NavisProtocolDecoder.java +++ b/src/org/traccar/protocol/NavisProtocolDecoder.java @@ -661,46 +661,16 @@ public class NavisProtocolDecoder extends BaseProtocolDecoder { switch (buf.readShortLE()) { // FLEX 1.0 case 0x417E: // "~A" - return processFLEXArray(new FLEXPositionParser() { - @Override - public ParseResult parsePosition(DeviceSession deviceSession, ByteBuf buf) { - return NavisProtocolDecoder.this.parseFLEXPosition(deviceSession, buf); - } - }, - "~A", deviceSession, channel, buf); + return processFLEXArray(this::parseFLEXPosition, "~A", deviceSession, channel, buf); case 0x547E: // "~T" - return processFLEXSingle(new FLEXPositionParser() { - @Override - public ParseResult parsePosition(DeviceSession deviceSession, ByteBuf buf) { - return NavisProtocolDecoder.this.parseFLEXPosition(deviceSession, buf); - } - }, - "~T", deviceSession, channel, buf); + return processFLEXSingle(this::parseFLEXPosition, "~T", deviceSession, channel, buf); case 0x437E: // "~C" - return processFLEXSingle(new FLEXPositionParser() { - @Override - public ParseResult parsePosition(DeviceSession deviceSession, ByteBuf buf) { - return NavisProtocolDecoder.this.parseFLEXPosition(deviceSession, buf); - } - }, - "~C", deviceSession, channel, buf); + return processFLEXSingle(this::parseFLEXPosition, "~C", deviceSession, channel, buf); // FLEX 2.0 (Extra packages) case 0x457E: // "~E" - return processFLEXArray(new FLEXPositionParser() { - @Override - public ParseResult parsePosition(DeviceSession deviceSession, ByteBuf buf) { - return NavisProtocolDecoder.this.parseFLEX20Position(deviceSession, buf); - } - }, - "~E", deviceSession, channel, buf); + return processFLEXArray(this::parseFLEX20Position, "~E", deviceSession, channel, buf); case 0x587E: // "~X" - return processFLEXSingle(new FLEXPositionParser() { - @Override - public ParseResult parsePosition(DeviceSession deviceSession, ByteBuf buf) { - return NavisProtocolDecoder.this.parseFLEX20Position(deviceSession, buf); - } - }, - "~X", deviceSession, channel, buf); + return processFLEXSingle(this::parseFLEX20Position, "~X", deviceSession, channel, buf); default: break; } -- cgit v1.2.3 From 2bed80fa2bbc70f70de7abd230c1d13472f58cd3 Mon Sep 17 00:00:00 2001 From: Evgeny S Maksimov Date: Mon, 21 Jan 2019 20:46:00 +0300 Subject: Detailing for visible satellites GPS and GLONASS --- src/org/traccar/protocol/NavisProtocolDecoder.java | 17 ++++++++++++++++- 1 file changed, 16 insertions(+), 1 deletion(-) (limited to 'src/org/traccar') diff --git a/src/org/traccar/protocol/NavisProtocolDecoder.java b/src/org/traccar/protocol/NavisProtocolDecoder.java index 39e3bdc0f..93e751012 100644 --- a/src/org/traccar/protocol/NavisProtocolDecoder.java +++ b/src/org/traccar/protocol/NavisProtocolDecoder.java @@ -458,7 +458,22 @@ public class NavisProtocolDecoder extends BaseProtocolDecoder { case 69: int satVisible = 0; for (int k = 0; k < 8; k++) { - satVisible += buf.readUnsignedByte(); + switch (k) { + case 0: + int satVisibleGLONASS = buf.readUnsignedByte(); + position.set("sat-visible-glonass", satVisibleGLONASS); + satVisible += satVisibleGLONASS; + break; + case 1: + int satVisibleGPS = buf.readUnsignedByte(); + position.set("sat-visible-gps", satVisibleGPS); + satVisible += satVisibleGPS; + break; + default: + // Don't detalize Galileo, Compass, Beidou, DORIS, IRNSS, QZSS + satVisible += buf.readUnsignedByte(); + break; + } } position.set(Position.KEY_SATELLITES_VISIBLE, satVisible); break; -- cgit v1.2.3 From f61893727534e888cf2143557bf6f143bdd64e60 Mon Sep 17 00:00:00 2001 From: Evgeny S Maksimov Date: Mon, 21 Jan 2019 22:53:22 +0300 Subject: Revert "Fixed two-field parameters" This reverts commit 3a0bcff44aba8b15d97a669dc8c959830644a8bd. --- src/org/traccar/protocol/NavisProtocolDecoder.java | 13 +++++++------ traccar-web | 2 +- 2 files changed, 8 insertions(+), 7 deletions(-) (limited to 'src/org/traccar') diff --git a/src/org/traccar/protocol/NavisProtocolDecoder.java b/src/org/traccar/protocol/NavisProtocolDecoder.java index 93e751012..4e5162b44 100644 --- a/src/org/traccar/protocol/NavisProtocolDecoder.java +++ b/src/org/traccar/protocol/NavisProtocolDecoder.java @@ -329,9 +329,6 @@ public class NavisProtocolDecoder extends BaseProtocolDecoder { position.setDeviceId(deviceSession.getDeviceId()); long index = 0; - int status = 0; - short input = 0; - short output = 0; for (int i = 0; i < flexBitfieldDataSize; i++) { if ((flexBitfield[(int) (i / 8)] & (0x80 >> i % 8)) == 0) { @@ -339,6 +336,10 @@ public class NavisProtocolDecoder extends BaseProtocolDecoder { continue; } + int status = 0; + short input = 0; + short output = 0; + switch (i) { case 0: index = buf.readUnsignedIntLE(); @@ -360,7 +361,7 @@ public class NavisProtocolDecoder extends BaseProtocolDecoder { break; case 5: int status2 = buf.readUnsignedByte(); - position.set(Position.KEY_STATUS, (short) ((status & 0xFF) | (status2 << 8))); + position.set(Position.KEY_STATUS, (short) ((status & 0xFF) | (status2 << 1))); break; case 6: position.set(Position.KEY_RSSI, buf.readUnsignedByte()); @@ -419,7 +420,7 @@ public class NavisProtocolDecoder extends BaseProtocolDecoder { break; case 29: short input2 = buf.readUnsignedByte(); - position.set(Position.KEY_INPUT, (short) ((input & 0xFF) | (input2 << 8))); + position.set(Position.KEY_INPUT, (short) ((input & 0xFF) | (input2 << 1))); for (int k = 0; k < 8; k++) { position.set(Position.PREFIX_IN + (k + 9), BitUtil.check(input2, k)); } @@ -433,7 +434,7 @@ public class NavisProtocolDecoder extends BaseProtocolDecoder { break; case 31: short output2 = buf.readUnsignedByte(); - position.set(Position.KEY_OUTPUT, (short) ((output & 0xFF) | (output2 << 8))); + position.set(Position.KEY_OUTPUT, (short) ((output & 0xFF) | (output2 << 1))); for (int k = 0; k < 8; k++) { position.set(Position.PREFIX_OUT + (k + 9), BitUtil.check(output2, k)); } diff --git a/traccar-web b/traccar-web index 5d0d92b9a..689d2b691 160000 --- a/traccar-web +++ b/traccar-web @@ -1 +1 @@ -Subproject commit 5d0d92b9a7b3170103aad0d09e21b1239444d249 +Subproject commit 689d2b691829301014e85b5f7ce5804b0649be09 -- cgit v1.2.3 From eae48f944a326bac20e49dac4fe577e7cc2a4102 Mon Sep 17 00:00:00 2001 From: Evgeny S Maksimov Date: Mon, 21 Jan 2019 22:55:20 +0300 Subject: Fixed two-field parameters --- src/org/traccar/protocol/NavisProtocolDecoder.java | 13 ++++++------- 1 file changed, 6 insertions(+), 7 deletions(-) (limited to 'src/org/traccar') diff --git a/src/org/traccar/protocol/NavisProtocolDecoder.java b/src/org/traccar/protocol/NavisProtocolDecoder.java index 4e5162b44..93e751012 100644 --- a/src/org/traccar/protocol/NavisProtocolDecoder.java +++ b/src/org/traccar/protocol/NavisProtocolDecoder.java @@ -329,6 +329,9 @@ public class NavisProtocolDecoder extends BaseProtocolDecoder { position.setDeviceId(deviceSession.getDeviceId()); long index = 0; + int status = 0; + short input = 0; + short output = 0; for (int i = 0; i < flexBitfieldDataSize; i++) { if ((flexBitfield[(int) (i / 8)] & (0x80 >> i % 8)) == 0) { @@ -336,10 +339,6 @@ public class NavisProtocolDecoder extends BaseProtocolDecoder { continue; } - int status = 0; - short input = 0; - short output = 0; - switch (i) { case 0: index = buf.readUnsignedIntLE(); @@ -361,7 +360,7 @@ public class NavisProtocolDecoder extends BaseProtocolDecoder { break; case 5: int status2 = buf.readUnsignedByte(); - position.set(Position.KEY_STATUS, (short) ((status & 0xFF) | (status2 << 1))); + position.set(Position.KEY_STATUS, (short) ((status & 0xFF) | (status2 << 8))); break; case 6: position.set(Position.KEY_RSSI, buf.readUnsignedByte()); @@ -420,7 +419,7 @@ public class NavisProtocolDecoder extends BaseProtocolDecoder { break; case 29: short input2 = buf.readUnsignedByte(); - position.set(Position.KEY_INPUT, (short) ((input & 0xFF) | (input2 << 1))); + position.set(Position.KEY_INPUT, (short) ((input & 0xFF) | (input2 << 8))); for (int k = 0; k < 8; k++) { position.set(Position.PREFIX_IN + (k + 9), BitUtil.check(input2, k)); } @@ -434,7 +433,7 @@ public class NavisProtocolDecoder extends BaseProtocolDecoder { break; case 31: short output2 = buf.readUnsignedByte(); - position.set(Position.KEY_OUTPUT, (short) ((output & 0xFF) | (output2 << 1))); + position.set(Position.KEY_OUTPUT, (short) ((output & 0xFF) | (output2 << 8))); for (int k = 0; k < 8; k++) { position.set(Position.PREFIX_OUT + (k + 9), BitUtil.check(output2, k)); } -- cgit v1.2.3 From b4a655445b6ad7a0ef96193a616f8bdec182ca54 Mon Sep 17 00:00:00 2001 From: Evgeny S Maksimov Date: Mon, 21 Jan 2019 23:17:04 +0300 Subject: Naming convention fix --- src/org/traccar/protocol/NavisFrameDecoder.java | 8 +-- src/org/traccar/protocol/NavisProtocolDecoder.java | 64 +++++++++++----------- 2 files changed, 36 insertions(+), 36 deletions(-) (limited to 'src/org/traccar') diff --git a/src/org/traccar/protocol/NavisFrameDecoder.java b/src/org/traccar/protocol/NavisFrameDecoder.java index b82a3a5fb..1d77c0d65 100644 --- a/src/org/traccar/protocol/NavisFrameDecoder.java +++ b/src/org/traccar/protocol/NavisFrameDecoder.java @@ -48,7 +48,7 @@ public class NavisFrameDecoder extends BaseFrameDecoder { return buf.readRetainedSlice(1); } else if (buf.getByte(buf.readerIndex()) == 0x7E /* "~" */) { // FLEX frame - if (protocolDecoder.getFLEXDataSize() == 0) { + if (protocolDecoder.getFlexDataSize() == 0) { return null; } if (buf.readableBytes() > MAX_FRAME_LENGTH) { @@ -60,14 +60,14 @@ public class NavisFrameDecoder extends BaseFrameDecoder { switch (buf.getByte(buf.readerIndex() + 1)) { // FLEX 1.0 case 0x41: // "A" - length = protocolDecoder.getFLEXDataSize() + length = protocolDecoder.getFlexDataSize() * buf.getByte(buf.readerIndex() + FLEX_HEADER_LENGTH) + 2; break; case 0x54: // "T" - length = protocolDecoder.getFLEXDataSize() + 5; + length = protocolDecoder.getFlexDataSize() + 5; break; case 0x43: // "C" - length = protocolDecoder.getFLEXDataSize() + 1; + length = protocolDecoder.getFlexDataSize() + 1; break; // FLEX 2.0 (Extra packages) case 0x45: // "E" diff --git a/src/org/traccar/protocol/NavisProtocolDecoder.java b/src/org/traccar/protocol/NavisProtocolDecoder.java index 93e751012..ed2562125 100644 --- a/src/org/traccar/protocol/NavisProtocolDecoder.java +++ b/src/org/traccar/protocol/NavisProtocolDecoder.java @@ -91,7 +91,7 @@ public class NavisProtocolDecoder extends BaseProtocolDecoder { } } - private ParseResult parseNTCBPosition(DeviceSession deviceSession, ByteBuf buf) { + private ParseResult parseNtcbPosition(DeviceSession deviceSession, ByteBuf buf) { Position position = new Position(getProtocolName()); position.setDeviceId(deviceSession.getDeviceId()); @@ -278,13 +278,13 @@ public class NavisProtocolDecoder extends BaseProtocolDecoder { return new ParseResult(index, position); } - private Object processNTCBSingle(DeviceSession deviceSession, Channel channel, ByteBuf buf) { - ParseResult result = parseNTCBPosition(deviceSession, buf); + private Object processNtcbSingle(DeviceSession deviceSession, Channel channel, ByteBuf buf) { + ParseResult result = parseNtcbPosition(deviceSession, buf); ByteBuf response = Unpooled.buffer(7); response.writeCharSequence("* positions = new LinkedList<>(); int count = buf.readUnsignedByte(); for (int i = 0; i < count; i++) { - Position position = parseNTCBPosition(deviceSession, buf).getPosition(); + Position position = parseNtcbPosition(deviceSession, buf).getPosition(); if (position.getFixTime() != null) { positions.add(position); } @@ -307,7 +307,7 @@ public class NavisProtocolDecoder extends BaseProtocolDecoder { ByteBuf response = Unpooled.buffer(7); response.writeCharSequence("* positions = new LinkedList<>(); int count = buf.readUnsignedByte(); @@ -563,7 +563,7 @@ public class NavisProtocolDecoder extends BaseProtocolDecoder { ByteBuf response = Unpooled.buffer(6); response.writeCharSequence(flexHeader, StandardCharsets.US_ASCII); response.writeByte(count); - sendFLEXReply(channel, response); + sendFlexReply(channel, response); if (positions.isEmpty()) { return null; @@ -572,7 +572,7 @@ public class NavisProtocolDecoder extends BaseProtocolDecoder { return positions; } - private Object processFLEXNegotiation(Channel channel, ByteBuf buf) { + private Object processFlexNegotiation(Channel channel, ByteBuf buf) { if ((byte) buf.readUnsignedByte() != (byte) 0xB0) { return null; } @@ -604,7 +604,7 @@ public class NavisProtocolDecoder extends BaseProtocolDecoder { response.writeByte(0xB0); response.writeByte(flexProtocolVersion); response.writeByte(flexStructVersion); - sendNTCBReply(channel, response); + sendNtcbReply(channel, response); return null; } @@ -612,7 +612,7 @@ public class NavisProtocolDecoder extends BaseProtocolDecoder { private Object processHandshake(Channel channel, SocketAddress remoteAddress, ByteBuf buf) { buf.skipBytes(1); // Colon symbol if (getDeviceSession(channel, remoteAddress, buf.toString(StandardCharsets.US_ASCII)) != null) { - sendNTCBReply(channel, Unpooled.copiedBuffer("*A" - return processNTCBArray(deviceSession, channel, buf); + return processNtcbArray(deviceSession, channel, buf); case 0x543E2A: // "*>T" - return processNTCBSingle(deviceSession, channel, buf); + return processNtcbSingle(deviceSession, channel, buf); case 0x463E2A: // "*>F" (*>FLEX) buf.skipBytes(3); - return processFLEXNegotiation(channel, buf); + return processFlexNegotiation(channel, buf); default: break; } @@ -735,7 +735,7 @@ public class NavisProtocolDecoder extends BaseProtocolDecoder { return null; } - public int getFLEXDataSize() { + public int getFlexDataSize() { return flexDataSize; } } -- cgit v1.2.3 From e655888ac17d6138a9d7a40fa2782a6406e7ed1e Mon Sep 17 00:00:00 2001 From: Evgeny S Maksimov Date: Tue, 22 Jan 2019 18:47:48 +0300 Subject: Use native checksums calculation --- src/org/traccar/protocol/NavisProtocolDecoder.java | 27 ++++------------------ 1 file changed, 5 insertions(+), 22 deletions(-) (limited to 'src/org/traccar') diff --git a/src/org/traccar/protocol/NavisProtocolDecoder.java b/src/org/traccar/protocol/NavisProtocolDecoder.java index ed2562125..955f3cc1f 100644 --- a/src/org/traccar/protocol/NavisProtocolDecoder.java +++ b/src/org/traccar/protocol/NavisProtocolDecoder.java @@ -25,6 +25,8 @@ import org.traccar.DeviceSession; import org.traccar.NetworkMessage; import org.traccar.Protocol; import org.traccar.helper.BitUtil; +import org.traccar.helper.Checksum; +import org.traccar.helper.Checksum.Algorithm; import org.traccar.helper.DateBuilder; import org.traccar.helper.UnitsConverter; import org.traccar.model.Position; @@ -617,25 +619,6 @@ public class NavisProtocolDecoder extends BaseProtocolDecoder { return null; } - private static byte xorChecksum(ByteBuf buf) { - byte sum = 0; - for (int i = 0; i < buf.readableBytes(); i++) { - sum ^= buf.getUnsignedByte(i); - } - return sum; - } - - private static byte src8Checksum(ByteBuf buf) { - byte sum = (byte) 0xFF; - for (int i = 0; i < buf.readableBytes(); i++) { - sum ^= buf.getUnsignedByte(i); - for (int j = 0; j < 8; j++) { - sum = (sum & 0x80) != 0 ? (byte) ((sum << 1) ^ 0x31) : (byte) (sum << 1); - } - } - return sum; - } - private void sendNtcbReply(Channel channel, ByteBuf data) { if (channel != null) { ByteBuf header = Unpooled.buffer(16); @@ -643,8 +626,8 @@ public class NavisProtocolDecoder extends BaseProtocolDecoder { header.writeIntLE((int) deviceUniqueId); header.writeIntLE((int) serverId); header.writeShortLE(data.readableBytes()); - header.writeByte(xorChecksum(data)); - header.writeByte(xorChecksum(header)); + header.writeByte(Checksum.xor(data.nioBuffer())); + header.writeByte(Checksum.xor(header.nioBuffer())); channel.writeAndFlush(new NetworkMessage(Unpooled.wrappedBuffer(header, data), channel.remoteAddress())); } @@ -653,7 +636,7 @@ public class NavisProtocolDecoder extends BaseProtocolDecoder { private void sendFlexReply(Channel channel, ByteBuf data) { if (channel != null) { ByteBuf cs = Unpooled.buffer(1); - cs.writeByte(src8Checksum(data)); + cs.writeByte(Checksum.crc8(new Algorithm(8, 0x31, 0xFF, false, false, 0x00), data.nioBuffer())); channel.writeAndFlush(new NetworkMessage(Unpooled.wrappedBuffer(data, cs), channel.remoteAddress())); } -- cgit v1.2.3 From 8385061cf3b2374890c9d854d3843cecbc5ae0b9 Mon Sep 17 00:00:00 2001 From: Evgeny S Maksimov Date: Tue, 22 Jan 2019 19:52:19 +0300 Subject: Revert unnecessary changes --- src/org/traccar/protocol/NavisProtocolDecoder.java | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) (limited to 'src/org/traccar') diff --git a/src/org/traccar/protocol/NavisProtocolDecoder.java b/src/org/traccar/protocol/NavisProtocolDecoder.java index 955f3cc1f..61c39aaf4 100644 --- a/src/org/traccar/protocol/NavisProtocolDecoder.java +++ b/src/org/traccar/protocol/NavisProtocolDecoder.java @@ -111,7 +111,7 @@ public class NavisProtocolDecoder extends BaseProtocolDecoder { position.set(Position.KEY_EVENT, buf.readUnsignedShortLE()); - buf.skipBytes(6); // Event time + buf.skipBytes(6); // event time short armedStatus = buf.readUnsignedByte(); if (isFormat(format, F10, F20, F30, F40, F50, F51, F52)) { @@ -508,7 +508,7 @@ public class NavisProtocolDecoder extends BaseProtocolDecoder { position.set(Position.KEY_INDEX, index); position.set(Position.KEY_EVENT, buf.readUnsignedShortLE()); - buf.skipBytes(4); // Event time + buf.skipBytes(4); // event time int navSensorState = buf.readUnsignedByte(); position.setValid(BitUtil.check(navSensorState, 1)); @@ -612,7 +612,7 @@ public class NavisProtocolDecoder extends BaseProtocolDecoder { } private Object processHandshake(Channel channel, SocketAddress remoteAddress, ByteBuf buf) { - buf.skipBytes(1); // Colon symbol + buf.readByte(); // colon symbol if (getDeviceSession(channel, remoteAddress, buf.toString(StandardCharsets.US_ASCII)) != null) { sendNtcbReply(channel, Unpooled.copiedBuffer("* Date: Tue, 22 Jan 2019 20:05:40 +0300 Subject: Instance variables optimization --- src/org/traccar/protocol/NavisProtocolDecoder.java | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) (limited to 'src/org/traccar') diff --git a/src/org/traccar/protocol/NavisProtocolDecoder.java b/src/org/traccar/protocol/NavisProtocolDecoder.java index 61c39aaf4..9ea843daa 100644 --- a/src/org/traccar/protocol/NavisProtocolDecoder.java +++ b/src/org/traccar/protocol/NavisProtocolDecoder.java @@ -44,7 +44,6 @@ public class NavisProtocolDecoder extends BaseProtocolDecoder { private int flexDataSize; // Bytes private int flexBitfieldDataSize; // Bits private final byte[] flexBitfield; - private byte flexProtocolVersion, flexStructVersion; private static final Logger LOGGER = LoggerFactory.getLogger(NavisProtocolDecoder.class); private static final int[] FLEX_FIELDS_SIZES = {4, 2, 4, 1, 1, 1, 1, 1, 4, 4, 4, 4, 4, 2, 4, 4, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 1, 1, 1, 1, 4, 4, 2, 2, 4, 2, 2, 2, 2, 2, 2, 2, 1, 1, 1, 1, 1, 1, 1, @@ -579,6 +578,8 @@ public class NavisProtocolDecoder extends BaseProtocolDecoder { return null; } + byte flexProtocolVersion, flexStructVersion; + flexProtocolVersion = (byte) buf.readUnsignedByte(); flexStructVersion = (byte) buf.readUnsignedByte(); if (flexProtocolVersion != (byte) 0x0A && flexProtocolVersion != (byte) 0x14) { -- cgit v1.2.3 From 8cf5581749554412d724ad36f0052dbfe37aa456 Mon Sep 17 00:00:00 2001 From: Evgeny S Maksimov Date: Tue, 22 Jan 2019 20:49:58 +0300 Subject: Use readXxx and readUnsignedXxx for skipping fields --- src/org/traccar/protocol/NavisProtocolDecoder.java | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) (limited to 'src/org/traccar') diff --git a/src/org/traccar/protocol/NavisProtocolDecoder.java b/src/org/traccar/protocol/NavisProtocolDecoder.java index 9ea843daa..4bce4e37f 100644 --- a/src/org/traccar/protocol/NavisProtocolDecoder.java +++ b/src/org/traccar/protocol/NavisProtocolDecoder.java @@ -501,13 +501,13 @@ public class NavisProtocolDecoder extends BaseProtocolDecoder { // Check buffer size and struct version if (length <= buf.readableBytes() && buf.readUnsignedByte() == 0x0A) { - buf.skipBytes(1); // Length of static part + buf.readUnsignedByte(); // Length of static part index = buf.readUnsignedIntLE(); position.set(Position.KEY_INDEX, index); position.set(Position.KEY_EVENT, buf.readUnsignedShortLE()); - buf.skipBytes(4); // event time + buf.readUnsignedInt(); // event time int navSensorState = buf.readUnsignedByte(); position.setValid(BitUtil.check(navSensorState, 1)); @@ -533,7 +533,7 @@ public class NavisProtocolDecoder extends BaseProtocolDecoder { private Object processFlexSingle( FlexPositionParser parser, String flexHeader, DeviceSession deviceSession, Channel channel, ByteBuf buf) { - buf.skipBytes(4); // Event index + buf.readUnsignedInt(); // Event index ParseResult result = parser.parsePosition(deviceSession, buf); -- cgit v1.2.3 From 7601d1625dbe3ffbbfeb0f81c224fc4bce8bbcdc Mon Sep 17 00:00:00 2001 From: Evgeny S Maksimov Date: Wed, 23 Jan 2019 22:43:09 +0300 Subject: Use BitUtil for some bit operations --- src/org/traccar/protocol/NavisProtocolDecoder.java | 16 ++++++++-------- 1 file changed, 8 insertions(+), 8 deletions(-) (limited to 'src/org/traccar') diff --git a/src/org/traccar/protocol/NavisProtocolDecoder.java b/src/org/traccar/protocol/NavisProtocolDecoder.java index 4bce4e37f..1e474556a 100644 --- a/src/org/traccar/protocol/NavisProtocolDecoder.java +++ b/src/org/traccar/protocol/NavisProtocolDecoder.java @@ -137,7 +137,7 @@ public class NavisProtocolDecoder extends BaseProtocolDecoder { } else if (isFormat(format, F50, F51, F52)) { short extField = buf.readUnsignedByte(); position.set(Position.KEY_OUTPUT, extField & 0x3); - position.set(Position.KEY_SATELLITES, extField >> 2); + position.set(Position.KEY_SATELLITES, BitUtil.from(extField, 2)); position.set(Position.PREFIX_OUT + 1, BitUtil.check(extField, 0)); position.set(Position.PREFIX_OUT + 2, BitUtil.check(extField, 1)); } else if (isFormat(format, F40, F60)) { @@ -160,10 +160,10 @@ public class NavisProtocolDecoder extends BaseProtocolDecoder { position.set(Position.PREFIX_IN + 2, BitUtil.check(input, 1)); position.set(Position.PREFIX_IN + 3, BitUtil.check(input, 2)); position.set(Position.PREFIX_IN + 4, BitUtil.check(input, 3)); - position.set(Position.PREFIX_IN + 5, (input & 0x70) >> 4); - position.set(Position.PREFIX_IN + 6, (input & 0x380) >> 7); - position.set(Position.PREFIX_IN + 7, (input & 0xC00) >> 10); - position.set(Position.PREFIX_IN + 8, (input & 0x3000) >> 12); + position.set(Position.PREFIX_IN + 5, BitUtil.between(input, 4, 7)); + position.set(Position.PREFIX_IN + 6, BitUtil.between(input, 7, 10)); + position.set(Position.PREFIX_IN + 7, BitUtil.between(input, 10, 12)); + position.set(Position.PREFIX_IN + 5, BitUtil.between(input, 12, 14)); } } else if (isFormat(format, F50, F51, F52, F60)) { short input = buf.readUnsignedByte(); @@ -227,7 +227,7 @@ public class NavisProtocolDecoder extends BaseProtocolDecoder { int navSensorState = buf.readUnsignedByte(); position.setValid(BitUtil.check(navSensorState, 1)); if (isFormat(format, F60)) { - position.set(Position.KEY_SATELLITES, navSensorState >> 2); + position.set(Position.KEY_SATELLITES, BitUtil.from(navSensorState, 2)); } DateBuilder dateBuilder = new DateBuilder() @@ -369,7 +369,7 @@ public class NavisProtocolDecoder extends BaseProtocolDecoder { case 7: int navSensorState = buf.readUnsignedByte(); position.setValid(BitUtil.check(navSensorState, 1)); - position.set(Position.KEY_SATELLITES, navSensorState >> 2); + position.set(Position.KEY_SATELLITES, BitUtil.from(navSensorState, 2)); break; case 8: position.setTime(new DateBuilder(new Date(buf.readUnsignedIntLE() * 1000)).getDate()); @@ -511,7 +511,7 @@ public class NavisProtocolDecoder extends BaseProtocolDecoder { int navSensorState = buf.readUnsignedByte(); position.setValid(BitUtil.check(navSensorState, 1)); - position.set(Position.KEY_SATELLITES, navSensorState >> 2); + position.set(Position.KEY_SATELLITES, BitUtil.from(navSensorState, 2)); position.setTime(new DateBuilder(new Date(buf.readUnsignedIntLE() * 1000)).getDate()); position.setLatitude(buf.readIntLE() / 600000.0); -- cgit v1.2.3 From 3fdf7c71df04dc327b692360a8560a0d6c125ded Mon Sep 17 00:00:00 2001 From: Evgeny S Maksimov Date: Wed, 23 Jan 2019 22:54:12 +0300 Subject: Minor fix --- src/org/traccar/protocol/NavisProtocolDecoder.java | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'src/org/traccar') diff --git a/src/org/traccar/protocol/NavisProtocolDecoder.java b/src/org/traccar/protocol/NavisProtocolDecoder.java index 1e474556a..1b19539da 100644 --- a/src/org/traccar/protocol/NavisProtocolDecoder.java +++ b/src/org/traccar/protocol/NavisProtocolDecoder.java @@ -163,7 +163,7 @@ public class NavisProtocolDecoder extends BaseProtocolDecoder { position.set(Position.PREFIX_IN + 5, BitUtil.between(input, 4, 7)); position.set(Position.PREFIX_IN + 6, BitUtil.between(input, 7, 10)); position.set(Position.PREFIX_IN + 7, BitUtil.between(input, 10, 12)); - position.set(Position.PREFIX_IN + 5, BitUtil.between(input, 12, 14)); + position.set(Position.PREFIX_IN + 8, BitUtil.between(input, 12, 14)); } } else if (isFormat(format, F50, F51, F52, F60)) { short input = buf.readUnsignedByte(); -- cgit v1.2.3 From 5cb6d4bc0f2254379391a44cd7d56fb9b85e353e Mon Sep 17 00:00:00 2001 From: Evgeny S Maksimov Date: Wed, 23 Jan 2019 23:50:54 +0300 Subject: Use BitUtil for the remaining bit operations --- src/org/traccar/protocol/NavisProtocolDecoder.java | 18 +++++++++--------- 1 file changed, 9 insertions(+), 9 deletions(-) (limited to 'src/org/traccar') diff --git a/src/org/traccar/protocol/NavisProtocolDecoder.java b/src/org/traccar/protocol/NavisProtocolDecoder.java index 1b19539da..8eda868b1 100644 --- a/src/org/traccar/protocol/NavisProtocolDecoder.java +++ b/src/org/traccar/protocol/NavisProtocolDecoder.java @@ -114,12 +114,12 @@ public class NavisProtocolDecoder extends BaseProtocolDecoder { short armedStatus = buf.readUnsignedByte(); if (isFormat(format, F10, F20, F30, F40, F50, F51, F52)) { - position.set(Position.KEY_ARMED, armedStatus & 0x7F); + position.set(Position.KEY_ARMED, BitUtil.to(armedStatus, 7)); if (BitUtil.check(armedStatus, 7)) { position.set(Position.KEY_ALARM, Position.ALARM_GENERAL); } } else if (isFormat(format, F60)) { - position.set(Position.KEY_ARMED, armedStatus & 0x1); + position.set(Position.KEY_ARMED, BitUtil.check(armedStatus, 0)); if (BitUtil.check(armedStatus, 1)) { position.set(Position.KEY_ALARM, Position.ALARM_GENERAL); } @@ -136,13 +136,13 @@ public class NavisProtocolDecoder extends BaseProtocolDecoder { } } else if (isFormat(format, F50, F51, F52)) { short extField = buf.readUnsignedByte(); - position.set(Position.KEY_OUTPUT, extField & 0x3); - position.set(Position.KEY_SATELLITES, BitUtil.from(extField, 2)); + position.set(Position.KEY_OUTPUT, BitUtil.to(extField, 2)); position.set(Position.PREFIX_OUT + 1, BitUtil.check(extField, 0)); position.set(Position.PREFIX_OUT + 2, BitUtil.check(extField, 1)); + position.set(Position.KEY_SATELLITES, BitUtil.from(extField, 2)); } else if (isFormat(format, F40, F60)) { short output = buf.readUnsignedByte(); - position.set(Position.KEY_OUTPUT, output & 0xF); + position.set(Position.KEY_OUTPUT, BitUtil.to(output, 4)); for (int i = 0; i < 4; i++) { position.set(Position.PREFIX_OUT + (i + 1), BitUtil.check(output, i)); } @@ -350,7 +350,7 @@ public class NavisProtocolDecoder extends BaseProtocolDecoder { break; case 3: short armedStatus = buf.readUnsignedByte(); - position.set(Position.KEY_ARMED, armedStatus & 0x1); + position.set(Position.KEY_ARMED, BitUtil.check(armedStatus, 0)); if (BitUtil.check(armedStatus, 1)) { position.set(Position.KEY_ALARM, Position.ALARM_GENERAL); } @@ -361,7 +361,7 @@ public class NavisProtocolDecoder extends BaseProtocolDecoder { break; case 5: int status2 = buf.readUnsignedByte(); - position.set(Position.KEY_STATUS, (short) ((status & 0xFF) | (status2 << 8))); + position.set(Position.KEY_STATUS, (short) (BitUtil.to(status, 8) | (status2 << 8))); break; case 6: position.set(Position.KEY_RSSI, buf.readUnsignedByte()); @@ -420,7 +420,7 @@ public class NavisProtocolDecoder extends BaseProtocolDecoder { break; case 29: short input2 = buf.readUnsignedByte(); - position.set(Position.KEY_INPUT, (short) ((input & 0xFF) | (input2 << 8))); + position.set(Position.KEY_INPUT, (short) (BitUtil.to(input, 8) | (input2 << 8))); for (int k = 0; k < 8; k++) { position.set(Position.PREFIX_IN + (k + 9), BitUtil.check(input2, k)); } @@ -434,7 +434,7 @@ public class NavisProtocolDecoder extends BaseProtocolDecoder { break; case 31: short output2 = buf.readUnsignedByte(); - position.set(Position.KEY_OUTPUT, (short) ((output & 0xFF) | (output2 << 8))); + position.set(Position.KEY_OUTPUT, (short) (BitUtil.to(output, 8) | (output2 << 8))); for (int k = 0; k < 8; k++) { position.set(Position.PREFIX_OUT + (k + 9), BitUtil.check(output2, k)); } -- cgit v1.2.3 From 95285d6f8c93d4a9c8e03d634b0a503695fe4449 Mon Sep 17 00:00:00 2001 From: Evgeny S Maksimov Date: Fri, 25 Jan 2019 23:23:24 +0300 Subject: Bit field traversing refactoring --- src/org/traccar/protocol/NavisProtocolDecoder.java | 10 ++++++++-- 1 file changed, 8 insertions(+), 2 deletions(-) (limited to 'src/org/traccar') diff --git a/src/org/traccar/protocol/NavisProtocolDecoder.java b/src/org/traccar/protocol/NavisProtocolDecoder.java index 8eda868b1..65c425053 100644 --- a/src/org/traccar/protocol/NavisProtocolDecoder.java +++ b/src/org/traccar/protocol/NavisProtocolDecoder.java @@ -317,6 +317,12 @@ public class NavisProtocolDecoder extends BaseProtocolDecoder { return positions; } + private boolean checkFlexBitfield(int index) { + int byteIndex = Math.floorDiv(index, 8); + int bitIndex = Math.floorMod(index, 8); + return BitUtil.check(flexBitfield[byteIndex], 7 - bitIndex); + } + private void skipFlexField(int index, ByteBuf buf) { if (index < FLEX_FIELDS_SIZES.length) { buf.skipBytes(FLEX_FIELDS_SIZES[index]); @@ -335,7 +341,7 @@ public class NavisProtocolDecoder extends BaseProtocolDecoder { short output = 0; for (int i = 0; i < flexBitfieldDataSize; i++) { - if ((flexBitfield[(int) (i / 8)] & (0x80 >> i % 8)) == 0) { + if (!checkFlexBitfield(i)) { // Skip FLEX field continue; } @@ -597,7 +603,7 @@ public class NavisProtocolDecoder extends BaseProtocolDecoder { flexDataSize = 0; for (int i = 0; i < flexBitfieldDataSize; i++) { - if ((flexBitfield[(int) (i / 8)] & (0x80 >> i % 8)) != 0) { + if (checkFlexBitfield(i)) { flexDataSize += FLEX_FIELDS_SIZES[i]; } } -- cgit v1.2.3 From cbddcd311a777f0fbe1dcea4105b01ef0ffa4e34 Mon Sep 17 00:00:00 2001 From: Evgeny S Maksimov Date: Mon, 28 Jan 2019 23:44:12 +0300 Subject: Message type parser refactoring --- src/org/traccar/protocol/NavisProtocolDecoder.java | 137 ++++++++++++--------- .../traccar/protocol/NavisProtocolDecoderTest.java | 9 +- 2 files changed, 82 insertions(+), 64 deletions(-) (limited to 'src/org/traccar') diff --git a/src/org/traccar/protocol/NavisProtocolDecoder.java b/src/org/traccar/protocol/NavisProtocolDecoder.java index 65c425053..decfae63f 100644 --- a/src/org/traccar/protocol/NavisProtocolDecoder.java +++ b/src/org/traccar/protocol/NavisProtocolDecoder.java @@ -649,82 +649,97 @@ public class NavisProtocolDecoder extends BaseProtocolDecoder { } } - @Override - protected Object decode( - Channel channel, SocketAddress remoteAddress, Object msg) throws Exception { + private Object decodeNtcb(Channel channel, SocketAddress remoteAddress, ByteBuf buf) { - ByteBuf buf = (ByteBuf) msg; + prefix = buf.toString(buf.readerIndex(), 4, StandardCharsets.US_ASCII); + buf.skipBytes(prefix.length()); // Prefix @NTC by default + serverId = buf.readUnsignedIntLE(); + deviceUniqueId = buf.readUnsignedIntLE(); + int length = buf.readUnsignedShortLE(); + buf.skipBytes(2); // Header and data XOR checksum - if (buf.getByte(buf.readerIndex()) == 0x7F) { - // FLEX keep alive message - return null; - } else if (buf.getByte(buf.readerIndex()) == 0x7E) { // "~" - // FLEX message - try { - DeviceSession deviceSession = getDeviceSession(channel, remoteAddress); - if (deviceSession != null) { - switch (buf.readShortLE()) { - // FLEX 1.0 - case 0x417E: // "~A" - return processFlexArray(this::parseFlexPosition, "~A", deviceSession, channel, buf); - case 0x547E: // "~T" - return processFlexSingle(this::parseFlexPosition, "~T", deviceSession, channel, buf); - case 0x437E: // "~C" - return processFlexSingle(this::parseFlexPosition, "~C", deviceSession, channel, buf); - // FLEX 2.0 (Extra packages) - case 0x457E: // "~E" - return processFlexArray(this::parseFlex20Position, "~E", deviceSession, channel, buf); - case 0x587E: // "~X" - return processFlexSingle(this::parseFlex20Position, "~X", deviceSession, channel, buf); + if (length == 0) { + return null; // Keep alive message + } + + String type = buf.toString(buf.readerIndex(), 3, StandardCharsets.US_ASCII); + buf.skipBytes(type.length()); + + if (type.equals("*>S")) { + return processHandshake(channel, remoteAddress, buf); + } else { + DeviceSession deviceSession = getDeviceSession(channel, remoteAddress); + if (deviceSession != null) { + try { + switch (type) { + case "*>A": + return processNtcbArray(deviceSession, channel, buf); + case "*>T": + return processNtcbSingle(deviceSession, channel, buf); + case "*>F": // "*>FLEX" + buf.skipBytes(3); + return processFlexNegotiation(channel, buf); default: break; } + } catch (IndexOutOfBoundsException error) { + LOGGER.warn("Navis NTCB message parsing error", error); } - } catch (IndexOutOfBoundsException error) { - LOGGER.warn("Navis FLEX message parsing error", error); - } - } else { - // NTCB message - prefix = buf.toString(buf.readerIndex(), 4, StandardCharsets.US_ASCII); - buf.skipBytes(prefix.length()); // Prefix @NTC by default - serverId = buf.readUnsignedIntLE(); - deviceUniqueId = buf.readUnsignedIntLE(); - int length = buf.readUnsignedShortLE(); - buf.skipBytes(2); // Header and data XOR checksum - - if (length == 0) { - return null; // Keep alive message } + } - int type = buf.getIntLE(buf.readerIndex()); - buf.skipBytes(3); - if ((type & 0xFFFFFF) == 0x533E2AL) { // "*>S" - return processHandshake(channel, remoteAddress, buf); - } else { - DeviceSession deviceSession = getDeviceSession(channel, remoteAddress); - if (deviceSession != null) { - try { - switch (type & 0xFFFFFF) { - case 0x413E2A: // "*>A" - return processNtcbArray(deviceSession, channel, buf); - case 0x543E2A: // "*>T" - return processNtcbSingle(deviceSession, channel, buf); - case 0x463E2A: // "*>F" (*>FLEX) - buf.skipBytes(3); - return processFlexNegotiation(channel, buf); - default: - break; - } - } catch (IndexOutOfBoundsException error) { - LOGGER.warn("Navis NTCB message parsing error", error); - } + return null; + } + + private Object decodeFlex(Channel channel, SocketAddress remoteAddress, ByteBuf buf) { + + String type = buf.toString(buf.readerIndex(), 2, StandardCharsets.US_ASCII); + buf.skipBytes(type.length()); + + DeviceSession deviceSession = getDeviceSession(channel, remoteAddress); + if (deviceSession != null) { + try { + switch (type) { + // FLEX 1.0 + case "~A": + return processFlexArray(this::parseFlexPosition, type, deviceSession, channel, buf); + case "~T": + case "~C": + return processFlexSingle(this::parseFlexPosition, type, deviceSession, channel, buf); + // FLEX 2.0 (Extra packages) + case "~E": + return processFlexArray(this::parseFlex20Position, type, deviceSession, channel, buf); + case "~X": + return processFlexSingle(this::parseFlex20Position, type, deviceSession, channel, buf); + default: + break; } + } catch (IndexOutOfBoundsException error) { + LOGGER.warn("Navis FLEX message parsing error", error); } } return null; } + @Override + protected Object decode( + Channel channel, SocketAddress remoteAddress, Object msg) throws Exception { + + ByteBuf buf = (ByteBuf) msg; + + if (buf.getByte(buf.readerIndex()) == 0x7F) { + // FLEX keep alive message + return null; + } + + if (flexDataSize > 0) { + return decodeFlex(channel, remoteAddress, buf); + } else { + return decodeNtcb(channel, remoteAddress, buf); + } + } + public int getFlexDataSize() { return flexDataSize; } diff --git a/test/org/traccar/protocol/NavisProtocolDecoderTest.java b/test/org/traccar/protocol/NavisProtocolDecoderTest.java index 7230bc0a1..5bf0c84bc 100644 --- a/test/org/traccar/protocol/NavisProtocolDecoderTest.java +++ b/test/org/traccar/protocol/NavisProtocolDecoderTest.java @@ -15,9 +15,6 @@ public class NavisProtocolDecoderTest extends ProtocolTest { verifyNull(decoder, binary( "404E5443010000007B000000130044342A3E533A383631373835303035323035303739")); - verifyNull(decoder, binary( - "404E5443010000007B000000130047372A3E533A383631373835303035313236303639")); - // NTCB F5.2 - Single verifyPosition(decoder, binary( "404e5443010000000000000059009adb2a3e54250000000000ff1500040b0a1008291838001200760ee600000000000000000000000f1500040b0a10ac20703fb1aec23f00000000320149668f430000000000000000000000000000000000000000000000f3808080"), @@ -55,6 +52,12 @@ public class NavisProtocolDecoderTest extends ProtocolTest { verifyPositions(decoder, binary( "7e4101080000000917c057405c002b001833c057405cbbce030225129101a00300007c6102408900400c1b3cfce3b23a12004710e000000000001bff7f000080bfffff80000080bfffffffffb2")); + decoder = new NavisProtocolDecoder(null); + + // Handshake + verifyNull(decoder, binary( + "404E5443010000007B000000130047372A3E533A383631373835303035313236303639")); + // FLEX 2.0 - Negotiation verifyNull(decoder, binary( "404e544301000000a9eef6021a003f8e2a3e464c4558b014147afffff008080800000e00000000000000")); -- cgit v1.2.3 From 5b4ab0d3fb7a04ddb3b062159329dd258137ac62 Mon Sep 17 00:00:00 2001 From: Evgeny S Maksimov Date: Mon, 28 Jan 2019 23:49:31 +0300 Subject: Minor fix for message type parser --- src/org/traccar/protocol/NavisProtocolDecoder.java | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) (limited to 'src/org/traccar') diff --git a/src/org/traccar/protocol/NavisProtocolDecoder.java b/src/org/traccar/protocol/NavisProtocolDecoder.java index decfae63f..582eccf3a 100644 --- a/src/org/traccar/protocol/NavisProtocolDecoder.java +++ b/src/org/traccar/protocol/NavisProtocolDecoder.java @@ -693,6 +693,11 @@ public class NavisProtocolDecoder extends BaseProtocolDecoder { private Object decodeFlex(Channel channel, SocketAddress remoteAddress, ByteBuf buf) { + if (buf.getByte(buf.readerIndex()) == 0x7F) { + // Keep alive message + return null; + } + String type = buf.toString(buf.readerIndex(), 2, StandardCharsets.US_ASCII); buf.skipBytes(type.length()); @@ -728,11 +733,6 @@ public class NavisProtocolDecoder extends BaseProtocolDecoder { ByteBuf buf = (ByteBuf) msg; - if (buf.getByte(buf.readerIndex()) == 0x7F) { - // FLEX keep alive message - return null; - } - if (flexDataSize > 0) { return decodeFlex(channel, remoteAddress, buf); } else { -- cgit v1.2.3 From 876026ef66bfc1d664300ee0478654ceae5675c7 Mon Sep 17 00:00:00 2001 From: Evgeny S Maksimov Date: Tue, 29 Jan 2019 00:11:11 +0300 Subject: Code style fixes --- src/org/traccar/protocol/NavisProtocolDecoder.java | 26 +++++++++++----------- 1 file changed, 13 insertions(+), 13 deletions(-) (limited to 'src/org/traccar') diff --git a/src/org/traccar/protocol/NavisProtocolDecoder.java b/src/org/traccar/protocol/NavisProtocolDecoder.java index 582eccf3a..0bebfe0d2 100644 --- a/src/org/traccar/protocol/NavisProtocolDecoder.java +++ b/src/org/traccar/protocol/NavisProtocolDecoder.java @@ -41,15 +41,15 @@ public class NavisProtocolDecoder extends BaseProtocolDecoder { private String prefix; private long deviceUniqueId, serverId; - private int flexDataSize; // Bytes - private int flexBitfieldDataSize; // Bits + private int flexDataSize; // bytes + private int flexBitfieldDataSize; // bits private final byte[] flexBitfield; private static final Logger LOGGER = LoggerFactory.getLogger(NavisProtocolDecoder.class); private static final int[] FLEX_FIELDS_SIZES = {4, 2, 4, 1, 1, 1, 1, 1, 4, 4, 4, 4, 4, 2, 4, 4, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 1, 1, 1, 1, 4, 4, 2, 2, 4, 2, 2, 2, 2, 2, 2, 2, 1, 1, 1, 1, 1, 1, 1, 1, 2, 4, 2, 1, 4, 2, 2, 2, 2, 2, 1, 1, 1, 2, 4, 2, 1, /* FLEX 2.0 */ 8, 2, 1, 16, 4, 2, 4, 37, 1, 1, 1, 1, 1, 1, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 6, 12, 24, 48, 1, 1, 1, 1, 4, 4, 1, 4, 2, 6, 2, 6, 2, - 2, 2, 2, 2, 2, 2, 2, 1, 2, 2, 2, 1}; // Bytes + 2, 2, 2, 2, 2, 2, 2, 1, 2, 2, 2, 1}; // bytes public NavisProtocolDecoder(Protocol protocol) { super(protocol); @@ -342,7 +342,7 @@ public class NavisProtocolDecoder extends BaseProtocolDecoder { for (int i = 0; i < flexBitfieldDataSize; i++) { if (!checkFlexBitfield(i)) { - // Skip FLEX field + // skip FLEX field continue; } @@ -458,7 +458,7 @@ public class NavisProtocolDecoder extends BaseProtocolDecoder { case 51: position.set(Position.PREFIX_TEMP + (i - 43), buf.readByte()); break; - case 68: // CAN Speed + case 68: // CAN Speed position.set("can-speed", buf.readUnsignedByte()); break; // FLEX 2.0 @@ -507,7 +507,7 @@ public class NavisProtocolDecoder extends BaseProtocolDecoder { // Check buffer size and struct version if (length <= buf.readableBytes() && buf.readUnsignedByte() == 0x0A) { - buf.readUnsignedByte(); // Length of static part + buf.readUnsignedByte(); // length of static part index = buf.readUnsignedIntLE(); position.set(Position.KEY_INDEX, index); @@ -527,7 +527,7 @@ public class NavisProtocolDecoder extends BaseProtocolDecoder { position.setCourse(buf.readUnsignedShortLE()); position.set(Position.KEY_ODOMETER, buf.readFloatLE() * 1000); - buf.skipBytes(length - buf.readerIndex() - 1); // Skip unused part + buf.skipBytes(length - buf.readerIndex() - 1); // skip unused part } return new ParseResult(index, position); @@ -539,7 +539,7 @@ public class NavisProtocolDecoder extends BaseProtocolDecoder { private Object processFlexSingle( FlexPositionParser parser, String flexHeader, DeviceSession deviceSession, Channel channel, ByteBuf buf) { - buf.readUnsignedInt(); // Event index + buf.readUnsignedInt(); // event index ParseResult result = parser.parsePosition(deviceSession, buf); @@ -652,14 +652,14 @@ public class NavisProtocolDecoder extends BaseProtocolDecoder { private Object decodeNtcb(Channel channel, SocketAddress remoteAddress, ByteBuf buf) { prefix = buf.toString(buf.readerIndex(), 4, StandardCharsets.US_ASCII); - buf.skipBytes(prefix.length()); // Prefix @NTC by default + buf.skipBytes(prefix.length()); // prefix @NTC by default serverId = buf.readUnsignedIntLE(); deviceUniqueId = buf.readUnsignedIntLE(); int length = buf.readUnsignedShortLE(); - buf.skipBytes(2); // Header and data XOR checksum + buf.skipBytes(2); // header and data XOR checksum if (length == 0) { - return null; // Keep alive message + return null; // keep alive message } String type = buf.toString(buf.readerIndex(), 3, StandardCharsets.US_ASCII); @@ -676,7 +676,7 @@ public class NavisProtocolDecoder extends BaseProtocolDecoder { return processNtcbArray(deviceSession, channel, buf); case "*>T": return processNtcbSingle(deviceSession, channel, buf); - case "*>F": // "*>FLEX" + case "*>F": // "*>FLEX" buf.skipBytes(3); return processFlexNegotiation(channel, buf); default: @@ -694,7 +694,7 @@ public class NavisProtocolDecoder extends BaseProtocolDecoder { private Object decodeFlex(Channel channel, SocketAddress remoteAddress, ByteBuf buf) { if (buf.getByte(buf.readerIndex()) == 0x7F) { - // Keep alive message + // keep alive message return null; } -- cgit v1.2.3 From e9d77d16a99874ef4c5eb44dc15994811d724b9d Mon Sep 17 00:00:00 2001 From: Evgeny S Maksimov Date: Tue, 29 Jan 2019 19:55:31 +0300 Subject: Support for downgrading the FLEX protocol version --- src/org/traccar/protocol/NavisProtocolDecoder.java | 32 ++++++++++++---------- 1 file changed, 17 insertions(+), 15 deletions(-) (limited to 'src/org/traccar') diff --git a/src/org/traccar/protocol/NavisProtocolDecoder.java b/src/org/traccar/protocol/NavisProtocolDecoder.java index 0bebfe0d2..f6fa75c58 100644 --- a/src/org/traccar/protocol/NavisProtocolDecoder.java +++ b/src/org/traccar/protocol/NavisProtocolDecoder.java @@ -588,24 +588,26 @@ public class NavisProtocolDecoder extends BaseProtocolDecoder { flexProtocolVersion = (byte) buf.readUnsignedByte(); flexStructVersion = (byte) buf.readUnsignedByte(); - if (flexProtocolVersion != (byte) 0x0A && flexProtocolVersion != (byte) 0x14) { - return null; - } - if (flexStructVersion != (byte) 0x0A && flexStructVersion != (byte) 0x14) { - return null; - } + if ((flexProtocolVersion == (byte) 0x0A || flexProtocolVersion == (byte) 0x14) + && (flexStructVersion == (byte) 0x0A || flexStructVersion == (byte) 0x14)) { - flexBitfieldDataSize = buf.readUnsignedByte(); - if (flexBitfieldDataSize > 122) { - return null; - } - buf.readBytes(flexBitfield, 0, (int) Math.ceil((double) flexBitfieldDataSize / 8)); + flexBitfieldDataSize = buf.readUnsignedByte(); + if (flexBitfieldDataSize > 122) { + return null; + } - flexDataSize = 0; - for (int i = 0; i < flexBitfieldDataSize; i++) { - if (checkFlexBitfield(i)) { - flexDataSize += FLEX_FIELDS_SIZES[i]; + buf.readBytes(flexBitfield, 0, (int) Math.ceil((double) flexBitfieldDataSize / 8)); + + flexDataSize = 0; + for (int i = 0; i < flexBitfieldDataSize; i++) { + if (checkFlexBitfield(i)) { + flexDataSize += FLEX_FIELDS_SIZES[i]; + } } + } else { + // Prepare request for downgrade of protocol version to FLEX 2.0 + flexProtocolVersion = 0x14; + flexStructVersion = 0x14; } ByteBuf response = Unpooled.buffer(9); -- cgit v1.2.3 From f68362485cf88d7deae178010c168124bc1fdba8 Mon Sep 17 00:00:00 2001 From: Evgeny S Maksimov Date: Tue, 29 Jan 2019 22:17:51 +0300 Subject: Fix comment --- src/org/traccar/protocol/NavisProtocolDecoder.java | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) (limited to 'src/org/traccar') diff --git a/src/org/traccar/protocol/NavisProtocolDecoder.java b/src/org/traccar/protocol/NavisProtocolDecoder.java index f6fa75c58..92d458559 100644 --- a/src/org/traccar/protocol/NavisProtocolDecoder.java +++ b/src/org/traccar/protocol/NavisProtocolDecoder.java @@ -588,7 +588,7 @@ public class NavisProtocolDecoder extends BaseProtocolDecoder { flexProtocolVersion = (byte) buf.readUnsignedByte(); flexStructVersion = (byte) buf.readUnsignedByte(); - if ((flexProtocolVersion == (byte) 0x0A || flexProtocolVersion == (byte) 0x14) + if ((flexProtocolVersion == (byte) 0x0A || flexProtocolVersion == (byte) 0x14) && (flexStructVersion == (byte) 0x0A || flexStructVersion == (byte) 0x14)) { flexBitfieldDataSize = buf.readUnsignedByte(); @@ -605,7 +605,7 @@ public class NavisProtocolDecoder extends BaseProtocolDecoder { } } } else { - // Prepare request for downgrade of protocol version to FLEX 2.0 + // Preparing request to downgrade protocol version to FLEX 2.0 flexProtocolVersion = 0x14; flexStructVersion = 0x14; } -- cgit v1.2.3 From ac13cf5611d40358eed31983399324fd4b68a8db Mon Sep 17 00:00:00 2001 From: Evgeny S Maksimov Date: Tue, 29 Jan 2019 23:56:24 +0300 Subject: Fix parsing of type "~C" FLEX messages --- src/org/traccar/protocol/NavisProtocolDecoder.java | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) (limited to 'src/org/traccar') diff --git a/src/org/traccar/protocol/NavisProtocolDecoder.java b/src/org/traccar/protocol/NavisProtocolDecoder.java index 92d458559..912e47369 100644 --- a/src/org/traccar/protocol/NavisProtocolDecoder.java +++ b/src/org/traccar/protocol/NavisProtocolDecoder.java @@ -539,7 +539,9 @@ public class NavisProtocolDecoder extends BaseProtocolDecoder { private Object processFlexSingle( FlexPositionParser parser, String flexHeader, DeviceSession deviceSession, Channel channel, ByteBuf buf) { - buf.readUnsignedInt(); // event index + if (!flexHeader.equals("~C")) { + buf.readUnsignedInt(); // event index + } ParseResult result = parser.parsePosition(deviceSession, buf); -- cgit v1.2.3 From a652d928263b473648f43d4f64c06549792eb653 Mon Sep 17 00:00:00 2001 From: Evgeny S Maksimov Date: Wed, 30 Jan 2019 01:28:35 +0300 Subject: Frame decoder refactoring --- src/org/traccar/protocol/NavisFrameDecoder.java | 29 +++++++++++++------------ 1 file changed, 15 insertions(+), 14 deletions(-) (limited to 'src/org/traccar') diff --git a/src/org/traccar/protocol/NavisFrameDecoder.java b/src/org/traccar/protocol/NavisFrameDecoder.java index 1d77c0d65..ff367ba77 100644 --- a/src/org/traccar/protocol/NavisFrameDecoder.java +++ b/src/org/traccar/protocol/NavisFrameDecoder.java @@ -19,6 +19,7 @@ import io.netty.buffer.ByteBuf; import io.netty.channel.Channel; import io.netty.channel.ChannelHandlerContext; import io.netty.handler.codec.TooLongFrameException; +import java.nio.charset.StandardCharsets; import org.traccar.BaseFrameDecoder; public class NavisFrameDecoder extends BaseFrameDecoder { @@ -46,31 +47,31 @@ public class NavisFrameDecoder extends BaseFrameDecoder { if (buf.getByte(buf.readerIndex()) == 0x7F) { // FLEX keep alive frame return buf.readRetainedSlice(1); - } else if (buf.getByte(buf.readerIndex()) == 0x7E /* "~" */) { + } + + if (protocolDecoder.getFlexDataSize() > 0) { // FLEX frame - if (protocolDecoder.getFlexDataSize() == 0) { - return null; - } if (buf.readableBytes() > MAX_FRAME_LENGTH) { throw new TooLongFrameException(); } if (buf.readableBytes() > FLEX_HEADER_LENGTH) { int length = 0; - switch (buf.getByte(buf.readerIndex() + 1)) { + String type = buf.toString(buf.readerIndex(), 2, StandardCharsets.US_ASCII); + switch (type) { // FLEX 1.0 - case 0x41: // "A" + case "~A": length = protocolDecoder.getFlexDataSize() - * buf.getByte(buf.readerIndex() + FLEX_HEADER_LENGTH) + 2; + * buf.getByte(buf.readerIndex() + FLEX_HEADER_LENGTH) + 1 + 1; break; - case 0x54: // "T" - length = protocolDecoder.getFlexDataSize() + 5; + case "~T": + length = protocolDecoder.getFlexDataSize() + 4 + 1; break; - case 0x43: // "C" + case "~C": length = protocolDecoder.getFlexDataSize() + 1; break; // FLEX 2.0 (Extra packages) - case 0x45: // "E" + case "~E": length++; for (int i = 0; i < buf.getByte(buf.readerIndex() + FLEX_HEADER_LENGTH); i++) { if (buf.readableBytes() > FLEX_HEADER_LENGTH + length + 1) { @@ -81,11 +82,11 @@ public class NavisFrameDecoder extends BaseFrameDecoder { } length++; break; - case 0x58: // "X" - length = buf.getUnsignedShortLE(buf.readerIndex() + FLEX_HEADER_LENGTH) + 7; + case "~X": + length = buf.getUnsignedShortLE(buf.readerIndex() + FLEX_HEADER_LENGTH) + 4 + 1; break; default: - break; + return null; } if (buf.readableBytes() >= FLEX_HEADER_LENGTH + length) { -- cgit v1.2.3 From da9e3571f686816c07159fb834ec8b9e6eaa3cda Mon Sep 17 00:00:00 2001 From: Evgeny S Maksimov Date: Thu, 31 Jan 2019 12:57:36 +0300 Subject: Review fixes --- src/org/traccar/protocol/NavisFrameDecoder.java | 11 +-- src/org/traccar/protocol/NavisProtocolDecoder.java | 100 +++++++-------------- .../traccar/protocol/NavisFrameDecoderTest.java | 21 +++-- .../traccar/protocol/NavisProtocolDecoderTest.java | 34 +++---- 4 files changed, 68 insertions(+), 98 deletions(-) (limited to 'src/org/traccar') diff --git a/src/org/traccar/protocol/NavisFrameDecoder.java b/src/org/traccar/protocol/NavisFrameDecoder.java index ff367ba77..9a3b3d45c 100644 --- a/src/org/traccar/protocol/NavisFrameDecoder.java +++ b/src/org/traccar/protocol/NavisFrameDecoder.java @@ -44,6 +44,10 @@ public class NavisFrameDecoder extends BaseFrameDecoder { return null; } + if (buf.readableBytes() > MAX_FRAME_LENGTH) { + throw new TooLongFrameException(); + } + if (buf.getByte(buf.readerIndex()) == 0x7F) { // FLEX keep alive frame return buf.readRetainedSlice(1); @@ -51,10 +55,6 @@ public class NavisFrameDecoder extends BaseFrameDecoder { if (protocolDecoder.getFlexDataSize() > 0) { // FLEX frame - if (buf.readableBytes() > MAX_FRAME_LENGTH) { - throw new TooLongFrameException(); - } - if (buf.readableBytes() > FLEX_HEADER_LENGTH) { int length = 0; String type = buf.toString(buf.readerIndex(), 2, StandardCharsets.US_ASCII); @@ -101,9 +101,6 @@ public class NavisFrameDecoder extends BaseFrameDecoder { int length = buf.getUnsignedShortLE(buf.readerIndex() + NTCB_LENGTH_OFFSET); if (buf.readableBytes() >= NTCB_HEADER_LENGTH + length) { - if (buf.readableBytes() > MAX_FRAME_LENGTH) { - throw new TooLongFrameException(); - } return buf.readRetainedSlice(NTCB_HEADER_LENGTH + length); } } diff --git a/src/org/traccar/protocol/NavisProtocolDecoder.java b/src/org/traccar/protocol/NavisProtocolDecoder.java index 912e47369..d3b3f9932 100644 --- a/src/org/traccar/protocol/NavisProtocolDecoder.java +++ b/src/org/traccar/protocol/NavisProtocolDecoder.java @@ -18,8 +18,6 @@ package org.traccar.protocol; import io.netty.buffer.ByteBuf; import io.netty.buffer.Unpooled; import io.netty.channel.Channel; -import org.slf4j.Logger; -import org.slf4j.LoggerFactory; import org.traccar.BaseProtocolDecoder; import org.traccar.DeviceSession; import org.traccar.NetworkMessage; @@ -44,7 +42,6 @@ public class NavisProtocolDecoder extends BaseProtocolDecoder { private int flexDataSize; // bytes private int flexBitfieldDataSize; // bits private final byte[] flexBitfield; - private static final Logger LOGGER = LoggerFactory.getLogger(NavisProtocolDecoder.class); private static final int[] FLEX_FIELDS_SIZES = {4, 2, 4, 1, 1, 1, 1, 1, 4, 4, 4, 4, 4, 2, 4, 4, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 1, 1, 1, 1, 4, 4, 2, 2, 4, 2, 2, 2, 2, 2, 2, 2, 1, 1, 1, 1, 1, 1, 1, 1, 2, 4, 2, 1, 4, 2, 2, 2, 2, 2, 1, 1, 1, 2, 4, 2, 1, /* FLEX 2.0 */ 8, 2, 1, 16, 4, 2, 4, 37, 1, @@ -323,12 +320,6 @@ public class NavisProtocolDecoder extends BaseProtocolDecoder { return BitUtil.check(flexBitfield[byteIndex], 7 - bitIndex); } - private void skipFlexField(int index, ByteBuf buf) { - if (index < FLEX_FIELDS_SIZES.length) { - buf.skipBytes(FLEX_FIELDS_SIZES[index]); - } - } - private ParseResult parseFlexPosition(DeviceSession deviceSession, ByteBuf buf) { Position position = new Position(getProtocolName()); @@ -342,7 +333,6 @@ public class NavisProtocolDecoder extends BaseProtocolDecoder { for (int i = 0; i < flexBitfieldDataSize; i++) { if (!checkFlexBitfield(i)) { - // skip FLEX field continue; } @@ -458,29 +448,14 @@ public class NavisProtocolDecoder extends BaseProtocolDecoder { case 51: position.set(Position.PREFIX_TEMP + (i - 43), buf.readByte()); break; - case 68: // CAN Speed + case 68: position.set("can-speed", buf.readUnsignedByte()); break; // FLEX 2.0 case 69: int satVisible = 0; for (int k = 0; k < 8; k++) { - switch (k) { - case 0: - int satVisibleGLONASS = buf.readUnsignedByte(); - position.set("sat-visible-glonass", satVisibleGLONASS); - satVisible += satVisibleGLONASS; - break; - case 1: - int satVisibleGPS = buf.readUnsignedByte(); - position.set("sat-visible-gps", satVisibleGPS); - satVisible += satVisibleGPS; - break; - default: - // Don't detalize Galileo, Compass, Beidou, DORIS, IRNSS, QZSS - satVisible += buf.readUnsignedByte(); - break; - } + satVisible += buf.readUnsignedByte(); } position.set(Position.KEY_SATELLITES_VISIBLE, satVisible); break; @@ -489,7 +464,9 @@ public class NavisProtocolDecoder extends BaseProtocolDecoder { position.set(Position.KEY_PDOP, buf.readUnsignedByte() * 0.1); break; default: - skipFlexField(i, buf); + if (i < FLEX_FIELDS_SIZES.length) { + buf.skipBytes(FLEX_FIELDS_SIZES[i]); + } break; } } @@ -505,7 +482,6 @@ public class NavisProtocolDecoder extends BaseProtocolDecoder { long index = 0; int length = buf.readUnsignedShort(); - // Check buffer size and struct version if (length <= buf.readableBytes() && buf.readUnsignedByte() == 0x0A) { buf.readUnsignedByte(); // length of static part @@ -586,12 +562,10 @@ public class NavisProtocolDecoder extends BaseProtocolDecoder { return null; } - byte flexProtocolVersion, flexStructVersion; - - flexProtocolVersion = (byte) buf.readUnsignedByte(); - flexStructVersion = (byte) buf.readUnsignedByte(); - if ((flexProtocolVersion == (byte) 0x0A || flexProtocolVersion == (byte) 0x14) - && (flexStructVersion == (byte) 0x0A || flexStructVersion == (byte) 0x14)) { + byte flexProtocolVersion = (byte) buf.readUnsignedByte(); + byte flexStructVersion = (byte) buf.readUnsignedByte(); + if ((flexProtocolVersion == 0x0A || flexProtocolVersion == 0x14) + && (flexStructVersion == 0x0A || flexStructVersion == 0x14)) { flexBitfieldDataSize = buf.readUnsignedByte(); if (flexBitfieldDataSize > 122) { @@ -674,20 +648,16 @@ public class NavisProtocolDecoder extends BaseProtocolDecoder { } else { DeviceSession deviceSession = getDeviceSession(channel, remoteAddress); if (deviceSession != null) { - try { - switch (type) { - case "*>A": - return processNtcbArray(deviceSession, channel, buf); - case "*>T": - return processNtcbSingle(deviceSession, channel, buf); - case "*>F": // "*>FLEX" - buf.skipBytes(3); - return processFlexNegotiation(channel, buf); - default: - break; - } - } catch (IndexOutOfBoundsException error) { - LOGGER.warn("Navis NTCB message parsing error", error); + switch (type) { + case "*>A": + return processNtcbArray(deviceSession, channel, buf); + case "*>T": + return processNtcbSingle(deviceSession, channel, buf); + case "*>F": + buf.skipBytes(3); + return processFlexNegotiation(channel, buf); + default: + break; } } } @@ -707,24 +677,20 @@ public class NavisProtocolDecoder extends BaseProtocolDecoder { DeviceSession deviceSession = getDeviceSession(channel, remoteAddress); if (deviceSession != null) { - try { - switch (type) { - // FLEX 1.0 - case "~A": - return processFlexArray(this::parseFlexPosition, type, deviceSession, channel, buf); - case "~T": - case "~C": - return processFlexSingle(this::parseFlexPosition, type, deviceSession, channel, buf); - // FLEX 2.0 (Extra packages) - case "~E": - return processFlexArray(this::parseFlex20Position, type, deviceSession, channel, buf); - case "~X": - return processFlexSingle(this::parseFlex20Position, type, deviceSession, channel, buf); - default: - break; - } - } catch (IndexOutOfBoundsException error) { - LOGGER.warn("Navis FLEX message parsing error", error); + switch (type) { + // FLEX 1.0 + case "~A": + return processFlexArray(this::parseFlexPosition, type, deviceSession, channel, buf); + case "~T": + case "~C": + return processFlexSingle(this::parseFlexPosition, type, deviceSession, channel, buf); + // FLEX 2.0 (Extra packages) + case "~E": + return processFlexArray(this::parseFlex20Position, type, deviceSession, channel, buf); + case "~X": + return processFlexSingle(this::parseFlex20Position, type, deviceSession, channel, buf); + default: + break; } } diff --git a/test/org/traccar/protocol/NavisFrameDecoderTest.java b/test/org/traccar/protocol/NavisFrameDecoderTest.java index 069f03d1b..5e8d8fd36 100644 --- a/test/org/traccar/protocol/NavisFrameDecoderTest.java +++ b/test/org/traccar/protocol/NavisFrameDecoderTest.java @@ -7,30 +7,33 @@ import org.junit.Test; public class NavisFrameDecoderTest extends ProtocolTest { @Test - public void testDecode() throws Exception { + public void testDecodeNtcb() throws Exception { NavisProtocolDecoder protocolDecoder = new NavisProtocolDecoder(null); NavisFrameDecoder frameDecoder = new NavisFrameDecoder(protocolDecoder); - // Handshake - verifyNull(protocolDecoder, binary( - "404E5443010000007B000000130044342A3E533A383631373835303035323035303739")); - - // NTCB F5.2 - Single verifyFrame(binary( "404e5443010000000000000059009adb2a3e54250000000000ff1500040b0a1008291838001200760ee600000000000000000000000f1500040b0a10ac20703fb1aec23f00000000320149668f430000000000000000000000000000000000000000000000f3808080"), frameDecoder.decode(null, null, binary("404e5443010000000000000059009adb2a3e54250000000000ff1500040b0a1008291838001200760ee600000000000000000000000f1500040b0a10ac20703fb1aec23f00000000320149668f430000000000000000000000000000000000000000000000f3808080"))); - // FLEX 1.0 - Negotiation + } + + @Test + public void testDecodeFlex10() throws Exception { + + NavisProtocolDecoder protocolDecoder = new NavisProtocolDecoder(null); + NavisFrameDecoder frameDecoder = new NavisFrameDecoder(protocolDecoder); + + verifyNull(protocolDecoder, binary( + "404e544301000000c9b5f602130046c52a3e533a383639363936303439373232383235")); + verifyNull(protocolDecoder, binary( "404e544301000000aaecf6021300c8712a3e464c4558b00a0a45ffff300a08080f8388")); - // FLEX 1.0 - Single verifyFrame(binary( "7e54040000000400000030129957405c000b00632f9857405ccace03021e129101a103000000000000c4005ba3fe3b00000000120046100000000000001aff7f000080bfffff80000080bfffffffff9f"), frameDecoder.decode(null, null, binary("7e54040000000400000030129957405c000b00632f9857405ccace03021e129101a103000000000000c4005ba3fe3b00000000120046100000000000001aff7f000080bfffff80000080bfffffffff9f"))); - // FLEX 1.0 - Array (1 message) verifyFrame(binary( "7e4101080000000917c057405c002b001833c057405cbbce030225129101a00300007c6102408900400c1b3cfce3b23a12004710e000000000001bff7f000080bfffff80000080bfffffffffb2"), frameDecoder.decode(null, null, binary("7e4101080000000917c057405c002b001833c057405cbbce030225129101a00300007c6102408900400c1b3cfce3b23a12004710e000000000001bff7f000080bfffff80000080bfffffffffb2"))); diff --git a/test/org/traccar/protocol/NavisProtocolDecoderTest.java b/test/org/traccar/protocol/NavisProtocolDecoderTest.java index 5bf0c84bc..33a6bab24 100644 --- a/test/org/traccar/protocol/NavisProtocolDecoderTest.java +++ b/test/org/traccar/protocol/NavisProtocolDecoderTest.java @@ -7,20 +7,20 @@ import org.junit.Test; public class NavisProtocolDecoderTest extends ProtocolTest { @Test - public void testDecode() throws Exception { + public void testDecodeNtcb() throws Exception { NavisProtocolDecoder decoder = new NavisProtocolDecoder(null); - // Handshake verifyNull(decoder, binary( "404E5443010000007B000000130044342A3E533A383631373835303035323035303739")); - // NTCB F5.2 - Single + verifyNull(decoder, binary( + "404E5443010000007B000000130047372A3E533A383631373835303035313236303639")); + verifyPosition(decoder, binary( "404e5443010000000000000059009adb2a3e54250000000000ff1500040b0a1008291838001200760ee600000000000000000000000f1500040b0a10ac20703fb1aec23f00000000320149668f430000000000000000000000000000000000000000000000f3808080"), position("2016-11-11 21:00:04.000", true, 53.74336, 87.14437)); - // NTCB 5.2 - Array (1 message) verifyPositions(decoder, binary( "404e544300000000040000005a00c6812a3e410125e3a60700011705071503011030210c0000fa200910e6000000000000000000000001082106150010ae97643f88a39f3f0000000090001fcc6c450000000000000000000000000000000000000000000000f6808080")); @@ -30,44 +30,48 @@ public class NavisProtocolDecoderTest extends ProtocolTest { verifyPositions(decoder, binary( "404E5443010000007B0000005A0050692A3E410125DB0E00000015110707110A0C0880630000AA39A2381600020000000000000000000C110708110A0CB389793F1AEF263F00000000120034F516440000000000000000000000FAFF000000FAFF000000FAFF80808080")); - // NTCB 6.0 - Single verifyPosition(decoder, binary( "404e544301000000cdfbf5027200852e2a3e5406aa170000c11116162410001310a9110e80996b281003000a0008000000000000000000d207d207ffffff00fbff00fbff00fbff00fbff00fbff00fbff00fbff2d808080ffffffffffff2b161624100013509b0302b0f89201830500000000000037002fb8cf43eed5843a35003500"), position("2019-01-16 22:22:36.000", true, 56.31800, 44.01523)); - // NTCB 6.0 - Array (1 message) verifyPositions(decoder, binary( "404e54430100000045635902730081972a3e4101060b7e0e000b171328050d00133029110e00bc6141100200000000000000000000000000d207d307ffffff00fbff00fbff00fbff00fbff00fbff00fbff00fbff02808080ffffffffffff4f1328050d001371cd0302c5109101a60300000000000000003d1b37470000000096009600")); + } + + @Test + public void testDecodeFlex10() throws Exception { + + NavisProtocolDecoder decoder = new NavisProtocolDecoder(null); + + verifyNull(decoder, binary( + "404e544301000000c9b5f602130046c52a3e533a383639363936303439373232383235")); - // FLEX 1.0 - Negotiation verifyNull(decoder, binary( "404e544301000000aaecf6021300c8712a3e464c4558b00a0a45ffff300a08080f8388")); - // FLEX 1.0 - Single verifyPosition(decoder, binary( "7e54040000000400000030129957405c000b00632f9857405ccace03021e129101a103000000000000c4005ba3fe3b00000000120046100000000000001aff7f000080bfffff80000080bfffffffff9f"), position("2019-01-17 10:23:20.000", true, 56.33996, 43.80762)); - // FLEX 1.0 - Array (1 message) verifyPositions(decoder, binary( "7e4101080000000917c057405c002b001833c057405cbbce030225129101a00300007c6102408900400c1b3cfce3b23a12004710e000000000001bff7f000080bfffff80000080bfffffffffb2")); + } - decoder = new NavisProtocolDecoder(null); + @Test + public void testDecodeFlex20() throws Exception { + + NavisProtocolDecoder decoder = new NavisProtocolDecoder(null); - // Handshake verifyNull(decoder, binary( - "404E5443010000007B000000130047372A3E533A383631373835303035313236303639")); + "404e544301000000a9eef602130043fb2a3e533a383639363936303439373337333835")); - // FLEX 2.0 - Negotiation verifyNull(decoder, binary( "404e544301000000a9eef6021a003f8e2a3e464c4558b014147afffff008080800000e00000000000000")); - // FLEX 2.0 - Single verifyPosition(decoder, binary( "7e5428000000280000002111d16b435c00a900154bd16b435ce19e030259f6920133050000b7623e429300c9e7f03f2ba45a3e1f001f007b6c5910850f0100001629080a000000000000060947"), position("2019-01-19 18:26:25.000", true, 56.31952, 44.01423)); - // FLEX 2.0 - Array (1 message) verifyPositions(decoder, binary( "7e4101270000000b17b16b435c00a9000d4bb26b435caaa2030229f29201620500000000000093004493d53fee892d3e1f001f00ac6c591081f00000001700080a0000000000000609f2")); } -- cgit v1.2.3 From 83e97b472e16d5dc16826aa4688e7430b8ecec29 Mon Sep 17 00:00:00 2001 From: Evgeny S Maksimov Date: Thu, 31 Jan 2019 13:07:26 +0300 Subject: Review fix --- src/org/traccar/protocol/NavisProtocolDecoder.java | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) (limited to 'src/org/traccar') diff --git a/src/org/traccar/protocol/NavisProtocolDecoder.java b/src/org/traccar/protocol/NavisProtocolDecoder.java index d3b3f9932..ad20ea61f 100644 --- a/src/org/traccar/protocol/NavisProtocolDecoder.java +++ b/src/org/traccar/protocol/NavisProtocolDecoder.java @@ -562,8 +562,8 @@ public class NavisProtocolDecoder extends BaseProtocolDecoder { return null; } - byte flexProtocolVersion = (byte) buf.readUnsignedByte(); - byte flexStructVersion = (byte) buf.readUnsignedByte(); + short flexProtocolVersion = buf.readUnsignedByte(); + short flexStructVersion = buf.readUnsignedByte(); if ((flexProtocolVersion == 0x0A || flexProtocolVersion == 0x14) && (flexStructVersion == 0x0A || flexStructVersion == 0x14)) { -- cgit v1.2.3 From a3c540a952b5136b1de2900c8947847f70b39446 Mon Sep 17 00:00:00 2001 From: Evgeny S Maksimov Date: Fri, 1 Feb 2019 00:56:35 +0300 Subject: Frame decoder refactoring --- src/org/traccar/protocol/NavisFrameDecoder.java | 30 ++++++++++++++-------- src/org/traccar/protocol/NavisProtocol.java | 5 ++-- .../traccar/protocol/NavisFrameDecoderTest.java | 12 +++------ 3 files changed, 24 insertions(+), 23 deletions(-) (limited to 'src/org/traccar') diff --git a/src/org/traccar/protocol/NavisFrameDecoder.java b/src/org/traccar/protocol/NavisFrameDecoder.java index 9a3b3d45c..0146243cd 100644 --- a/src/org/traccar/protocol/NavisFrameDecoder.java +++ b/src/org/traccar/protocol/NavisFrameDecoder.java @@ -21,20 +21,17 @@ import io.netty.channel.ChannelHandlerContext; import io.netty.handler.codec.TooLongFrameException; import java.nio.charset.StandardCharsets; import org.traccar.BaseFrameDecoder; +import org.traccar.BasePipelineFactory; public class NavisFrameDecoder extends BaseFrameDecoder { + private int flexDataSize; // bytes + private static final int NTCB_HEADER_LENGTH = 16; private static final int NTCB_LENGTH_OFFSET = 12; private static final int FLEX_HEADER_LENGTH = 2; private static final int MAX_FRAME_LENGTH = 65551; - private final NavisProtocolDecoder protocolDecoder; - - public NavisFrameDecoder(NavisProtocolDecoder protocolDecoder) { - this.protocolDecoder = protocolDecoder; - } - @Override protected Object decode( ChannelHandlerContext ctx, Channel channel, ByteBuf buf) throws Exception { @@ -53,7 +50,15 @@ public class NavisFrameDecoder extends BaseFrameDecoder { return buf.readRetainedSlice(1); } - if (protocolDecoder.getFlexDataSize() > 0) { + if (ctx != null) { + NavisProtocolDecoder protocolDecoder = + BasePipelineFactory.getHandler(ctx.pipeline(), NavisProtocolDecoder.class); + if (protocolDecoder != null) { + flexDataSize = protocolDecoder.getFlexDataSize(); + } + } + + if (flexDataSize > 0) { // FLEX frame if (buf.readableBytes() > FLEX_HEADER_LENGTH) { int length = 0; @@ -61,14 +66,13 @@ public class NavisFrameDecoder extends BaseFrameDecoder { switch (type) { // FLEX 1.0 case "~A": - length = protocolDecoder.getFlexDataSize() - * buf.getByte(buf.readerIndex() + FLEX_HEADER_LENGTH) + 1 + 1; + length = flexDataSize * buf.getByte(buf.readerIndex() + FLEX_HEADER_LENGTH) + 1 + 1; break; case "~T": - length = protocolDecoder.getFlexDataSize() + 4 + 1; + length = flexDataSize + 4 + 1; break; case "~C": - length = protocolDecoder.getFlexDataSize() + 1; + length = flexDataSize + 1; break; // FLEX 2.0 (Extra packages) case "~E": @@ -108,4 +112,8 @@ public class NavisFrameDecoder extends BaseFrameDecoder { return null; } + public void setFlexDataSize(int flexDataSize) { + this.flexDataSize = flexDataSize; + } + } diff --git a/src/org/traccar/protocol/NavisProtocol.java b/src/org/traccar/protocol/NavisProtocol.java index 628b78fd4..db0eba8c1 100644 --- a/src/org/traccar/protocol/NavisProtocol.java +++ b/src/org/traccar/protocol/NavisProtocol.java @@ -25,9 +25,8 @@ public class NavisProtocol extends BaseProtocol { addServer(new TrackerServer(false, getName()) { @Override protected void addProtocolHandlers(PipelineBuilder pipeline) { - NavisProtocolDecoder protocolDecoder = new NavisProtocolDecoder(NavisProtocol.this); - pipeline.addLast(new NavisFrameDecoder(protocolDecoder)); - pipeline.addLast(protocolDecoder); + pipeline.addLast(new NavisFrameDecoder()); + pipeline.addLast(new NavisProtocolDecoder(NavisProtocol.this)); } }); } diff --git a/test/org/traccar/protocol/NavisFrameDecoderTest.java b/test/org/traccar/protocol/NavisFrameDecoderTest.java index 5e8d8fd36..0ebfeacd2 100644 --- a/test/org/traccar/protocol/NavisFrameDecoderTest.java +++ b/test/org/traccar/protocol/NavisFrameDecoderTest.java @@ -9,8 +9,7 @@ public class NavisFrameDecoderTest extends ProtocolTest { @Test public void testDecodeNtcb() throws Exception { - NavisProtocolDecoder protocolDecoder = new NavisProtocolDecoder(null); - NavisFrameDecoder frameDecoder = new NavisFrameDecoder(protocolDecoder); + NavisFrameDecoder frameDecoder = new NavisFrameDecoder(); verifyFrame(binary( "404e5443010000000000000059009adb2a3e54250000000000ff1500040b0a1008291838001200760ee600000000000000000000000f1500040b0a10ac20703fb1aec23f00000000320149668f430000000000000000000000000000000000000000000000f3808080"), @@ -21,14 +20,9 @@ public class NavisFrameDecoderTest extends ProtocolTest { @Test public void testDecodeFlex10() throws Exception { - NavisProtocolDecoder protocolDecoder = new NavisProtocolDecoder(null); - NavisFrameDecoder frameDecoder = new NavisFrameDecoder(protocolDecoder); + NavisFrameDecoder frameDecoder = new NavisFrameDecoder(); - verifyNull(protocolDecoder, binary( - "404e544301000000c9b5f602130046c52a3e533a383639363936303439373232383235")); - - verifyNull(protocolDecoder, binary( - "404e544301000000aaecf6021300c8712a3e464c4558b00a0a45ffff300a08080f8388")); + frameDecoder.setFlexDataSize(73); verifyFrame(binary( "7e54040000000400000030129957405c000b00632f9857405ccace03021e129101a103000000000000c4005ba3fe3b00000000120046100000000000001aff7f000080bfffff80000080bfffffffff9f"), -- cgit v1.2.3