Initial cloud-services repo - gateway service + pkg modules
This commit is contained in:
212
pkg/digitaltwin/sendv2.go
Normal file
212
pkg/digitaltwin/sendv2.go
Normal file
@@ -0,0 +1,212 @@
|
||||
package digitaltwin
|
||||
|
||||
import (
|
||||
"encoding/json"
|
||||
|
||||
cache "fiskerinc.com/modules/cachev2"
|
||||
"fiskerinc.com/modules/common"
|
||||
"fiskerinc.com/modules/db/queries"
|
||||
"fiskerinc.com/modules/logger"
|
||||
redis "fiskerinc.com/modules/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
|
||||
}
|
||||
Reference in New Issue
Block a user