144 lines
4.6 KiB
Go
144 lines
4.6 KiB
Go
package manifestsender
|
|
|
|
import (
|
|
"fmt"
|
|
"time"
|
|
|
|
"errors"
|
|
|
|
"github.com/fiskerinc/cloud-services/pkg/carcommand"
|
|
"github.com/fiskerinc/cloud-services/pkg/common"
|
|
"github.com/fiskerinc/cloud-services/pkg/common/carupdatestatus"
|
|
"github.com/fiskerinc/cloud-services/pkg/db/queries"
|
|
"github.com/fiskerinc/cloud-services/pkg/logger"
|
|
"github.com/fiskerinc/cloud-services/pkg/utils/whereami"
|
|
)
|
|
|
|
// ProcessConfigUpdate handles all steps on the config only update
|
|
// It will create a car_update record, manifest record, car_update_status record
|
|
type ProcessConfigUpdateStruct struct {
|
|
VIN string // The vin of the car that configuration we are generating
|
|
Username string // The username of who is generating this update
|
|
Name string // The name of the generated manifest, leave blank for auto generated. name,version is enforced unique
|
|
SendToCar bool // True to send the manifest to the car
|
|
DontCreateDatabaseEntry bool // False to create database entry, by default. Cannot be true with SendToCar being true
|
|
Forced bool
|
|
}
|
|
|
|
var ERR_SEND_AND_DATABASE_MISMATCH = errors.New("cannot send to car with dont create database entry")
|
|
|
|
// If called from aftersales, this will be marked as an aftersales update, which are not sent to the car
|
|
// and they are automatically cancelled when they are hit cancel on the portal
|
|
func (t *TBOXManifestSender) ProcessConfigUpdate(input ProcessConfigUpdateStruct, ccd queries.CarConfigDataInterface) (ucm common.UpdateConfigManifest, err error) {
|
|
if input.DontCreateDatabaseEntry && input.SendToCar {
|
|
return ucm, ERR_SEND_AND_DATABASE_MISMATCH
|
|
}
|
|
|
|
// We have the send to car, so that should be all the info we need to make changes based on the system :()()
|
|
// Get the VOD and CDSs for the car
|
|
cds, err := t.getVODCDS(input.VIN, ccd)
|
|
if err != nil {
|
|
return
|
|
}
|
|
|
|
manifest := common.UpdateManifest{}
|
|
if input.Name != "" {
|
|
manifest.Name = input.Name
|
|
} else {
|
|
manifest.Name = fmt.Sprintf("configuration update %s %s", input.VIN, time.Now().Format("2006-01-02"))
|
|
}
|
|
|
|
manifest.Version = time.Now().Format("2006-01-02 15:04:05")
|
|
manifest.Description = fmt.Sprintf("configuration for %s by %s", input.VIN, input.Username)
|
|
manifest.ManifestType = common.ConfigUpdateType
|
|
|
|
if input.Forced {
|
|
manifest.Type = common.ManifestTypeForced
|
|
} else {
|
|
manifest.Type = common.ManifestTypeStandard
|
|
}
|
|
|
|
manifestDB := t.db.GetUpdateManifests()
|
|
if !input.DontCreateDatabaseEntry {
|
|
_, err = manifestDB.Insert(&manifest)
|
|
if err != nil {
|
|
return
|
|
}
|
|
}
|
|
|
|
// AddCDSToECUs calls AddVOD
|
|
// AddECUsFromCDSList requires the manifest having been inserted so that they
|
|
// have the manifestID
|
|
manifest.AddECUsFromCDSList(cds)
|
|
manifest.SortECUs()
|
|
manifest.FillECUList()
|
|
|
|
// Create a car update for this manifest ot be sent as
|
|
updatesDB := t.db.GetCarUpdates()
|
|
update := common.CarUpdate{
|
|
VIN: input.VIN,
|
|
UpdateManifestID: manifest.ID,
|
|
UpdateManifest: &manifest,
|
|
Username: input.Username,
|
|
Status: carupdatestatus.Pending,
|
|
}
|
|
|
|
if whereami.Service == whereami.AFTERSALES {
|
|
input.SendToCar = false
|
|
update.UpdateSource = common.UPDATE_SOURCE_AFTERSALES
|
|
} else {
|
|
update.UpdateSource = common.UPDATE_SOURCE_OTA
|
|
}
|
|
|
|
err = insertUpdateDatabase(input, updatesDB, manifestDB, manifest, &update)
|
|
if err != nil {
|
|
return
|
|
}
|
|
|
|
manifest.CarUpdateID = update.ID
|
|
|
|
manifest.Scrub(common.TRex)
|
|
ucm = manifest.ToUpdateConfigManifest()
|
|
|
|
if !input.SendToCar {
|
|
return
|
|
}
|
|
return ucm, t.SendConfig(input.VIN, ucm)
|
|
}
|
|
|
|
func insertUpdateDatabase(input ProcessConfigUpdateStruct, updatesDB queries.CarUpdatesInterface, manifestDB queries.UpdateManifestsInterface, manifest common.UpdateManifest, update *common.CarUpdate) (err error) {
|
|
if !input.DontCreateDatabaseEntry {
|
|
_, err = updatesDB.InsertAndCreateStatus(update)
|
|
if err != nil {
|
|
_, err2 := manifestDB.Delete(&manifest)
|
|
if err2 != nil {
|
|
err = errors.Join(err, err2)
|
|
}
|
|
return
|
|
}
|
|
}
|
|
return
|
|
}
|
|
|
|
func (t *TBOXManifestSender) SendConfig(vin string, manifest common.UpdateConfigManifest) (err error) {
|
|
err = t.Redis.SafeQueueMessage(common.TRex.Key(vin), common.Message{
|
|
Handler: "config_update",
|
|
Data: manifest,
|
|
})
|
|
if err != nil {
|
|
return err
|
|
}
|
|
|
|
logger.At(logger.Info(), common.TRex.Key(vin), "update").Msgf("TBOXManifestSender sent %v %s %d", common.TRex, vin, manifest.CarUpdateID)
|
|
|
|
// For now, do not check on config update if the car wakes up correctly
|
|
if manifest.Type == common.ManifestTypeForced && t.sms != nil{
|
|
_, err = carcommand.QueueSMSWakeUp(vin, false, t.Redis, t.db.GetCars(), t.sms)
|
|
if err != nil {
|
|
return err
|
|
}
|
|
}
|
|
|
|
return nil
|
|
}
|