fix(gateway): keep canonical stats fields in field events
This commit is contained in:
@@ -30,6 +30,7 @@ func BuildFieldsEnvelope(env envelope.FrameEnvelope) (envelope.FrameEnvelope, bo
|
|||||||
if !ok {
|
if !ok {
|
||||||
return envelope.FrameEnvelope{}, false
|
return envelope.FrameEnvelope{}, false
|
||||||
}
|
}
|
||||||
|
statFields := fieldsWithCanonicalStats(fields, env.Fields)
|
||||||
out := envelope.FrameEnvelope{
|
out := envelope.FrameEnvelope{
|
||||||
EventID: env.StableEventID() + ":fields",
|
EventID: env.StableEventID() + ":fields",
|
||||||
TraceID: env.TraceID,
|
TraceID: env.TraceID,
|
||||||
@@ -44,7 +45,7 @@ func BuildFieldsEnvelope(env envelope.FrameEnvelope) (envelope.FrameEnvelope, bo
|
|||||||
SourceEndpoint: env.SourceEndpoint,
|
SourceEndpoint: env.SourceEndpoint,
|
||||||
EventTimeMS: env.EventTimeMS,
|
EventTimeMS: env.EventTimeMS,
|
||||||
ReceivedAtMS: env.ReceivedAtMS,
|
ReceivedAtMS: env.ReceivedAtMS,
|
||||||
Fields: fields,
|
Fields: statFields,
|
||||||
ParsedFields: fields,
|
ParsedFields: fields,
|
||||||
ParsedFieldTypes: fieldTypes,
|
ParsedFieldTypes: fieldTypes,
|
||||||
Parsed: map[string]any{
|
Parsed: map[string]any{
|
||||||
@@ -56,6 +57,22 @@ func BuildFieldsEnvelope(env envelope.FrameEnvelope) (envelope.FrameEnvelope, bo
|
|||||||
return out, true
|
return out, true
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func fieldsWithCanonicalStats(mapped map[string]any, canonical map[string]any) map[string]any {
|
||||||
|
out := cloneAnyMap(mapped)
|
||||||
|
for _, key := range []string{
|
||||||
|
envelope.FieldTotalMileageKM,
|
||||||
|
envelope.FieldSpeedKMH,
|
||||||
|
envelope.FieldSOCPercent,
|
||||||
|
envelope.FieldLongitude,
|
||||||
|
envelope.FieldLatitude,
|
||||||
|
} {
|
||||||
|
if value, ok := canonical[key]; ok && value != nil {
|
||||||
|
out[key] = value
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return out
|
||||||
|
}
|
||||||
|
|
||||||
func EnsureParsedFields(env *envelope.FrameEnvelope) bool {
|
func EnsureParsedFields(env *envelope.FrameEnvelope) bool {
|
||||||
if env == nil {
|
if env == nil {
|
||||||
return false
|
return false
|
||||||
|
|||||||
@@ -39,7 +39,7 @@ func TestRealtimeKVFieldsFromGB32960ParsedDomains(t *testing.T) {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
func TestBuildFieldsEnvelopeUsesOnlyMappedFieldNames(t *testing.T) {
|
func TestBuildFieldsEnvelopeKeepsMappedAndCanonicalStatFields(t *testing.T) {
|
||||||
fieldsEnv, ok := BuildFieldsEnvelope(envelope.FrameEnvelope{
|
fieldsEnv, ok := BuildFieldsEnvelope(envelope.FrameEnvelope{
|
||||||
Protocol: envelope.ProtocolGB32960,
|
Protocol: envelope.ProtocolGB32960,
|
||||||
VIN: "VIN001",
|
VIN: "VIN001",
|
||||||
@@ -65,9 +65,9 @@ func TestBuildFieldsEnvelopeUsesOnlyMappedFieldNames(t *testing.T) {
|
|||||||
if !ok {
|
if !ok {
|
||||||
t.Fatal("BuildFieldsEnvelope() should emit mapped fields")
|
t.Fatal("BuildFieldsEnvelope() should emit mapped fields")
|
||||||
}
|
}
|
||||||
for _, bareKey := range []string{"charge_status", "soc_percent", "total_mileage_km"} {
|
for _, bareKey := range []string{"charge_status"} {
|
||||||
if _, exists := fieldsEnv.Fields[bareKey]; exists {
|
if _, exists := fieldsEnv.Fields[bareKey]; exists {
|
||||||
t.Fatalf("fields envelope should not expose bare env.Fields key %q: %#v", bareKey, fieldsEnv.Fields)
|
t.Fatalf("fields envelope should not expose non-canonical bare env.Fields key %q: %#v", bareKey, fieldsEnv.Fields)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
for _, mappedKey := range []string{
|
for _, mappedKey := range []string{
|
||||||
@@ -79,6 +79,14 @@ func TestBuildFieldsEnvelopeUsesOnlyMappedFieldNames(t *testing.T) {
|
|||||||
t.Fatalf("fields envelope missing mapped key %q: %#v", mappedKey, fieldsEnv.Fields)
|
t.Fatalf("fields envelope missing mapped key %q: %#v", mappedKey, fieldsEnv.Fields)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
for _, canonicalKey := range []string{envelope.FieldSOCPercent, envelope.FieldTotalMileageKM} {
|
||||||
|
if _, exists := fieldsEnv.Fields[canonicalKey]; !exists {
|
||||||
|
t.Fatalf("fields envelope should keep canonical stat key %q: %#v", canonicalKey, fieldsEnv.Fields)
|
||||||
|
}
|
||||||
|
if _, exists := fieldsEnv.ParsedFields[canonicalKey]; exists {
|
||||||
|
t.Fatalf("parsed fields should stay protocol-mapped without canonical duplicate %q: %#v", canonicalKey, fieldsEnv.ParsedFields)
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
func TestRealtimeKVFieldsFromJT808ParsedFields(t *testing.T) {
|
func TestRealtimeKVFieldsFromJT808ParsedFields(t *testing.T) {
|
||||||
|
|||||||
Reference in New Issue
Block a user