aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorAnton Tananaev <anton@traccar.org>2024-04-15 21:34:55 -0700
committerAnton Tananaev <anton@traccar.org>2024-04-15 21:34:55 -0700
commit132f619e996328c6fcb68d824b63edba69c8a2d6 (patch)
tree977a87ef35c898197c481776eb110d2f96f8aa7e
parent9af6b90e51ff8e2a35fcf52381b9800e508a3edd (diff)
downloadtrackermap-server-132f619e996328c6fcb68d824b63edba69c8a2d6.tar.gz
trackermap-server-132f619e996328c6fcb68d824b63edba69c8a2d6.tar.bz2
trackermap-server-132f619e996328c6fcb68d824b63edba69c8a2d6.zip
Handle Snapper concatenated packet
-rw-r--r--src/main/java/org/traccar/protocol/SnapperProtocolDecoder.java163
-rw-r--r--src/test/java/org/traccar/protocol/SnapperProtocolDecoderTest.java4
2 files changed, 100 insertions, 67 deletions
diff --git a/src/main/java/org/traccar/protocol/SnapperProtocolDecoder.java b/src/main/java/org/traccar/protocol/SnapperProtocolDecoder.java
index 3119e347e..315731c20 100644
--- a/src/main/java/org/traccar/protocol/SnapperProtocolDecoder.java
+++ b/src/main/java/org/traccar/protocol/SnapperProtocolDecoder.java
@@ -33,6 +33,7 @@ import java.net.SocketAddress;
import java.nio.ByteBuffer;
import java.nio.charset.StandardCharsets;
import java.text.DateFormat;
+import java.text.ParseException;
import java.text.SimpleDateFormat;
import java.util.TimeZone;
@@ -77,6 +78,68 @@ public class SnapperProtocolDecoder extends BaseProtocolDecoder {
}
}
+ private void decodeEvents(Position position, ByteBuf buf) {
+
+ position.set(Position.KEY_EVENT, buf.readUnsignedByte());
+ buf.readUnsignedByte(); // info 1
+ buf.readUnsignedByte(); // info 2
+ buf.readUnsignedIntLE(); // timestamp
+ buf.readUnsignedByte(); // timezone
+ }
+
+ private void decodeTechInfo(Position position, ByteBuf buf) {
+
+ for (int i = 0; i < 5; i++) {
+ buf.readUnsignedByte(); // index
+ int type = buf.readUnsignedByte();
+ switch (type) {
+ case 0x00:
+ position.set(Position.KEY_POWER, buf.readUnsignedByte() * 0.1);
+ position.set(Position.KEY_DEVICE_TEMP, buf.readByte());
+ position.set(Position.KEY_RSSI, buf.readUnsignedByte());
+ break;
+ case 0x01:
+ position.set("interiorTemp", buf.readByte());
+ position.set("engineTemp", buf.readByte());
+ buf.readUnsignedByte(); // reserved
+ break;
+ default:
+ buf.skipBytes(3);
+ break;
+ }
+ }
+ }
+
+ private void decodeGpsData(Position position, ByteBuf buf) throws ParseException {
+
+ String content = buf.readCharSequence(buf.readableBytes(), StandardCharsets.US_ASCII).toString();
+ JsonObject json = Json.createReader(new StringReader(content)).readObject();
+
+ DateFormat dateFormat = new SimpleDateFormat("ddMMyyHHmmss");
+ dateFormat.setTimeZone(TimeZone.getTimeZone("UTC"));
+ position.setTime(dateFormat.parse(json.getString("d") + json.getString("t").split("\\.")[0]));
+
+ String lat = json.getString("la");
+ position.setLatitude(Integer.parseInt(lat.substring(0, 2)) + Double.parseDouble(lat.substring(2)) / 60);
+ String lon = json.getString("lo");
+ position.setLongitude(Integer.parseInt(lon.substring(0, 3)) + Double.parseDouble(lon.substring(3)) / 60);
+
+ int flags = Integer.parseInt(json.getString("f"), 16);
+ position.setValid(BitUtil.check(flags, 1));
+ if (!BitUtil.check(flags, 6)) {
+ position.setLatitude(-position.getLatitude());
+ }
+ if (!BitUtil.check(flags, 7)) {
+ position.setLongitude(-position.getLongitude());
+ }
+
+ position.setAltitude(Double.parseDouble(json.getString("a")));
+ position.setSpeed(Double.parseDouble(json.getString("s")));
+ position.setCourse(Double.parseDouble(json.getString("c")));
+
+ position.set(Position.KEY_SATELLITES, Integer.parseInt(json.getString("sv")));
+ }
+
@Override
protected Object decode(
Channel channel, SocketAddress remoteAddress, Object msg) throws Exception {
@@ -94,7 +157,7 @@ public class SnapperProtocolDecoder extends BaseProtocolDecoder {
}
buf.readUnsignedShortLE(); // encryption
- buf.readUnsignedIntLE(); // length
+ int length = buf.readIntLE();
buf.readUnsignedByte(); // flags
buf.readUnsignedMediumLE(); // reserved
int index = buf.readUnsignedShortLE();
@@ -110,71 +173,41 @@ public class SnapperProtocolDecoder extends BaseProtocolDecoder {
Position position = new Position(getProtocolName());
position.setDeviceId(deviceSession.getDeviceId());
- if (type == MSG_SEND_EVENTS) {
-
- position.set(Position.KEY_EVENT, buf.readUnsignedByte());
- buf.readUnsignedByte(); // info 1
- buf.readUnsignedByte(); // info 2
- getLastLocation(position, null); // TODO read timestamp
- return position;
-
- } else if (type == MSG_SEND_TECH_INFO) {
-
- buf.readUnsignedByte(); // index
- int subtype = buf.readUnsignedByte();
- switch (subtype) {
- case 0x00:
- position.set(Position.KEY_POWER, buf.readUnsignedByte() * 0.1);
- position.set(Position.KEY_DEVICE_TEMP, buf.readByte());
- position.set(Position.KEY_RSSI, buf.readUnsignedByte());
- break;
- case 0x01:
- position.set("interiorTemp", buf.readByte());
- position.set("engineTemp", buf.readByte());
- default:
- break;
- }
- getLastLocation(position, null);
- return position;
-
- } else if (type == MSG_SEND_GPS_DATA) {
-
- String content = buf.readCharSequence(buf.readableBytes(), StandardCharsets.US_ASCII).toString();
- JsonObject json = Json.createReader(new StringReader(content)).readObject();
-
- //{"f":"DE","t":"092304.01","d":"110813","la":"5117.6370",
- // "lo":"01655.3959","a":"00166.6","s":"","c":"","sv":"08","p":"01.6"}
-
- DateFormat dateFormat = new SimpleDateFormat("ddMMyyHHmmss.SS");
- dateFormat.setTimeZone(TimeZone.getTimeZone("UTC"));
- position.setTime(dateFormat.parse(json.getString("d") + json.getString("t")));
-
- String lat = json.getString("la");
- position.setLatitude(Integer.parseInt(lat.substring(0, 2)) + Double.parseDouble(lat.substring(2)) / 60);
- String lon = json.getString("lo");
- position.setLongitude(Integer.parseInt(lon.substring(0, 3)) + Double.parseDouble(lon.substring(3)) / 60);
-
- int flags = Integer.parseInt(json.getString("f"));
- position.setValid(BitUtil.check(flags, 1));
- if (!BitUtil.check(flags, 6)) {
- position.setLatitude(-position.getLatitude());
- }
- if (!BitUtil.check(flags, 7)) {
- position.setLongitude(-position.getLongitude());
- }
-
- position.setAltitude(Double.parseDouble(json.getString("a")));
- position.setSpeed(Double.parseDouble(json.getString("s")));
- position.setCourse(Double.parseDouble(json.getString("c")));
-
- position.set(Position.KEY_SATELLITES, Integer.parseInt(json.getString("sv")));
-
- return position;
-
+ switch (type) {
+ case MSG_SEND_EVENTS:
+ decodeEvents(position, buf);
+ getLastLocation(position, null); // TODO read timestamp
+ return position;
+ case MSG_SEND_TECH_INFO:
+ decodeTechInfo(position, buf);
+ getLastLocation(position, null);
+ return position;
+ case MSG_SEND_GPS_DATA:
+ decodeGpsData(position, buf.readSlice(length));
+ return position;
+ case MSG_SEND_CONCATENATED_PACKET:
+ int count = buf.readUnsignedShortLE();
+ for (int i = 0; i < count; i++) {
+ int partType = buf.readUnsignedShortLE();
+ int partLength = buf.readUnsignedShortLE();
+ switch (partType) {
+ case MSG_SEND_EVENTS:
+ decodeEvents(position, buf);
+ break;
+ case MSG_SEND_TECH_INFO:
+ decodeTechInfo(position, buf);
+ break;
+ case MSG_SEND_GPS_DATA:
+ decodeGpsData(position, buf.readSlice(partLength));
+ break;
+ default:
+ buf.skipBytes(partLength);
+ break;
+ }
+ }
+ default:
+ return null;
}
-
-
- return null;
}
}
diff --git a/src/test/java/org/traccar/protocol/SnapperProtocolDecoderTest.java b/src/test/java/org/traccar/protocol/SnapperProtocolDecoderTest.java
index c334565f9..103f1f48e 100644
--- a/src/test/java/org/traccar/protocol/SnapperProtocolDecoderTest.java
+++ b/src/test/java/org/traccar/protocol/SnapperProtocolDecoderTest.java
@@ -13,8 +13,8 @@ public class SnapperProtocolDecoderTest extends ProtocolTest {
verifyNull(decoder, binary(
"4b0341a6b0c608000040000005000000000000007d5e14010068656c6c6f"));
- // data sample
- // {"f":"DE","t":"092304.01","d":"110813","la":"5117.6370","lo":"01655.3959","a":"00166.6","s":"","c":"","sv":"08","p":"01.6"}
+ verifyNull(decoder, binary(
+ "4b044daff87aff5b8aad00007b010000000013ea0c006837000500210008003e000058c48fa94823001900000080000200018080000002deff0f0003404000000400000034008c007b2273223a22303034303438222c226332223a2230303030303030303030303030303030222c226132223a2230303030303030303030303030303030222c226f223a2230303030222c2274223a2230303030222c227a223a223030222c2277223a223030222c2272223a222d222c226d223a223030303030303030222c2262223a223030303030303030227d320079007b2266223a224445222c2274223a22303932383336222c2264223a22313530343234222c226c61223a22353334312e34333732222c226c6f223a2230303935342e30373036222c2261223a22382e34222c2273223a22302e3030222c2263223a2232362e3036222c227376223a223135222c2270223a22227d33003f007b2263223a22323632222c226e223a223033222c2262223a5b7b226c223a2232423334222c2263223a223030303041313231222c2273223a223132227d5d7d"));
}