From 6eb1837b796f51bd2a84d091b706a7ae1d4952a0 Mon Sep 17 00:00:00 2001 From: Anton Tananaev Date: Tue, 7 Jul 2015 15:20:48 +1200 Subject: Improve Aplicom id parsing --- src/org/traccar/helper/Crc.java | 30 +++++---- .../traccar/protocol/AplicomProtocolDecoder.java | 72 ++++++++-------------- .../traccar/protocol/MeiligaoProtocolDecoder.java | 2 +- test/org/traccar/helper/CrcTest.java | 15 +++++ 4 files changed, 57 insertions(+), 62 deletions(-) create mode 100644 test/org/traccar/helper/CrcTest.java diff --git a/src/org/traccar/helper/Crc.java b/src/org/traccar/helper/Crc.java index 213d1192a..418ec3132 100644 --- a/src/org/traccar/helper/Crc.java +++ b/src/org/traccar/helper/Crc.java @@ -154,21 +154,25 @@ public class Crc { return String.format("*%02x", checksum).toUpperCase(); } - public static String luhnChecksum(String s) { - int sum = 0; - boolean evenPosition = true; - for (int i = s.length() - 1; i >= 0; i--) { - int n = Integer.parseInt(s.substring(i, i + 1)); - if (evenPosition) { - n *= 2; - if (n > 9) { - n = (n % 10) + 1; + public static long luhnChecksum(long imei) { + long checksum = 0; + long remain = imei; + + for (int i = 0; remain != 0; i++) { + long digit = remain % 10; + + if ((i % 2) == 0) { + digit *= 2; + if (digit >= 10) { + digit = 1 + (digit % 10); } } - sum += n; - evenPosition = !evenPosition; + + checksum += digit; + remain /= 10; } - return String.valueOf(10 - sum % 10); - } + + return 10 - (checksum % 10); + } } diff --git a/src/org/traccar/protocol/AplicomProtocolDecoder.java b/src/org/traccar/protocol/AplicomProtocolDecoder.java index 045eb2adc..573cccecf 100644 --- a/src/org/traccar/protocol/AplicomProtocolDecoder.java +++ b/src/org/traccar/protocol/AplicomProtocolDecoder.java @@ -26,6 +26,7 @@ import org.jboss.netty.channel.ChannelHandlerContext; import org.traccar.BaseProtocolDecoder; import org.traccar.Context; import org.traccar.helper.ChannelBufferTools; +import org.traccar.helper.Crc; import org.traccar.helper.UnitsConverter; import org.traccar.model.Event; import org.traccar.model.Position; @@ -40,68 +41,41 @@ public class AplicomProtocolDecoder extends BaseProtocolDecoder { private static final long IMEI_BASE_TC65_V28 = 358244010000000L; private static final long IMEI_BASE_TC65I_V11 = 0x14143B4000000L; + private static boolean validateImei(long imei) { + return Crc.luhnChecksum(imei / 10) == imei % 10; + } + private static long imeiFromUnitId(long unitId) { - if(unitId == 0) { - return 0L; - } else if(unitId < 0x1000000) { - // Assume TC65i. + + if (unitId == 0) { + + return 0; + + } else { + + // Try TC65i long imei = IMEI_BASE_TC65I_V11 + unitId; - if(validateImei(imei)) { + if (validateImei(imei)) { return imei; } - // No? Maybe it's TC65 v2.8? + // Try TC65 v2.8 imei = IMEI_BASE_TC65_V28 + ((unitId + 0xA8180) & 0xFFFFFF); - if(validateImei(imei)) { + if (validateImei(imei)) { return imei; } - // Still no match? How about TC65 v2.0? + // Try TC65 v2.0 imei = IMEI_BASE_TC65_V20 + unitId; - if(validateImei(imei)) { + if (validateImei(imei)) { return imei; } - } else { - // Unit ID is full IMEI, just check it. - if(validateImei(unitId)) { - return unitId; - } + } return unitId; } - - private static boolean validateImei(long imei2) { - - int checksum = 0; - long remain = imei2; - - // Iterate through all meaningful digits. - for (int i = 0; remain != 0; i++) { - // Extract the rightmost digit, that is, compute - // imei modulo 10 (or remainder of imei / 10). - int digit = (int) (remain % 10); - - // For each even-positioned digit, calculate the value - // to be added to sum: Double the digit and then sum up - // the digits of the result. - // Example: 7 -> 2*7 = 14 -> 1 + 4 = 5 - if (0 != (i % 2)) { - digit = digit * 2; - if (digit >= 10) { - digit = digit - 9; - } - } - checksum = checksum + digit; - - // Remove the rightmost digit as it's already processed. - remain = remain / 10; - } - // The IMEI is valid if the calculated checksum is dividable by 10. - return 0 == (checksum % 10); - } - private static final int DEFAULT_SELECTOR = 0x0002FC; private static final int EVENT_DATA = 119; @@ -115,12 +89,14 @@ public class AplicomProtocolDecoder extends BaseProtocolDecoder { buf.readUnsignedByte(); // marker int version = buf.readUnsignedByte(); + + String imei; if ((version & 0x80) != 0) { - buf.skipBytes(4); // unit id high + imei = String.valueOf((buf.readUnsignedInt() << (3 * 8)) | buf.readUnsignedMedium()); + } else { + imei = String.valueOf(imeiFromUnitId(buf.readUnsignedMedium())); } - String imei = String.valueOf(imeiFromUnitId(buf.readUnsignedMedium())); - buf.readUnsignedShort(); // length // Selector diff --git a/src/org/traccar/protocol/MeiligaoProtocolDecoder.java b/src/org/traccar/protocol/MeiligaoProtocolDecoder.java index f17d2e168..faa2f122e 100644 --- a/src/org/traccar/protocol/MeiligaoProtocolDecoder.java +++ b/src/org/traccar/protocol/MeiligaoProtocolDecoder.java @@ -89,7 +89,7 @@ public class MeiligaoProtocolDecoder extends BaseProtocolDecoder { } if (id.length() == 14) { - id += Crc.luhnChecksum(id); // IMEI checksum + id += Crc.luhnChecksum(Long.valueOf(id)); // IMEI checksum } return id; } diff --git a/test/org/traccar/helper/CrcTest.java b/test/org/traccar/helper/CrcTest.java new file mode 100644 index 000000000..46e7dfc79 --- /dev/null +++ b/test/org/traccar/helper/CrcTest.java @@ -0,0 +1,15 @@ +package org.traccar.helper; + +import org.junit.Assert; +import org.junit.Test; + +public class CrcTest { + + @Test + public void testLuhnChecksum() { + + Assert.assertEquals(7, Crc.luhnChecksum(12345678901234L)); + + } + +} -- cgit v1.2.3