feat: make gb32960 archive history query production ready
This commit is contained in:
30
modules/core/ingest-codec-common/pom.xml
Normal file
30
modules/core/ingest-codec-common/pom.xml
Normal file
@@ -0,0 +1,30 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<project xmlns="http://maven.apache.org/POM/4.0.0">
|
||||
<modelVersion>4.0.0</modelVersion>
|
||||
<parent>
|
||||
<groupId>com.lingniu.ingest</groupId>
|
||||
<artifactId>lingniu-vehicle-ingest</artifactId>
|
||||
<version>0.1.0-SNAPSHOT</version>
|
||||
<relativePath>../../../pom.xml</relativePath>
|
||||
</parent>
|
||||
<artifactId>ingest-codec-common</artifactId>
|
||||
<name>ingest-codec-common</name>
|
||||
<description>BCD / CRC / BCC / bit utils 等公共编解码工具。</description>
|
||||
|
||||
<dependencies>
|
||||
<dependency>
|
||||
<groupId>io.netty</groupId>
|
||||
<artifactId>netty-buffer</artifactId>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>org.junit.jupiter</groupId>
|
||||
<artifactId>junit-jupiter</artifactId>
|
||||
<scope>test</scope>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>org.assertj</groupId>
|
||||
<artifactId>assertj-core</artifactId>
|
||||
<scope>test</scope>
|
||||
</dependency>
|
||||
</dependencies>
|
||||
</project>
|
||||
@@ -0,0 +1,19 @@
|
||||
package com.lingniu.ingest.codec;
|
||||
|
||||
/** BCC(异或校验)。GB/T 32960 与 JT/T 808 都使用此方式做帧尾校验。 */
|
||||
public final class BccChecksum {
|
||||
|
||||
private BccChecksum() {}
|
||||
|
||||
public static byte compute(byte[] data, int offset, int length) {
|
||||
byte sum = 0;
|
||||
for (int i = offset; i < offset + length; i++) {
|
||||
sum ^= data[i];
|
||||
}
|
||||
return sum;
|
||||
}
|
||||
|
||||
public static boolean verify(byte[] data, int offset, int length, byte expected) {
|
||||
return compute(data, offset, length) == expected;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,30 @@
|
||||
package com.lingniu.ingest.codec;
|
||||
|
||||
/** BCD (Binary-Coded Decimal) 编解码。JT/T 808 的手机号、时间戳常用。 */
|
||||
public final class BcdCodec {
|
||||
|
||||
private BcdCodec() {}
|
||||
|
||||
public static byte[] encode(String decimal) {
|
||||
int len = (decimal.length() + 1) / 2;
|
||||
byte[] out = new byte[len];
|
||||
int idx = decimal.length() % 2;
|
||||
if (idx == 1) {
|
||||
out[0] = (byte) Character.digit(decimal.charAt(0), 10);
|
||||
}
|
||||
for (int i = idx; i < decimal.length(); i += 2) {
|
||||
int hi = Character.digit(decimal.charAt(i), 10);
|
||||
int lo = Character.digit(decimal.charAt(i + 1), 10);
|
||||
out[(i + idx) / 2] = (byte) ((hi << 4) | lo);
|
||||
}
|
||||
return out;
|
||||
}
|
||||
|
||||
public static String decode(byte[] bcd) {
|
||||
StringBuilder sb = new StringBuilder(bcd.length * 2);
|
||||
for (byte b : bcd) {
|
||||
sb.append((b >> 4) & 0x0F).append(b & 0x0F);
|
||||
}
|
||||
return sb.toString();
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,34 @@
|
||||
package com.lingniu.ingest.codec;
|
||||
|
||||
/** 位运算工具:从字节数组读写无符号整数。 */
|
||||
public final class BitUtils {
|
||||
|
||||
private BitUtils() {}
|
||||
|
||||
public static int readUint8(byte[] buf, int offset) {
|
||||
return buf[offset] & 0xFF;
|
||||
}
|
||||
|
||||
public static int readUint16BE(byte[] buf, int offset) {
|
||||
return ((buf[offset] & 0xFF) << 8) | (buf[offset + 1] & 0xFF);
|
||||
}
|
||||
|
||||
public static long readUint32BE(byte[] buf, int offset) {
|
||||
return ((long) (buf[offset] & 0xFF) << 24)
|
||||
| ((long) (buf[offset + 1] & 0xFF) << 16)
|
||||
| ((long) (buf[offset + 2] & 0xFF) << 8)
|
||||
| (buf[offset + 3] & 0xFF);
|
||||
}
|
||||
|
||||
public static void writeUint16BE(byte[] buf, int offset, int value) {
|
||||
buf[offset] = (byte) ((value >> 8) & 0xFF);
|
||||
buf[offset + 1] = (byte) (value & 0xFF);
|
||||
}
|
||||
|
||||
public static void writeUint32BE(byte[] buf, int offset, long value) {
|
||||
buf[offset] = (byte) ((value >> 24) & 0xFF);
|
||||
buf[offset + 1] = (byte) ((value >> 16) & 0xFF);
|
||||
buf[offset + 2] = (byte) ((value >> 8) & 0xFF);
|
||||
buf[offset + 3] = (byte) (value & 0xFF);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,28 @@
|
||||
package com.lingniu.ingest.codec;
|
||||
|
||||
import org.junit.jupiter.api.Test;
|
||||
|
||||
import static org.assertj.core.api.Assertions.assertThat;
|
||||
|
||||
class BcdCodecTest {
|
||||
|
||||
@Test
|
||||
void roundTripEvenLength() {
|
||||
// 偶数位直接等值
|
||||
byte[] bcd = BcdCodec.encode("1380013800");
|
||||
assertThat(BcdCodec.decode(bcd)).isEqualTo("1380013800");
|
||||
}
|
||||
|
||||
@Test
|
||||
void roundTripOddLengthPadsLeadingZero() {
|
||||
// 奇数位会在高位补 0
|
||||
byte[] bcd = BcdCodec.encode("13800138000");
|
||||
assertThat(BcdCodec.decode(bcd)).isEqualTo("013800138000");
|
||||
}
|
||||
|
||||
@Test
|
||||
void checksumMatches() {
|
||||
byte[] data = {0x01, 0x02, 0x03, 0x04};
|
||||
assertThat(BccChecksum.compute(data, 0, data.length)).isEqualTo((byte) 0x04);
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user