From 7ad1a25e8ee6580c83063275102703ed17912389 Mon Sep 17 00:00:00 2001 From: lingniu Date: Thu, 2 Jul 2026 01:04:14 +0800 Subject: [PATCH] fix: normalize yutong mqtt mileage units --- .../internal/protocol/yutongmqtt/parser.go | 17 ++++++++++++++++- .../internal/protocol/yutongmqtt/parser_test.go | 16 ++++++++++++++++ 2 files changed, 32 insertions(+), 1 deletion(-) diff --git a/go/vehicle-gateway/internal/protocol/yutongmqtt/parser.go b/go/vehicle-gateway/internal/protocol/yutongmqtt/parser.go index 9eff6fb5..09f1f822 100644 --- a/go/vehicle-gateway/internal/protocol/yutongmqtt/parser.go +++ b/go/vehicle-gateway/internal/protocol/yutongmqtt/parser.go @@ -69,7 +69,7 @@ func fieldsFromData(data map[string]any) map[string]any { fields[envelope.FieldSpeedKMH] = speed } if mileage, ok := firstFloat(data, "TOTAL_MILEAGE", "totalMileage", "total_mileage_km"); ok { - fields[envelope.FieldTotalMileageKM] = mileage + fields[envelope.FieldTotalMileageKM] = normalizeTotalMileageKM(mileage) } if soc, ok := firstFloat(data, "BATTERY_CAPACITY_SOC", "soc", "SOC", "soc_percent"); ok { fields[envelope.FieldSOCPercent] = soc @@ -166,6 +166,14 @@ func parseTimeMS(raw string, fallback int64) int64 { if raw == "" { return fallback } + for _, layout := range []string{ + "2006-01-02 15:04:05.000", + "2006-01-02 15:04:05", + } { + if parsed, err := time.ParseInLocation(layout, raw, time.FixedZone("Asia/Shanghai", 8*3600)); err == nil { + return parsed.UnixMilli() + } + } if len(raw) == 14 { if parsed, err := time.ParseInLocation("20060102150405", raw, time.FixedZone("Asia/Shanghai", 8*3600)); err == nil { return parsed.UnixMilli() @@ -187,3 +195,10 @@ func looksLikeVIN(value string) bool { value = strings.TrimSpace(value) return len(value) == 17 } + +func normalizeTotalMileageKM(value float64) float64 { + if value > 1_000_000 { + return value / 1000 + } + return value +} diff --git a/go/vehicle-gateway/internal/protocol/yutongmqtt/parser_test.go b/go/vehicle-gateway/internal/protocol/yutongmqtt/parser_test.go index f348322c..91b5ef54 100644 --- a/go/vehicle-gateway/internal/protocol/yutongmqtt/parser_test.go +++ b/go/vehicle-gateway/internal/protocol/yutongmqtt/parser_test.go @@ -64,6 +64,22 @@ func TestParseMessageUsesDeviceAsVehicleKeyWhenNotVIN(t *testing.T) { assertFloatField(t, env, envelope.FieldSpeedKMH, 12.3) } +func TestParseMessageNormalizesProductionMileageMeters(t *testing.T) { + payload := []byte(`{ + "device":"LMRKH9AC3R1004101", + "time":"2026-07-02 01:02:04.085", + "data":{"TOTAL_MILEAGE":56905000,"METER_SPEED":19} + }`) + env, err := ParseMessage("yutong", "/ytforward/shln/1", payload, 1782940000000) + if err != nil { + t.Fatalf("ParseMessage() error = %v", err) + } + assertFloatField(t, env, envelope.FieldTotalMileageKM, 56905) + if env.EventTimeMS != 1782925324085 { + t.Fatalf("event time = %d, want 1782925324085", env.EventTimeMS) + } +} + func TestParseMessageRejectsMalformedJSON(t *testing.T) { _, err := ParseMessage("endpoint-a", "/bad", []byte("{bad-json"), 1782745114999) if !errors.Is(err, ErrInvalidJSON) {