Initial cloud-services repo - gateway service + pkg modules
This commit is contained in:
28
pkg/usecase_helpers/ecu_keys.go
Normal file
28
pkg/usecase_helpers/ecu_keys.go
Normal file
@@ -0,0 +1,28 @@
|
||||
package usecase_helpers
|
||||
|
||||
import (
|
||||
"fiskerinc.com/modules/common"
|
||||
"fiskerinc.com/modules/db/queries"
|
||||
)
|
||||
|
||||
func NewECUKeys(eccKeys queries.EccKeysInterface) *EcuKeys {
|
||||
return &EcuKeys{
|
||||
eccKeys: eccKeys,
|
||||
}
|
||||
}
|
||||
|
||||
type EcuKeys struct {
|
||||
eccKeys queries.EccKeysInterface
|
||||
}
|
||||
|
||||
func (e EcuKeys) AddECUECCKeys(manifest *common.UpdateManifest) error {
|
||||
ecus := manifest.GetECUs()
|
||||
keys, err := e.eccKeys.SelectPrivateKeysByECUsEnv(ecus, manifest.Env)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
manifest.AddECUECCKeys(keys)
|
||||
|
||||
return nil
|
||||
}
|
||||
34
pkg/usecase_helpers/ecus.go
Normal file
34
pkg/usecase_helpers/ecus.go
Normal file
@@ -0,0 +1,34 @@
|
||||
package usecase_helpers
|
||||
|
||||
import (
|
||||
"fiskerinc.com/modules/common"
|
||||
"fiskerinc.com/modules/db/queries"
|
||||
)
|
||||
|
||||
// PopulateECUsCurrentVersion adds CurrentVersion field in provided ecus list of
|
||||
// a specific vehicle, defined by vin.
|
||||
// Since the ecus amount doesn't change, we don't need returning ecus and
|
||||
// caller can use the same variable he provided in the function.
|
||||
func PopulateECUsCurrentVersion(cars queries.CarsInterface, vin string, ecus []*common.UpdateManifestECU) error {
|
||||
ids := make([]string, 0, len(ecus))
|
||||
for _, ecu := range ecus {
|
||||
ids = append(ids, ecu.ECU)
|
||||
}
|
||||
|
||||
carECUs, err := cars.GetCarECUs(common.CarECUFilter{VIN: vin, ECUs: ids, Unique: true}, nil)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
carECUsMap := make(map[string]string, len(carECUs))
|
||||
for _, ecu := range carECUs {
|
||||
carECUsMap[ecu.ECU] = ecu.Version
|
||||
}
|
||||
|
||||
for index, ecu := range ecus {
|
||||
ecu.CurrentVersion = carECUsMap[ecu.ECU]
|
||||
ecus[index] = ecu
|
||||
}
|
||||
|
||||
return nil
|
||||
}
|
||||
78
pkg/usecase_helpers/ecus_test.go
Normal file
78
pkg/usecase_helpers/ecus_test.go
Normal file
@@ -0,0 +1,78 @@
|
||||
package usecase_helpers
|
||||
|
||||
import (
|
||||
"testing"
|
||||
|
||||
m "fiskerinc.com/modules/common"
|
||||
"fiskerinc.com/modules/db/queries"
|
||||
"fiskerinc.com/modules/db/queries/mocks"
|
||||
"github.com/pkg/errors"
|
||||
"github.com/stretchr/testify/assert"
|
||||
)
|
||||
|
||||
var someErr = errors.New("some err")
|
||||
|
||||
func TestPopulateECUsCurrentVersion(t *testing.T) {
|
||||
mockVIN := ""
|
||||
tests := map[string]struct {
|
||||
cars queries.CarsInterface
|
||||
ecus []*m.UpdateManifestECU
|
||||
expEcus []*m.UpdateManifestECU
|
||||
expErr error
|
||||
}{
|
||||
"correct": {
|
||||
cars: &mocks.MockCars{
|
||||
SelectCarECUs: []m.CarECU{
|
||||
{ECU: "TREX", Version: " S213C213"},
|
||||
{ECU: "PKC", Version: " S213C222"},
|
||||
},
|
||||
},
|
||||
ecus: []*m.UpdateManifestECU{
|
||||
{ECU: "TREX"},
|
||||
{ECU: "PKC"},
|
||||
{ECU: "MPT"},
|
||||
},
|
||||
expEcus: []*m.UpdateManifestECU{
|
||||
{ECU: "TREX", CurrentVersion: " S213C213"},
|
||||
{ECU: "PKC", CurrentVersion: " S213C222"},
|
||||
{ECU: "MPT"},
|
||||
},
|
||||
},
|
||||
"empty_car_ecus": {
|
||||
cars: &mocks.MockCars{},
|
||||
ecus: []*m.UpdateManifestECU{
|
||||
{ECU: "TREX"},
|
||||
{ECU: "PKC"},
|
||||
{ECU: "MPT"},
|
||||
},
|
||||
expEcus: []*m.UpdateManifestECU{
|
||||
{ECU: "TREX"},
|
||||
{ECU: "PKC"},
|
||||
{ECU: "MPT"},
|
||||
},
|
||||
},
|
||||
"get_car_ecus_error": {
|
||||
cars: &mocks.MockCars{
|
||||
DBMockHelper: mocks.DBMockHelper{Error: someErr},
|
||||
},
|
||||
ecus: []*m.UpdateManifestECU{
|
||||
{ECU: "TREX"},
|
||||
{ECU: "PKC"},
|
||||
{ECU: "MPT"},
|
||||
},
|
||||
expErr: someErr,
|
||||
},
|
||||
}
|
||||
|
||||
for tname, tt := range tests {
|
||||
t.Run(tname, func(t *testing.T) {
|
||||
err := PopulateECUsCurrentVersion(tt.cars, mockVIN, tt.ecus)
|
||||
if err != nil && tt.expErr != nil {
|
||||
assert.Equal(t, tt.expErr.Error(), err.Error())
|
||||
return
|
||||
}
|
||||
assert.Equal(t, tt.expErr, err)
|
||||
assert.Equal(t, tt.expEcus, tt.ecus)
|
||||
})
|
||||
}
|
||||
}
|
||||
174
pkg/usecase_helpers/get_cds.go
Normal file
174
pkg/usecase_helpers/get_cds.go
Normal file
@@ -0,0 +1,174 @@
|
||||
package usecase_helpers
|
||||
|
||||
import (
|
||||
"encoding/hex"
|
||||
"encoding/json"
|
||||
"fmt"
|
||||
"strings"
|
||||
|
||||
"fiskerinc.com/modules/common"
|
||||
"fiskerinc.com/modules/db/queries"
|
||||
"fiskerinc.com/modules/logger"
|
||||
"fiskerinc.com/modules/utils/envtool"
|
||||
"fiskerinc.com/modules/utils/vod"
|
||||
vconfig "fiskerinc.com/modules/vehicleconfig"
|
||||
"github.com/go-pg/pg/v10"
|
||||
"github.com/pkg/errors"
|
||||
)
|
||||
|
||||
var noCDSResult = map[string]string{}
|
||||
|
||||
func GetCDS(config vconfig.ConfigServiceInterface, ccd queries.CarConfigDataInterface, vin string) (map[string]string, error) {
|
||||
// if SAP is not available, get the stored feature codes instead
|
||||
conf, err := getStoredFeatureCodes(vin, ccd)
|
||||
if err != nil {
|
||||
logger.At(logger.Error(), common.TRex.Key(vin), "update").
|
||||
Err(err).Send()
|
||||
|
||||
return nil, err
|
||||
}
|
||||
|
||||
if len(conf.Features) == 0 {
|
||||
return noCDSResult, nil
|
||||
}
|
||||
|
||||
featureCodes := make([]string, 0, len(conf.Features))
|
||||
for _, f := range conf.Features {
|
||||
featureCodes = append(featureCodes, f.FeatureCode)
|
||||
}
|
||||
|
||||
sYear := fmt.Sprint(conf.ModelYear)
|
||||
if len(sYear) > 2 {
|
||||
sYear = sYear[2:]
|
||||
}
|
||||
|
||||
pdxVersion := getPDXVersion(vin)
|
||||
vodcdsReq := common.NewVODCDSRequest()
|
||||
vodcdsReq.ModelYear = sYear
|
||||
vodcdsReq.VersionDModelYear = conf.VersionDuringModelYear
|
||||
vodcdsReq.FeatureCodes = featureCodes
|
||||
vodcdsReq.PDXIndexVersion = pdxVersion
|
||||
vodcdsReq.VehicleVIN = vin
|
||||
|
||||
cdsMap, err := config.GetCDS(vodcdsReq)
|
||||
if err != nil {
|
||||
logger.At(logger.Error(), common.TRex.Key(vin), "update").
|
||||
Str("request", fmt.Sprintf("%v", vodcdsReq)).
|
||||
Err(err).Send()
|
||||
return nil, err
|
||||
}
|
||||
|
||||
// Lazy way to fix some tests instead of fixing the tests
|
||||
bcm, ok := cdsMap["BCM"]
|
||||
if ok {
|
||||
bcm = overwriteBCMBeep(bcm)
|
||||
bcm = overwriteBCMSequentialLighting(bcm)
|
||||
cdsMap["BCM"] = bcm
|
||||
}
|
||||
icc, ok := cdsMap["ICC"]
|
||||
if ok {
|
||||
icc = overwriteICCHotSpot(icc)
|
||||
cdsMap["ICC"] = icc
|
||||
}
|
||||
|
||||
cdsMap = cdsNameTransform(cdsMap)
|
||||
cdsMap = cdsRemoval(cdsMap)
|
||||
return cdsMap, nil
|
||||
}
|
||||
|
||||
func overwriteBCMBeep(bcm string) string {
|
||||
// COD_Sirene_Master_beep_type adding rule 161300 -> no beep.
|
||||
bcmR := []rune(bcm)
|
||||
bcmR[39] = '0'
|
||||
bcm = string(bcmR)
|
||||
|
||||
return overwriteCalc(bcm)
|
||||
}
|
||||
|
||||
func overwriteBCMSequentialLighting(bcm string) string {
|
||||
bcmR := []rune(bcm)
|
||||
bcmR[25] = '1'
|
||||
bcm = string(bcmR)
|
||||
|
||||
return overwriteCalc(bcm)
|
||||
}
|
||||
|
||||
func overwriteICCHotSpot(icc string) string {
|
||||
// COD_Car_as_Hotspot removal of rule 130100 -> without. !130100 is with hotspot
|
||||
iccR := []rune(icc)
|
||||
iccR[127] = '1'
|
||||
icc = string(iccR)
|
||||
|
||||
return overwriteCalc(icc)
|
||||
}
|
||||
|
||||
// Given the modified coding string, we will calculate the hex values and such
|
||||
func overwriteCalc(ecu string) string {
|
||||
vodHelper := vod.NewVODHelper(false, false, false)
|
||||
|
||||
hexECU, err := hex.DecodeString(ecu)
|
||||
if err != nil {
|
||||
panic(err)
|
||||
}
|
||||
// chop off CRC
|
||||
hexECU = hexECU[:len(hexECU)-1]
|
||||
// CRC does not include short vin value
|
||||
steinway := hexECU[9:]
|
||||
crc := vodHelper.GenerateCRC(steinway)
|
||||
//crc := crc8.Checksum(hexBCMData, v.table)
|
||||
|
||||
hexECU = append(hexECU, crc)
|
||||
|
||||
ecu = hex.EncodeToString(hexECU)
|
||||
ecu = strings.ToUpper(ecu)
|
||||
return ecu
|
||||
}
|
||||
|
||||
func getStoredFeatureCodes(vin string, db queries.CarConfigDataInterface) (common.SAPResponse, error) {
|
||||
config, err := db.SelectByVIN(vin)
|
||||
if err != nil {
|
||||
if errors.Is(err, pg.ErrNoRows) {
|
||||
// Default config if none is available in db
|
||||
config = common.CarConfigData{
|
||||
ConfigData: `{"modelYear":0,"versionDuringModelYear":"","modelType":"","features":[]}`,
|
||||
}
|
||||
err = nil
|
||||
} else {
|
||||
return common.SAPResponse{}, err
|
||||
}
|
||||
}
|
||||
|
||||
var parsedConfig common.SAPResponse
|
||||
|
||||
err = json.Unmarshal([]byte(config.ConfigData), &parsedConfig)
|
||||
|
||||
return parsedConfig, err
|
||||
}
|
||||
|
||||
func getPDXVersion(vin string) (pdxVersion string) {
|
||||
return envtool.GetEnv("PDX_FILE_VERSION", "V3.20.0")
|
||||
}
|
||||
|
||||
// Need to replace certain names to match up with new ones, and remove ECU's that arn't being coded
|
||||
func cdsNameTransform(cdsMap map[string]string) map[string]string {
|
||||
for ecuName, ecuReplacement := range common.ECUReplacement() {
|
||||
cdsString, ok := cdsMap[ecuName]
|
||||
if !ok {
|
||||
continue
|
||||
}
|
||||
delete(cdsMap, ecuName)
|
||||
cdsMap[ecuReplacement] = cdsString
|
||||
}
|
||||
return cdsMap
|
||||
}
|
||||
|
||||
// Run this after the name transform. If the ecu is not in the list to send, don't send it
|
||||
func cdsRemoval(cdsMap map[string]string) map[string]string {
|
||||
for ecuName := range cdsMap {
|
||||
_, ok := common.FilterECUConfigurationMap[ecuName]
|
||||
if ok {
|
||||
delete(cdsMap, ecuName)
|
||||
}
|
||||
}
|
||||
return cdsMap
|
||||
}
|
||||
142
pkg/usecase_helpers/get_cds_test.go
Normal file
142
pkg/usecase_helpers/get_cds_test.go
Normal file
@@ -0,0 +1,142 @@
|
||||
package usecase_helpers
|
||||
|
||||
import (
|
||||
"encoding/json"
|
||||
"os"
|
||||
"testing"
|
||||
|
||||
"fiskerinc.com/modules/common"
|
||||
"fiskerinc.com/modules/db"
|
||||
"fiskerinc.com/modules/db/queries"
|
||||
"github.com/stretchr/testify/assert"
|
||||
)
|
||||
|
||||
func init() {
|
||||
os.Setenv("NO_CDS_ECUS", "VCU, NTN")
|
||||
}
|
||||
|
||||
func TestCDSRenameAndRemoval(t *testing.T) {
|
||||
common.BuildFilterECUConfigurationMap()
|
||||
cdsMap := map[string]string{
|
||||
"GW": "000547303031313632FF7CFF7F0040",
|
||||
"VCU": "0003473030313136320102010A",
|
||||
"PDU": "00024730303131363202768F",
|
||||
"EPS": "000147303031313632011D",
|
||||
"EPS2": "000147303031313632011D",
|
||||
"ESP": "000F47303031313632000001012301027600000101000002B0",
|
||||
}
|
||||
|
||||
expectedMap := map[string]string{
|
||||
"GW": "000547303031313632FF7CFF7F0040",
|
||||
"EPS1": "000147303031313632011D",
|
||||
"EPS2": "000147303031313632011D",
|
||||
"ESP": "000F47303031313632000001012301027600000101000002B0",
|
||||
"OBC": "00024730303131363202768F",
|
||||
}
|
||||
|
||||
cdsMap = cdsNameTransform(cdsMap)
|
||||
cdsMap = cdsRemoval(cdsMap)
|
||||
|
||||
if !assert.Equal(t, expectedMap, cdsMap) {
|
||||
t.Fail()
|
||||
}
|
||||
}
|
||||
|
||||
func TestGetCDSFromDB(t *testing.T) {
|
||||
|
||||
os.Setenv("DB_USER", "fiskercloud")
|
||||
os.Setenv("DB_PASSWORD", "ywo5ea8OPN1E4V9&")
|
||||
os.Setenv("DB_HOST", "cec-prd-cloud-2.postgres.database.azure.com")
|
||||
os.Setenv("DB_NAME", "postgres")
|
||||
os.Setenv("DB_SSLMODE", "require")
|
||||
client := &db.DBClient{}
|
||||
client.RegisterManyToManyRel([]interface{}{
|
||||
(*common.CarToDriver)(nil),
|
||||
})
|
||||
err := client.InitSchema([]interface{}{
|
||||
(*common.UpdateManifest)(nil),
|
||||
(*common.Car)(nil),
|
||||
(*common.CarToDriver)(nil),
|
||||
(*common.CarUpdateStatus)(nil),
|
||||
(*common.CarUpdate)(nil),
|
||||
(*common.FileKey)(nil),
|
||||
(*common.RatePlanTMobile)(nil),
|
||||
})
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
|
||||
carConfigData := &queries.CarConfigData{}
|
||||
carConfigData.SetClient(client)
|
||||
|
||||
res, err := getStoredFeatureCodes("VCF1ZBU28PG002114", carConfigData)
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
featureCodes := make([]string, 0, len(res.Features))
|
||||
for _, c := range res.Features {
|
||||
featureCodes = append(featureCodes, c.FeatureCode)
|
||||
}
|
||||
featureCodesString, _ := json.Marshal(featureCodes)
|
||||
_ = featureCodesString
|
||||
t.Logf("%s\n", featureCodesString)
|
||||
}
|
||||
|
||||
|
||||
func TestBCMBeepOverwrite(t *testing.T){
|
||||
// Generated on local test ODX.
|
||||
withBeep := "001247303032313134000100010001010101000201010101010073"
|
||||
noBeep := "0012473030323131340001000100010101010000010101010100C9"
|
||||
expectNoChange := overwriteBCMBeep(noBeep)
|
||||
if expectNoChange != noBeep {
|
||||
t.Errorf("expected No Change between \n%s\n%s\n", noBeep, expectNoChange)
|
||||
}
|
||||
|
||||
expectChange := overwriteBCMBeep(withBeep)
|
||||
if expectChange != noBeep {
|
||||
t.Errorf("expected Change to match between \n%s\n%s\n", noBeep, expectChange)
|
||||
}
|
||||
}
|
||||
|
||||
// Should change these tests to ignore the headers, and only check the actual byteage
|
||||
func TestBCMSequentialLightingOverwrite(t *testing.T){
|
||||
noLight := "001247303032313732000100000201010101020001010001010071"
|
||||
withLight := "0012473030323137320001000102010101010200010100010100F0"
|
||||
|
||||
expectNoChange := overwriteBCMSequentialLighting(withLight)
|
||||
if expectNoChange != withLight {
|
||||
t.Errorf("expected No Change between \n%s\n%s\n", withLight, expectNoChange)
|
||||
}
|
||||
|
||||
expectChange := overwriteBCMSequentialLighting(noLight)
|
||||
if expectChange != withLight {
|
||||
t.Errorf("expected Change to match between \n%s\n%s\n", withLight, expectChange)
|
||||
}
|
||||
}
|
||||
|
||||
func TestICCOverwrite(t *testing.T){
|
||||
withoutHotSpot := "010047303032313134230108400000020401010001000000010000000001010000000001020000000001000000010000000100000000000000000001010100000000000001010101000100000000010000000000000000000001000101000102010101010101000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000E5" // Ivans with 130100
|
||||
withHotSpot := "0100473030323131342301084000000204010100010000000100000000010100000000010200000000010000000100000001000000000000000000010101000100000000010101010001000000000100000000000000000000010001010001020101010101010000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000009D" // Ivans -> MID_BLUE_MATTE from COL 57 the value 4
|
||||
|
||||
expectedChange := overwriteICCHotSpot(withoutHotSpot)
|
||||
if expectedChange == withoutHotSpot {
|
||||
t.Error("my life is meanignless")
|
||||
}
|
||||
if expectedChange != withHotSpot {
|
||||
t.Errorf("Expected {2} to become {1} \n%s\n%s\n", withHotSpot, expectedChange)
|
||||
}
|
||||
|
||||
expectNoChange := overwriteICCHotSpot(withHotSpot)
|
||||
if expectNoChange != withHotSpot {
|
||||
t.Errorf("expected No Change to match between \n%s\n%s\n", withHotSpot, expectNoChange)
|
||||
}
|
||||
}
|
||||
|
||||
// Give a input, and check if the bit is correct
|
||||
func TestHasICCHotSpot(t *testing.T) {
|
||||
input := "0100473030323131342301084000000204010100010000000100000000010100000000010200000000010000000100000001000000000000000000010101000100000000010101010001000000000100000000000000000000010001010001020101010101010000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000009D"
|
||||
out := overwriteICCHotSpot(input)
|
||||
if input != out {
|
||||
t.Fail()
|
||||
}
|
||||
}
|
||||
136
pkg/usecase_helpers/update_notifier.go
Normal file
136
pkg/usecase_helpers/update_notifier.go
Normal file
@@ -0,0 +1,136 @@
|
||||
package usecase_helpers
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"net/http"
|
||||
"strings"
|
||||
|
||||
"fiskerinc.com/modules/common"
|
||||
"fiskerinc.com/modules/common/carupdatestatus"
|
||||
"fiskerinc.com/modules/db/queries"
|
||||
e "fiskerinc.com/modules/errors"
|
||||
"fiskerinc.com/modules/grpc/kafka_grpc"
|
||||
"fiskerinc.com/modules/kafka"
|
||||
"github.com/pkg/errors"
|
||||
"google.golang.org/protobuf/proto"
|
||||
)
|
||||
|
||||
type UpdateNotifierInterface interface {
|
||||
Send(vins []string, manifest common.UpdateManifest, username string) ([]common.CarUpdate, error)
|
||||
}
|
||||
|
||||
func NewUpdateNotifier(
|
||||
cu queries.CarUpdatesInterface,
|
||||
pr kafka.ProducerInterface,
|
||||
) UpdateNotifierInterface {
|
||||
return &updateNotifier{
|
||||
carUpdates: cu,
|
||||
producer: pr,
|
||||
}
|
||||
}
|
||||
|
||||
type updateNotifier struct {
|
||||
carUpdates queries.CarUpdatesInterface
|
||||
producer kafka.ProducerInterface
|
||||
targetService string
|
||||
}
|
||||
|
||||
// Expect only ota or another service that actually sends the update to the car to call this
|
||||
func (un *updateNotifier) Send(vins []string, manifest common.UpdateManifest, username string) ([]common.CarUpdate, error) {
|
||||
carUpdateList := make([]common.CarUpdate, len(vins))
|
||||
|
||||
pendingVins := make([]string, 0)
|
||||
|
||||
for _, vin := range vins {
|
||||
pending, err := un.carUpdates.HasPendingUpdates(manifest.ID, vin)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
if pending {
|
||||
pendingVins = append(pendingVins, vin)
|
||||
}
|
||||
}
|
||||
|
||||
if len(pendingVins) > 0 {
|
||||
err := e.NewCustomError(fmt.Sprintf("pending update exists for %s", strings.Join(pendingVins, ", ")), http.StatusForbidden)
|
||||
return carUpdateList, errors.WithStack(err)
|
||||
}
|
||||
|
||||
// For each car, we create a new car_update entry, and then try to send the manifest to the car
|
||||
for i, vin := range vins {
|
||||
carUpdate, err := un.insertCarUpdate(un.carUpdates, manifest.ID, vin, username)
|
||||
if err != nil {
|
||||
return carUpdateList, err
|
||||
}
|
||||
|
||||
err = un.sendManifest(vin, username, carUpdate.ID)
|
||||
if err != nil {
|
||||
un.cancel(un.carUpdates, carUpdate.ID, vin, "Failed to queue message to Kafka, error: "+err.Error())
|
||||
return carUpdateList, err
|
||||
}
|
||||
|
||||
carUpdateList[i] = carUpdate
|
||||
}
|
||||
|
||||
return carUpdateList, nil
|
||||
}
|
||||
|
||||
func (un *updateNotifier) sendManifest(vin string, username string, carUpdateID int64) error {
|
||||
|
||||
data := &kafka_grpc.GRPC_AttendantPayload_UpdateManifest{
|
||||
UpdateManifest: &kafka_grpc.UpdateManifest{
|
||||
CarUpdateId: carUpdateID,
|
||||
},
|
||||
}
|
||||
kafkaMSG := kafka_grpc.GRPC_AttendantPayload{
|
||||
Handler: "send_manifest",
|
||||
Data: data,
|
||||
}
|
||||
|
||||
binaryPayload, _ := proto.Marshal(&kafkaMSG)
|
||||
return un.producer.ProduceBinary(kafka.AttendantServiceGRPCKafka, common.Service.Key(vin), binaryPayload, map[string][]byte{
|
||||
"id": []byte(username),
|
||||
})
|
||||
}
|
||||
|
||||
func (un *updateNotifier) insertCarUpdate(db queries.CarUpdatesInterface, manifestID int64, vin string, username string) (common.CarUpdate, error) {
|
||||
up := common.CarUpdate{
|
||||
UpdateManifestID: manifestID,
|
||||
VIN: vin,
|
||||
Status: "pending",
|
||||
Username: username,
|
||||
UpdateSource: common.UPDATE_SOURCE_OTA,
|
||||
}
|
||||
_, err := db.Insert(&up)
|
||||
if err != nil {
|
||||
return up, err
|
||||
}
|
||||
|
||||
_, err = db.LogStatus(&up)
|
||||
return up, err
|
||||
}
|
||||
|
||||
func (un *updateNotifier) cancel(db queries.CarUpdatesInterface, updateID int64, vin string, info string) {
|
||||
up := common.CarUpdate{
|
||||
ID: updateID,
|
||||
Status: carupdatestatus.ManifestCanceled,
|
||||
Info: info,
|
||||
}
|
||||
db.UpdateStatus(&up)
|
||||
}
|
||||
|
||||
type JSONCarUpdatesRequest struct {
|
||||
UpdateManifestID int64 `json:"manifest_id" validate:"required"`
|
||||
VINs []string `json:"vins" validate:"required,gte=1,lte=1000,dive,vin"`
|
||||
}
|
||||
|
||||
type JSONOneCarUpdatesRequest struct {
|
||||
UpdateManifestID int64 `json:"manifest_id" validate:"required"`
|
||||
VIN string `json:"vin" validate:"required,vin"`
|
||||
}
|
||||
|
||||
type JSONFleetUpdatesRequest struct {
|
||||
UpdateManifestID int64 `json:"manifest_id" validate:"required"`
|
||||
FleetNames []string `json:"fleet_names" validate:"required,gte=1,lte=1000,dive,fleet"`
|
||||
}
|
||||
Reference in New Issue
Block a user