feat: track jt808 registration identity

This commit is contained in:
lingniu
2026-07-01 23:17:29 +08:00
parent dd95101499
commit a72977cd79
4 changed files with 317 additions and 0 deletions

View File

@@ -1,6 +1,7 @@
package jt808
import (
"encoding/binary"
"encoding/hex"
"testing"
@@ -114,6 +115,61 @@ func TestParseFrameSupportsJT8082019VersionedHeader(t *testing.T) {
}
}
func TestParseFrameParsesRegistrationIdentity(t *testing.T) {
body := make([]byte, 0, 46)
body = binary.BigEndian.AppendUint16(body, 16)
body = binary.BigEndian.AppendUint16(body, 32)
body = appendFixedASCII(body, "YUTNG", 5)
body = appendFixedASCII(body, "ZK6105CHEVNPG4", 20)
body = appendFixedASCII(body, "DEV0001", 7)
body = append(body, 2)
body = append(body, []byte("TEST123")...)
env, err := ParseFrame(buildFrame(0x0100, "013079963379", 7, body), 1782918600000, "115.231.168.135:43625")
if err != nil {
t.Fatalf("ParseFrame() error = %v", err)
}
if env.MessageID != "0x0100" {
t.Fatalf("message id = %q", env.MessageID)
}
if env.Phone != "013079963379" {
t.Fatalf("phone = %q", env.Phone)
}
if env.DeviceID != "DEV0001" {
t.Fatalf("device id = %q", env.DeviceID)
}
if env.Plate != "TEST123" {
t.Fatalf("plate = %q", env.Plate)
}
registration, ok := env.Parsed["registration"].(map[string]any)
if !ok {
t.Fatalf("registration missing: %#v", env.Parsed)
}
if registration["manufacturer"] != "YUTNG" || registration["device_type"] != "ZK6105CHEVNPG4" {
t.Fatalf("registration fields = %#v", registration)
}
if registration["plate_color"] != uint8(2) {
t.Fatalf("plate color = %#v", registration["plate_color"])
}
}
func TestParseFrameParsesAuthenticationToken(t *testing.T) {
env, err := ParseFrame(buildFrame(0x0102, "064646848757", 8, []byte("g7gps")), 1782918600000, "115.231.168.135:43625")
if err != nil {
t.Fatalf("ParseFrame() error = %v", err)
}
if env.MessageID != "0x0102" {
t.Fatalf("message id = %q", env.MessageID)
}
auth, ok := env.Parsed["authentication"].(map[string]any)
if !ok {
t.Fatalf("authentication missing: %#v", env.Parsed)
}
if auth["token"] != "g7gps" {
t.Fatalf("token = %#v", auth["token"])
}
}
func TestExtractFramesHandlesEscapedPayload(t *testing.T) {
payload := []byte{0x02, 0x00, 0x00, 0x02, 0x01, 0x33, 0x07, 0x79, 0x54, 0x25, 0x00, 0x01, 0x7e, 0x7d}
frame := append([]byte{0x7e}, escape(append(payload, checksum(payload)))...)
@@ -131,6 +187,41 @@ func TestExtractFramesHandlesEscapedPayload(t *testing.T) {
}
}
func buildFrame(messageID uint16, phone string, sequence uint16, body []byte) []byte {
payload := make([]byte, 0, 12+len(body)+1)
payload = binary.BigEndian.AppendUint16(payload, messageID)
payload = binary.BigEndian.AppendUint16(payload, uint16(len(body)))
payload = append(payload, encodeBCD(phone, 6)...)
payload = binary.BigEndian.AppendUint16(payload, sequence)
payload = append(payload, body...)
payload = append(payload, checksum(payload))
return payload
}
func appendFixedASCII(out []byte, value string, size int) []byte {
start := len(out)
out = append(out, make([]byte, size)...)
copy(out[start:], []byte(value))
return out
}
func encodeBCD(value string, size int) []byte {
out := make([]byte, size)
if len(value)%2 == 1 {
value = "0" + value
}
if len(value) > size*2 {
value = value[len(value)-size*2:]
}
for len(value) < size*2 {
value = "0" + value
}
for i := 0; i < size; i++ {
out[i] = (value[i*2]-'0')<<4 | (value[i*2+1] - '0')
}
return out
}
func assertFloatField(t *testing.T, env envelope.FrameEnvelope, key string, want float64) {
t.Helper()
got, ok := env.Fields[key].(float64)