213 lines
5.8 KiB
Go
213 lines
5.8 KiB
Go
package digitaltwin
|
|
|
|
import (
|
|
"encoding/json"
|
|
|
|
cache "github.com/fiskerinc/cloud-services/pkg/cachev2"
|
|
"github.com/fiskerinc/cloud-services/pkg/common"
|
|
"github.com/fiskerinc/cloud-services/pkg/db/queries"
|
|
"github.com/fiskerinc/cloud-services/pkg/logger"
|
|
redis "github.com/fiskerinc/cloud-services/pkg/redisv2"
|
|
"github.com/pkg/errors"
|
|
)
|
|
|
|
func NewSendDigitalTwinV2(redisClient redis.ClientInterface, cars queries.CarsInterface) SendDigitalTwinV2 {
|
|
return SendDigitalTwinV2{
|
|
redisClient: redisClient,
|
|
carsDB: cars,
|
|
}
|
|
}
|
|
|
|
type SendDigitalTwinV2 struct {
|
|
redisClient redis.ClientInterface
|
|
carsDB queries.CarsInterface
|
|
parser *cache.VehicleState
|
|
}
|
|
|
|
func (d *SendDigitalTwinV2) Close() {
|
|
d.carsDB = nil
|
|
}
|
|
|
|
func (d *SendDigitalTwinV2) GetDigitalTwin(vin string) (*common.JSONDigitalTwin, error) {
|
|
state, err := d.getVehicleState(vin)
|
|
if err != nil {
|
|
return nil, err
|
|
}
|
|
|
|
var battery *common.JSONBattery
|
|
var windows *common.JSONWindows
|
|
var climateControl *common.JSONClimateControl
|
|
|
|
battery = consolidateBatteryV2(state)
|
|
|
|
// Consolidate windows
|
|
if state.Windows != nil && state.MiscWindows != nil && state.Sunroof != nil {
|
|
windows = &common.JSONWindows{}
|
|
|
|
// Main windows
|
|
windows.LeftFront = state.Windows.LeftFront
|
|
windows.LeftRear = state.Windows.LeftRear
|
|
windows.RightFront = state.Windows.RightFront
|
|
windows.RightRear = state.Windows.RightRear
|
|
|
|
// Miscellaneous windows
|
|
windows.LeftRearQuarter = state.MiscWindows.LeftRearQuarter
|
|
windows.RightRearQuarter = state.MiscWindows.RightRearQuarter
|
|
windows.RearWindshield = state.MiscWindows.RearWindshield
|
|
|
|
// Sunroof
|
|
windows.Sunroof = state.Sunroof.Sunroof
|
|
}
|
|
|
|
// Consolidate climate control
|
|
if state.CabinClimate != nil && state.RearDefrost != nil && state.DriverSeatHeat != nil &&
|
|
state.PassengerSeatHeat != nil && state.SteeringWheelHeat != nil && state.AmbientTemperature != nil {
|
|
climateControl = &common.JSONClimateControl{}
|
|
|
|
climateControl.CabinTemperature = state.CabinClimate.CabinTemperature
|
|
climateControl.RearDefrost = state.RearDefrost.On
|
|
climateControl.DriverSeatHeat = state.DriverSeatHeat.Level
|
|
climateControl.PassengerSeatHeat = state.PassengerSeatHeat.Level
|
|
climateControl.SteeringWheelHeat = state.SteeringWheelHeat.On
|
|
climateControl.AmbientTemperature = state.AmbientTemperature.Temperature
|
|
climateControl.InternalTemperature = state.CabinClimate.InternalTemperature
|
|
}
|
|
|
|
twinForDrivers := &common.JSONDigitalTwin{
|
|
VIN: vin,
|
|
Online: state.Online,
|
|
OnlineHMI: state.OnlineHMI,
|
|
VehicleSpeed: state.VehicleSpeed,
|
|
Gear: state.Gear,
|
|
Battery: battery,
|
|
Doors: state.Doors,
|
|
Location: state.Location,
|
|
Locks: state.Locks,
|
|
Windows: windows,
|
|
ClimateControl: climateControl,
|
|
TRexVersion: state.TRexVersion,
|
|
IP: state.IP,
|
|
VehicleReadyState: state.VehicleReadyState,
|
|
ExpandedSignals: state.ExpandedSignals,
|
|
UpdatedAt: state.UpdatedAt,
|
|
}
|
|
|
|
return twinForDrivers, nil
|
|
}
|
|
|
|
func consolidateBatteryV2(state common.CarState) *common.JSONBattery {
|
|
battery := common.JSONBattery{}
|
|
if state.StateOfCharge != nil {
|
|
battery.StateOfCharge = &state.StateOfCharge.Usable
|
|
}
|
|
if state.Battery != nil {
|
|
battery.Percent = &state.Battery.Percent
|
|
battery.TotalMileageOdometer = &state.Battery.TotalMileageOdometer
|
|
}
|
|
if state.MaxRange != nil {
|
|
battery.MaxMiles = &state.MaxRange.MaxMiles
|
|
}
|
|
if state.VCU0x260 != nil {
|
|
battery.ChargeType = &state.VCU0x260.ChargeType
|
|
}
|
|
if state.ChargingMetrics != nil {
|
|
battery.RemainingChargingTime = &state.ChargingMetrics.RemainingChargingTime
|
|
}
|
|
if state.ChargingMetrics != nil {
|
|
battery.RemainingChargingTimeFull = &state.ChargingMetrics.RemainingChargingTimeFull
|
|
}
|
|
if state.CellTemperature != nil {
|
|
battery.AvgCellTemperature = &state.CellTemperature.AvgBatteryTemp
|
|
}
|
|
|
|
if battery == (common.JSONBattery{}) {
|
|
return nil
|
|
}
|
|
|
|
return &battery
|
|
}
|
|
|
|
func (d *SendDigitalTwinV2) sendToDriver(twin *common.JSONDigitalTwin, driver string) error {
|
|
dt, err := json.Marshal(twin)
|
|
if err != nil {
|
|
logger.Error().Err(errors.WithStack(err)).Send()
|
|
}
|
|
sdt := string(dt)
|
|
logger.Debug().Msg(sdt)
|
|
|
|
logger.Info().Interface("digital twin", twin).Msg("send to driver add to redis")
|
|
err = d.redisClient.SafePublishMessage(
|
|
common.Mobile.Key(driver),
|
|
common.Message{
|
|
Handler: "digital_twin",
|
|
Data: twin,
|
|
},
|
|
)
|
|
return err
|
|
}
|
|
|
|
func (d *SendDigitalTwinV2) SendToDriver(vin string, driver string) error {
|
|
ok, err := d.verifyCarToDriver(vin, driver)
|
|
if err != nil {
|
|
return err
|
|
} else if !ok {
|
|
return cache.ErrInvalidCarToDriverAssociation(vin, driver)
|
|
}
|
|
|
|
twin, err := d.GetDigitalTwin(vin)
|
|
if err != nil {
|
|
return err
|
|
}
|
|
|
|
return d.sendToDriver(twin, driver)
|
|
}
|
|
|
|
func (d *SendDigitalTwinV2) Send(vin string) error {
|
|
// Get the digital twin
|
|
redisDigitalTwin, err := d.GetDigitalTwin(vin)
|
|
if err != nil {
|
|
return err
|
|
}
|
|
drivers, err := d.retrieveDriverIDs(vin)
|
|
if err != nil {
|
|
return err
|
|
}
|
|
if len(drivers) == 0 {
|
|
return nil
|
|
}
|
|
|
|
if redisDigitalTwin != nil {
|
|
for _, driver := range drivers {
|
|
|
|
err = d.sendToDriver(redisDigitalTwin, driver)
|
|
if err != nil {
|
|
logger.Error().Err(err)
|
|
}
|
|
}
|
|
}
|
|
|
|
return nil
|
|
}
|
|
|
|
func (d *SendDigitalTwinV2) getVehicleState(vin string) (common.CarState, error) {
|
|
return d.getParser().Get(vin)
|
|
}
|
|
|
|
func (d *SendDigitalTwinV2) verifyCarToDriver(vin string, driver string) (bool, error) {
|
|
return cache.VerifyCarToDriver(d.redisClient, d.carsDB, vin, driver)
|
|
}
|
|
|
|
func (d *SendDigitalTwinV2) retrieveDriverIDs(vin string) ([]string, error) {
|
|
drivers := cache.NewDriversCache(d.redisClient, d.carsDB)
|
|
|
|
return drivers.RetrieveDriverIDs(vin)
|
|
}
|
|
|
|
func (d *SendDigitalTwinV2) getParser() *cache.VehicleState {
|
|
if d.parser == nil {
|
|
d.parser = cache.NewVehicleState(d.redisClient)
|
|
}
|
|
|
|
return d.parser
|
|
}
|