package cachev2 import ( "encoding/json" "github.com/fiskerinc/cloud-services/pkg/common" "github.com/fiskerinc/cloud-services/pkg/logger" "github.com/fiskerinc/cloud-services/pkg/mongo" "github.com/fiskerinc/cloud-services/pkg/redis" "github.com/fiskerinc/cloud-services/pkg/utils/envtool" "github.com/fiskerinc/cloud-services/pkg/utils/elptr" redigo "github.com/gomodule/redigo/redis" "github.com/pkg/errors" ) const ( ENABLE_DBG_MASK_EV_NAME = "ENABLE_DEBUGMASK" ENABLE_DBG_MASK_VAL_FALSE = "0" ENABLE_DBG_MASK_VAL_TRUE = "1" ENABLE_DBG_MASK_VAL_DEFAULT = ENABLE_DBG_MASK_VAL_FALSE ) // This flag is to decide whether retrieved value of DebugMask is to be passed to TrexCfg or not. // When the flag is true, the retrieved value is passed; else no value is passed. // The value of flag is fetched from the specific environmental variable. If that environmental // variable is not present / not defined, we assume the flag itself to be FALSE. That is the // default value (FALSE) of the environmental variable. When user/developer has set this evironmental // variable correctly, the flag can become TRUE in which case the value is passed to TrexCfg. var ENABLE_DEBUG_MASK = DbgMaskEnabled() // method introduced so as unit testing is easier otherwise not necessary since environment variables // can't be changed so easily subsequent to a process start (meaning revaluation at runtime of no much use). func DbgMaskEnabled() bool { return envtool.GetEnv(ENABLE_DBG_MASK_EV_NAME, ENABLE_DBG_MASK_VAL_DEFAULT) == ENABLE_DBG_MASK_VAL_TRUE } func RetrieveVehicleConfig(r redis.Client, m mongo.Client, id string) (*common.TRexConfigResponse, error) { config := &common.TRexConfigResponse{} reply, err := checkCacheForVehicleConfig(r, id) if err != nil { return nil, errors.WithStack(err) } if reply != nil { err = json.Unmarshal(reply, config) if err != nil { return nil, errors.WithStack(err) } if config.CANBus.DTCEnabled == nil { config.CANBus.DTCEnabled = elptr.ElPtr(false) } return config, nil } config.LogLevel = common.Critical // config.Log = &common.LogConfig{ // Matches: []common.LogConfigChannel{ // { // Channel: common.ChannelCMD, // Level: common.Trace, // }, // }, // } config.CANBus.Enabled = true config.CANBus.DataLogger = true filters := make(FiltersMap) f, err := checkFleetsDBForVehicleConfig(m, id) if err != nil { logger.Warn().Err(err).Send() } if f != nil { config.CANBus = f.CANBus config.LogLevel = f.LogLevel filters.AppendFilters(f.CANBus.Filters) } v, err := checkVehiclesDBForVehicleConfig(m, id) if err != nil { logger.Warn().Err(err).Send() } if v != nil { config.CANBus = v.CANBus config.LogLevel = v.LogLevel config.DLTEnabled = v.DLTEnabled config.DLTLevel = v.DLTLevel // we should evaluate at run-time, not just at start-up time if ENABLE_DEBUG_MASK { config.DebugMask = v.DebugMask } config.IDPSEnabled = v.IDPSEnabled filters.AppendFilters(v.CANBus.Filters) } config.CANBus.Filters = filters.ToSlice() if config.CANBus.DTCEnabled == nil { config.CANBus.DTCEnabled = elptr.ElPtr(false) } err = setCacheForVehicleConfig(r, id, config) return config, err } func checkCacheForVehicleConfig(r redis.Client, id string) ([]byte, error) { key := redis.CarConfigKey(id) reply, err := redigo.Bytes(r.Execute("GET", key)) if err != nil { if errors.Is(err, redigo.ErrNil) { return nil, nil } return nil, err } return reply, nil } func checkVehiclesDBForVehicleConfig(m mongo.Client, id string) (*mongo.Vehicle, error) { return m.GetVehicles().FindVehicle(&mongo.Vehicle{VIN: id}) } func checkFleetsDBForVehicleConfig(m mongo.Client, id string) (*mongo.Fleet, error) { return m.GetFleets().GetCANBusForVehicle(id) } func setCacheForVehicleConfig(r redis.Client, id string, config *common.TRexConfigResponse) error { key := redis.CarConfigKey(id) data, err := json.Marshal(config) if err != nil { return errors.WithStack(err) } batch := redis.NewRedisBatchCommands() batch.Add("SET", key, data) batch.Add("EXPIRE", key, redisObjectExpire.Seconds()) _, err = r.ExecuteBatch(batch) if err != nil { return errors.WithStack(err) } return nil } func RemoveCacheConfigForVehicles(r redis.Client, vins []string) error { batch := redis.NewRedisBatchCommands() for _, vin := range vins { batch.Add("DEL", redis.CarConfigKey(vin)) } _, err := r.ExecuteBatch(batch) if err != nil { return errors.WithStack(err) } return nil } type IntervalEdgeMask struct { Interval *int EdgeMask *common.BinaryHex } type FiltersMap map[string]IntervalEdgeMask func (f FiltersMap) AppendFilters(filters []common.CANFilter) { for _, filter := range filters { if filter.EdgeMask != nil && filter.EdgeMask.String() != "" { f[filter.CANID] = IntervalEdgeMask{ EdgeMask: filter.EdgeMask, } } else if filter.Interval != nil { f[filter.CANID] = IntervalEdgeMask{ Interval: filter.Interval, } } } } func (f FiltersMap) ToSlice() []common.CANFilter { filters := make([]common.CANFilter, 0, len(f)) for k, v := range f { filters = append(filters, common.CANFilter{ CANID: k, Interval: v.Interval, EdgeMask: v.EdgeMask, }) } return filters }