From 0ad9b4c84b5eb4b9b58f8ca45adff99526ae193e Mon Sep 17 00:00:00 2001 From: Matjaž Črnko Date: Sun, 1 Oct 2023 00:06:27 +0200 Subject: Ruptela: Support Heartbeat message type --- src/main/java/org/traccar/protocol/RuptelaProtocolDecoder.java | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/src/main/java/org/traccar/protocol/RuptelaProtocolDecoder.java b/src/main/java/org/traccar/protocol/RuptelaProtocolDecoder.java index 649de7c5c..b381b93f8 100644 --- a/src/main/java/org/traccar/protocol/RuptelaProtocolDecoder.java +++ b/src/main/java/org/traccar/protocol/RuptelaProtocolDecoder.java @@ -51,6 +51,7 @@ public class RuptelaProtocolDecoder extends BaseProtocolDecoder { public static final int MSG_SMS_VIA_GPRS = 8; public static final int MSG_DTCS = 9; public static final int MSG_IDENTIFICATION = 15; + public static final int MSG_HEARTBEAT = 16; public static final int MSG_SET_IO = 17; public static final int MSG_FILES = 37; public static final int MSG_EXTENDED_RECORDS = 68; @@ -388,7 +389,7 @@ public class RuptelaProtocolDecoder extends BaseProtocolDecoder { return null; - } else if (type == MSG_IDENTIFICATION) { + } else if (type == MSG_IDENTIFICATION || type == MSG_HEARTBEAT) { ByteBuf content = Unpooled.buffer(); content.writeByte(1); -- cgit v1.2.3 From 60e9026a968fb639a617670d8b03e052381d5c55 Mon Sep 17 00:00:00 2001 From: Matjaž Črnko Date: Sun, 1 Oct 2023 00:12:02 +0200 Subject: Ruptela: Fix a bug with extended records spanning multiple messages --- src/main/java/org/traccar/protocol/RuptelaProtocolDecoder.java | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/src/main/java/org/traccar/protocol/RuptelaProtocolDecoder.java b/src/main/java/org/traccar/protocol/RuptelaProtocolDecoder.java index b381b93f8..d4f9808ae 100644 --- a/src/main/java/org/traccar/protocol/RuptelaProtocolDecoder.java +++ b/src/main/java/org/traccar/protocol/RuptelaProtocolDecoder.java @@ -243,7 +243,11 @@ public class RuptelaProtocolDecoder extends BaseProtocolDecoder { int currentRecord = BitUtil.to(recordExtension, 4); if (currentRecord > 0 && currentRecord <= mergeRecordCount) { - position = positions.remove(positions.size() - 1); + if (positions.size() == 0) { + getLastLocation(position, null); + } else { + position = positions.remove(positions.size() - 1); + } } } -- cgit v1.2.3 From 630a32e817526735a77b4aa375a3ac39bcf780d8 Mon Sep 17 00:00:00 2001 From: Matjaž Črnko Date: Sun, 1 Oct 2023 01:03:06 +0200 Subject: Ruptela: Anwser with a negative ack on exceptions - this creates a retry delay so that the device does not burn thorough the data. --- .../traccar/protocol/RuptelaProtocolDecoder.java | 157 +++++++++++---------- 1 file changed, 84 insertions(+), 73 deletions(-) diff --git a/src/main/java/org/traccar/protocol/RuptelaProtocolDecoder.java b/src/main/java/org/traccar/protocol/RuptelaProtocolDecoder.java index d4f9808ae..720926db2 100644 --- a/src/main/java/org/traccar/protocol/RuptelaProtocolDecoder.java +++ b/src/main/java/org/traccar/protocol/RuptelaProtocolDecoder.java @@ -227,92 +227,103 @@ public class RuptelaProtocolDecoder extends BaseProtocolDecoder { List positions = new LinkedList<>(); - buf.readUnsignedByte(); // records left - int count = buf.readUnsignedByte(); + try { + buf.readUnsignedByte(); // records left + int count = buf.readUnsignedByte(); - for (int i = 0; i < count; i++) { - Position position = new Position(getProtocolName()); - position.setDeviceId(deviceSession.getDeviceId()); + for (int i = 0; i < count; i++) { + Position position = new Position(getProtocolName()); + position.setDeviceId(deviceSession.getDeviceId()); - position.setTime(new Date(buf.readUnsignedInt() * 1000)); - buf.readUnsignedByte(); // timestamp extension - - if (type == MSG_EXTENDED_RECORDS) { - int recordExtension = buf.readUnsignedByte(); - int mergeRecordCount = BitUtil.from(recordExtension, 4); - int currentRecord = BitUtil.to(recordExtension, 4); - - if (currentRecord > 0 && currentRecord <= mergeRecordCount) { - if (positions.size() == 0) { - getLastLocation(position, null); - } else { - position = positions.remove(positions.size() - 1); + position.setTime(new Date(buf.readUnsignedInt() * 1000)); + buf.readUnsignedByte(); // timestamp extension + + if (type == MSG_EXTENDED_RECORDS) { + int recordExtension = buf.readUnsignedByte(); + int mergeRecordCount = BitUtil.from(recordExtension, 4); + int currentRecord = BitUtil.to(recordExtension, 4); + + if (currentRecord > 0 && currentRecord <= mergeRecordCount) { + if (positions.size() == 0) { + getLastLocation(position, null); + } else { + position = positions.remove(positions.size() - 1); + } } } - } - buf.readUnsignedByte(); // priority (reserved) - - int longitude = buf.readInt(); - int latitude = buf.readInt(); - if (longitude > Integer.MIN_VALUE && latitude > Integer.MIN_VALUE) { - position.setValid(true); - position.setLongitude(longitude / 10000000.0); - position.setLatitude(latitude / 10000000.0); - position.setAltitude(buf.readUnsignedShort() / 10.0); - position.setCourse(buf.readUnsignedShort() / 100.0); - position.set(Position.KEY_SATELLITES, buf.readUnsignedByte()); - position.setSpeed(UnitsConverter.knotsFromKph(buf.readUnsignedShort())); - position.set(Position.KEY_HDOP, buf.readUnsignedByte() / 10.0); - } else { - buf.skipBytes(8); - getLastLocation(position, null); - } + buf.readUnsignedByte(); // priority (reserved) + + int longitude = buf.readInt(); + int latitude = buf.readInt(); + if (longitude > Integer.MIN_VALUE && latitude > Integer.MIN_VALUE) { + position.setValid(true); + position.setLongitude(longitude / 10000000.0); + position.setLatitude(latitude / 10000000.0); + position.setAltitude(buf.readUnsignedShort() / 10.0); + position.setCourse(buf.readUnsignedShort() / 100.0); + position.set(Position.KEY_SATELLITES, buf.readUnsignedByte()); + position.setSpeed(UnitsConverter.knotsFromKph(buf.readUnsignedShort())); + position.set(Position.KEY_HDOP, buf.readUnsignedByte() / 10.0); + } else { + buf.skipBytes(8); + getLastLocation(position, null); + } - if (type == MSG_EXTENDED_RECORDS) { - position.set(Position.KEY_EVENT, buf.readUnsignedShort()); - } else { - position.set(Position.KEY_EVENT, buf.readUnsignedByte()); - } + if (type == MSG_EXTENDED_RECORDS) { + position.set(Position.KEY_EVENT, buf.readUnsignedShort()); + } else { + position.set(Position.KEY_EVENT, buf.readUnsignedByte()); + } - // Read 1 byte data - int valueCount = buf.readUnsignedByte(); - for (int j = 0; j < valueCount; j++) { - int id = type == MSG_EXTENDED_RECORDS ? buf.readUnsignedShort() : buf.readUnsignedByte(); - decodeParameter(position, id, buf, 1); - } + // Read 1 byte data + int valueCount = buf.readUnsignedByte(); + for (int j = 0; j < valueCount; j++) { + int id = type == MSG_EXTENDED_RECORDS ? buf.readUnsignedShort() : buf.readUnsignedByte(); + decodeParameter(position, id, buf, 1); + } - // Read 2 byte data - valueCount = buf.readUnsignedByte(); - for (int j = 0; j < valueCount; j++) { - int id = type == MSG_EXTENDED_RECORDS ? buf.readUnsignedShort() : buf.readUnsignedByte(); - decodeParameter(position, id, buf, 2); - } + // Read 2 byte data + valueCount = buf.readUnsignedByte(); + for (int j = 0; j < valueCount; j++) { + int id = type == MSG_EXTENDED_RECORDS ? buf.readUnsignedShort() : buf.readUnsignedByte(); + decodeParameter(position, id, buf, 2); + } - // Read 4 byte data - valueCount = buf.readUnsignedByte(); - for (int j = 0; j < valueCount; j++) { - int id = type == MSG_EXTENDED_RECORDS ? buf.readUnsignedShort() : buf.readUnsignedByte(); - decodeParameter(position, id, buf, 4); - } + // Read 4 byte data + valueCount = buf.readUnsignedByte(); + for (int j = 0; j < valueCount; j++) { + int id = type == MSG_EXTENDED_RECORDS ? buf.readUnsignedShort() : buf.readUnsignedByte(); + decodeParameter(position, id, buf, 4); + } - // Read 8 byte data - valueCount = buf.readUnsignedByte(); - for (int j = 0; j < valueCount; j++) { - int id = type == MSG_EXTENDED_RECORDS ? buf.readUnsignedShort() : buf.readUnsignedByte(); - decodeParameter(position, id, buf, 8); - } + // Read 8 byte data + valueCount = buf.readUnsignedByte(); + for (int j = 0; j < valueCount; j++) { + int id = type == MSG_EXTENDED_RECORDS ? buf.readUnsignedShort() : buf.readUnsignedByte(); + decodeParameter(position, id, buf, 8); + } - decodeDriver(position, Position.PREFIX_IO + 126, Position.PREFIX_IO + 127); // can driver - decodeDriver(position, Position.PREFIX_IO + 155, Position.PREFIX_IO + 156); // tco driver + decodeDriver(position, Position.PREFIX_IO + 126, Position.PREFIX_IO + 127); // can driver + decodeDriver(position, Position.PREFIX_IO + 155, Position.PREFIX_IO + 156); // tco driver - Long tagIdPart1 = (Long) position.getAttributes().remove(Position.PREFIX_IO + 760); - Long tagIdPart2 = (Long) position.getAttributes().remove(Position.PREFIX_IO + 761); - if (tagIdPart1 != null && tagIdPart2 != null) { - position.set("tagId", Long.toHexString(tagIdPart1) + Long.toHexString(tagIdPart2)); - } + Long tagIdPart1 = (Long) position.getAttributes().remove(Position.PREFIX_IO + 760); + Long tagIdPart2 = (Long) position.getAttributes().remove(Position.PREFIX_IO + 761); + if (tagIdPart1 != null && tagIdPart2 != null) { + position.set("tagId", Long.toHexString(tagIdPart1) + Long.toHexString(tagIdPart2)); + } - positions.add(position); + positions.add(position); + } + } catch (Exception e) { + ByteBuf content = Unpooled.buffer(); + content.writeByte(0); + ByteBuf response = RuptelaProtocolEncoder.encodeContent(0, content); + content.release(); + if (channel != null) { + channel.writeAndFlush(new NetworkMessage(response, remoteAddress)); + } + throw e; } if (channel != null) { -- cgit v1.2.3 From 0867ac8efb8c4b033a9d22ce311ffcf301971b24 Mon Sep 17 00:00:00 2001 From: Matjaž Črnko Date: Wed, 4 Oct 2023 15:37:34 +0200 Subject: Ruptela: remove exception handling. --- .../traccar/protocol/RuptelaProtocolDecoder.java | 157 ++++++++++----------- 1 file changed, 73 insertions(+), 84 deletions(-) diff --git a/src/main/java/org/traccar/protocol/RuptelaProtocolDecoder.java b/src/main/java/org/traccar/protocol/RuptelaProtocolDecoder.java index 720926db2..d4f9808ae 100644 --- a/src/main/java/org/traccar/protocol/RuptelaProtocolDecoder.java +++ b/src/main/java/org/traccar/protocol/RuptelaProtocolDecoder.java @@ -227,103 +227,92 @@ public class RuptelaProtocolDecoder extends BaseProtocolDecoder { List positions = new LinkedList<>(); - try { - buf.readUnsignedByte(); // records left - int count = buf.readUnsignedByte(); - - for (int i = 0; i < count; i++) { - Position position = new Position(getProtocolName()); - position.setDeviceId(deviceSession.getDeviceId()); - - position.setTime(new Date(buf.readUnsignedInt() * 1000)); - buf.readUnsignedByte(); // timestamp extension + buf.readUnsignedByte(); // records left + int count = buf.readUnsignedByte(); - if (type == MSG_EXTENDED_RECORDS) { - int recordExtension = buf.readUnsignedByte(); - int mergeRecordCount = BitUtil.from(recordExtension, 4); - int currentRecord = BitUtil.to(recordExtension, 4); + for (int i = 0; i < count; i++) { + Position position = new Position(getProtocolName()); + position.setDeviceId(deviceSession.getDeviceId()); - if (currentRecord > 0 && currentRecord <= mergeRecordCount) { - if (positions.size() == 0) { - getLastLocation(position, null); - } else { - position = positions.remove(positions.size() - 1); - } + position.setTime(new Date(buf.readUnsignedInt() * 1000)); + buf.readUnsignedByte(); // timestamp extension + + if (type == MSG_EXTENDED_RECORDS) { + int recordExtension = buf.readUnsignedByte(); + int mergeRecordCount = BitUtil.from(recordExtension, 4); + int currentRecord = BitUtil.to(recordExtension, 4); + + if (currentRecord > 0 && currentRecord <= mergeRecordCount) { + if (positions.size() == 0) { + getLastLocation(position, null); + } else { + position = positions.remove(positions.size() - 1); } } + } - buf.readUnsignedByte(); // priority (reserved) - - int longitude = buf.readInt(); - int latitude = buf.readInt(); - if (longitude > Integer.MIN_VALUE && latitude > Integer.MIN_VALUE) { - position.setValid(true); - position.setLongitude(longitude / 10000000.0); - position.setLatitude(latitude / 10000000.0); - position.setAltitude(buf.readUnsignedShort() / 10.0); - position.setCourse(buf.readUnsignedShort() / 100.0); - position.set(Position.KEY_SATELLITES, buf.readUnsignedByte()); - position.setSpeed(UnitsConverter.knotsFromKph(buf.readUnsignedShort())); - position.set(Position.KEY_HDOP, buf.readUnsignedByte() / 10.0); - } else { - buf.skipBytes(8); - getLastLocation(position, null); - } - - if (type == MSG_EXTENDED_RECORDS) { - position.set(Position.KEY_EVENT, buf.readUnsignedShort()); - } else { - position.set(Position.KEY_EVENT, buf.readUnsignedByte()); - } + buf.readUnsignedByte(); // priority (reserved) + + int longitude = buf.readInt(); + int latitude = buf.readInt(); + if (longitude > Integer.MIN_VALUE && latitude > Integer.MIN_VALUE) { + position.setValid(true); + position.setLongitude(longitude / 10000000.0); + position.setLatitude(latitude / 10000000.0); + position.setAltitude(buf.readUnsignedShort() / 10.0); + position.setCourse(buf.readUnsignedShort() / 100.0); + position.set(Position.KEY_SATELLITES, buf.readUnsignedByte()); + position.setSpeed(UnitsConverter.knotsFromKph(buf.readUnsignedShort())); + position.set(Position.KEY_HDOP, buf.readUnsignedByte() / 10.0); + } else { + buf.skipBytes(8); + getLastLocation(position, null); + } - // Read 1 byte data - int valueCount = buf.readUnsignedByte(); - for (int j = 0; j < valueCount; j++) { - int id = type == MSG_EXTENDED_RECORDS ? buf.readUnsignedShort() : buf.readUnsignedByte(); - decodeParameter(position, id, buf, 1); - } + if (type == MSG_EXTENDED_RECORDS) { + position.set(Position.KEY_EVENT, buf.readUnsignedShort()); + } else { + position.set(Position.KEY_EVENT, buf.readUnsignedByte()); + } - // Read 2 byte data - valueCount = buf.readUnsignedByte(); - for (int j = 0; j < valueCount; j++) { - int id = type == MSG_EXTENDED_RECORDS ? buf.readUnsignedShort() : buf.readUnsignedByte(); - decodeParameter(position, id, buf, 2); - } + // Read 1 byte data + int valueCount = buf.readUnsignedByte(); + for (int j = 0; j < valueCount; j++) { + int id = type == MSG_EXTENDED_RECORDS ? buf.readUnsignedShort() : buf.readUnsignedByte(); + decodeParameter(position, id, buf, 1); + } - // Read 4 byte data - valueCount = buf.readUnsignedByte(); - for (int j = 0; j < valueCount; j++) { - int id = type == MSG_EXTENDED_RECORDS ? buf.readUnsignedShort() : buf.readUnsignedByte(); - decodeParameter(position, id, buf, 4); - } + // Read 2 byte data + valueCount = buf.readUnsignedByte(); + for (int j = 0; j < valueCount; j++) { + int id = type == MSG_EXTENDED_RECORDS ? buf.readUnsignedShort() : buf.readUnsignedByte(); + decodeParameter(position, id, buf, 2); + } - // Read 8 byte data - valueCount = buf.readUnsignedByte(); - for (int j = 0; j < valueCount; j++) { - int id = type == MSG_EXTENDED_RECORDS ? buf.readUnsignedShort() : buf.readUnsignedByte(); - decodeParameter(position, id, buf, 8); - } + // Read 4 byte data + valueCount = buf.readUnsignedByte(); + for (int j = 0; j < valueCount; j++) { + int id = type == MSG_EXTENDED_RECORDS ? buf.readUnsignedShort() : buf.readUnsignedByte(); + decodeParameter(position, id, buf, 4); + } - decodeDriver(position, Position.PREFIX_IO + 126, Position.PREFIX_IO + 127); // can driver - decodeDriver(position, Position.PREFIX_IO + 155, Position.PREFIX_IO + 156); // tco driver + // Read 8 byte data + valueCount = buf.readUnsignedByte(); + for (int j = 0; j < valueCount; j++) { + int id = type == MSG_EXTENDED_RECORDS ? buf.readUnsignedShort() : buf.readUnsignedByte(); + decodeParameter(position, id, buf, 8); + } - Long tagIdPart1 = (Long) position.getAttributes().remove(Position.PREFIX_IO + 760); - Long tagIdPart2 = (Long) position.getAttributes().remove(Position.PREFIX_IO + 761); - if (tagIdPart1 != null && tagIdPart2 != null) { - position.set("tagId", Long.toHexString(tagIdPart1) + Long.toHexString(tagIdPart2)); - } + decodeDriver(position, Position.PREFIX_IO + 126, Position.PREFIX_IO + 127); // can driver + decodeDriver(position, Position.PREFIX_IO + 155, Position.PREFIX_IO + 156); // tco driver - positions.add(position); + Long tagIdPart1 = (Long) position.getAttributes().remove(Position.PREFIX_IO + 760); + Long tagIdPart2 = (Long) position.getAttributes().remove(Position.PREFIX_IO + 761); + if (tagIdPart1 != null && tagIdPart2 != null) { + position.set("tagId", Long.toHexString(tagIdPart1) + Long.toHexString(tagIdPart2)); } - } catch (Exception e) { - ByteBuf content = Unpooled.buffer(); - content.writeByte(0); - ByteBuf response = RuptelaProtocolEncoder.encodeContent(0, content); - content.release(); - if (channel != null) { - channel.writeAndFlush(new NetworkMessage(response, remoteAddress)); - } - throw e; + + positions.add(position); } if (channel != null) { -- cgit v1.2.3