From cdf892cd39c528929284728562beef3220e91cf3 Mon Sep 17 00:00:00 2001 From: Anton Tananaev Date: Sun, 22 Nov 2020 16:41:39 -0800 Subject: Decode fault codes --- .../traccar/protocol/HuaShengProtocolDecoder.java | 231 +++++++++++++-------- .../protocol/HuaShengProtocolDecoderTest.java | 4 + .../traccar/protocol/KhdProtocolDecoderTest.java | 3 + 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 @@ -17,6 +17,10 @@ public class HuaShengProtocolDecoderTest extends ProtocolTest { verifyNull(decoder, binary( "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")); -- cgit v1.2.3