mirror of
https://github.com/traccar/traccar.git
synced 2026-04-17 21:57:26 -04:00
Add more CRC32 algorithms
This commit is contained in:
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright 2012 - 2018 Anton Tananaev (anton@traccar.org)
|
||||
* Copyright 2012 - 2026 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.
|
||||
@@ -17,13 +17,26 @@ 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 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 CRC8_DALLAS = new Algorithm(8, 0x31, 0x00, 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 final Algorithm CRC32_STANDARD = new Algorithm(32, 0x04C11DB7, 0xFFFFFFFF, true, true, 0xFFFFFFFF);
|
||||
public static final Algorithm CRC32_MPEG2 = new Algorithm(32, 0x04C11DB7, 0xFFFFFFFF, false, false, 0x00000000);
|
||||
|
||||
public static class Algorithm {
|
||||
|
||||
private final int poly;
|
||||
@@ -39,7 +52,13 @@ public final class Checksum {
|
||||
this.refIn = refIn;
|
||||
this.refOut = refOut;
|
||||
this.xorOut = xorOut;
|
||||
this.table = bits == 8 ? initTable8() : initTable16();
|
||||
if (bits == 8) {
|
||||
this.table = initTable8();
|
||||
} else if (bits == 16) {
|
||||
this.table = initTable16();
|
||||
} else {
|
||||
this.table = initTable32();
|
||||
}
|
||||
}
|
||||
|
||||
private int[] initTable8() {
|
||||
@@ -76,6 +95,22 @@ public final class Checksum {
|
||||
return table;
|
||||
}
|
||||
|
||||
private int[] initTable32() {
|
||||
int[] table = new int[256];
|
||||
for (int i = 0; i < 256; i++) {
|
||||
int crc = i << 24;
|
||||
for (int j = 0; j < 8; j++) {
|
||||
if ((crc & 0x80000000) != 0) {
|
||||
crc = (crc << 1) ^ poly;
|
||||
} else {
|
||||
crc <<= 1;
|
||||
}
|
||||
}
|
||||
table[i] = crc;
|
||||
}
|
||||
return table;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
private static int reverse(int value, int bits) {
|
||||
@@ -117,23 +152,19 @@ public final class Checksum {
|
||||
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 CRC8_DALLAS = new Algorithm(8, 0x31, 0x00, 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();
|
||||
public static int crc32(Algorithm algorithm, ByteBuffer buf) {
|
||||
int crc = algorithm.init;
|
||||
while (buf.hasRemaining()) {
|
||||
checksum.update(buf.get());
|
||||
int b = buf.get() & 0xFF;
|
||||
if (algorithm.refIn) {
|
||||
b = reverse(b, 8);
|
||||
}
|
||||
crc = (crc << 8) ^ algorithm.table[((crc >> 24) & 0xFF) ^ b];
|
||||
}
|
||||
return (int) checksum.getValue();
|
||||
if (algorithm.refOut) {
|
||||
crc = reverse(crc, 32);
|
||||
}
|
||||
return crc ^ algorithm.xorOut;
|
||||
}
|
||||
|
||||
public static int xor(ByteBuffer buf) {
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright 2013 - 2018 Anton Tananaev (anton@traccar.org)
|
||||
* Copyright 2013 - 2026 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.
|
||||
@@ -70,7 +70,7 @@ public class ApelProtocolDecoder extends BaseProtocolDecoder {
|
||||
ByteBuf request = Unpooled.buffer(8);
|
||||
request.writeShortLE(type);
|
||||
request.writeShortLE(0);
|
||||
request.writeIntLE(Checksum.crc32(request.nioBuffer(0, 4)));
|
||||
request.writeIntLE(Checksum.crc32(Checksum.CRC32_STANDARD, request.nioBuffer(0, 4)));
|
||||
channel.writeAndFlush(new NetworkMessage(request, channel.remoteAddress()));
|
||||
}
|
||||
|
||||
@@ -83,7 +83,7 @@ public class ApelProtocolDecoder extends BaseProtocolDecoder {
|
||||
request.writeShortLE(6);
|
||||
request.writeIntLE((int) lastIndex);
|
||||
request.writeShortLE(512);
|
||||
request.writeIntLE(Checksum.crc32(request.nioBuffer(0, 10)));
|
||||
request.writeIntLE(Checksum.crc32(Checksum.CRC32_STANDARD, request.nioBuffer(0, 10)));
|
||||
channel.writeAndFlush(new NetworkMessage(request, channel.remoteAddress()));
|
||||
}
|
||||
}
|
||||
|
||||
@@ -31,6 +31,14 @@ public class ChecksumTest {
|
||||
assertEquals(0x31c3, Checksum.crc16(Checksum.CRC16_XMODEM, buf.nioBuffer()));
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testCrc32() {
|
||||
ByteBuf buf = Unpooled.copiedBuffer("123456789", StandardCharsets.US_ASCII);
|
||||
|
||||
assertEquals(0xcbf43926, Checksum.crc32(Checksum.CRC32_STANDARD, buf.nioBuffer()));
|
||||
assertEquals(0x0376e6e7, Checksum.crc32(Checksum.CRC32_MPEG2, buf.nioBuffer()));
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testLuhn() {
|
||||
assertEquals(7, Checksum.luhn(12345678901234L));
|
||||
|
||||
Reference in New Issue
Block a user