Initial cloud-services repo - gateway service + pkg modules
This commit is contained in:
218
pkg/digitaltwin/send.go
Normal file
218
pkg/digitaltwin/send.go
Normal file
@@ -0,0 +1,218 @@
|
||||
package digitaltwin
|
||||
|
||||
import (
|
||||
"encoding/json"
|
||||
|
||||
"fiskerinc.com/modules/cache"
|
||||
"fiskerinc.com/modules/common"
|
||||
"fiskerinc.com/modules/db/queries"
|
||||
"fiskerinc.com/modules/logger"
|
||||
"fiskerinc.com/modules/redis"
|
||||
"github.com/pkg/errors"
|
||||
)
|
||||
|
||||
func NewSendDigitalTwin(redis redis.ClientPoolInterface, cars queries.CarsInterface) SendDigitalTwin {
|
||||
return SendDigitalTwin{
|
||||
redisClientPool: redis,
|
||||
carsDB: cars,
|
||||
}
|
||||
}
|
||||
|
||||
type SendDigitalTwin struct {
|
||||
redisClientPool redis.ClientPoolInterface
|
||||
carsDB queries.CarsInterface
|
||||
parser *cache.VehicleState
|
||||
}
|
||||
|
||||
func (d *SendDigitalTwin) Close() {
|
||||
d.carsDB = nil
|
||||
}
|
||||
|
||||
func (d *SendDigitalTwin) GetDigitalTwin(vin string) (*common.JSONDigitalTwin, error) {
|
||||
state, err := d.getVehicleState(vin)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
return CreateDigitalTwinResponse(vin, state), nil
|
||||
}
|
||||
|
||||
func CreateDigitalTwinResponse(vin string, state common.CarState) *common.JSONDigitalTwin {
|
||||
var battery *common.JSONBattery
|
||||
var windows *common.JSONWindows
|
||||
var climateControl *common.JSONClimateControl
|
||||
|
||||
battery = consolidateBattery(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
|
||||
}
|
||||
|
||||
func consolidateBattery(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 *SendDigitalTwin) 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")
|
||||
client := d.redisClientPool.GetFromPool()
|
||||
defer client.Close()
|
||||
err = client.SafePublishMessage(
|
||||
common.Mobile.Key(driver),
|
||||
common.Message{
|
||||
Handler: "digital_twin",
|
||||
Data: twin,
|
||||
},
|
||||
)
|
||||
return err
|
||||
}
|
||||
|
||||
func (d *SendDigitalTwin) 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 *SendDigitalTwin) 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 *SendDigitalTwin) getVehicleState(vin string) (common.CarState, error) {
|
||||
return d.getParser().Get(vin)
|
||||
}
|
||||
|
||||
func (d *SendDigitalTwin) verifyCarToDriver(vin string, driver string) (bool, error) {
|
||||
return cache.VerifyCarToDriver(d.redisClientPool, d.carsDB, vin, driver)
|
||||
}
|
||||
|
||||
func (d *SendDigitalTwin) retrieveDriverIDs(vin string) ([]string, error) {
|
||||
drivers := cache.NewDriversCache(d.redisClientPool, d.carsDB)
|
||||
|
||||
return drivers.RetrieveDriverIDs(vin)
|
||||
}
|
||||
|
||||
func (d *SendDigitalTwin) getParser() *cache.VehicleState {
|
||||
if d.parser == nil {
|
||||
d.parser = cache.NewVehicleState(d.redisClientPool)
|
||||
}
|
||||
|
||||
return d.parser
|
||||
}
|
||||
Reference in New Issue
Block a user