From 17a9b88676b1cef214f1944e39151c7df8f4e3b0 Mon Sep 17 00:00:00 2001 From: Anton Tananaev Date: Sun, 30 Jan 2022 11:50:17 -0800 Subject: Add crash reconstruction report --- .../traccar/protocol/SuntechProtocolDecoder.java | 97 +++++++++++++++++++++- .../protocol/SuntechProtocolDecoderTest.java | 13 +++ 2 files changed, 108 insertions(+), 2 deletions(-) diff --git a/src/main/java/org/traccar/protocol/SuntechProtocolDecoder.java b/src/main/java/org/traccar/protocol/SuntechProtocolDecoder.java index 2d00ea81e..9d832c84e 100644 --- a/src/main/java/org/traccar/protocol/SuntechProtocolDecoder.java +++ b/src/main/java/org/traccar/protocol/SuntechProtocolDecoder.java @@ -1,5 +1,5 @@ /* - * Copyright 2013 - 2021 Anton Tananaev (anton@traccar.org) + * Copyright 2013 - 2022 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. @@ -17,6 +17,7 @@ package org.traccar.protocol; import io.netty.buffer.ByteBuf; import io.netty.buffer.ByteBufUtil; +import io.netty.buffer.Unpooled; import io.netty.channel.Channel; import org.traccar.BaseProtocolDecoder; import org.traccar.Context; @@ -34,6 +35,11 @@ import java.nio.charset.StandardCharsets; import java.text.DateFormat; import java.text.ParseException; import java.text.SimpleDateFormat; +import java.util.Arrays; +import java.util.Collection; +import java.util.Date; +import java.util.LinkedList; +import java.util.List; import java.util.TimeZone; public class SuntechProtocolDecoder extends BaseProtocolDecoder { @@ -46,6 +52,8 @@ public class SuntechProtocolDecoder extends BaseProtocolDecoder { private boolean includeRpm; private boolean includeTemp; + private ByteBuf crash; + public SuntechProtocolDecoder(Protocol protocol) { super(protocol); } @@ -732,6 +740,89 @@ public class SuntechProtocolDecoder extends BaseProtocolDecoder { return position; } + private Collection decodeCrashReport(Channel channel, SocketAddress remoteAddress, ByteBuf buf) { + + if (buf.getByte(buf.readerIndex() + 3) != ';') { + return null; + } + + String[] values = buf.readCharSequence(23, StandardCharsets.US_ASCII).toString().split(";"); + + DeviceSession deviceSession = getDeviceSession(channel, remoteAddress, values[1]); + if (deviceSession == null) { + return null; + } + + int currentIndex = Integer.parseInt(values[2]); + int totalIndex = Integer.parseInt(values[3]); + + if (crash == null) { + crash = Unpooled.buffer(); + } + + crash.writeBytes(buf.readSlice(buf.readableBytes() - 3)); + + if (currentIndex == totalIndex) { + + LinkedList positions = new LinkedList<>(); + + Date crashTime = new DateBuilder() + .setDate(crash.readUnsignedByte(), crash.readUnsignedByte(), crash.readUnsignedByte()) + .setTime(crash.readUnsignedByte(), crash.readUnsignedByte(), crash.readUnsignedByte()) + .getDate(); + + List times = Arrays.asList( + new Date(crashTime.getTime() - 3000), + new Date(crashTime.getTime() - 2000), + new Date(crashTime.getTime() - 1000), + new Date(crashTime.getTime() + 1000)); + + for (Date time : times) { + + Position position = new Position(getProtocolName()); + position.setDeviceId(deviceSession.getDeviceId()); + + position.setValid(true); + position.setTime(time); + position.setLatitude(crash.readIntLE() * 0.0000001); + position.setLongitude(crash.readIntLE() * 0.0000001); + position.setSpeed(UnitsConverter.knotsFromKph(crash.readUnsignedShort() * 0.01)); + position.setCourse(crash.readUnsignedShort() * 0.01); + + StringBuilder value = new StringBuilder("["); + for (int i = 0; i < 100; i++){ + if (value.length() > 1) { + value.append(","); + } + value.append("["); + value.append(crash.readShortLE()); + value.append(","); + value.append(crash.readShortLE()); + value.append(","); + value.append(crash.readShortLE()); + value.append("]"); + } + value.append("]"); + + position.set(Position.KEY_G_SENSOR, value.toString()); + + positions.add(position); + + } + + crash.release(); + crash = null; + + return positions; + + } else { + + return null; + + } + + } + @Override protected Object decode( Channel channel, SocketAddress remoteAddress, Object msg) throws Exception { @@ -747,7 +838,9 @@ public class SuntechProtocolDecoder extends BaseProtocolDecoder { String[] values = buf.toString(StandardCharsets.US_ASCII).split(";"); prefix = values[0]; - if (prefix.length() < 5) { + if (prefix.equals("CRR")) { + return decodeCrashReport(channel, remoteAddress, buf); + } else if (prefix.length() < 5) { return decodeUniversal(channel, remoteAddress, values); } else if (prefix.endsWith("HTE")) { return decodeTravelReport(channel, remoteAddress, values); diff --git a/src/test/java/org/traccar/protocol/SuntechProtocolDecoderTest.java b/src/test/java/org/traccar/protocol/SuntechProtocolDecoderTest.java index a9720f437..098758728 100644 --- a/src/test/java/org/traccar/protocol/SuntechProtocolDecoderTest.java +++ b/src/test/java/org/traccar/protocol/SuntechProtocolDecoderTest.java @@ -1,5 +1,6 @@ package org.traccar.protocol; +import org.junit.Ignore; import org.junit.Test; import org.traccar.ProtocolTest; import org.traccar.model.Position; @@ -257,4 +258,16 @@ public class SuntechProtocolDecoderTest extends ProtocolTest { } + @Ignore + @Test + public void testDecodeCrash() throws Exception { + + var decoder = new SuntechProtocolDecoder(null); + + verifyAttribute(decoder, binary( + "4352523b303931303030303036333b313b313b303135303b16011c150f0ad82f6c0000000000ae037085fbff7700fd00faff6300f30000006800fb000d007100fa00f32f6c00000000005e044a80fcff6f000301e1ff5d00e900e1ff6400e600f4ff5b00ec000a306c00000000002104248306006c000501fcff5b00e00001006e000101eeff4e00e10022306c00000000005c041a7e00006a00010100005d00f800b5ff7cffdf0050009300fc003b44350d"), + Position.KEY_G_SENSOR, ""); + + } + } -- cgit v1.2.3