package towmanparklocation import ( "sync" "time" "fiskerinc.com/modules/cachev2" "fiskerinc.com/modules/db" "fiskerinc.com/modules/logger" "fiskerinc.com/modules/redisv2" ) func (plt *ParkLocationTracker) VCUGearSig(vin string, newState int) { // Fast exit if the car is not being parked if newState != 1 { return } _, ok := plt.WatchList[vin] if !ok { return } // WRITE park location to DB // DOn't want to slow down the signal processing, so do this async go plt.recordParkLocation(vin) } // Probably would be better with a channel and a worker, but this is fine for now func (plt *ParkLocationTracker) recordParkLocation(vin string) { // Fetch the location from redis -- how did copilot know this? location, err := cachev2.GetVehicleLocation(vin, plt.RedisClient) if err != nil { logger.Err(err).Str("VIN", vin).Msg("failed to get vehicle location for park location") return } // Write to DB _, err = plt.DBClient.GetConn().Exec("INSERT INTO towman.parked_locations (vin, latitude, longitude) VALUES (?, ?, ?)", vin, location.Latitude, location.Longitude) if err != nil { logger.Err(err).Str("VIN", vin).Msg("failed to record park location to DB") return } } func (plt *ParkLocationTracker) UpdateVehicleList() { dbVINS := []string{} _, err := plt.DBClient.GetConn().Query(&dbVINS, "SELECT vin FROM towman.vehicles") if err != nil { logger.Err(err).Msg("failed to update parked vehicle list") return } // Make anew watchmap newWatchList := make(map[string]struct{}) for _, vin := range dbVINS { newWatchList[vin] = struct{}{} } // Only need to lock before we assign the new map plt.WatchListSync.Lock() defer plt.WatchListSync.Unlock() // assign watchmap plt.WatchList = newWatchList } func (plt *ParkLocationTracker) IsVehicleWatched(vin string) (watched bool) { plt.WatchListSync.RLock() _, ok := plt.WatchList[vin] plt.WatchListSync.RUnlock() return ok } func InitParkLocationTracker(dbClient *db.DBClient, redisClient *redisv2.Connection) (plt *ParkLocationTracker) { plt = &ParkLocationTracker{ WatchList: make(map[string]struct{}), } plt.DBClient = dbClient plt.RedisClient = redisClient go plt.SeedDaily() return } // This list won't update that often func (plt *ParkLocationTracker) SeedDaily() { plt.UpdateVehicleList() time.AfterFunc(time.Hour*24, plt.SeedDaily) } type ParkLocationTracker struct { WatchList map[string]struct{} // VINs being tracked for parking location DBClient *db.DBClient RedisClient *redisv2.Connection WatchListSync sync.RWMutex }