Files
lingniu-vehicle-ingest/go/vehicle-gateway/internal/feichibridge/model.go

95 lines
2.1 KiB
Go

package feichibridge
import (
"encoding/json"
"fmt"
"strconv"
"strings"
"time"
)
var shanghai = time.FixedZone("Asia/Shanghai", 8*60*60)
type Vehicle struct {
VehicleID string `json:"vehicleId"`
VIN string `json:"vin"`
OnlineStatus any `json:"onlineStatus"`
UpdateTime string `json:"updateTime"`
RuleTypeName string `json:"ruleTypeName"`
}
type Snapshot struct {
VehicleID string `json:"vehicleId"`
VIN string `json:"vin"`
DataItems map[string]string `json:"dataItems"`
}
type Record map[string]string
type collectionEnvelope[T any] struct {
Code any `json:"code"`
Data []T `json:"data"`
}
type objectEnvelope[T any] struct {
Code any `json:"code"`
Data T `json:"data"`
}
type historySegment struct {
Subdata []Record `json:"subdata"`
}
func apiCodeOK(code any) bool {
switch value := code.(type) {
case nil:
return true
case float64:
return value == 0 || value == 200
case string:
return value == "" || value == "0" || value == "200"
default:
return false
}
}
func recordTime(record Record) (time.Time, error) {
for _, key := range []string{"2000", "9999", "dataTime", "updateTime", "time"} {
if raw := strings.TrimSpace(record[key]); raw != "" {
return parseSourceTime(raw)
}
}
return time.Time{}, fmt.Errorf("source record has no timestamp")
}
func parseSourceTime(raw string) (time.Time, error) {
raw = strings.TrimSpace(raw)
for _, layout := range []string{
"2006-01-02 15:04:05",
"2006-01-02T15:04:05",
time.RFC3339Nano,
} {
if layout == time.RFC3339Nano {
if parsed, err := time.Parse(layout, raw); err == nil {
return parsed, nil
}
continue
}
if parsed, err := time.ParseInLocation(layout, raw, shanghai); err == nil {
return parsed, nil
}
}
if unixMS, err := strconv.ParseInt(raw, 10, 64); err == nil {
if unixMS < 10_000_000_000 {
return time.Unix(unixMS, 0).In(shanghai), nil
}
return time.UnixMilli(unixMS).In(shanghai), nil
}
return time.Time{}, fmt.Errorf("unsupported source timestamp %q", raw)
}
func canonicalHash(record Record) string {
encoded, _ := json.Marshal(record)
return hashBytes(encoded)
}