package manifestsender import ( "errors" "fmt" "fiskerinc.com/modules/carcommand" "fiskerinc.com/modules/common" "fiskerinc.com/modules/common/manifestfingerprintparams" "fiskerinc.com/modules/db/queries" q "fiskerinc.com/modules/db/queries" "fiskerinc.com/modules/grpc/sms" "fiskerinc.com/modules/logger" "fiskerinc.com/modules/redis" uhelpers "fiskerinc.com/modules/usecase_helpers" "fiskerinc.com/modules/validator" vconfig "fiskerinc.com/modules/vehicleconfig" errorspkg "github.com/pkg/errors" ) var FailedToGetCDS = errors.New("did not send tbox as we had failed to get cds") type ManifestSenderDB interface { GetUpdateManifests() q.UpdateManifestsInterface GetCars() q.CarsInterface GetCarUpdates() q.CarUpdatesInterface } func NewTBOXManifestSender( r redis.Client, conf vconfig.ConfigServiceInterface, db ManifestSenderDB, sms sms.SMSServiceClient, cds map[string]string, ) *TBOXManifestSender { t := &TBOXManifestSender{ Redis: r, db: db, conf: conf, sms: sms, cds: cds, } return t } type TBOXManifestSender struct { Redis redis.Client db ManifestSenderDB conf vconfig.ConfigServiceInterface sms sms.SMSServiceClient cds map[string]string // I think this can/should be removed. Unused in config route } func (t *TBOXManifestSender) Close() { t.Redis = nil } func (t *TBOXManifestSender) addRollback(manifest *common.UpdateManifest, vin string) error { if !manifest.RollbackEnabled { return nil } var err error db := t.db.GetUpdateManifests() for _, ecu := range manifest.ECUs { var rollbacks []*common.UpdateManifestECU rollbacks, err = db.ECURollback(ecu, vin) if err != nil { return errorspkg.WithStack(err) } ecu.Rollback = rollbacks } manifest.RemoveOriginalS19HexFilesRollbacks() return nil } // Prepare a manifest, gets cds data if need be // This is called in two different locations. One form send_manifest.go and another from car_update_progress.go // send_manifest.go includes all the fields one could want, the car_update_progress is not func (t *TBOXManifestSender) ProcessSoftwareUpdate(vin string, manifest *common.UpdateManifest, ccd queries.CarConfigDataInterface) (smsID string, err error) { // Add rollbacks to manifest err = t.addRollback(manifest, vin) if err != nil { return } // No CDS means some tasks in the send_manifest has not been run // like VOD, CDS, ECU sorting, removing original s19 hex files, and current versions if t.cds == nil { var cds map[string]string cds, err = t.getVODCDS(vin, ccd) if err != nil { return } t.cds = cds manifest.SortECUs() manifest.RemoveOriginalS19HexFiles() manifest.RemoveOriginalS19HexFilesRollbacks() err = uhelpers.PopulateECUsCurrentVersion(t.db.GetCars(), vin, manifest.ECUs) if err != nil { return } } // Definitely need to transform the ECU's before the CDS are added so the names all match manifest.TransformECUNames() manifest.AddCDSToECUs(t.cds) manifest.FilterCompatibleECUs(vin) err = t.checkSUMS(manifest) if err != nil { return } fpparams := manifestfingerprintparams.GetFPParams() manifest.GenerateFingerprint(fpparams.CurTime(), fpparams.ManifestSerial()) manifest.Scrub(common.TRex) return t.Send(vin, *manifest) } func (t *TBOXManifestSender) checkSUMS(manifest *common.UpdateManifest) error { if manifest.ManifestType == common.ConfigUpdateType { return nil } err := validator.ValidateField(manifest.SUMS, "required,sums_version") if err == nil { err = manifest.AddSUMSToVOD() } return err } // Send the update_manifest out redis to Trex, assume the manifest is all ready to go // If we try to send a wakeup sms and the car does not have an ICCID we do not fail, as hopefully it it a test trex func (t *TBOXManifestSender) Send(vin string, manifest common.UpdateManifest) (smsID string, err error) { logger.Debug().Msgf("Sending redis queue- %s, key- %s, hander- %s, data- %v", "manifestsender", vin, "update_manifest", manifest) err = t.Redis.SafeQueueMessage(common.TRex.Key(vin), common.Message{ Handler: "update_manifest", Data: manifest, }) if err != nil { return "", err } // Here need to wake it up again logger.At(logger.Info(), common.TRex.Key(vin), "update").Msgf("TBOXManifestSender sent %v %s %d", common.TRex, vin, manifest.CarUpdateID) if manifest.Type == common.ManifestTypeForced { var queueResponse *sms.SMSQueueResponse queueResponse, err = carcommand.QueueSMSWakeUp(vin, true, t.Redis, t.db.GetCars(), t.sms) if err != nil { if errors.Is(err, carcommand.ErrNoICCIDForWakeUp) { err = nil queueResponse.SentSuccessful = true } else { return "", err } } if queueResponse.SentSuccessful { smsID = queueResponse.SmsMsgID } else { err = fmt.Errorf("failed to awake car for Send TBOXManifestSender for vin: %s, car update: %d", vin, manifest.CarUpdateID) } } return smsID, err } func (t *TBOXManifestSender) getVODCDS(vin string, db queries.CarConfigDataInterface) (map[string]string, error) { return uhelpers.GetCDS(t.conf, db, vin) }