feat: expose vehicle map data APIs

This commit is contained in:
lingniu
2026-08-03 19:55:38 +08:00
parent 3c4bece72c
commit 8539af13e6
8 changed files with 492 additions and 7 deletions

View File

@@ -137,6 +137,90 @@ func (r *MySQLRepository) TotalMileage(ctx context.Context, vin string, at time.
return nil, nil
}
func (r *MySQLRepository) RealtimeVehicles(ctx context.Context, vins []string, now time.Time) (map[string]RealtimeVehiclePoint, error) {
out := make(map[string]RealtimeVehiclePoint, len(vins))
if len(vins) == 0 {
return out, nil
}
placeholders := strings.TrimRight(strings.Repeat("?,", len(vins)), ",")
args := make([]any, 0, len(vins)+1)
for _, vin := range vins {
args = append(args, vin)
}
args = append(args, now.Add(-10*time.Minute))
query := `
SELECT l.vin,l.protocol,COALESCE(l.longitude,0),COALESCE(l.latitude,0),
COALESCE(l.speed_kmh,0),COALESCE(l.total_mileage_km,0),l.updated_at
FROM vehicle_realtime_location l
WHERE BINARY l.vin IN (` + placeholders + `)
ORDER BY l.vin,
CASE WHEN l.updated_at>=? THEN 0 ELSE 1 END,
CASE l.protocol WHEN 'GB32960' THEN 10 WHEN 'YUTONG_MQTT' THEN 20 WHEN 'JT808' THEN 30 ELSE 100 END,
l.updated_at DESC,l.protocol ASC`
rows, err := r.db.QueryContext(ctx, query, args...)
if err != nil {
return nil, err
}
defer rows.Close()
for rows.Next() {
var point RealtimeVehiclePoint
if err := rows.Scan(&point.VIN, &point.Protocol, &point.Longitude, &point.Latitude, &point.SpeedKmh, &point.TotalMileageKm, &point.ObservedAt); err != nil {
return nil, err
}
if _, exists := out[point.VIN]; !exists {
out[point.VIN] = point
}
}
return out, rows.Err()
}
func (r *MySQLRepository) HydrogenStations(ctx context.Context, request HydrogenStationRequest) ([]HydrogenStation, error) {
where := []string{
"s.longitude BETWEEN -180 AND 180",
"s.latitude BETWEEN -90 AND 90",
"NOT (s.longitude=0 AND s.latitude=0)",
}
args := make([]any, 0, 3)
if request.Province != "" {
where = append(where, "s.province=?")
args = append(args, request.Province)
}
if request.City != "" {
where = append(where, "s.city=?")
args = append(args, request.City)
}
if request.CooperateOnly != nil {
if *request.CooperateOnly {
where = append(where, "s.inner_site_id IS NOT NULL")
} else {
where = append(where, "s.inner_site_id IS NULL")
}
}
rows, err := r.db.QueryContext(ctx, `
SELECT CAST(s.id AS CHAR),COALESCE(NULLIF(s.fixed_station_name,''),NULLIF(s.station_name,''),''),
COALESCE(h.station_short_name,''),COALESCE(s.station_address,''),
s.longitude,s.latitude,COALESCE(s.province,''),COALESCE(s.city,''),COALESCE(s.district,''),
CASE WHEN s.inner_site_id IS NULL THEN 0 ELSE 1 END
FROM ln_asset_management.tab_outside_hydrogen_site s
LEFT JOIN ln_asset_management.hydrogen_station h ON h.id=s.inner_site_id AND h.del_flag='0'
WHERE `+strings.Join(where, " AND ")+`
ORDER BY s.province,s.city,s.fixed_station_name,s.id
LIMIT 2000`, args...)
if err != nil {
return nil, err
}
defer rows.Close()
stations := make([]HydrogenStation, 0, 512)
for rows.Next() {
var station HydrogenStation
if err := rows.Scan(&station.ID, &station.Name, &station.ShortName, &station.Address, &station.Longitude, &station.Latitude, &station.Province, &station.City, &station.District, &station.Cooperative); err != nil {
return nil, err
}
stations = append(stations, station)
}
return stations, rows.Err()
}
func (r *MySQLRepository) DailyHydrogen(ctx context.Context, vins []string, date string) (map[string]DailyHydrogen, error) {
if len(vins) == 0 {
return map[string]DailyHydrogen{}, nil