Files
cloud-services/pkg/common/car_state.go

553 lines
15 KiB
Go

package common
import (
"encoding/json"
"time"
"github.com/pkg/errors"
)
type CarState struct {
Online bool `json:"online"`
OnlineHMI bool `json:"online_hmi"`
Battery *Battery `json:"battery,omitempty"`
MaxRange *MaxRange `json:"max_range,omitempty"`
Doors *Doors `json:"doors,omitempty"`
Location *Location `json:"location,omitempty"`
Locks *Locks `json:"door_locks,omitempty"`
Windows *Windows `json:"windows,omitempty"`
MiscWindows *MiscWindows `json:"misc_windows,omitempty"`
Sunroof *Sunroof `json:"sunroof,omitempty"`
CabinClimate *CabinClimate `json:"cabin_climate,omitempty"`
RearDefrost *RearDefrost `json:"rear_defrost,omitempty"`
DriverSeatHeat *DriverSeatHeat `json:"driver_seat_heat,omitempty"`
PassengerSeatHeat *PassengerSeatHeat `json:"passenger_seat_heat,omitempty"`
SteeringWheelHeat *SteeringWheelHeat `json:"steering_wheel_heat,omitempty"`
AmbientTemperature *AmbientTemperature `json:"ambient_temperature,omitempty"`
CellTemperature *CellTemperature `json:"cell_temp,omitempty"`
VehicleSpeed *VehicleSpeed `json:"vehicle_speed,omitempty"`
VCU0x260 *VCU0x260Descriptor `json:"vcu0x260,omitempty"`
ChargingMetrics *VCUChargingMetrics `json:"charging_metrics,omitempty"`
Gear *Gear `json:"gear,omitempty"`
StateOfCharge *StateOfCharge `json:"state_of_charge,omitempty"`
TRexVersion string `json:"trex_version,omitempty"`
DBCVersion string `json:"dbc_version,omitempty"`
IP string `json:"ip,omitempty"`
UpdatedAt *time.Time `json:"updated,omitempty"`
SafeState *SafeState `json:"safe_state,omitempty"`
DriverOccupySeatState *int `json:"driver_occupy_seat_state,omitempty"`
PowerMode *int `json:"power_mode,omitempty"`
ChargingStatus *int `json:"charging_status,omitempty"`
VehicleReadyState *VehicleReadyState `json:"vehicle_ready_state,omitempty"`
Battery12V *Battery12V `json:"battery_12v,omitempty"` // maybe make it Battery12v
ExpandedSignals *ExpandedSignals `json:"expanded_signals,omitempty"`
}
func (c *CarState) GetBattery() *Battery {
if c.Battery == nil {
c.Battery = &Battery{}
}
return c.Battery
}
func (c *CarState) GetMaxRange() *MaxRange {
if c.MaxRange == nil {
c.MaxRange = &MaxRange{}
}
return c.MaxRange
}
func (c *CarState) GetDoors() *Doors {
if c.Doors == nil {
c.Doors = &Doors{}
}
return c.Doors
}
func (c *CarState) UpdateLocation(value []byte) error {
loc := Location{}
err := loc.Unmarshal(value)
if err != nil {
return err
}
location := c.GetLocation()
location.Latitude = loc.Latitude
location.Longitude = loc.Longitude
// Altitude could have already been set from GPS_ALTITUDE so do not overwrite unless it is a non-zero
if loc.Altitude != 0 {
location.Altitude = loc.Altitude
}
return nil
}
func (c *CarState) GetLocation() *Location {
if c.Location == nil {
c.Location = &Location{}
}
return c.Location
}
func (c *CarState) GetLocks() *Locks {
if c.Locks == nil {
c.Locks = &Locks{}
}
return c.Locks
}
func (c *CarState) GetWindows() *Windows {
if c.Windows == nil {
c.Windows = &Windows{}
}
return c.Windows
}
func (c *CarState) GetMiscWindows() *MiscWindows {
if c.MiscWindows == nil {
c.MiscWindows = &MiscWindows{}
}
return c.MiscWindows
}
func (c *CarState) GetSunroof() *Sunroof {
if c.Sunroof == nil {
c.Sunroof = &Sunroof{}
}
return c.Sunroof
}
func (c *CarState) GetCabinClimate() *CabinClimate {
if c.CabinClimate == nil {
c.CabinClimate = &CabinClimate{}
}
return c.CabinClimate
}
func (c *CarState) GetRearDefrost() *RearDefrost {
if c.RearDefrost == nil {
c.RearDefrost = &RearDefrost{}
}
return c.RearDefrost
}
func (c *CarState) GetDriverSeatHeat() *DriverSeatHeat {
if c.DriverSeatHeat == nil {
c.DriverSeatHeat = &DriverSeatHeat{}
}
return c.DriverSeatHeat
}
func (c *CarState) GetPassengerSeatHeat() *PassengerSeatHeat {
if c.PassengerSeatHeat == nil {
c.PassengerSeatHeat = &PassengerSeatHeat{}
}
return c.PassengerSeatHeat
}
func (c *CarState) GetSteeringWheelHeat() *SteeringWheelHeat {
if c.SteeringWheelHeat == nil {
c.SteeringWheelHeat = &SteeringWheelHeat{}
}
return c.SteeringWheelHeat
}
func (c *CarState) GetAmbientTemperature() *AmbientTemperature {
if c.AmbientTemperature == nil {
c.AmbientTemperature = &AmbientTemperature{}
}
return c.AmbientTemperature
}
func (c *CarState) GetCellTemperature() *CellTemperature {
if c.CellTemperature == nil {
c.CellTemperature = &CellTemperature{}
}
return c.CellTemperature
}
func (c *CarState) GetVCU0x260() *VCU0x260Descriptor {
if c.VCU0x260 == nil {
c.VCU0x260 = &VCU0x260Descriptor{}
}
return c.VCU0x260
}
func (c *CarState) GetChargingMetrics() *VCUChargingMetrics {
if c.ChargingMetrics == nil {
c.ChargingMetrics = &VCUChargingMetrics{}
}
return c.ChargingMetrics
}
func (c *CarState) GetGear() *Gear {
if c.Gear == nil {
c.Gear = &Gear{}
}
return c.Gear
}
func (c *CarState) GetStateOfCharge() *StateOfCharge {
if c.StateOfCharge == nil {
c.StateOfCharge = &StateOfCharge{}
}
return c.StateOfCharge
}
func (c *CarState) GetVehicleSpeed() *VehicleSpeed {
if c.VehicleSpeed == nil {
c.VehicleSpeed = &VehicleSpeed{}
}
return c.VehicleSpeed
}
// Battery represents the battery state of the car
type Battery struct {
Percent int `json:"percent" redis:"percent"`
TotalMileageOdometer int `json:"total_mileage_odometer"`
BatteryVoltage float64 `json:"battery_voltage"` // The fact that this is called battery voltage is really dumb. Its the 12 volt battery, not the high voltage one
}
func (b *Battery) Marshal() ([]byte, error) {
data, err := json.Marshal(*b)
return data, errors.WithStack(err)
}
func (b *Battery) Unmarshal(data []byte) error {
err := json.Unmarshal(data, b)
return errors.WithStack(err)
}
// StateOfCharge represents the battery state of charge
type StateOfCharge struct {
Usable int `json:"usable"`
Health int `json:"health"`
}
type SafeState struct {
VehicleSafeState bool `json:"vehicle_safe_state" redis:"vehicle_safe_state"`
VCUSafeState bool `json:"vcu_safe_state" redis:"vcu_safe_state"`
MCUFrontSafeState bool `json:"mcu_front_safe_state" redis:"mcu_front_safe_state"`
MCURearSafeState bool `json:"mcu_rear_safe_state" redis:"mcu_rear_safe_state"`
MCURearDecoupState bool `json:"mcu_rear_decoup_state" redis:"mcu_rear_decoup_state"`
MCUFrontInverterError bool `json:"mcu_front_inverter_error" redis:"mcu_front_inverter_error"`
MCURearInverterError bool `json:"mcu_rear_inverter_error" redis:"mcu_rear_inverter_error"`
}
func (s *SafeState) Marshal() ([]byte, error) {
data, err := json.Marshal(*s)
return data, errors.WithStack(err)
}
func (s *SafeState) Unmarshal(data []byte) error {
err := json.Unmarshal(data, s)
return errors.WithStack(err)
}
func (c *CarState) GetSafeState() *SafeState {
if c.SafeState == nil {
c.SafeState = &SafeState{}
}
return c.SafeState
}
// MaxRange represents the predicted max range of the car
type MaxRange struct {
MaxMiles int `json:"max_miles" redis:"max_miles"`
}
type VehicleReadyState struct {
IsVehicleReady bool `json:"is_vehicle_ready" redis:"is_vehicle_ready"`
}
func (c *CarState) GetVehicleReadyState() *VehicleReadyState {
if c.VehicleReadyState == nil {
c.VehicleReadyState = &VehicleReadyState{}
}
return c.VehicleReadyState
}
func (b *MaxRange) Marshal() ([]byte, error) {
data, err := json.Marshal(*b)
return data, errors.WithStack(err)
}
func (b *MaxRange) Unmarshal(data []byte) error {
err := json.Unmarshal(data, b)
return errors.WithStack(err)
}
// Doors represents the doors state of the car
// false means closed, true means open
type Doors struct {
Hood bool `json:"hood" redis:"hood"`
LeftFront bool `json:"left_front" redis:"left_front"`
LeftRear bool `json:"left_rear" redis:"left_rear"`
RightFront bool `json:"right_front" redis:"right_front"`
RightRear bool `json:"right_rear" redis:"right_rear"`
Trunk bool `json:"trunk" redis:"trunk"`
}
func (d *Doors) Marshal() ([]byte, error) {
data, err := json.Marshal(*d)
return data, errors.WithStack(err)
}
func (d *Doors) Unmarshal(data []byte) error {
err := json.Unmarshal(data, d)
return errors.WithStack(err)
}
// Locks represents the lock state of the car
type Locks struct {
Driver bool `json:"driver" redis:"driver"`
All bool `json:"all" redis:"all"`
}
func (l *Locks) Marshal() ([]byte, error) {
data, err := json.Marshal(*l)
return data, errors.WithStack(err)
}
func (l *Locks) Unmarshal(data []byte) error {
err := json.Unmarshal(data, l)
return errors.WithStack(err)
}
// Windows represents the windows state of the car
//
// value is a percentage 0-100 in increments of 0.5
type Windows struct {
LeftFront int `json:"left_front" redis:"left_front"`
LeftRear int `json:"left_rear" redis:"left_rear"`
RightFront int `json:"right_front" redis:"right_front"`
RightRear int `json:"right_rear" redis:"right_rear"`
}
func (w *Windows) Marshal() ([]byte, error) {
data, err := json.Marshal(*w)
return data, errors.WithStack(err)
}
func (w *Windows) Unmarshal(data []byte) error {
err := json.Unmarshal(data, w)
return errors.WithStack(err)
}
// MiscWindows represents the windows state of the car for misc windows (left / right rear quarter and rear windshield)
// value is a percentage 0-100 in increments of 0.5
type MiscWindows struct {
LeftRearQuarter int `json:"left_rear_quarter" redis:"left_rear_quarter"`
RightRearQuarter int `json:"right_rear_quarter" redis:"right_rear_quarter"`
RearWindshield int `json:"rear_windshield" redis:"rear_windshield"`
}
func (w *MiscWindows) Marshal() ([]byte, error) {
data, err := json.Marshal(*w)
return data, errors.WithStack(err)
}
func (w *MiscWindows) Unmarshal(data []byte) error {
err := json.Unmarshal(data, w)
return errors.WithStack(err)
}
type Sunroof struct {
Sunroof int `json:"sunroof" redis:"sunroof"`
}
func (s *Sunroof) Marshal() ([]byte, error) {
data, err := json.Marshal(*s)
return data, errors.WithStack(err)
}
func (s *Sunroof) Unmarshal(data []byte) error {
err := json.Unmarshal(data, s)
return errors.WithStack(err)
}
type CabinClimate struct {
CabinTemperature int `json:"cabin_temperature" redis:"cabin_temperature"`
InternalTemperature int `json:"internal_temperature" redis:"internal_temperature"`
}
func (w *CabinClimate) Marshal() ([]byte, error) {
data, err := json.Marshal(*w)
return data, errors.WithStack(err)
}
func (w *CabinClimate) Unmarshal(data []byte) error {
err := json.Unmarshal(data, w)
return errors.WithStack(err)
}
type RearDefrost struct {
On bool `json:"on" redis:"on"`
}
func (w *RearDefrost) Marshal() ([]byte, error) {
data, err := json.Marshal(*w)
return data, errors.WithStack(err)
}
func (w *RearDefrost) Unmarshal(data []byte) error {
err := json.Unmarshal(data, w)
return errors.WithStack(err)
}
type DriverSeatHeat struct {
Level int `json:"level" redis:"level"`
}
func (w *DriverSeatHeat) Marshal() ([]byte, error) {
data, err := json.Marshal(*w)
return data, errors.WithStack(err)
}
func (w *DriverSeatHeat) Unmarshal(data []byte) error {
err := json.Unmarshal(data, w)
return errors.WithStack(err)
}
type PassengerSeatHeat struct {
Level int `json:"level" redis:"level"`
}
func (w *PassengerSeatHeat) Marshal() ([]byte, error) {
data, err := json.Marshal(*w)
return data, errors.WithStack(err)
}
func (w *PassengerSeatHeat) Unmarshal(data []byte) error {
err := json.Unmarshal(data, w)
return errors.WithStack(err)
}
type SteeringWheelHeat struct {
On bool `json:"on" redis:"on"`
}
func (w *SteeringWheelHeat) Marshal() ([]byte, error) {
data, err := json.Marshal(*w)
return data, errors.WithStack(err)
}
func (w *SteeringWheelHeat) Unmarshal(data []byte) error {
err := json.Unmarshal(data, w)
return errors.WithStack(err)
}
type AmbientTemperature struct {
Temperature int `json:"temperature" redis:"temperature"`
}
func (w *AmbientTemperature) Marshal() ([]byte, error) {
data, err := json.Marshal(*w)
return data, errors.WithStack(err)
}
func (w *AmbientTemperature) Unmarshal(data []byte) error {
err := json.Unmarshal(data, w)
return errors.WithStack(err)
}
type VehicleSpeed struct {
Speed float64 `json:"speed" redis:"speed"`
}
func (w *VehicleSpeed) Marshal() ([]byte, error) {
data, err := json.Marshal(*w)
return data, errors.WithStack(err)
}
func (w *VehicleSpeed) Unmarshal(data []byte) error {
err := json.Unmarshal(data, w)
return errors.WithStack(err)
}
type CellTemperature struct {
AvgBatteryTemp int `json:"avg_battery_temp"`
}
type VCU0x260Descriptor struct {
ChargeType string `json:"charge_type"`
}
type VCUChargingMetrics struct {
RemainingChargingTime int `json:"remaining_charging_time"`
RemainingChargingTimeFull int `json:"remaining_charging_time_full"`
}
type Gear struct {
InPark bool `json:"in_park"`
Immobilizer string `json:"immobilizer,omitempty"`
}
type Battery12V struct {
IBS_BatteryVoltage *float64 `json:"voltage,omitempty"` // 12 Volt battery voltage
IBS_StateOfCharge *float64 `json:"percent_charge,omitempty"` // Percentages of the voltage out of about 15.5 Volts
IBS_StateOfHealth *int `json:"health,omitempty"` // estimated health of the 12v battery
}
func (c *CarState) GetBattery12V() *Battery12V {
if c.Battery12V == nil {
c.Battery12V = &Battery12V{}
}
return c.Battery12V
}
type ExpandedSignals struct {
// IBS_SOCUpperTolerance *float64 //unconfirmed
// IBS_SOCLowerTolerance *float64 //unconfirmed
IBS_NominalCapacity *int `json:",omitempty"`
IBS_AvailableCapacity *int `json:",omitempty"`
BCM_TotMilg_ODO *float64 `json:",omitempty"`
BMS_SwVersS *int `json:",omitempty"`
BMS_SwVersM *int `json:",omitempty"`
BMS_SwVers *int `json:",omitempty"`
BMS_AccueDchaTotAh *int `json:",omitempty"`
BMS_AccueChrgTotAh *int `json:",omitempty"`
}
func (c *CarState) GetExpandedSignals() *ExpandedSignals {
if c.ExpandedSignals == nil {
c.ExpandedSignals = &ExpandedSignals{}
}
return c.ExpandedSignals
}
// I am quite certain there is no reason to have these custom marshalers, but want to keep with the current form incase of unexpected side effects
func (w *ExpandedSignals) Marshal() ([]byte, error) {
data, err := json.Marshal(*w)
return data, errors.WithStack(err)
}
func (w *ExpandedSignals) Unmarshal(data []byte) error {
err := json.Unmarshal(data, w)
return errors.WithStack(err)
}