feat: expand vehicle data platform capabilities

This commit is contained in:
lingniu
2026-07-27 16:46:15 +08:00
parent e3a1f80f86
commit 3c4bece72c
650 changed files with 62155 additions and 2552 deletions

View File

@@ -53,20 +53,23 @@ type Writer struct {
projectionKeysByPrefix map[string]map[string]struct{}
baselineKeysByPrefix map[string]map[string]struct{}
lastGPSAccumulation map[string]time.Time
hydrogenTankCapacities map[string]float64
gpsAccumulationInterval time.Duration
}
type MetricSample struct {
VIN string
Protocol envelope.Protocol
StatDate string
TotalMileageKM float64
EventTime time.Time
SourceKey string
Phone string
DeviceID string
SourceEndpoint string
PlatformName string
VIN string
Protocol envelope.Protocol
StatDate string
TotalMileageKM float64
EventTime time.Time
SourceKey string
Phone string
DeviceID string
SourceEndpoint string
PlatformName string
PureHydrogenActive bool
PureHydrogenModeKnown bool
}
type AppendResult struct {
@@ -91,6 +94,11 @@ type AppendResult struct {
ProjectionsAttempted int
ProjectionsWritten int
ProjectionsSkippedThrottled int
HydrogenSamplesFound int
HydrogenSamplesWritten int
HydrogenSamplesDuplicate int
HydrogenSamplesInvalid int
HydrogenSamplesNotCurrent int
}
type ProjectionFlushResult struct {
@@ -161,6 +169,7 @@ func NewWriter(exec Execer, loc *time.Location) *Writer {
projectionKeysByPrefix: map[string]map[string]struct{}{},
baselineKeysByPrefix: map[string]map[string]struct{}{},
lastGPSAccumulation: map[string]time.Time{},
hydrogenTankCapacities: map[string]float64{},
gpsAccumulationInterval: defaultGPSAccumulationInterval,
}
if query, ok := exec.(Queryer); ok {
@@ -169,6 +178,25 @@ func NewWriter(exec Execer, loc *time.Location) *Writer {
return writer
}
func (w *Writer) ReloadHydrogenTankCapacities(ctx context.Context) (int, error) {
capacities, err := LoadHydrogenTankCapacities(ctx, w.query)
if err != nil {
return 0, err
}
w.mu.Lock()
w.hydrogenTankCapacities = capacities
w.mu.Unlock()
return len(capacities), nil
}
func (w *Writer) HydrogenTankCapacityLiters(vin string) (float64, bool) {
vin = strings.ToUpper(strings.TrimSpace(vin))
w.mu.Lock()
defer w.mu.Unlock()
capacity, ok := w.hydrogenTankCapacities[vin]
return capacity, ok
}
func (w *Writer) SetSourceTouchInterval(interval time.Duration) {
w.mu.Lock()
defer w.mu.Unlock()
@@ -273,6 +301,8 @@ func (w *Writer) EnsureSchema(ctx context.Context) error {
GPSMileageStateTableSQL,
DailyMileageSourceTableSQL,
DailyMileageTableSQL,
HydrogenTankCapacityTableSQL,
HydrogenStreamStateTableSQL,
} {
if _, err := w.exec.ExecContext(ctx, statement); err != nil {
return err
@@ -300,6 +330,16 @@ func (w *Writer) AppendWithResult(ctx context.Context, env envelope.FrameEnvelop
seenAt := w.sourceSeenAt(env)
w.maybeCleanupCaches(seenAt)
identity, hasSource := NewSourceIdentityFromEnvelope(env)
capacityLiters, _ := w.HydrogenTankCapacityLiters(env.VIN)
hydrogen, err := AppendHydrogenStream(ctx, w.exec, env, w.loc, time.Now(), capacityLiters)
if err != nil {
return result, err
}
result.HydrogenSamplesFound = hydrogen.Found
result.HydrogenSamplesWritten = hydrogen.Written
result.HydrogenSamplesDuplicate = hydrogen.Duplicate
result.HydrogenSamplesInvalid = hydrogen.Invalid
result.HydrogenSamplesNotCurrent = hydrogen.NotCurrent
var sourceResult AppendResult
if hasSource && ShouldManageDataSource(identity) {
if w.shouldTouchSource(identity, seenAt) {
@@ -316,6 +356,11 @@ func (w *Writer) AppendWithResult(ctx context.Context, env envelope.FrameEnvelop
sourceResult.SourceTouchesSkippedUnmanaged = 1
}
samples, extractionResult, err := samplesFromEnvelopeWithResult(env, w.loc)
extractionResult.HydrogenSamplesFound = result.HydrogenSamplesFound
extractionResult.HydrogenSamplesWritten = result.HydrogenSamplesWritten
extractionResult.HydrogenSamplesDuplicate = result.HydrogenSamplesDuplicate
extractionResult.HydrogenSamplesInvalid = result.HydrogenSamplesInvalid
extractionResult.HydrogenSamplesNotCurrent = result.HydrogenSamplesNotCurrent
result = extractionResult
result.SourceTouchesAttempted += sourceResult.SourceTouchesAttempted
result.SourceTouchesWritten += sourceResult.SourceTouchesWritten
@@ -1191,18 +1236,21 @@ func samplesFromEnvelopeWithResult(env envelope.FrameEnvelope, loc *time.Locatio
result.SamplesAdjustedFutureEventTime = 1
}
statDate := time.UnixMilli(eventMS).In(loc).Format("2006-01-02")
pureHydrogenActive, pureHydrogenModeKnown := PureHydrogenModeFromEnvelope(env)
result.SamplesFound = 1
return []MetricSample{{
VIN: vin,
Protocol: env.Protocol,
StatDate: statDate,
TotalMileageKM: totalMileage,
EventTime: time.UnixMilli(eventMS).In(loc),
SourceKey: sourceKey(env),
Phone: strings.TrimSpace(env.Phone),
DeviceID: strings.TrimSpace(env.DeviceID),
SourceEndpoint: strings.TrimSpace(env.SourceEndpoint),
PlatformName: strings.TrimSpace(env.PlatformName),
VIN: vin,
Protocol: env.Protocol,
StatDate: statDate,
TotalMileageKM: totalMileage,
EventTime: time.UnixMilli(eventMS).In(loc),
SourceKey: sourceKey(env),
Phone: strings.TrimSpace(env.Phone),
DeviceID: strings.TrimSpace(env.DeviceID),
SourceEndpoint: strings.TrimSpace(env.SourceEndpoint),
PlatformName: strings.TrimSpace(env.PlatformName),
PureHydrogenActive: pureHydrogenActive,
PureHydrogenModeKnown: pureHydrogenModeKnown,
}}, result, nil
}