diff options
author | Iván Ávalos <avalos@disroot.org> | 2024-03-07 22:59:12 -0600 |
---|---|---|
committer | Iván Ávalos <avalos@disroot.org> | 2024-03-07 22:59:12 -0600 |
commit | 00d3ddf7b5e335a5112a28a547c4c9ec2c3bd1d2 (patch) | |
tree | a02ecb75a8533194314d32c0c667520bff5e919d /src/main/java/org/traccar/protocol/HuabaoProtocolDecoder.java | |
parent | 8e1bc703227a875c20e453704d774ce5772f2621 (diff) | |
parent | 75b404db5c790bf37c05fabf1cbbd2027ad1db25 (diff) | |
download | trackermap-server-00d3ddf7b5e335a5112a28a547c4c9ec2c3bd1d2.tar.gz trackermap-server-00d3ddf7b5e335a5112a28a547c4c9ec2c3bd1d2.tar.bz2 trackermap-server-00d3ddf7b5e335a5112a28a547c4c9ec2c3bd1d2.zip |
Merge branch 'master' of https://github.com/traccar/traccar
Diffstat (limited to 'src/main/java/org/traccar/protocol/HuabaoProtocolDecoder.java')
-rw-r--r-- | src/main/java/org/traccar/protocol/HuabaoProtocolDecoder.java | 283 |
1 files changed, 266 insertions, 17 deletions
diff --git a/src/main/java/org/traccar/protocol/HuabaoProtocolDecoder.java b/src/main/java/org/traccar/protocol/HuabaoProtocolDecoder.java index d0bbeebb5..0a8540543 100644 --- a/src/main/java/org/traccar/protocol/HuabaoProtocolDecoder.java +++ b/src/main/java/org/traccar/protocol/HuabaoProtocolDecoder.java @@ -1,5 +1,5 @@ /* - * Copyright 2015 - 2022 Anton Tananaev (anton@traccar.org) + * Copyright 2015 - 2023 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. @@ -131,7 +131,10 @@ public class HuabaoProtocolDecoder extends BaseProtocolDecoder { if (BitUtil.check(value, 8)) { return Position.ALARM_POWER_OFF; } - if (BitUtil.check(value, 17)) { + if (BitUtil.check(value, 15)) { + return Position.ALARM_VIBRATION; + } + if (BitUtil.check(value, 16) || BitUtil.check(value, 17)) { return Position.ALARM_TAMPERING; } if (BitUtil.check(value, 20)) { @@ -140,7 +143,7 @@ public class HuabaoProtocolDecoder extends BaseProtocolDecoder { if (BitUtil.check(value, 28)) { return Position.ALARM_MOVEMENT; } - if (BitUtil.check(value, 29)) { + if (BitUtil.check(value, 29) || BitUtil.check(value, 30)) { return Position.ALARM_ACCIDENT; } return null; @@ -169,7 +172,7 @@ public class HuabaoProtocolDecoder extends BaseProtocolDecoder { } else { long imei = id.getUnsignedShort(0); imei = (imei << 32) + id.getUnsignedInt(2); - return String.valueOf(imei); + return String.valueOf(imei) + Checksum.luhn(imei); } } @@ -294,6 +297,8 @@ public class HuabaoProtocolDecoder extends BaseProtocolDecoder { } else if (type == MSG_TRANSPARENT) { + sendGeneralResponse(channel, remoteAddress, id, type, index); + return decodeTransparent(deviceSession, buf); } @@ -327,6 +332,16 @@ public class HuabaoProtocolDecoder extends BaseProtocolDecoder { case 0x03: position.set(Position.KEY_OBD_SPEED, buf.readUnsignedShort() * 0.1); break; + case 0x56: + buf.readUnsignedByte(); // power level + position.set(Position.KEY_BATTERY_LEVEL, buf.readUnsignedByte()); + break; + case 0x61: + position.set(Position.KEY_POWER, buf.readUnsignedShort() * 0.01); + break; + case 0x69: + position.set(Position.KEY_BATTERY, buf.readUnsignedShort() * 0.01); + break; case 0x80: position.set(Position.KEY_OBD_SPEED, buf.readUnsignedByte()); break; @@ -388,6 +403,7 @@ public class HuabaoProtocolDecoder extends BaseProtocolDecoder { int status = buf.readInt(); position.set(Position.KEY_IGNITION, BitUtil.check(status, 0)); + position.set(Position.KEY_MOTION, BitUtil.check(status, 4)); position.set(Position.KEY_BLOCKED, BitUtil.check(status, 10)); position.set(Position.KEY_CHARGE, BitUtil.check(status, 26)); @@ -448,6 +464,7 @@ public class HuabaoProtocolDecoder extends BaseProtocolDecoder { int subtype = buf.readUnsignedByte(); int length = buf.readUnsignedByte(); int endIndex = buf.readerIndex() + length; + String stringValue; switch (subtype) { case 0x01: position.set(Position.KEY_ODOMETER, buf.readUnsignedInt() * 100); @@ -455,8 +472,12 @@ public class HuabaoProtocolDecoder extends BaseProtocolDecoder { case 0x02: position.set(Position.KEY_FUEL_LEVEL, buf.readUnsignedShort() * 0.1); break; + case 0x25: + position.set(Position.KEY_INPUT, buf.readUnsignedInt()); + break; case 0x2b: - position.set(Position.KEY_FUEL_CONSUMPTION, buf.readUnsignedInt()); + position.set(Position.PREFIX_ADC + 1, buf.readUnsignedShort()); + position.set(Position.PREFIX_ADC + 2, buf.readUnsignedShort()); break; case 0x30: position.set(Position.KEY_RSSI, buf.readUnsignedByte()); @@ -465,12 +486,75 @@ public class HuabaoProtocolDecoder extends BaseProtocolDecoder { position.set(Position.KEY_SATELLITES, buf.readUnsignedByte()); break; case 0x33: - String sentence = buf.readCharSequence(length, StandardCharsets.US_ASCII).toString(); - if (sentence.startsWith("*M00")) { - String lockStatus = sentence.substring(8, 8 + 7); + stringValue = buf.readCharSequence(length, StandardCharsets.US_ASCII).toString(); + if (stringValue.startsWith("*M00")) { + String lockStatus = stringValue.substring(8, 8 + 7); position.set(Position.KEY_BATTERY, Integer.parseInt(lockStatus.substring(2, 5)) * 0.01); } break; + case 0x56: + position.set(Position.KEY_BATTERY_LEVEL, buf.readUnsignedByte() * 10); + buf.readUnsignedByte(); // reserved + break; + case 0x57: + int alarm = buf.readUnsignedShort(); + position.set(Position.KEY_ALARM, BitUtil.check(alarm, 8) ? Position.ALARM_ACCELERATION : null); + position.set(Position.KEY_ALARM, BitUtil.check(alarm, 9) ? Position.ALARM_BRAKING : null); + position.set(Position.KEY_ALARM, BitUtil.check(alarm, 10) ? Position.ALARM_CORNERING : null); + buf.readUnsignedShort(); // external switch state + buf.skipBytes(4); // reserved + break; + case 0x60: + int event = buf.readUnsignedShort(); + position.set(Position.KEY_EVENT, event); + if (event >= 0x0061 && event <= 0x0066) { + buf.skipBytes(6); // lock id + stringValue = buf.readCharSequence(8, StandardCharsets.US_ASCII).toString(); + position.set(Position.KEY_DRIVER_UNIQUE_ID, stringValue); + } + break; + case 0x63: + for (int i = 1; i <= length / 11; i++) { + position.set("lock" + i + "Id", ByteBufUtil.hexDump(buf.readSlice(6))); + position.set("lock" + i + "Battery", buf.readUnsignedShort() * 0.001); + position.set("lock" + i + "Seal", buf.readUnsignedByte() == 0x31); + buf.readUnsignedByte(); // physical state + buf.readUnsignedByte(); // rssi + } + break; + case 0x64: + buf.readUnsignedInt(); // alarm serial number + buf.readUnsignedByte(); // alarm status + position.set("adasAlarm", buf.readUnsignedByte()); + break; + case 0x65: + buf.readUnsignedInt(); // alarm serial number + buf.readUnsignedByte(); // alarm status + position.set("dmsAlarm", buf.readUnsignedByte()); + break; + case 0x70: + buf.readUnsignedInt(); // alarm serial number + buf.readUnsignedByte(); // alarm status + switch (buf.readUnsignedByte()) { + case 0x01: + position.set(Position.KEY_ALARM, Position.ALARM_ACCELERATION); + break; + case 0x02: + position.set(Position.KEY_ALARM, Position.ALARM_BRAKING); + break; + case 0x03: + position.set(Position.KEY_ALARM, Position.ALARM_CORNERING); + break; + case 0x16: + position.set(Position.KEY_ALARM, Position.ALARM_ACCIDENT); + break; + default: + break; + } + break; + case 0x69: + position.set(Position.KEY_BATTERY, buf.readUnsignedShort() * 0.01); + break; case 0x80: buf.readUnsignedByte(); // content endIndex = buf.writerIndex() - 2; @@ -492,8 +576,8 @@ public class HuabaoProtocolDecoder extends BaseProtocolDecoder { break; case 0x94: if (length > 0) { - position.set( - Position.KEY_VIN, buf.readCharSequence(length, StandardCharsets.US_ASCII).toString()); + stringValue = buf.readCharSequence(length, StandardCharsets.US_ASCII).toString(); + position.set(Position.KEY_VIN, stringValue); } break; case 0xA7: @@ -503,6 +587,14 @@ public class HuabaoProtocolDecoder extends BaseProtocolDecoder { case 0xAC: position.set(Position.KEY_ODOMETER, buf.readUnsignedInt()); break; + case 0xBC: + stringValue = buf.readCharSequence(length, StandardCharsets.US_ASCII).toString(); + position.set("driver", stringValue.trim()); + break; + case 0xBD: + stringValue = buf.readCharSequence(length, StandardCharsets.US_ASCII).toString(); + position.set(Position.KEY_DRIVER_UNIQUE_ID, stringValue); + break; case 0xD0: long userStatus = buf.readUnsignedInt(); if (BitUtil.check(userStatus, 3)) { @@ -513,7 +605,12 @@ public class HuabaoProtocolDecoder extends BaseProtocolDecoder { position.set(Position.KEY_POWER, buf.readUnsignedShort() * 0.1); break; case 0xD4: - position.set(Position.KEY_BATTERY_LEVEL, buf.readUnsignedByte()); + case 0xE1: + if (length == 1) { + position.set(Position.KEY_BATTERY_LEVEL, buf.readUnsignedByte()); + } else { + position.set(Position.KEY_DRIVER_UNIQUE_ID, String.valueOf(buf.readUnsignedInt())); + } break; case 0xD5: if (length == 2) { @@ -536,6 +633,9 @@ public class HuabaoProtocolDecoder extends BaseProtocolDecoder { position.set(Position.KEY_MOTION, BitUtil.check(deviceStatus, 2)); position.set("cover", BitUtil.check(deviceStatus, 3)); break; + case 0xE2: + position.set(Position.KEY_FUEL_LEVEL, buf.readUnsignedInt() * 0.1); + break; case 0xE6: while (buf.readerIndex() < endIndex) { int sensorIndex = buf.readUnsignedByte(); @@ -589,8 +689,8 @@ public class HuabaoProtocolDecoder extends BaseProtocolDecoder { } break; case 0xED: - String license = buf.readCharSequence(length, StandardCharsets.US_ASCII).toString().trim(); - position.set("driverLicense", license); + stringValue = buf.readCharSequence(length, StandardCharsets.US_ASCII).toString(); + position.set(Position.KEY_CARD, stringValue.trim()); break; case 0xEE: position.set(Position.KEY_RSSI, buf.readUnsignedByte()); @@ -663,6 +763,8 @@ public class HuabaoProtocolDecoder extends BaseProtocolDecoder { case 0xFE: if (length == 1) { position.set(Position.KEY_BATTERY_LEVEL, buf.readUnsignedByte()); + } else if (length == 2) { + position.set(Position.KEY_POWER, buf.readUnsignedShort() * 0.1); } else { int mark = buf.readUnsignedByte(); if (mark == 0x7C) { @@ -721,12 +823,15 @@ public class HuabaoProtocolDecoder extends BaseProtocolDecoder { int battery = buf.readUnsignedByte(); if (battery <= 100) { position.set(Position.KEY_BATTERY_LEVEL, battery); - } else if (battery == 0xAA) { + } else if (battery == 0xAA || battery == 0xAB) { position.set(Position.KEY_CHARGE, true); } - position.setNetwork(new Network(CellTower.fromCidLac( - getConfig(), buf.readUnsignedInt(), buf.readUnsignedShort()))); + long cid = buf.readUnsignedInt(); + int lac = buf.readUnsignedShort(); + if (cid > 0 && lac > 0) { + position.setNetwork(new Network(CellTower.fromCidLac(getConfig(), cid, lac))); + } int product = buf.readUnsignedByte(); int status = buf.readUnsignedShort(); @@ -738,6 +843,9 @@ public class HuabaoProtocolDecoder extends BaseProtocolDecoder { } } else if (product == 3) { position.set(Position.KEY_BLOCKED, BitUtil.check(status, 5)); + if (BitUtil.check(alarm, 0)) { + position.set(Position.KEY_ALARM, Position.ALARM_OVERSPEED); + } if (BitUtil.check(alarm, 1)) { position.set(Position.KEY_ALARM, Position.ALARM_LOW_POWER); } @@ -747,10 +855,69 @@ public class HuabaoProtocolDecoder extends BaseProtocolDecoder { if (BitUtil.check(alarm, 3)) { position.set(Position.KEY_ALARM, Position.ALARM_LOW_BATTERY); } + if (BitUtil.check(alarm, 5)) { + position.set(Position.KEY_ALARM, Position.ALARM_GEOFENCE_ENTER); + } + if (BitUtil.check(alarm, 6)) { + position.set(Position.KEY_ALARM, Position.ALARM_GEOFENCE_EXIT); + } } position.set(Position.KEY_STATUS, status); + while (buf.readableBytes() > 2) { + int id = buf.readUnsignedByte(); + int length = buf.readUnsignedByte(); + switch (id) { + case 0x02: + position.setAltitude(buf.readShort()); + break; + case 0x10: + position.set("wakeSource", buf.readUnsignedByte()); + break; + case 0x0A: + if (length == 3) { + buf.readUnsignedShort(); // mcc + buf.readUnsignedByte(); // mnc + } else { + buf.skipBytes(length); + } + break; + case 0x0B: + position.set("lockCommand", buf.readUnsignedByte()); + if (length >= 5 && length <= 6) { + position.set("lockCard", buf.readUnsignedInt()); + } else if (length >= 7) { + position.set("lockPassword", buf.readCharSequence(6, StandardCharsets.US_ASCII).toString()); + } + if (length % 2 == 0) { + position.set("unlockResult", buf.readUnsignedByte()); + } + break; + case 0x0C: + int x = buf.readUnsignedShort(); + if (x > 0x8000) { + x -= 0x10000; + } + int y = buf.readUnsignedShort(); + if (y > 0x8000) { + y -= 0x10000; + } + int z = buf.readUnsignedShort(); + if (z > 0x8000) { + z -= 0x10000; + } + position.set("tilt", String.format("[%d,%d,%d]", x, y, z)); + break; + case 0xFC: + position.set(Position.KEY_GEOFENCE, buf.readUnsignedByte()); + break; + default: + buf.skipBytes(length); + break; + } + } + return position; } @@ -782,6 +949,7 @@ public class HuabaoProtocolDecoder extends BaseProtocolDecoder { int type = buf.readUnsignedByte(); if (type == 0xF0) { + Position position = new Position(getProtocolName()); position.setDeviceId(deviceSession.getDeviceId()); @@ -823,6 +991,34 @@ public class HuabaoProtocolDecoder extends BaseProtocolDecoder { case 0x0539: position.set(Position.KEY_FUEL_CONSUMPTION, buf.readUnsignedShort() * 0.01); break; + case 0x052B: + position.set(Position.KEY_FUEL_LEVEL, buf.readUnsignedByte()); + break; + case 0x052D: + position.set(Position.KEY_COOLANT_TEMP, buf.readUnsignedByte() - 40); + break; + case 0x052E: + position.set("airTemp", buf.readUnsignedByte() - 40); + break; + case 0x0530: + position.set(Position.KEY_POWER, buf.readUnsignedShort() * 0.001); + break; + case 0x0535: + position.set(Position.KEY_OBD_SPEED, buf.readUnsignedShort() * 0.1); + break; + case 0x0536: + position.set(Position.KEY_RPM, buf.readUnsignedShort()); + break; + case 0x053D: + position.set("intakePressure", buf.readUnsignedShort() * 0.1); + break; + case 0x0544: + position.set("liquidLevel", buf.readUnsignedByte()); + break; + case 0x0547: + case 0x0548: + position.set(Position.KEY_THROTTLE, buf.readUnsignedByte()); + break; default: switch (length) { case 1: @@ -841,15 +1037,40 @@ public class HuabaoProtocolDecoder extends BaseProtocolDecoder { break; } } + getLastLocation(position, time); + decodeCoordinates(position, buf); + position.setTime(time); + break; + case 0x02: + List<String> codes = new LinkedList<>(); + count = buf.readUnsignedShort(); + for (int i = 0; i < count; i++) { + buf.readUnsignedInt(); // system id + int codeCount = buf.readUnsignedShort(); + for (int j = 0; j < codeCount; j++) { + buf.readUnsignedInt(); // dtc + buf.readUnsignedInt(); // status + codes.add(buf.readCharSequence( + buf.readUnsignedShort(), StandardCharsets.US_ASCII).toString().trim()); + } + } + position.set(Position.KEY_DTCS, String.join(" ", codes)); + getLastLocation(position, time); decodeCoordinates(position, buf); position.setTime(time); break; case 0x03: count = buf.readUnsignedByte(); for (int i = 0; i < count; i++) { - int id = buf.readUnsignedShort(); + int id = buf.readUnsignedByte(); int length = buf.readUnsignedByte(); switch (id) { + case 0x01: + position.set(Position.KEY_ALARM, Position.ALARM_POWER_RESTORED); + break; + case 0x02: + position.set(Position.KEY_ALARM, Position.ALARM_POWER_CUT); + break; case 0x1A: position.set(Position.KEY_ALARM, Position.ALARM_ACCELERATION); break; @@ -867,11 +1088,21 @@ public class HuabaoProtocolDecoder extends BaseProtocolDecoder { case 0x23: position.set(Position.KEY_ALARM, Position.ALARM_FATIGUE_DRIVING); break; + case 0x26: + case 0x27: + case 0x28: + position.set(Position.KEY_ALARM, Position.ALARM_ACCIDENT); + break; + case 0x31: + case 0x32: + position.set(Position.KEY_ALARM, Position.ALARM_DOOR); + break; default: break; } buf.skipBytes(length); } + getLastLocation(position, time); decodeCoordinates(position, buf); position.setTime(time); break; @@ -886,6 +1117,24 @@ public class HuabaoProtocolDecoder extends BaseProtocolDecoder { } return position; + + } else if (type == 0xFF) { + + Position position = new Position(getProtocolName()); + position.setDeviceId(deviceSession.getDeviceId()); + + position.setValid(true); + position.setTime(readDate(buf, deviceSession.get(DeviceSession.KEY_TIMEZONE))); + position.setLatitude(buf.readInt() * 0.000001); + position.setLongitude(buf.readInt() * 0.000001); + position.setAltitude(buf.readShort()); + position.setSpeed(UnitsConverter.knotsFromKph(buf.readUnsignedShort() * 0.1)); + position.setCourse(buf.readUnsignedShort()); + + // TODO more positions and g sensor data + + return position; + } return null; |