diff options
author | Anton Tananaev <anton.tananaev@gmail.com> | 2019-03-31 22:35:39 -0700 |
---|---|---|
committer | Anton Tananaev <anton.tananaev@gmail.com> | 2019-03-31 22:35:39 -0700 |
commit | 59416923dcb3a756eaf532cc4259f2f6625c0762 (patch) | |
tree | 9082dae6616deac8fda432b7bfd80e4a52b6d9dc /src/main/java/org/traccar/helper/Checksum.java | |
parent | 79a129dd6327d932133d6b9a50190d3f4927bff9 (diff) | |
download | trackermap-server-59416923dcb3a756eaf532cc4259f2f6625c0762.tar.gz trackermap-server-59416923dcb3a756eaf532cc4259f2f6625c0762.tar.bz2 trackermap-server-59416923dcb3a756eaf532cc4259f2f6625c0762.zip |
Convert project to gradle
Diffstat (limited to 'src/main/java/org/traccar/helper/Checksum.java')
-rw-r--r-- | src/main/java/org/traccar/helper/Checksum.java | 200 |
1 files changed, 200 insertions, 0 deletions
diff --git a/src/main/java/org/traccar/helper/Checksum.java b/src/main/java/org/traccar/helper/Checksum.java new file mode 100644 index 000000000..adfa697c5 --- /dev/null +++ b/src/main/java/org/traccar/helper/Checksum.java @@ -0,0 +1,200 @@ +/* + * Copyright 2012 - 2018 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. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package org.traccar.helper; + +import java.nio.ByteBuffer; +import java.nio.charset.StandardCharsets; +import java.util.zip.CRC32; + +public final class Checksum { + + private Checksum() { + } + + public static class Algorithm { + + private int poly; + private int init; + private boolean refIn; + private boolean refOut; + private int xorOut; + private int[] table; + + public Algorithm(int bits, int poly, int init, boolean refIn, boolean refOut, int xorOut) { + this.poly = poly; + this.init = init; + this.refIn = refIn; + this.refOut = refOut; + this.xorOut = xorOut; + this.table = bits == 8 ? initTable8() : initTable16(); + } + + private int[] initTable8() { + int[] table = new int[256]; + int crc; + for (int i = 0; i < 256; i++) { + crc = i; + for (int j = 0; j < 8; j++) { + boolean bit = (crc & 0x80) != 0; + crc <<= 1; + if (bit) { + crc ^= poly; + } + } + table[i] = crc & 0xFF; + } + return table; + } + + private int[] initTable16() { + int[] table = new int[256]; + int crc; + for (int i = 0; i < 256; i++) { + crc = i << 8; + for (int j = 0; j < 8; j++) { + boolean bit = (crc & 0x8000) != 0; + crc <<= 1; + if (bit) { + crc ^= poly; + } + } + table[i] = crc & 0xFFFF; + } + return table; + } + + } + + private static int reverse(int value, int bits) { + int result = 0; + for (int i = 0; i < bits; i++) { + result = (result << 1) | (value & 1); + value >>= 1; + } + return result; + } + + public static int crc8(Algorithm algorithm, ByteBuffer buf) { + int crc = algorithm.init; + while (buf.hasRemaining()) { + int b = buf.get() & 0xFF; + if (algorithm.refIn) { + b = reverse(b, 8); + } + crc = algorithm.table[(crc & 0xFF) ^ b]; + } + if (algorithm.refOut) { + crc = reverse(crc, 8); + } + return (crc ^ algorithm.xorOut) & 0xFF; + } + + public static int crc16(Algorithm algorithm, ByteBuffer buf) { + int crc = algorithm.init; + while (buf.hasRemaining()) { + int b = buf.get() & 0xFF; + if (algorithm.refIn) { + b = reverse(b, 8); + } + crc = (crc << 8) ^ algorithm.table[((crc >> 8) & 0xFF) ^ b]; + } + if (algorithm.refOut) { + crc = reverse(crc, 16); + } + return (crc ^ algorithm.xorOut) & 0xFFFF; + } + + public static final Algorithm CRC8_EGTS = new Algorithm(8, 0x31, 0xFF, false, false, 0x00); + public static final Algorithm CRC8_ROHC = new Algorithm(8, 0x07, 0xFF, true, true, 0x00); + + public static final Algorithm CRC16_IBM = new Algorithm(16, 0x8005, 0x0000, true, true, 0x0000); + public static final Algorithm CRC16_X25 = new Algorithm(16, 0x1021, 0xFFFF, true, true, 0xFFFF); + public static final Algorithm CRC16_MODBUS = new Algorithm(16, 0x8005, 0xFFFF, true, true, 0x0000); + public static final Algorithm CRC16_CCITT_FALSE = new Algorithm(16, 0x1021, 0xFFFF, false, false, 0x0000); + public static final Algorithm CRC16_KERMIT = new Algorithm(16, 0x1021, 0x0000, true, true, 0x0000); + public static final Algorithm CRC16_XMODEM = new Algorithm(16, 0x1021, 0x0000, false, false, 0x0000); + + public static int crc32(ByteBuffer buf) { + CRC32 checksum = new CRC32(); + while (buf.hasRemaining()) { + checksum.update(buf.get()); + } + return (int) checksum.getValue(); + } + + public static int xor(ByteBuffer buf) { + int checksum = 0; + while (buf.hasRemaining()) { + checksum ^= buf.get(); + } + return checksum; + } + + public static int xor(String string) { + byte checksum = 0; + for (byte b : string.getBytes(StandardCharsets.US_ASCII)) { + checksum ^= b; + } + return checksum; + } + + public static String nmea(String msg) { + int checksum = 0; + byte[] bytes = msg.getBytes(StandardCharsets.US_ASCII); + for (int i = 1; i < bytes.length; i++) { + checksum ^= bytes[i]; + } + return String.format("*%02x", checksum).toUpperCase(); + } + + public static int sum(ByteBuffer buf) { + byte checksum = 0; + while (buf.hasRemaining()) { + checksum += buf.get(); + } + return checksum; + } + + public static String sum(String msg) { + byte checksum = 0; + for (byte b : msg.getBytes(StandardCharsets.US_ASCII)) { + checksum += b; + } + return String.format("%02X", checksum).toUpperCase(); + } + + public static long luhn(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); + } + } + + checksum += digit; + remain /= 10; + } + + return (10 - (checksum % 10)) % 10; + } + +} |