feat: build vehicle data platform and production pipeline

This commit is contained in:
lingniu
2026-07-14 12:35:33 +08:00
parent b452be3b94
commit bb59303a4b
270 changed files with 88016 additions and 1975 deletions

View File

@@ -52,6 +52,9 @@ func ParseMessage(endpoint string, topic string, payload []byte, receivedAtMS in
DeviceID: deviceID,
Plate: plate,
SourceEndpoint: "mqtt://" + endpoint + topic,
SourceCode: sourceCodeFromEndpoint(endpoint),
PlatformName: platformNameFromEndpoint(endpoint),
SourceKind: "PLATFORM",
EventTimeMS: eventTimeMS,
ReceivedAtMS: receivedAtMS,
RawText: string(payload),
@@ -63,6 +66,32 @@ func ParseMessage(endpoint string, topic string, payload []byte, receivedAtMS in
return env, nil
}
func platformNameFromEndpoint(endpoint string) string {
endpoint = strings.TrimSpace(endpoint)
if strings.EqualFold(endpoint, "yutong") {
return "宇通"
}
return endpoint
}
func sourceCodeFromEndpoint(endpoint string) string {
endpoint = strings.TrimSpace(endpoint)
var builder strings.Builder
for _, r := range endpoint {
switch {
case r >= 'a' && r <= 'z':
builder.WriteRune(r)
case r >= 'A' && r <= 'Z':
builder.WriteRune(r)
case r >= '0' && r <= '9':
builder.WriteRune(r)
case r == '_' || r == '-' || r == '.':
builder.WriteRune(r)
}
}
return builder.String()
}
func fieldsFromData(data map[string]any) map[string]any {
fields := map[string]any{}
if speed, ok := firstFloat(data, "METER_SPEED", "speed", "speed_kmh"); ok {

View File

@@ -47,6 +47,20 @@ func TestParseMessageMapsYutongPayloadToEnvelope(t *testing.T) {
if env.RawText == "" || env.Parsed["data"] == nil {
t.Fatalf("raw/parsed missing: %#v", env)
}
if env.SourceCode != "endpoint-a" || env.PlatformName != "endpoint-a" || env.SourceKind != "PLATFORM" {
t.Fatalf("source metadata = code:%q platform:%q kind:%q", env.SourceCode, env.PlatformName, env.SourceKind)
}
}
func TestParseMessageUsesYutongEndpointDisplayName(t *testing.T) {
payload := []byte(`{"device":"LMRKH9AC3R1004101","time":"20260413100000","data":{"TOTAL_MILEAGE":56905000}}`)
env, err := ParseMessage("yutong", "/ytforward/shln/1", payload, 1782745114999)
if err != nil {
t.Fatalf("ParseMessage() error = %v", err)
}
if env.SourceCode != "yutong" || env.PlatformName != "宇通" || env.SourceKind != "PLATFORM" {
t.Fatalf("source metadata = code:%q platform:%q kind:%q", env.SourceCode, env.PlatformName, env.SourceKind)
}
}
func TestParseMessageUsesDeviceAsVehicleKeyWhenNotVIN(t *testing.T) {