fix: align jt808 parser with protocol variants

This commit is contained in:
lingniu
2026-07-02 00:14:02 +08:00
parent b0150a5503
commit 9045b871d6
2 changed files with 244 additions and 26 deletions

View File

@@ -115,6 +115,36 @@ func TestParseFrameSupportsJT8082019VersionedHeader(t *testing.T) {
}
}
func TestParseFrameRejectsTruncatedSubpackageHeader(t *testing.T) {
payload := []byte{0x02, 0x00, 0x20, 0x00}
payload = append(payload, encodeBCD("013307795425", 6)...)
payload = binary.BigEndian.AppendUint16(payload, 1)
payload = append(payload, checksum(payload))
_, err := ParseFrame(payload, 1782914967713, "115.231.168.135:43625")
if err == nil {
t.Fatal("expected truncated subpackage header to fail")
}
}
func TestParseLocationAppliesSouthWestStatusBits(t *testing.T) {
body := make([]byte, 28)
binary.BigEndian.PutUint32(body[4:8], (1<<2)|(1<<3))
binary.BigEndian.PutUint32(body[8:12], 12345678)
binary.BigEndian.PutUint32(body[12:16], 98765432)
location, err := parseLocation(body)
if err != nil {
t.Fatalf("parseLocation() error = %v", err)
}
if location.Latitude != -12.345678 {
t.Fatalf("latitude = %v", location.Latitude)
}
if location.Longitude != -98.765432 {
t.Fatalf("longitude = %v", location.Longitude)
}
}
func TestParseFrameParsesRegistrationIdentity(t *testing.T) {
body := make([]byte, 0, 46)
body = binary.BigEndian.AppendUint16(body, 16)
@@ -153,6 +183,38 @@ func TestParseFrameParsesRegistrationIdentity(t *testing.T) {
}
}
func TestParseFrameParsesJT8082019RegistrationIdentity(t *testing.T) {
body := make([]byte, 0, 84)
body = binary.BigEndian.AppendUint16(body, 16)
body = binary.BigEndian.AppendUint16(body, 32)
body = appendFixedASCII(body, "YUTONG00001", 11)
body = appendFixedASCII(body, "ZK6105CHEVNPG4-2019", 30)
body = appendFixedASCII(body, "DEV201900000000000000000000001", 30)
body = append(body, 2)
body = append(body, []byte("TEST2019")...)
env, err := ParseFrame(buildVersionedFrame(0x0100, "14894135060", 11, body), 1782918600000, "115.231.168.135:43625")
if err != nil {
t.Fatalf("ParseFrame() error = %v", err)
}
if env.Phone != "14894135060" {
t.Fatalf("phone = %q", env.Phone)
}
if env.DeviceID != "DEV201900000000000000000000001" {
t.Fatalf("device id = %q", env.DeviceID)
}
if env.Plate != "TEST2019" {
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["schema_version"] != "2019" || registration["manufacturer"] != "YUTONG00001" {
t.Fatalf("registration fields = %#v", registration)
}
}
func TestParseFrameDecodesGBKRegistrationPlate(t *testing.T) {
body := make([]byte, 0, 46)
body = binary.BigEndian.AppendUint16(body, 16)
@@ -172,6 +234,26 @@ func TestParseFrameDecodesGBKRegistrationPlate(t *testing.T) {
}
}
func TestParseFrameParsesJT8082019Authentication(t *testing.T) {
body := []byte{5}
body = append(body, []byte("TOKEN")...)
body = appendFixedASCII(body, "123456789012345", 15)
body = append(body, 4)
body = append(body, []byte("v1.2")...)
env, err := ParseFrame(buildVersionedFrame(0x0102, "14894135060", 12, body), 1782918600000, "115.231.168.135:43625")
if err != nil {
t.Fatalf("ParseFrame() error = %v", err)
}
auth, ok := env.Parsed["authentication"].(map[string]any)
if !ok {
t.Fatalf("authentication missing: %#v", env.Parsed)
}
if auth["token"] != "TOKEN" || auth["imei"] != "123456789012345" || auth["software_version"] != "v1.2" {
t.Fatalf("authentication = %#v", auth)
}
}
func TestParseFrameParsesAuthenticationToken(t *testing.T) {
env, err := ParseFrame(buildFrame(0x0102, "064646848757", 8, []byte("g7gps")), 1782918600000, "115.231.168.135:43625")
if err != nil {
@@ -217,6 +299,18 @@ func buildFrame(messageID uint16, phone string, sequence uint16, body []byte) []
return payload
}
func buildVersionedFrame(messageID uint16, phone string, sequence uint16, body []byte) []byte {
payload := make([]byte, 0, 17+len(body)+1)
payload = binary.BigEndian.AppendUint16(payload, messageID)
payload = binary.BigEndian.AppendUint16(payload, 0x4000|uint16(len(body)))
payload = append(payload, 1)
payload = append(payload, encodeBCD(phone, 10)...)
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)...)