Enhance MySubaru API integration with improved error handling and new utility functions
All checks were successful
Golan Testing / testing (1.24.x, ubuntu-latest) (push) Successful in 25s
All checks were successful
Golan Testing / testing (1.24.x, ubuntu-latest) (push) Successful in 25s
- Refactor Response struct's parse method to return detailed error messages based on API error codes. - Introduce UnixTime type for handling Unix timestamps in JSON marshaling and unmarshaling. - Add email masking utility function to obfuscate email addresses for privacy. - Implement containsValueInStruct function to check for substring presence in struct fields. - Create comprehensive unit tests for UnixTime, email masking, and struct value checking. - Update vehicle service request method documentation for clarity.
This commit is contained in:
401
mysubaru.go
401
mysubaru.go
@ -2,6 +2,10 @@ package mysubaru
|
||||
|
||||
import (
|
||||
"encoding/json"
|
||||
"errors"
|
||||
"fmt"
|
||||
"log/slog"
|
||||
"time"
|
||||
)
|
||||
|
||||
// Response represents the structure of a response from the MySubaru API.
|
||||
@ -12,18 +16,59 @@ type Response struct {
|
||||
Data json.RawMessage `json:"data"` // Data struct
|
||||
}
|
||||
|
||||
// parse .
|
||||
// func (r *Response) parse(b []byte, logger *slog.Logger) bool {
|
||||
// err := json.Unmarshal(b, &r)
|
||||
// if err != nil {
|
||||
// logger.Error("error while parsing json", "error", err.Error())
|
||||
// return false
|
||||
// }
|
||||
// return true
|
||||
// }
|
||||
// parse parses the JSON response from the MySubaru API into a Response struct.
|
||||
func (r *Response) parse(b []byte, logger *slog.Logger) (*Response, error) {
|
||||
err := json.Unmarshal(b, &r)
|
||||
if err != nil {
|
||||
logger.Error("error while parsing json", "error", err.Error())
|
||||
return nil, errors.New("error while parsing json: " + err.Error())
|
||||
}
|
||||
|
||||
// Unmarshal .
|
||||
// func (r *Response) Unmarshal(b []byte) {}
|
||||
if !r.Success && r.ErrorCode != "" {
|
||||
logger.Error("error in response", "errorCode", r.ErrorCode, "dataName", r.DataName)
|
||||
switch r.ErrorCode {
|
||||
// G2 API errors
|
||||
case API_ERRORS["API_ERROR_NO_ACCOUNT"]:
|
||||
return r, errors.New("error in response: Account not found")
|
||||
case API_ERRORS["API_ERROR_INVALID_ACCOUNT"]:
|
||||
return r, errors.New("error in response: Invalid Account")
|
||||
case API_ERRORS["API_ERROR_INVALID_CREDENTIALS"]:
|
||||
return r, errors.New("error in response: Invalid Credentials")
|
||||
case API_ERRORS["API_ERROR_INVALID_TOKEN"]:
|
||||
return r, errors.New("error in response: Invalid Token")
|
||||
case API_ERRORS["API_ERROR_PASSWORD_WARNING"]:
|
||||
return r, errors.New("error in response: Mutiple failed login attempts, password warning")
|
||||
case API_ERRORS["API_ERROR_TOO_MANY_ATTEMPTS"]:
|
||||
return r, errors.New("error in response: Too many attempts, please try again later")
|
||||
case API_ERRORS["API_ERROR_ACCOUNT_LOCKED"]:
|
||||
return r, errors.New("error in response: Account Locked")
|
||||
case API_ERRORS["API_ERROR_NO_VEHICLES"]:
|
||||
return r, errors.New("error in response: No vehicles found for the account")
|
||||
case API_ERRORS["API_ERROR_VEHICLE_SETUP"]:
|
||||
return r, errors.New("error in response: Vehicle setup is not complete")
|
||||
case API_ERRORS["API_ERROR_VEHICLE_NOT_IN_ACCOUNT"]:
|
||||
return r, errors.New("error in response: Vehicle not in account")
|
||||
case API_ERRORS["API_ERROR_SERVICE_ALREADY_STARTED"]:
|
||||
return r, errors.New("error in response: Service already started")
|
||||
case API_ERRORS["API_ERROR_SOA_403"]:
|
||||
return r, errors.New("error in response: Unable to parse response body, SOA 403 error")
|
||||
// G1 API errors
|
||||
case API_ERRORS["API_ERROR_G1_NO_SUBSCRIPTION"]:
|
||||
return r, errors.New("error in response: No subscription found for the vehicle")
|
||||
case API_ERRORS["API_ERROR_G1_STOLEN_VEHICLE"]:
|
||||
return r, errors.New("error in response: Car is reported as stolen")
|
||||
case API_ERRORS["API_ERROR_G1_INVALID_PIN"]:
|
||||
return r, errors.New("error in response: Invalid PIN")
|
||||
case API_ERRORS["API_ERROR_G1_PIN_LOCKED"]:
|
||||
return r, errors.New("error in response: PIN is locked")
|
||||
case API_ERRORS["API_ERROR_G1_SERVICE_ALREADY_STARTED"]:
|
||||
return r, errors.New("error in response: Service already started")
|
||||
}
|
||||
return r, errors.New("error in response: " + r.ErrorCode)
|
||||
}
|
||||
|
||||
return r, nil
|
||||
}
|
||||
|
||||
// Request represents the structure of a request to the MySubaru API.
|
||||
type Request struct {
|
||||
@ -46,41 +91,83 @@ type Request struct {
|
||||
StartConfiguration *string `json:"startConfiguration,omitempty"` //
|
||||
}
|
||||
|
||||
// Account .
|
||||
type Account struct {
|
||||
MarketID int `json:"marketId"`
|
||||
AccountKey int `json:"accountKey"`
|
||||
FirstName string `json:"firstName"`
|
||||
LastName string `json:"lastName"`
|
||||
ZipCode string `json:"zipCode"`
|
||||
ZipCode5 string `json:"zipCode5"`
|
||||
LastLoginDate int64 `json:"lastLoginDate"`
|
||||
CreatedDate int64 `json:"createdDate"`
|
||||
// account .
|
||||
type account struct {
|
||||
MarketID int `json:"marketId"`
|
||||
AccountKey int `json:"accountKey"`
|
||||
FirstName string `json:"firstName"`
|
||||
LastName string `json:"lastName"`
|
||||
ZipCode string `json:"zipCode"`
|
||||
ZipCode5 string `json:"zipCode5"`
|
||||
LastLoginDate UnixTime `json:"lastLoginDate"`
|
||||
CreatedDate UnixTime `json:"createdDate"`
|
||||
}
|
||||
|
||||
// Customer .
|
||||
type Customer struct {
|
||||
SessionCustomer string `json:"sessionCustomer"`
|
||||
Email string `json:"email"`
|
||||
FirstName string `json:"firstName"`
|
||||
LastName string `json:"lastName"`
|
||||
Zip string `json:"zip"`
|
||||
OemCustID string `json:"oemCustId"`
|
||||
Phone string `json:"phone"`
|
||||
SessionCustomer SessionCustomer `json:"sessionCustomer,omitempty"` // struct | Only by performing a RefreshVehicles request
|
||||
Email string `json:"email"`
|
||||
FirstName string `json:"firstName"`
|
||||
LastName string `json:"lastName"`
|
||||
Zip string `json:"zip"`
|
||||
OemCustID string `json:"oemCustId"`
|
||||
Phone string `json:"phone"`
|
||||
}
|
||||
|
||||
// SessionCustomer .
|
||||
type SessionCustomer struct {
|
||||
FirstName string `json:"firstName,omitempty"`
|
||||
LastName string `json:"lastName,omitempty"`
|
||||
Title string `json:"title,omitempty"`
|
||||
Suffix string `json:"suffix,omitempty"`
|
||||
Email string `json:"email"`
|
||||
Address string `json:"address"`
|
||||
Address2 string `json:"address2,omitempty"`
|
||||
City string `json:"city"`
|
||||
State string `json:"state"`
|
||||
Zip string `json:"zip"`
|
||||
CellularPhone string `json:"cellularPhone,omitempty"`
|
||||
WorkPhone string `json:"workPhone,omitempty"`
|
||||
HomePhone string `json:"homePhone,omitempty"`
|
||||
CountryCode string `json:"countryCode"`
|
||||
RelationshipType any `json:"relationshipType,omitempty"`
|
||||
Gender string `json:"gender,omitempty"`
|
||||
DealerCode any `json:"dealerCode,omitempty"`
|
||||
OemCustID string `json:"oemCustId"`
|
||||
CreateMysAccount any `json:"createMysAccount,omitempty"`
|
||||
SourceSystemCode string `json:"sourceSystemCode"`
|
||||
Vehicles []struct {
|
||||
Vin string `json:"vin"`
|
||||
SiebelVehicleRelationship string `json:"siebelVehicleRelationship"` // TM Subscriber | Previous TM Subscriber | Previous Owner
|
||||
Primary bool `json:"primary"` // true | false
|
||||
OemCustID string `json:"oemCustId"` // CRM-41PLM-5TYE | 1-8K7OBOJ | 1-8JY3UVS | CRM-44UFUA14-V
|
||||
Status string `json:"status,omitempty"` // "Active" | "Draft" | "Inactive"
|
||||
} `json:"vehicles"`
|
||||
Phone string `json:"phone,omitempty"`
|
||||
Zip5Digits string `json:"zip5Digits"`
|
||||
PrimaryPersonalCountry string `json:"primaryPersonalCountry"`
|
||||
}
|
||||
|
||||
// DataMap .
|
||||
// "dataName": "dataMap"
|
||||
type dataMap struct {
|
||||
Username string `json:"userName"`
|
||||
Email string `json:"email"`
|
||||
}
|
||||
|
||||
// SessionData .
|
||||
// "dataName": "sessionData"
|
||||
type SessionData struct {
|
||||
SessionChanged bool `json:"sessionChanged"`
|
||||
VehicleInactivated bool `json:"vehicleInactivated"`
|
||||
Account Account `json:"account"`
|
||||
ResetPassword bool `json:"resetPassword"`
|
||||
DeviceID string `json:"deviceId"`
|
||||
SessionID string `json:"sessionId"`
|
||||
DeviceRegistered bool `json:"deviceRegistered"`
|
||||
Account account `json:"account"`
|
||||
PasswordToken string `json:"passwordToken"`
|
||||
ResetPassword bool `json:"resetPassword"`
|
||||
SessionID string `json:"sessionId"`
|
||||
SessionChanged bool `json:"sessionChanged"`
|
||||
DeviceID string `json:"deviceId"`
|
||||
DeviceRegistered bool `json:"deviceRegistered"`
|
||||
RegisteredDevicePermanent bool `json:"registeredDevicePermanent"`
|
||||
Vehicles []VehicleData `json:"vehicles"`
|
||||
VehicleInactivated bool `json:"vehicleInactivated"`
|
||||
RightToRepairEnabled bool `json:"rightToRepairEnabled"`
|
||||
RightToRepairStates string `json:"rightToRepairStates"`
|
||||
CurrentVehicleIndex int `json:"currentVehicleIndex"`
|
||||
@ -93,54 +180,53 @@ type SessionData struct {
|
||||
DigitalGlobeTransparentTileService string `json:"digitalGlobeTransparentTileService"`
|
||||
TomtomKey string `json:"tomtomKey"`
|
||||
SatelliteViewEnabled bool `json:"satelliteViewEnabled"`
|
||||
RegisteredDevicePermanent bool `json:"registeredDevicePermanent"`
|
||||
}
|
||||
|
||||
// Vehicle .
|
||||
// "dataName": "vehicle"
|
||||
type VehicleData struct {
|
||||
Customer Customer `json:"customer"` // Customer struct
|
||||
UserOemCustID string `json:"userOemCustId"` // CRM-631-HQN48K
|
||||
OemCustID string `json:"oemCustId"` // CRM-631-HQN48K
|
||||
Active bool `json:"active"` // true | false
|
||||
Email string `json:"email"` // null | email@address.com
|
||||
FirstName string `json:"firstName"` // null | First Name
|
||||
LastName string `json:"lastName"` // null | Last Name
|
||||
Zip string `json:"zip"` // 12345
|
||||
Phone string `json:"phone"` // null | 123-456-7890
|
||||
StolenVehicle bool `json:"stolenVehicle"` // true | false
|
||||
VehicleName string `json:"vehicleName"` // Subaru Outback LXT
|
||||
Features []string `json:"features"` // "11.6MMAN", "ABS_MIL", "ACCS", "AHBL_MIL", "ATF_MIL", "AWD_MIL", "BSD", "BSDRCT_MIL", "CEL_MIL", "EBD_MIL", "EOL_MIL", "EPAS_MIL", "EPB_MIL", "ESS_MIL", "EYESIGHT", "ISS_MIL", "NAV_TOMTOM", "OPL_MIL", "RAB_MIL", "RCC", "REARBRK", "RES", "RESCC", "RHSF", "RPOI", "RPOIA", "SRH_MIL", "SRS_MIL", "TEL_MIL", "TPMS_MIL", "VDC_MIL", "WASH_MIL", "g2"
|
||||
Vin string `json:"vin"` // 4Y1SL65848Z411439
|
||||
VehicleKey int64 `json:"vehicleKey"` // 3832950
|
||||
Nickname string `json:"nickname"` // Subaru Outback LXT
|
||||
ModelName string `json:"modelName"` // Outback
|
||||
ModelYear string `json:"modelYear"` // 2020
|
||||
ModelCode string `json:"modelCode"` // LDJ
|
||||
ExtDescrip string `json:"extDescrip"` // Abyss Blue Pearl (ext color)
|
||||
IntDescrip string `json:"intDescrip"` // Gray (int color)
|
||||
TransCode string `json:"transCode"` // CVT
|
||||
EngineSize float64 `json:"engineSize"` // 2.4
|
||||
Phev bool `json:"phev"` // null
|
||||
CachedStateCode string `json:"cachedStateCode"` // NJ
|
||||
LicensePlate string `json:"licensePlate"` // NJ
|
||||
LicensePlateState string `json:"licensePlateState"` // ABCDEF
|
||||
SubscriptionStatus string `json:"subscriptionStatus"` // ACTIVE
|
||||
SubscriptionFeatures []string `json:"subscriptionFeatures"` // "[ REMOTE ], [ SAFETY ], [ Retail | Finance3 | RetailPHEV ]""
|
||||
SubscriptionPlans []string `json:"subscriptionPlans"` // []
|
||||
VehicleGeoPosition GeoPosition `json:"vehicleGeoPosition"` // GeoPosition struct
|
||||
AccessLevel int `json:"accessLevel"` // -1
|
||||
VehicleMileage int `json:"vehicleMileage"` // null
|
||||
CrmRightToRepair bool `json:"crmRightToRepair"` // true | false
|
||||
AuthorizedVehicle bool `json:"authorizedVehicle"` // false | true
|
||||
NeedMileagePrompt bool `json:"needMileagePrompt"` // false | true
|
||||
RemoteServicePinExist bool `json:"remoteServicePinExist"` // true | false
|
||||
NeedEmergencyContactPrompt bool `json:"needEmergencyContactPrompt"` // false | true
|
||||
Show3GSunsetBanner bool `json:"show3gSunsetBanner"` // false | true
|
||||
Provisioned bool `json:"provisioned"` // true | false
|
||||
TimeZone string `json:"timeZone"` // America/New_York
|
||||
SunsetUpgraded bool `json:"sunsetUpgraded"` // true | false
|
||||
PreferredDealer string `json:"preferredDealer"` // null |
|
||||
Customer Customer `json:"customer"` // Customer struct
|
||||
OemCustID string `json:"oemCustId"` // CRM-631-HQN48K
|
||||
UserOemCustID string `json:"userOemCustId"` // CRM-631-HQN48K
|
||||
Active bool `json:"active"` // true | false
|
||||
Email string `json:"email"` // null | email@address.com
|
||||
FirstName string `json:"firstName,omitempty"` // null | First Name
|
||||
LastName string `json:"lastName,omitempty"` // null | Last Name
|
||||
Zip string `json:"zip"` // 12345
|
||||
Phone string `json:"phone,omitempty"` // null | 123-456-7890
|
||||
StolenVehicle bool `json:"stolenVehicle"` // true | false
|
||||
VehicleName string `json:"vehicleName"` // Subaru Outback LXT
|
||||
Features []string `json:"features"` // "11.6MMAN", "ABS_MIL", "ACCS", "AHBL_MIL", "ATF_MIL", "AWD_MIL", "BSD", "BSDRCT_MIL", "CEL_MIL", "EBD_MIL", "EOL_MIL", "EPAS_MIL", "EPB_MIL", "ESS_MIL", "EYESIGHT", "ISS_MIL", "NAV_TOMTOM", "OPL_MIL", "RAB_MIL", "RCC", "REARBRK", "RES", "RESCC", "RHSF", "RPOI", "RPOIA", "SRH_MIL", "SRS_MIL", "TEL_MIL", "TPMS_MIL", "VDC_MIL", "WASH_MIL", "g2"
|
||||
Vin string `json:"vin"` // 4Y1SL65848Z411439
|
||||
VehicleKey int64 `json:"vehicleKey"` // 3832950
|
||||
Nickname string `json:"nickname"` // Subaru Outback LXT
|
||||
ModelName string `json:"modelName"` // Outback
|
||||
ModelYear string `json:"modelYear"` // 2020
|
||||
ModelCode string `json:"modelCode"` // LDJ
|
||||
ExtDescrip string `json:"extDescrip"` // Abyss Blue Pearl (ext color)
|
||||
IntDescrip string `json:"intDescrip"` // Gray (int color)
|
||||
TransCode string `json:"transCode"` // CVT
|
||||
EngineSize float64 `json:"engineSize"` // 2.4
|
||||
Phev bool `json:"phev"` // null
|
||||
CachedStateCode string `json:"cachedStateCode"` // NJ
|
||||
LicensePlate string `json:"licensePlate"` // NJ
|
||||
LicensePlateState string `json:"licensePlateState"` // ABCDEF
|
||||
SubscriptionStatus string `json:"subscriptionStatus"` // ACTIVE
|
||||
SubscriptionFeatures []string `json:"subscriptionFeatures"` // "[ REMOTE ], [ SAFETY ], [ Retail | Finance3 | RetailPHEV ]""
|
||||
SubscriptionPlans []string `json:"subscriptionPlans,omitempty"` // []
|
||||
VehicleGeoPosition GeoPosition `json:"vehicleGeoPosition"` // GeoPosition struct
|
||||
AccessLevel int `json:"accessLevel"` // -1
|
||||
VehicleMileage int `json:"vehicleMileage,omitempty"` // null
|
||||
CrmRightToRepair bool `json:"crmRightToRepair"` // true | false
|
||||
AuthorizedVehicle bool `json:"authorizedVehicle"` // false | true
|
||||
NeedMileagePrompt bool `json:"needMileagePrompt"` // false | true
|
||||
RemoteServicePinExist bool `json:"remoteServicePinExist"` // true | false
|
||||
NeedEmergencyContactPrompt bool `json:"needEmergencyContactPrompt"` // false | true
|
||||
Show3GSunsetBanner bool `json:"show3gSunsetBanner"` // false | true
|
||||
Provisioned bool `json:"provisioned"` // true | false
|
||||
TimeZone string `json:"timeZone"` // America/New_York
|
||||
SunsetUpgraded bool `json:"sunsetUpgraded"` // true | false
|
||||
PreferredDealer string `json:"preferredDealer,omitempty"` // null |
|
||||
}
|
||||
|
||||
// GeoPosition .
|
||||
@ -166,65 +252,58 @@ type GeoPosition struct {
|
||||
// }
|
||||
|
||||
// VehicleStatus .
|
||||
// "dataName":null
|
||||
// parts = []{"door", "tire", "tyre", "window"}
|
||||
// prefix = []{"pressure", "status"}
|
||||
// suffix = []{"status", "position", "unit", "psi"}
|
||||
// positions = []{"front", "rear", "sunroof", "boot", "enginehood"}
|
||||
// subPositions []{"left", "right"}
|
||||
|
||||
type VehicleStatus struct {
|
||||
VehicleId int64 `json:"vhsId"` // + 9969776690 5198812434
|
||||
OdometerValue int `json:"odometerValue"` // + 23787
|
||||
OdometerValueKm int `json:"odometerValueKilometers"` // + 38273
|
||||
EventDate int64 `json:"eventDate"` // + 1701896993000
|
||||
EventDateStr string `json:"eventDateStr"` // + 2023-12-06T21:09+0000
|
||||
EventDateCarUser int64 `json:"eventDateCarUser"` // + 1701896993000
|
||||
EventDateStrCarUser string `json:"eventDateStrCarUser"` // + 2023-12-06T21:09+0000
|
||||
Latitude float64 `json:"latitude"` // + 40.700183
|
||||
Longitude float64 `json:"longitude"` // + -74.401372
|
||||
Heading int `json:"positionHeadingDegree,string"` // + "154"
|
||||
DistanceToEmptyFuelMiles float64 `json:"distanceToEmptyFuelMiles"` // + 209.4
|
||||
DistanceToEmptyFuelKilometers int `json:"distanceToEmptyFuelKilometers"` // + 337
|
||||
DistanceToEmptyFuelMiles10s int `json:"distanceToEmptyFuelMiles10s"` // + 210
|
||||
DistanceToEmptyFuelKilometers10s int `json:"distanceToEmptyFuelKilometers10s"` // + 340
|
||||
AvgFuelConsumptionMpg float64 `json:"avgFuelConsumptionMpg"` // + 18.4
|
||||
AvgFuelConsumptionLitersPer100Kilometers float64 `json:"avgFuelConsumptionLitersPer100Kilometers"` // + 12.8
|
||||
RemainingFuelPercent int `json:"remainingFuelPercent"` // + 82
|
||||
TirePressureFrontLeft int `json:"tirePressureFrontLeft,string,omitempty"` // + "2275"
|
||||
TirePressureFrontRight int `json:"tirePressureFrontRight,string,omitempty"` // + "2344"
|
||||
TirePressureRearLeft int `json:"tirePressureRearLeft,string,omitempty"` // + "2413"
|
||||
TirePressureRearRight int `json:"tirePressureRearRight,string,omitempty"` // + "2344"
|
||||
TirePressureFrontLeftPsi float64 `json:"tirePressureFrontLeftPsi,string,omitempty"` // + "33"
|
||||
TirePressureFrontRightPsi float64 `json:"tirePressureFrontRightPsi,string,omitempty"` // + "34"
|
||||
TirePressureRearLeftPsi float64 `json:"tirePressureRearLeftPsi,string,omitempty"` // + "35"
|
||||
TirePressureRearRightPsi float64 `json:"tirePressureRearRightPsi,string,omitempty"` // + "34"
|
||||
TyreStatusFrontLeft string `json:"tyreStatusFrontLeft"` // + "UNKNOWN"
|
||||
TyreStatusFrontRight string `json:"tyreStatusFrontRight"` // + "UNKNOWN"
|
||||
TyreStatusRearLeft string `json:"tyreStatusRearLeft"` // + "UNKNOWN"
|
||||
TyreStatusRearRight string `json:"tyreStatusRearRight"` // + "UNKNOWN"
|
||||
EvStateOfChargePercent float64 `json:"evStateOfChargePercent,omitempty"` // + null
|
||||
EvDistanceToEmptyMiles int `json:"evDistanceToEmptyMiles,omitempty"` // + null
|
||||
EvDistanceToEmptyKilometers int `json:"evDistanceToEmptyKilometers,omitempty"` // + null
|
||||
EvDistanceToEmptyByStateMiles int `json:"evDistanceToEmptyByStateMiles,omitempty"` // + null
|
||||
EvDistanceToEmptyByStateKilometers int `json:"evDistanceToEmptyByStateKilometers,omitempty"` // + null
|
||||
VehicleStateType string `json:"vehicleStateType"` // + "IGNITION_OFF | IGNITION_ON"
|
||||
WindowFrontLeftStatus string `json:"windowFrontLeftStatus"` // CLOSE | VENTED | OPEN
|
||||
WindowFrontRightStatus string `json:"windowFrontRightStatus"` // CLOSE | VENTED | OPEN
|
||||
WindowRearLeftStatus string `json:"windowRearLeftStatus"` // CLOSE | VENTED | OPEN
|
||||
WindowRearRightStatus string `json:"windowRearRightStatus"` // CLOSE | VENTED | OPEN
|
||||
WindowSunroofStatus string `json:"windowSunroofStatus"` // CLOSE | SLIDE_PARTLY_OPEN | OPEN | TILT
|
||||
DoorBootPosition string `json:"doorBootPosition"` // CLOSED | OPEN
|
||||
DoorEngineHoodPosition string `json:"doorEngineHoodPosition"` // CLOSED | OPEN
|
||||
DoorFrontLeftPosition string `json:"doorFrontLeftPosition"` // CLOSED | OPEN
|
||||
DoorFrontRightPosition string `json:"doorFrontRightPosition"` // CLOSED | OPEN
|
||||
DoorRearLeftPosition string `json:"doorRearLeftPosition"` // CLOSED | OPEN
|
||||
DoorRearRightPosition string `json:"doorRearRightPosition"` // CLOSED | OPEN
|
||||
DoorBootLockStatus string `json:"doorBootLockStatus"` // LOCKED | UNLOCKED
|
||||
DoorFrontLeftLockStatus string `json:"doorFrontLeftLockStatus"` // LOCKED | UNLOCKED
|
||||
DoorFrontRightLockStatus string `json:"doorFrontRightLockStatus"` // LOCKED | UNLOCKED
|
||||
DoorRearLeftLockStatus string `json:"doorRearLeftLockStatus"` // LOCKED | UNLOCKED
|
||||
DoorRearRightLockStatus string `json:"doorRearRightLockStatus"` // LOCKED | UNLOCKED
|
||||
VehicleId int64 `json:"vhsId"` // + 9969776690 5198812434
|
||||
OdometerValue int `json:"odometerValue"` // + 23787
|
||||
OdometerValueKm int `json:"odometerValueKilometers"` // + 38273
|
||||
EventDate UnixTime `json:"eventDate"` // + 1701896993000
|
||||
EventDateStr string `json:"eventDateStr"` // + 2023-12-06T21:09+0000
|
||||
EventDateCarUser UnixTime `json:"eventDateCarUser"` // + 1701896993000
|
||||
EventDateStrCarUser string `json:"eventDateStrCarUser"` // + 2023-12-06T21:09+0000
|
||||
Latitude float64 `json:"latitude"` // + 40.700183
|
||||
Longitude float64 `json:"longitude"` // + -74.401372
|
||||
Heading int `json:"positionHeadingDegree,string"` // + "154"
|
||||
DistanceToEmptyFuelMiles float64 `json:"distanceToEmptyFuelMiles"` // + 209.4
|
||||
DistanceToEmptyFuelKilometers int `json:"distanceToEmptyFuelKilometers"` // + 337
|
||||
DistanceToEmptyFuelMiles10s int `json:"distanceToEmptyFuelMiles10s"` // + 210
|
||||
DistanceToEmptyFuelKilometers10s int `json:"distanceToEmptyFuelKilometers10s"` // + 340
|
||||
AvgFuelConsumptionMpg float64 `json:"avgFuelConsumptionMpg"` // + 18.4
|
||||
AvgFuelConsumptionLitersPer100Kilometers float64 `json:"avgFuelConsumptionLitersPer100Kilometers"` // + 12.8
|
||||
RemainingFuelPercent int `json:"remainingFuelPercent"` // + 82
|
||||
TirePressureFrontLeft int `json:"tirePressureFrontLeft,string,omitempty"` // + "2275"
|
||||
TirePressureFrontRight int `json:"tirePressureFrontRight,string,omitempty"` // + "2344"
|
||||
TirePressureRearLeft int `json:"tirePressureRearLeft,string,omitempty"` // + "2413"
|
||||
TirePressureRearRight int `json:"tirePressureRearRight,string,omitempty"` // + "2344"
|
||||
TirePressureFrontLeftPsi float64 `json:"tirePressureFrontLeftPsi,string,omitempty"` // + "33"
|
||||
TirePressureFrontRightPsi float64 `json:"tirePressureFrontRightPsi,string,omitempty"` // + "34"
|
||||
TirePressureRearLeftPsi float64 `json:"tirePressureRearLeftPsi,string,omitempty"` // + "35"
|
||||
TirePressureRearRightPsi float64 `json:"tirePressureRearRightPsi,string,omitempty"` // + "34"
|
||||
TyreStatusFrontLeft string `json:"tyreStatusFrontLeft"` // + "UNKNOWN"
|
||||
TyreStatusFrontRight string `json:"tyreStatusFrontRight"` // + "UNKNOWN"
|
||||
TyreStatusRearLeft string `json:"tyreStatusRearLeft"` // + "UNKNOWN"
|
||||
TyreStatusRearRight string `json:"tyreStatusRearRight"` // + "UNKNOWN"
|
||||
EvStateOfChargePercent float64 `json:"evStateOfChargePercent,omitempty"` // + null
|
||||
EvDistanceToEmptyMiles int `json:"evDistanceToEmptyMiles,omitempty"` // + null
|
||||
EvDistanceToEmptyKilometers int `json:"evDistanceToEmptyKilometers,omitempty"` // + null
|
||||
EvDistanceToEmptyByStateMiles int `json:"evDistanceToEmptyByStateMiles,omitempty"` // + null
|
||||
EvDistanceToEmptyByStateKilometers int `json:"evDistanceToEmptyByStateKilometers,omitempty"` // + null
|
||||
VehicleStateType string `json:"vehicleStateType"` // + "IGNITION_OFF | IGNITION_ON"
|
||||
WindowFrontLeftStatus string `json:"windowFrontLeftStatus"` // CLOSE | VENTED | OPEN
|
||||
WindowFrontRightStatus string `json:"windowFrontRightStatus"` // CLOSE | VENTED | OPEN
|
||||
WindowRearLeftStatus string `json:"windowRearLeftStatus"` // CLOSE | VENTED | OPEN
|
||||
WindowRearRightStatus string `json:"windowRearRightStatus"` // CLOSE | VENTED | OPEN
|
||||
WindowSunroofStatus string `json:"windowSunroofStatus"` // CLOSE | SLIDE_PARTLY_OPEN | OPEN | TILT
|
||||
DoorBootPosition string `json:"doorBootPosition"` // CLOSED | OPEN
|
||||
DoorEngineHoodPosition string `json:"doorEngineHoodPosition"` // CLOSED | OPEN
|
||||
DoorFrontLeftPosition string `json:"doorFrontLeftPosition"` // CLOSED | OPEN
|
||||
DoorFrontRightPosition string `json:"doorFrontRightPosition"` // CLOSED | OPEN
|
||||
DoorRearLeftPosition string `json:"doorRearLeftPosition"` // CLOSED | OPEN
|
||||
DoorRearRightPosition string `json:"doorRearRightPosition"` // CLOSED | OPEN
|
||||
DoorBootLockStatus string `json:"doorBootLockStatus"` // LOCKED | UNLOCKED
|
||||
DoorFrontLeftLockStatus string `json:"doorFrontLeftLockStatus"` // LOCKED | UNLOCKED
|
||||
DoorFrontRightLockStatus string `json:"doorFrontRightLockStatus"` // LOCKED | UNLOCKED
|
||||
DoorRearLeftLockStatus string `json:"doorRearLeftLockStatus"` // LOCKED | UNLOCKED
|
||||
DoorRearRightLockStatus string `json:"doorRearRightLockStatus"` // LOCKED | UNLOCKED
|
||||
}
|
||||
|
||||
// VehicleCondition .
|
||||
@ -287,6 +366,7 @@ type VehicleCondition struct {
|
||||
// "dataName": "remoteServiceStatus"
|
||||
type ServiceRequest struct {
|
||||
ServiceRequestID string `json:"serviceRequestId,omitempty"` // 4S4BTGND8L3137058_1640294426029_19_@NGTP
|
||||
Vin string `json:"vin"` // 4S4BTGND8L3137058
|
||||
Success bool `json:"success"` // false | true // Could be in the false state while the executed request in the progress
|
||||
Cancelled bool `json:"cancelled"` // false | true
|
||||
RemoteServiceType string `json:"remoteServiceType"` // vehicleStatus | condition | locate | unlock | lock | lightsOnly | engineStart | engineStop | phevChargeNow
|
||||
@ -294,8 +374,7 @@ type ServiceRequest struct {
|
||||
SubState string `json:"subState,omitempty"` // null
|
||||
ErrorCode string `json:"errorCode,omitempty"` // null:null
|
||||
Result json.RawMessage `json:"result,omitempty"` // struct
|
||||
UpdateTime int64 `json:"updateTime,omitempty"` // timestamp
|
||||
Vin string `json:"vin"` // 4S4BTGND8L3137058
|
||||
UpdateTime UnixTime `json:"updateTime,omitempty"` // timestamp // is empty if the request is started
|
||||
}
|
||||
|
||||
// climateSettings: [ climateSettings ]
|
||||
@ -334,3 +413,49 @@ type ErrorResponse struct {
|
||||
ErrorLabel string `json:"errorLabel"` // "404-soa-unableToParseResponseBody"
|
||||
ErrorDescription string `json:"errorDescription,omitempty"` // null
|
||||
}
|
||||
|
||||
// UnixTime is a wrapper around time.Time that allows us to marshal and unmarshal Unix timestamps
|
||||
type UnixTime struct {
|
||||
time.Time
|
||||
}
|
||||
|
||||
// UnmarshalJSON is the method that satisfies the Unmarshaller interface
|
||||
// Note that it uses a pointer receiver. It needs this because it will be modifying the embedded time.Time instance
|
||||
func (u *UnixTime) UnmarshalJSON(b []byte) error {
|
||||
var timestamp int64
|
||||
err := json.Unmarshal(b, ×tamp)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
u.Time = time.Unix(timestamp, 0)
|
||||
return nil
|
||||
}
|
||||
|
||||
// MarshalJSON turns our time.Time back into an int
|
||||
func (u UnixTime) MarshalJSON() ([]byte, error) {
|
||||
return []byte(fmt.Sprintf("%d", (u.Time.Unix()))), nil
|
||||
}
|
||||
|
||||
// CustomTime1 "2021-12-22T13:14:47" is a custom type for unmarshalling time strings
|
||||
type CustomTime1 struct {
|
||||
time.Time
|
||||
}
|
||||
|
||||
// UnmarshalJSON implements the json.Unmarshaler interface
|
||||
func (ct *CustomTime1) UnmarshalJSON(b []byte) (err error) {
|
||||
// Use the correct layout string for the desired format
|
||||
const layout = "2006-01-02T15:04:05"
|
||||
ct.Time, err = time.Parse(layout, string(b))
|
||||
return
|
||||
}
|
||||
|
||||
// CustomTime2 "2023-04-10T17:50:54+0000" is a custom type for unmarshalling time strings
|
||||
type CustomTime2 struct {
|
||||
time.Time
|
||||
}
|
||||
|
||||
func (ct *CustomTime2) UnmarshalJSON(b []byte) (err error) {
|
||||
const layout = "2006-01-02T15:04:05-0700"
|
||||
ct.Time, err = time.Parse(layout, string(b)) // Parse the string using the custom layout
|
||||
return
|
||||
}
|
||||
|
Reference in New Issue
Block a user