aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--src/main/java/org/traccar/protocol/HuaShengProtocolDecoder.java231
-rw-r--r--src/test/java/org/traccar/protocol/HuaShengProtocolDecoderTest.java4
-rw-r--r--src/test/java/org/traccar/protocol/KhdProtocolDecoderTest.java3
3 files changed, 152 insertions, 86 deletions
diff --git a/src/main/java/org/traccar/protocol/HuaShengProtocolDecoder.java b/src/main/java/org/traccar/protocol/HuaShengProtocolDecoder.java
index f1d146bda..7b0eed943 100644
--- a/src/main/java/org/traccar/protocol/HuaShengProtocolDecoder.java
+++ b/src/main/java/org/traccar/protocol/HuaShengProtocolDecoder.java
@@ -16,6 +16,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;
@@ -43,6 +44,8 @@ public class HuaShengProtocolDecoder extends BaseProtocolDecoder {
public static final int MSG_POSITION_RSP = 0xFF01;
public static final int MSG_LOGIN = 0xAA02;
public static final int MSG_LOGIN_RSP = 0xFF03;
+ public static final int MSG_UPFAULT = 0xAA12;
+ public static final int MSG_UPFAULT_RSP = 0xFF13;
public static final int MSG_HSO_REQ = 0x0002;
public static final int MSG_HSO_RSP = 0x0003;
@@ -123,111 +126,167 @@ public class HuaShengProtocolDecoder extends BaseProtocolDecoder {
sendResponse(channel, MSG_HSO_RSP, index, null);
- } else if (type == MSG_POSITION) {
+ } else if (type == MSG_UPFAULT) {
- DeviceSession deviceSession = getDeviceSession(channel, remoteAddress);
- if (deviceSession == null) {
- return null;
- }
+ return decodeFaultCodes(channel, remoteAddress, buf, index);
- Position position = new Position(getProtocolName());
- position.setDeviceId(deviceSession.getDeviceId());
+ } else if (type == MSG_POSITION) {
- int status = buf.readUnsignedShort();
+ return decodePosition(channel, remoteAddress, buf, index);
- position.setValid(BitUtil.check(status, 15));
+ }
- position.set(Position.KEY_STATUS, status);
- position.set(Position.KEY_IGNITION, BitUtil.check(status, 14));
+ return null;
+ }
- int event = buf.readUnsignedShort();
- position.set(Position.KEY_ALARM, decodeAlarm(event));
- position.set(Position.KEY_EVENT, event);
+ private Position decodeFaultCodes(
+ Channel channel, SocketAddress remoteAddress, ByteBuf buf, int index) {
- String time = buf.readCharSequence(12, StandardCharsets.US_ASCII).toString();
+ DeviceSession deviceSession = getDeviceSession(channel, remoteAddress);
+ if (deviceSession == null) {
+ return null;
+ }
- DateBuilder dateBuilder = new DateBuilder()
- .setYear(Integer.parseInt(time.substring(0, 2)))
- .setMonth(Integer.parseInt(time.substring(2, 4)))
- .setDay(Integer.parseInt(time.substring(4, 6)))
- .setHour(Integer.parseInt(time.substring(6, 8)))
- .setMinute(Integer.parseInt(time.substring(8, 10)))
- .setSecond(Integer.parseInt(time.substring(10, 12)));
- position.setTime(dateBuilder.getDate());
+ Position position = new Position(getProtocolName());
+ position.setDeviceId(deviceSession.getDeviceId());
- position.setLongitude(buf.readInt() * 0.00001);
- position.setLatitude(buf.readInt() * 0.00001);
+ getLastLocation(position, null);
- position.setSpeed(UnitsConverter.knotsFromKph(buf.readUnsignedShort()));
- position.setCourse(buf.readUnsignedShort());
- position.setAltitude(buf.readUnsignedShort());
+ buf.readUnsignedShort(); // type
+ buf.readUnsignedShort(); // length
- position.set(Position.KEY_ODOMETER, buf.readUnsignedShort() * 1000);
+ StringBuilder codes = new StringBuilder();
+ while (buf.readableBytes() > 2) {
+ String value = ByteBufUtil.hexDump(buf.readSlice(2));
+ int digit = Integer.parseInt(value.substring(0, 1), 16);
+ char prefix;
+ switch (digit >> 2) {
+ default:
+ prefix = 'P';
+ break;
+ case 1:
+ prefix = 'C';
+ break;
+ case 2:
+ prefix = 'B';
+ break;
+ case 3:
+ prefix = 'U';
+ break;
+ }
+ codes.append(prefix).append(digit % 4).append(value.substring(1));
+ if (buf.readableBytes() > 2) {
+ codes.append(' ');
+ }
+ }
- Network network = new Network();
+ position.set(Position.KEY_DTCS, codes.toString());
- while (buf.readableBytes() > 4) {
- int subtype = buf.readUnsignedShort();
- int length = buf.readUnsignedShort() - 4;
- switch (subtype) {
- case 0x0001:
- position.set(Position.KEY_COOLANT_TEMP, buf.readUnsignedByte() - 40);
- position.set(Position.KEY_RPM, buf.readUnsignedShort());
- position.set("averageSpeed", buf.readUnsignedByte());
- buf.readUnsignedShort(); // interval fuel consumption
- position.set(Position.KEY_FUEL_CONSUMPTION, buf.readUnsignedShort() * 0.01);
- position.set(Position.KEY_ODOMETER_TRIP, buf.readUnsignedShort());
- position.set(Position.KEY_POWER, buf.readUnsignedShort() * 0.01);
- position.set(Position.KEY_FUEL_LEVEL, buf.readUnsignedByte() * 0.4);
- buf.readUnsignedInt(); // trip id
- break;
- case 0x0005:
- position.set(Position.KEY_RSSI, buf.readUnsignedByte());
- position.set(Position.KEY_HDOP, buf.readUnsignedByte());
- buf.readUnsignedInt(); // run time
- break;
- case 0x0009:
- position.set(
- Position.KEY_VIN, buf.readCharSequence(length, StandardCharsets.US_ASCII).toString());
- break;
- case 0x0011:
- position.set(Position.KEY_HOURS, buf.readUnsignedInt() * 0.05);
- break;
- case 0x0020:
- String[] cells = buf.readCharSequence(
- length, StandardCharsets.US_ASCII).toString().split("\\+");
- for (String cell : cells) {
- String[] values = cell.split("@");
- network.addCellTower(CellTower.from(
- Integer.parseInt(values[0]), Integer.parseInt(values[1]),
- Integer.parseInt(values[2], 16), Integer.parseInt(values[3], 16)));
- }
- break;
- case 0x0021:
- String[] points = buf.readCharSequence(
- length, StandardCharsets.US_ASCII).toString().split("\\+");
- for (String point : points) {
- String[] values = point.split("@");
- network.addWifiAccessPoint(WifiAccessPoint.from(values[0], Integer.parseInt(values[1])));
- }
- break;
- default:
- buf.skipBytes(length);
- break;
- }
- }
+ return position;
+ }
- if (network.getCellTowers() != null || network.getWifiAccessPoints() != null) {
- position.setNetwork(network);
- }
+ private Position decodePosition(
+ Channel channel, SocketAddress remoteAddress, ByteBuf buf, int index) {
- sendResponse(channel, MSG_POSITION_RSP, index, null);
+ DeviceSession deviceSession = getDeviceSession(channel, remoteAddress);
+ if (deviceSession == null) {
+ return null;
+ }
- return position;
+ Position position = new Position(getProtocolName());
+ position.setDeviceId(deviceSession.getDeviceId());
+
+ int status = buf.readUnsignedShort();
+
+ position.setValid(BitUtil.check(status, 15));
+
+ position.set(Position.KEY_STATUS, status);
+ position.set(Position.KEY_IGNITION, BitUtil.check(status, 14));
+
+ int event = buf.readUnsignedShort();
+ position.set(Position.KEY_ALARM, decodeAlarm(event));
+ position.set(Position.KEY_EVENT, event);
+
+ String time = buf.readCharSequence(12, StandardCharsets.US_ASCII).toString();
+
+ DateBuilder dateBuilder = new DateBuilder()
+ .setYear(Integer.parseInt(time.substring(0, 2)))
+ .setMonth(Integer.parseInt(time.substring(2, 4)))
+ .setDay(Integer.parseInt(time.substring(4, 6)))
+ .setHour(Integer.parseInt(time.substring(6, 8)))
+ .setMinute(Integer.parseInt(time.substring(8, 10)))
+ .setSecond(Integer.parseInt(time.substring(10, 12)));
+ position.setTime(dateBuilder.getDate());
+
+ position.setLongitude(buf.readInt() * 0.00001);
+ position.setLatitude(buf.readInt() * 0.00001);
+
+ position.setSpeed(UnitsConverter.knotsFromKph(buf.readUnsignedShort()));
+ position.setCourse(buf.readUnsignedShort());
+ position.setAltitude(buf.readUnsignedShort());
+
+ position.set(Position.KEY_ODOMETER, buf.readUnsignedShort() * 1000);
+
+ Network network = new Network();
+
+ while (buf.readableBytes() > 4) {
+ int subtype = buf.readUnsignedShort();
+ int length = buf.readUnsignedShort() - 4;
+ switch (subtype) {
+ case 0x0001:
+ position.set(Position.KEY_COOLANT_TEMP, buf.readUnsignedByte() - 40);
+ position.set(Position.KEY_RPM, buf.readUnsignedShort());
+ position.set("averageSpeed", buf.readUnsignedByte());
+ buf.readUnsignedShort(); // interval fuel consumption
+ position.set(Position.KEY_FUEL_CONSUMPTION, buf.readUnsignedShort() * 0.01);
+ position.set(Position.KEY_ODOMETER_TRIP, buf.readUnsignedShort());
+ position.set(Position.KEY_POWER, buf.readUnsignedShort() * 0.01);
+ position.set(Position.KEY_FUEL_LEVEL, buf.readUnsignedByte() * 0.4);
+ buf.readUnsignedInt(); // trip id
+ break;
+ case 0x0005:
+ position.set(Position.KEY_RSSI, buf.readUnsignedByte());
+ position.set(Position.KEY_HDOP, buf.readUnsignedByte());
+ buf.readUnsignedInt(); // run time
+ break;
+ case 0x0009:
+ position.set(
+ Position.KEY_VIN, buf.readCharSequence(length, StandardCharsets.US_ASCII).toString());
+ break;
+ case 0x0011:
+ position.set(Position.KEY_HOURS, buf.readUnsignedInt() * 0.05);
+ break;
+ case 0x0020:
+ String[] cells = buf.readCharSequence(
+ length, StandardCharsets.US_ASCII).toString().split("\\+");
+ for (String cell : cells) {
+ String[] values = cell.split("@");
+ network.addCellTower(CellTower.from(
+ Integer.parseInt(values[0]), Integer.parseInt(values[1]),
+ Integer.parseInt(values[2], 16), Integer.parseInt(values[3], 16)));
+ }
+ break;
+ case 0x0021:
+ String[] points = buf.readCharSequence(
+ length, StandardCharsets.US_ASCII).toString().split("\\+");
+ for (String point : points) {
+ String[] values = point.split("@");
+ network.addWifiAccessPoint(WifiAccessPoint.from(values[0], Integer.parseInt(values[1])));
+ }
+ break;
+ default:
+ buf.skipBytes(length);
+ break;
+ }
+ }
+ if (network.getCellTowers() != null || network.getWifiAccessPoints() != null) {
+ position.setNetwork(network);
}
- return null;
+ sendResponse(channel, MSG_POSITION_RSP, index, null);
+
+ return position;
}
}
diff --git a/src/test/java/org/traccar/protocol/HuaShengProtocolDecoderTest.java b/src/test/java/org/traccar/protocol/HuaShengProtocolDecoderTest.java
index 9ba31e08a..7348ec547 100644
--- a/src/test/java/org/traccar/protocol/HuaShengProtocolDecoderTest.java
+++ b/src/test/java/org/traccar/protocol/HuaShengProtocolDecoderTest.java
@@ -18,6 +18,10 @@ public class HuaShengProtocolDecoderTest extends ProtocolTest {
"c000000077aa0200000000000e000100143347315f48312e315f56312e30372e54000300133335353835353035303434303635380004000b3531323030303000050005010006000400070004000800050000090018383936313032353431343533333239313833360d000a000f796573696e7465726e6574c0"));
verifyAttribute(decoder, binary(
+ "C00000001CAA120000000000020001001001000200030043008200C100C0"),
+ Position.KEY_DTCS, "P0100 P0200 P0300 C0300 B0200 U0100");
+
+ verifyAttribute(decoder, binary(
"c000000049aa0000000000028e8800000032303038323630373534323800e1d47fffcd163d0000000000f30000000100157703f8000046000000000aade0ffffffff0011000800000496c0"),
Position.KEY_HOURS, 58.7);
diff --git a/src/test/java/org/traccar/protocol/KhdProtocolDecoderTest.java b/src/test/java/org/traccar/protocol/KhdProtocolDecoderTest.java
index 62b6070b6..aa80c1cd9 100644
--- a/src/test/java/org/traccar/protocol/KhdProtocolDecoderTest.java
+++ b/src/test/java/org/traccar/protocol/KhdProtocolDecoderTest.java
@@ -10,6 +10,9 @@ public class KhdProtocolDecoderTest extends ProtocolTest {
KhdProtocolDecoder decoder = new KhdProtocolDecoder(null);
+ verifyPosition(decoder, binary(
+ "2929a3003420b2ab46201115115601800115110350825100000133fb00df4bfdff0d000000000000000900000c180887d9ffffffffffff960d"));
+
verifyNull(decoder, binary(
"2929b1000605162935b80d"));