fix: enrich jt808 location additional parsing

This commit is contained in:
lingniu
2026-07-02 00:36:51 +08:00
parent dd73fdbb5b
commit e37dd39c89
2 changed files with 162 additions and 12 deletions

View File

@@ -10,6 +10,7 @@ import (
const sampleLocationFrame = "7E020000320133077954250001000000000048000301D2C4C707376139000A00E6004F26063016235701040001900C2504000000000202000030011F31010F867E"
const real2019LocationFrame = "7E02004046010000000001489413506007CB00000000004C000301D276AB06FBFF4B000D014E00E826070122092214040000000017020000010400013361030201402504000000012A02000030011D310112EA0402008000C57E"
const fullAdditionalLocationFrame = "7e020000800123456789017fff000004000000080006eeb6ad02633df701380003006320070719235901040000000b02020016030200210402002c051e3737370000000000000000000000000000000000000000000000000000001105420000004212064d0000004d4d1307000000580058582504000000632a02000a2b040000001430011e31012806020001927e"
func TestExtractFramesUnescapesAndParsesLocationWithTotalMileage(t *testing.T) {
stream, err := hex.DecodeString(sampleLocationFrame + "7E02000000")
@@ -63,6 +64,13 @@ func TestExtractFramesUnescapesAndParsesLocationWithTotalMileage(t *testing.T) {
if additional[0]["id"] != "0x01" || additional[0]["value_hex"] != "0001900C" {
t.Fatalf("unexpected first additional item: %#v", additional[0])
}
parsed, ok := additional[0]["parsed"].(map[string]any)
if !ok {
t.Fatalf("mileage parsed field missing: %#v", additional[0])
}
if parsed["raw_value_tenth_km"] != uint32(102412) || parsed["value"] != 10241.2 {
t.Fatalf("unexpected mileage parsed value: %#v", parsed)
}
}
func TestParseFrameSupportsJT8082019VersionedHeader(t *testing.T) {
@@ -115,6 +123,59 @@ func TestParseFrameSupportsJT8082019VersionedHeader(t *testing.T) {
}
}
func TestParseFrameParsesCommonLocationAdditionalItems(t *testing.T) {
stream, err := hex.DecodeString(fullAdditionalLocationFrame)
if err != nil {
t.Fatal(err)
}
frames, remainder, err := ExtractFrames(stream)
if err != nil {
t.Fatalf("ExtractFrames() error = %v", err)
}
if len(frames) != 1 || len(remainder) != 0 {
t.Fatalf("unexpected split result frames=%d remainder=%s", len(frames), hex.EncodeToString(remainder))
}
env, err := ParseFrame(frames[0], 1782914967713, "127.0.0.1:808")
if err != nil {
t.Fatalf("ParseFrame() error = %v", err)
}
if env.Phone != "012345678901" {
t.Fatalf("phone = %q", env.Phone)
}
assertFloatField(t, env, envelope.FieldTotalMileageKM, 1.1)
location := env.Parsed["location"].(map[string]any)
additional := location["additional"].([]map[string]any)
byID := map[string]map[string]any{}
for _, item := range additional {
byID[item["id"].(string)] = item["parsed"].(map[string]any)
}
if byID["0x01"]["raw_value_tenth_km"] != uint32(11) || byID["0x01"]["value"] != 1.1 {
t.Fatalf("mileage parsed = %#v", byID["0x01"])
}
if byID["0x05"]["name"] != "tire_pressure" {
t.Fatalf("tire pressure missing: %#v", byID["0x05"])
}
tireValues := byID["0x05"]["values"].([]map[string]any)
if tireValues[0]["value"] != byte(0x37) || tireValues[0]["valid"] != true {
t.Fatalf("tire pressure first value = %#v", tireValues[0])
}
if byID["0x11"]["location_type"] != byte(0x42) || byID["0x11"]["area_id"] != uint32(0x42) {
t.Fatalf("overspeed parsed = %#v", byID["0x11"])
}
if byID["0x12"]["location_type"] != byte(0x4d) || byID["0x12"]["area_id"] != uint32(0x4d) || byID["0x12"]["direction"] != byte(0x4d) {
t.Fatalf("area route parsed = %#v", byID["0x12"])
}
if byID["0x13"]["road_section_id"] != uint32(0x58) || byID["0x13"]["driving_time_seconds"] != uint16(0x58) {
t.Fatalf("road section parsed = %#v", byID["0x13"])
}
ioBits := byID["0x2A"]["bits"].(map[string]bool)
if ioBits["deep_sleep"] || !ioBits["sleep"] {
t.Fatalf("io bits = %#v", ioBits)
}
}
func TestParseFrameRejectsTruncatedSubpackageHeader(t *testing.T) {
payload := []byte{0x02, 0x00, 0x20, 0x00}
payload = append(payload, encodeBCD("013307795425", 6)...)