From c5833f49feae54b453d667ea02a82fada43a7d46 Mon Sep 17 00:00:00 2001 From: Anton Tananaev Date: Thu, 30 May 2024 18:24:06 -0700 Subject: Add Suntech universal serial type --- .../traccar/protocol/SuntechProtocolDecoder.java | 158 +++++++++++---------- .../protocol/SuntechProtocolDecoderTest.java | 4 + 2 files changed, 89 insertions(+), 73 deletions(-) diff --git a/src/main/java/org/traccar/protocol/SuntechProtocolDecoder.java b/src/main/java/org/traccar/protocol/SuntechProtocolDecoder.java index 53c4a5d02..c9d6f16ef 100644 --- a/src/main/java/org/traccar/protocol/SuntechProtocolDecoder.java +++ b/src/main/java/org/traccar/protocol/SuntechProtocolDecoder.java @@ -295,6 +295,60 @@ public class SuntechProtocolDecoder extends BaseProtocolDecoder { return position; } + private int decodeSerialData(Position position, String[] values, int index) { + + int remaining = Integer.parseInt(values[index++]); + double totalFuel = 0; + while (remaining > 0) { + String attribute = values[index++]; + if (attribute.startsWith("CabAVL")) { + String[] data = attribute.split(","); + double fuel1 = Double.parseDouble(data[2]); + if (fuel1 > 0) { + totalFuel += fuel1; + position.set("fuel1", fuel1); + } + double fuel2 = Double.parseDouble(data[3]); + if (fuel2 > 0) { + totalFuel += fuel2; + position.set("fuel2", fuel2); + } + } else if (attribute.startsWith("GTSL")) { + position.set(Position.KEY_DRIVER_UNIQUE_ID, attribute.split("\\|")[4]); + } else if (attribute.contains("=")) { + String[] pair = attribute.split("="); + if (pair.length >= 2) { + String value = pair[1].trim(); + if (value.contains(".")) { + value = value.substring(0, value.indexOf('.')); + } + switch (pair[0].charAt(0)) { + case 't': + position.set(Position.PREFIX_TEMP + pair[0].charAt(2), Integer.parseInt(value, 16)); + break; + case 'N': + int fuel = Integer.parseInt(value, 16); + totalFuel += fuel; + position.set("fuel" + pair[0].charAt(2), fuel); + break; + case 'Q': + position.set("drivingQuality", Integer.parseInt(value, 16)); + break; + default: + break; + } + } + } else { + position.set("serial", attribute.trim()); + } + remaining -= attribute.length() + 1; + } + if (totalFuel > 0) { + position.set(Position.KEY_FUEL_LEVEL, totalFuel); + } + return index + 1; // checksum + } + private Position decode2356( Channel channel, SocketAddress remoteAddress, String protocol, String[] values) throws ParseException { int index = 0; @@ -371,56 +425,7 @@ public class SuntechProtocolDecoder extends BaseProtocolDecoder { position.set(Position.KEY_ALARM, decodeAlert(Integer.parseInt(values[index++]))); break; case "UEX": - int remaining = Integer.parseInt(values[index++]); - double totalFuel = 0; - while (remaining > 0) { - String attribute = values[index++]; - if (attribute.startsWith("CabAVL")) { - String[] data = attribute.split(","); - double fuel1 = Double.parseDouble(data[2]); - if (fuel1 > 0) { - totalFuel += fuel1; - position.set("fuel1", fuel1); - } - double fuel2 = Double.parseDouble(data[3]); - if (fuel2 > 0) { - totalFuel += fuel2; - position.set("fuel2", fuel2); - } - } else if (attribute.startsWith("GTSL")) { - position.set(Position.KEY_DRIVER_UNIQUE_ID, attribute.split("\\|")[4]); - } else if (attribute.contains("=")) { - String[] pair = attribute.split("="); - if (pair.length >= 2) { - String value = pair[1].trim(); - if (value.contains(".")) { - value = value.substring(0, value.indexOf('.')); - } - switch (pair[0].charAt(0)) { - case 't': - position.set(Position.PREFIX_TEMP + pair[0].charAt(2), Integer.parseInt(value, 16)); - break; - case 'N': - int fuel = Integer.parseInt(value, 16); - totalFuel += fuel; - position.set("fuel" + pair[0].charAt(2), fuel); - break; - case 'Q': - position.set("drivingQuality", Integer.parseInt(value, 16)); - break; - default: - break; - } - } - } else { - position.set("serial", attribute.trim()); - } - remaining -= attribute.length() + 1; - } - if (totalFuel > 0) { - position.set(Position.KEY_FUEL_LEVEL, totalFuel); - } - index += 1; // checksum + index = decodeSerialData(position, values, index); break; default: break; @@ -482,7 +487,8 @@ public class SuntechProtocolDecoder extends BaseProtocolDecoder { String type = values[index++]; - if (!type.equals("STT") && !type.equals("ALT") && !type.equals("BLE") && !type.equals("RES")) { + if (!type.equals("STT") && !type.equals("ALT") && !type.equals("BLE") && !type.equals("RES") + && !type.equals("UEX")) { return null; } @@ -601,34 +607,40 @@ public class SuntechProtocolDecoder extends BaseProtocolDecoder { position.set(Position.KEY_OUTPUT, Integer.parseInt(values[index++])); } - if (type.equals("ALT")) { - if (BitUtil.check(mask, 19)) { - int alertId = Integer.parseInt(values[index++]); - position.set(Position.KEY_ALARM, decodeAlert(alertId)); - } - if (BitUtil.check(mask, 20)) { - position.set("alertModifier", values[index++]); - } - if (BitUtil.check(mask, 21)) { - position.set("alertData", values[index++]); - } - } else { - if (BitUtil.check(mask, 19)) { - position.set("mode", Integer.parseInt(values[index++])); - } - if (BitUtil.check(mask, 20)) { - position.set("reason", Integer.parseInt(values[index++])); - } - if (BitUtil.check(mask, 21)) { - position.set(Position.KEY_INDEX, Integer.parseInt(values[index++])); - } + switch (type) { + case "ALT": + if (BitUtil.check(mask, 19)) { + int alertId = Integer.parseInt(values[index++]); + position.set(Position.KEY_ALARM, decodeAlert(alertId)); + } + if (BitUtil.check(mask, 20)) { + position.set("alertModifier", values[index++]); + } + if (BitUtil.check(mask, 21)) { + position.set("alertData", values[index++]); + } + break; + case "UEX": + index = decodeSerialData(position, values, index); + break; + default: + if (BitUtil.check(mask, 19)) { + position.set("mode", Integer.parseInt(values[index++])); + } + if (BitUtil.check(mask, 20)) { + position.set("reason", Integer.parseInt(values[index++])); + } + if (BitUtil.check(mask, 21)) { + position.set(Position.KEY_INDEX, Integer.parseInt(values[index++])); + } + break; } if (BitUtil.check(mask, 22)) { index += 1; // reserved } - if (BitUtil.check(mask, 23)) { + if (BitUtil.check(mask, 23) && !type.equals("UEX")) { int assignMask = Integer.parseInt(values[index++], 16); for (int i = 0; i <= 30; i++) { if (BitUtil.check(assignMask, i)) { diff --git a/src/test/java/org/traccar/protocol/SuntechProtocolDecoderTest.java b/src/test/java/org/traccar/protocol/SuntechProtocolDecoderTest.java index d656bba13..67fa43dec 100644 --- a/src/test/java/org/traccar/protocol/SuntechProtocolDecoderTest.java +++ b/src/test/java/org/traccar/protocol/SuntechProtocolDecoderTest.java @@ -12,6 +12,10 @@ public class SuntechProtocolDecoderTest extends ProtocolTest { var decoder = inject(new SuntechProtocolDecoder(null)); + verifyAttribute(decoder, buffer( + "UEX;1610020241;03FFFFFF;161;3.0.9;0;20240506;15:52:55;00006697;724;11;4EDA;33;-5.129240;-42.797868;0.00;0.00;11;1;00000001;00000000;24;GTSL|6|1|0|22574684|1|\r\n;A7;;164;0;11.82"), + Position.KEY_DRIVER_UNIQUE_ID, "22574684"); + verifyAttributes(decoder, buffer( "ST410STT;109815653;445;03;16531;724;10;-77;6011;7;16273;724;10;7511;0;0;13903;724;10;6011;0;0;7671;724;10;7111;0;0;16533;724;10;6011;0;0;0;0;0;0;0;0;0;0;0;0;0;0;3.86;0;0098;1;003;;;;;;;;;")); -- cgit v1.2.3