Files
cloud-services/pkg/mongo/dtc_codes.go

155 lines
4.4 KiB
Go

package mongo
import (
"context"
"strconv"
"strings"
"sync"
"time"
"fiskerinc.com/modules/common"
"fiskerinc.com/modules/logger"
"github.com/pkg/errors"
"go.mongodb.org/mongo-driver/bson"
"go.mongodb.org/mongo-driver/mongo"
)
type DTCCollectionInterface interface {
GetDTCDefinitionByHexString(troubleCodeHex string) (info common.DTCInformation, err error)
GetLatestPDXVersions() (latestVersion PDXVersion, err error)
}
var (
pdxMongodbOnce sync.Once
pdxMongodbInstance *DTCCollection
)
type DTCCollection struct {
CollectionInterface
Client *mongo.Client
DB *mongo.Database
}
func GetPDXMongoClient() (*DTCCollection, error) {
var err error
pdxMongodbOnce.Do(func() {
logger.Info().Msg("init MongoDB instance")
pdxMongodbInstance = &DTCCollection{}
var cl *mongo.Client
var db *mongo.Database
cl, db, err = NewMongoConnection(ODXDB)
pdxMongodbInstance.Client = cl
pdxMongodbInstance.DB = db
})
return pdxMongodbInstance, err
}
// Given a Hex String for 3 bytes, get the dtc information from mongo
func (coll *DTCCollection) GetDTCDefinitionByHexString(troubleCodeHex string, ecuSource string) (info *common.DTCInformation, err error) {
if replacement, exist := common.CarDTCLookupInverse[ecuSource]; exist {
ecuSource = replacement
}
collect := coll.DB.Collection("dtc_lookup")
//db.dtc_lookup.aggregate({"$match": {"ecuName": "ECU", "DtcUniqueId": "V2.6.0"}}, {"$unwind": "$dtcData.DtcList"}, {"$match": {"dtcData.DtcList.TroubleCodeHex":"800156"}}, {"$project":{"_id": 0, "Obj": "$dtcData.DtcList"}})
pdxVersion, err := coll.GetLatestPDXVersions()
if err != nil {
return
}
a := bson.D{}
if ecuSource == "AMP" {
a = bson.D{{"$match", bson.D{{"ecuName", bson.M{"$in": []string{"AMPSO", "AMPHA"}}}, {"DtcUniqueId", pdxVersion.PDXVersion}}}}
} else {
a = bson.D{{"$match", bson.D{{"ecuName", ecuSource}, {"DtcUniqueId", pdxVersion.PDXVersion}}}}
}
b := bson.D{{"$unwind", "$dtcData.DtcList"}}
c := bson.D{{"$match", bson.D{{"dtcData.DtcList.TroubleCodeHex", troubleCodeHex}}}}
d := bson.D{{"$project", bson.D{{"_id", 0}, {"Obj", "$dtcData.DtcList"}}}}
cursor, err := collect.Aggregate(context.Background(), mongo.Pipeline{a, b, c, d})
if err != nil {
err = errors.WithStack(err)
logger.Err(err).Msg("Failed to call aggregate in GetDTCDefinitionByHexString")
return
}
var obj DTCOuterObj
for cursor.Next(context.Background()) {
err = cursor.Decode(&obj)
if err != nil {
err = errors.WithStack(err)
logger.Err(err).Msg("Failed to decode mongo object into DTCInformation")
return
}
info = &obj.DTCInformation
}
return
}
// This value should be cached for a period of time
func (coll *DTCCollection) GetLatestPDXVersions() (latestVersion PDXVersion, err error) {
//db.vod_lookup.aggregate({"$project": {"VodUniqueId": 1, "createDate": 1, "updateDate": 1}})
collect := coll.DB.Collection("vod_lookup")
a := bson.D{{"$project", bson.D{{"VodUniqueId", 1}, {"createDate", 1}, {"updateDate", 1}, {"_id", 0}}}}
cursor, err := collect.Aggregate(context.Background(), mongo.Pipeline{a})
if err != nil {
err = errors.WithStack(err)
logger.Err(err).Msg("")
return
}
// Need to determine the latest version
for cursor.Next(context.Background()) {
var ag PDXVersion
err = cursor.Decode(&ag)
if err != nil {
err = errors.WithStack(err)
logger.Err(err).Msg("")
return
}
if isVersionNewer(latestVersion.PDXVersion, ag.PDXVersion) {
latestVersion = ag
}
}
return
}
// Give the one we have as the newest, and then the new value to compare to
func isVersionNewer(lastNewest, newPossibleNewest string) (isNewer bool) {
// Better algorithm, turn V1.3.2.1 => 1321 and add any 0's on the end if the other number is longer
if lastNewest == "" {
return true
}
// Remove the V
lastNewest = lastNewest[1:]
newPossibleNewest = newPossibleNewest[1:]
last := strings.Split(lastNewest, ".")
new := strings.Split(newPossibleNewest, ".")
for x := 0; x < len(last); x++ {
// We have gotten to the end of the second string without being less, so we are greater, like a hotfix
if x >= len(new) {
return false
}
l, _ := strconv.Atoi(last[x])
n, _ := strconv.Atoi(new[x])
if n > l {
return true
} else if l > n {
return false
}
}
return len(new) > len(last)
}
type DTCOuterObj struct {
common.DTCInformation `bson:"Obj"`
}
type PDXVersion struct {
PDXVersion string `bson:"VodUniqueId"`
CreatedTime time.Time `bson:"createDate"`
UpdatedTime time.Time `bson:"updateDate"`
}