Alphan version
All checks were successful
Golan Testing / testing (1.24.x, ubuntu-latest) (push) Successful in 25s

This commit is contained in:
2025-06-01 20:40:38 -04:00
parent f4fa996d53
commit b0385b15ab
4 changed files with 184 additions and 185 deletions

105
client.go
View File

@ -2,7 +2,6 @@ package mysubaru
import (
"encoding/json"
"fmt"
"io"
"log/slog"
"sync"
@ -283,15 +282,15 @@ func (c *Client) execute(requestUrl string, method string, params map[string]str
// Finished RemoteServiceState Service Request does not include Service Request ID
c.logger.Debug("Remote service request completed successfully")
case sr.RemoteServiceState == "started":
time.Sleep(3 * time.Second)
time.Sleep(5 * time.Second)
c.logger.Debug("Subaru API reports remote service request (started) is in progress", "id", sr.ServiceRequestID)
c.execute(pollingUrl, GET, map[string]string{"serviceRequestId": sr.ServiceRequestID}, pollingUrl, false)
case sr.RemoteServiceState == "stopping":
time.Sleep(3 * time.Second)
time.Sleep(5 * time.Second)
c.logger.Debug("Subaru API reports remote service request (stopping) is in progress", "id", sr.ServiceRequestID)
c.execute(pollingUrl, GET, map[string]string{"serviceRequestId": sr.ServiceRequestID}, pollingUrl, false)
default:
time.Sleep(3 * time.Second)
time.Sleep(5 * time.Second)
c.logger.Debug("Subaru API reports remote service request (stopping) is in progress")
c.execute(pollingUrl, GET, map[string]string{"serviceRequestId": sr.ServiceRequestID}, pollingUrl, false)
}
@ -507,57 +506,57 @@ func (c *Client) setDeviceName() bool {
return true
}
// listDevices .
func (c *Client) listDevices() {
// Accept: application/json, text/javascript, */*; q=0.01
// Accept-Encoding: gzip, deflate, br
// Accept-Language: en-US,en;q=0.9,ru;q=0.8
// Connection: keep-alive
// Cookie: ORA_OTD_JROUTE=ozLwELf5jS-NHQ2CKZorOFfRgb8uo6lL; soa-visitor=12212021VHWnkqERZYThWe87TLUhr2Db; AMCVS_94001C8B532957140A490D4D%40AdobeOrg=1; mys-referringCodes=7~direct~; s_cc=true; AMCVS_subarucom%40AdobeOrg=1; style=null; s_pv=login.html; AMCV_subarucom%40AdobeOrg=-1124106680%7CMCIDTS%7C18988%7CMCMID%7C81535064704660726005836131001032500276%7CMCAID%7CNONE%7CMCOPTOUT-1640567559s%7CNONE%7CvVersion%7C5.2.0; AMCV_94001C8B532957140A490D4D%40AdobeOrg=-1124106680%7CMCIDTS%7C18988%7CMCMID%7C76913534164341455390435376071204508177%7CMCAID%7CNONE%7CMCOPTOUT-1640567559s%7CNONE%7CvVersion%7C5.2.0; s_sq=subarumysubarucwpprod%3D%2526c.%2526a.%2526activitymap.%2526page%253Dlogin.html%2526link%253DLog%252520In%2526region%253DloginForm%2526pageIDType%253D1%2526.activitymap%2526.a%2526.c%2526pid%253Dlogin.html%2526pidt%253D1%2526oid%253DLog%252520In%2526oidt%253D3%2526ot%253DSUBMIT; JSESSIONID=9685CFEB7888A0E6E25239D559E3B580; X-Oracle-BMC-LBS-Route=89e3283ece707e8a0ba4850e1a622122e039fd3d27da03a11a2ff120e313e9b656c62fd8a7c42ae8061a49ad6e1caf63a49d7befe4ad2a0194b0aeca
// Host: www.mysubaru.com
// Referer: https://www.mysubaru.com/profile/authorizedDevices.html
// User-Agent: Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15_7) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/95.0.4638.69 Safari/537.36
// X-Requested-With: XMLHttpRequest
resp, err := c.httpClient.
SetBaseURL(WEB_API_SERVER[c.country]).
R().
EnableTrace().
Get(apiURLs["WEB_API_LIST_DEVICES"])
// // listDevices .
// func (c *Client) listDevices() {
// // Accept: application/json, text/javascript, */*; q=0.01
// // Accept-Encoding: gzip, deflate, br
// // Accept-Language: en-US,en;q=0.9,ru;q=0.8
// // Connection: keep-alive
// // Cookie: ORA_OTD_JROUTE=ozLwELf5jS-NHQ2CKZorOFfRgb8uo6lL; soa-visitor=12212021VHWnkqERZYThWe87TLUhr2Db; AMCVS_94001C8B532957140A490D4D%40AdobeOrg=1; mys-referringCodes=7~direct~; s_cc=true; AMCVS_subarucom%40AdobeOrg=1; style=null; s_pv=login.html; AMCV_subarucom%40AdobeOrg=-1124106680%7CMCIDTS%7C18988%7CMCMID%7C81535064704660726005836131001032500276%7CMCAID%7CNONE%7CMCOPTOUT-1640567559s%7CNONE%7CvVersion%7C5.2.0; AMCV_94001C8B532957140A490D4D%40AdobeOrg=-1124106680%7CMCIDTS%7C18988%7CMCMID%7C76913534164341455390435376071204508177%7CMCAID%7CNONE%7CMCOPTOUT-1640567559s%7CNONE%7CvVersion%7C5.2.0; s_sq=subarumysubarucwpprod%3D%2526c.%2526a.%2526activitymap.%2526page%253Dlogin.html%2526link%253DLog%252520In%2526region%253DloginForm%2526pageIDType%253D1%2526.activitymap%2526.a%2526.c%2526pid%253Dlogin.html%2526pidt%253D1%2526oid%253DLog%252520In%2526oidt%253D3%2526ot%253DSUBMIT; JSESSIONID=9685CFEB7888A0E6E25239D559E3B580; X-Oracle-BMC-LBS-Route=89e3283ece707e8a0ba4850e1a622122e039fd3d27da03a11a2ff120e313e9b656c62fd8a7c42ae8061a49ad6e1caf63a49d7befe4ad2a0194b0aeca
// // Host: www.mysubaru.com
// // Referer: https://www.mysubaru.com/profile/authorizedDevices.html
// // User-Agent: Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15_7) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/95.0.4638.69 Safari/537.36
// // X-Requested-With: XMLHttpRequest
// resp, err := c.httpClient.
// SetBaseURL(WEB_API_SERVER[c.country]).
// R().
// EnableTrace().
// Get(apiURLs["WEB_API_LIST_DEVICES"])
// Explore response object
fmt.Println("Response Info:")
fmt.Println(" Error :", err)
fmt.Println(" Status Code:", resp.StatusCode())
fmt.Println(" Status :", resp.Status())
fmt.Println(" Proto :", resp.Proto())
fmt.Println(" Time :", resp.Duration())
fmt.Println(" Received At:", resp.ReceivedAt())
// fmt.Println(" Body :\n", resp)
fmt.Println()
// // Explore response object
// fmt.Println("Response Info:")
// fmt.Println(" Error :", err)
// fmt.Println(" Status Code:", resp.StatusCode())
// fmt.Println(" Status :", resp.Status())
// fmt.Println(" Proto :", resp.Proto())
// fmt.Println(" Time :", resp.Duration())
// fmt.Println(" Received At:", resp.ReceivedAt())
// // fmt.Println(" Body :\n", resp)
// fmt.Println()
// Explore trace info
fmt.Println("Request Trace Info:")
ti := resp.Request.TraceInfo()
fmt.Println(" DNSLookup :", ti.DNSLookup)
fmt.Println(" ConnTime :", ti.ConnTime)
fmt.Println(" TCPConnTime :", ti.TCPConnTime)
fmt.Println(" TLSHandshake :", ti.TLSHandshake)
fmt.Println(" ServerTime :", ti.ServerTime)
fmt.Println(" ResponseTime :", ti.ResponseTime)
fmt.Println(" TotalTime :", ti.TotalTime)
fmt.Println(" IsConnReused :", ti.IsConnReused)
fmt.Println(" IsConnWasIdle :", ti.IsConnWasIdle)
fmt.Println(" ConnIdleTime :", ti.ConnIdleTime)
fmt.Println(" RequestAttempt:", ti.RequestAttempt)
fmt.Println(" RemoteAddr :", ti.RemoteAddr)
// // Explore trace info
// fmt.Println("Request Trace Info:")
// ti := resp.Request.TraceInfo()
// fmt.Println(" DNSLookup :", ti.DNSLookup)
// fmt.Println(" ConnTime :", ti.ConnTime)
// fmt.Println(" TCPConnTime :", ti.TCPConnTime)
// fmt.Println(" TLSHandshake :", ti.TLSHandshake)
// fmt.Println(" ServerTime :", ti.ServerTime)
// fmt.Println(" ResponseTime :", ti.ResponseTime)
// fmt.Println(" TotalTime :", ti.TotalTime)
// fmt.Println(" IsConnReused :", ti.IsConnReused)
// fmt.Println(" IsConnWasIdle :", ti.IsConnWasIdle)
// fmt.Println(" ConnIdleTime :", ti.ConnIdleTime)
// fmt.Println(" RequestAttempt:", ti.RequestAttempt)
// fmt.Println(" RemoteAddr :", ti.RemoteAddr)
// c.logger.Debug("LIST DEVICES OUTPUT", "body", string([]byte(resp.Body())))
// // c.logger.Debug("LIST DEVICES OUTPUT", "body", string([]byte(resp.Body())))
// c.httpClient.SetBaseURL(WEB_API_SERVER[c.country]).SetCookies(c.cookies)
// reqURL := apiURLs["WEB_API_LIST_DEVICES"]
// resp := c.execute(reqURL, GET, map[string]string{}, "", false)
// // c.httpClient.SetBaseURL(WEB_API_SERVER[c.country]).SetCookies(c.cookies)
// // reqURL := apiURLs["WEB_API_LIST_DEVICES"]
// // resp := c.execute(reqURL, GET, map[string]string{}, "", false)
// if isResponseSuccessfull(resp) {
// logger.Debugf("LIST DEVICES OUTPUT >> %v\n", string(resp))
// }
}
// // if isResponseSuccessfull(resp) {
// // logger.Debugf("LIST DEVICES OUTPUT >> %v\n", string(resp))
// // }
// }

154
consts.go
View File

@ -74,42 +74,44 @@ var apiURLs = map[string]string{
// "API_G2_SAVE_CLIMATE_SETTINGS": "/service/g2/remoteEngineStart/save.json",
}
// TODO: Get back and add wrapper to support Feature List
// API_VEHICLE_FEATURES items that determine available functionality
// 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 SRS_MIL TEL_MIL TIF_35 TIR_33 TPMS_MIL VDC_MIL WASH_MIL g2
// 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 OPL_MIL PANPM-TUIRWAOC PWAAADWWAP RAB_MIL RCC REARBRK RES RESCC RHSF RPOI RPOIA RTGU RVFS SRH_MIL SRS_MIL TEL_MIL TIF_35 TIR_33 TLD TPMS_MIL VALET VDC_MIL WASH_MIL g3
var apiFeatures = map[string]string{
"API_FEATURE_PHEV": "PHEV",
"API_FEATURE_REMOTE_START": "RES",
"API_FEATURE_REMOTE": "REMOTE",
"API_FEATURE_SAFETY": "SAFETY",
"API_FEATURE_ACTIVE": "ACTIVE",
"API_FEATURE_MOONROOF_PANORAMIC": "PANPM-DG2G",
"API_FEATURE_MOONROOF_POWER": "PANPM-TUIRWAOC",
"API_FEATURE_POWER_WINDOWS": "PWAAADWWAP",
"API_FEATURE_FRONT_TIRE_RECOMMENDED_PRESSURE_PREFIX": "TIF_",
"API_FEATURE_REAR_TIRE_RECOMMENDED_PRESSURE_PREFIX": "TIR_",
"API_FEATURE_G1_TELEMATICS": "g1",
"API_FEATURE_G2_TELEMATICS": "g2",
"API_FEATURE_G3_TELEMATICS": "g3",
}
// var apiFeatures = map[string]string{
// "API_FEATURE_PHEV": "PHEV",
// "API_FEATURE_REMOTE_START": "RES",
// "API_FEATURE_REMOTE": "REMOTE",
// "API_FEATURE_SAFETY": "SAFETY",
// "API_FEATURE_ACTIVE": "ACTIVE",
// "API_FEATURE_MOONROOF_PANORAMIC": "PANPM-DG2G",
// "API_FEATURE_MOONROOF_POWER": "PANPM-TUIRWAOC",
// "API_FEATURE_POWER_WINDOWS": "PWAAADWWAP",
// "API_FEATURE_FRONT_TIRE_RECOMMENDED_PRESSURE_PREFIX": "TIF_",
// "API_FEATURE_REAR_TIRE_RECOMMENDED_PRESSURE_PREFIX": "TIR_",
// "API_FEATURE_G1_TELEMATICS": "g1",
// "API_FEATURE_G2_TELEMATICS": "g2",
// "API_FEATURE_G3_TELEMATICS": "g3",
// }
var apiErrors = map[string]string{
"ERROR_SOA_403": "403-soa-unableToParseResponseBody", // G2 Error Codes
"ERROR_INVALID_CREDENTIALS": "InvalidCredentials",
"ERROR_SERVICE_ALREADY_STARTED": "ServiceAlreadyStarted",
"ERROR_INVALID_ACCOUNT": "invalidAccount",
"ERROR_PASSWORD_WARNING": "passwordWarning",
"ERROR_ACCOUNT_LOCKED": "accountLocked",
"ERROR_NO_VEHICLES": "noVehiclesOnAccount",
"ERROR_NO_ACCOUNT": "accountNotFound",
"ERROR_TOO_MANY_ATTEMPTS": "tooManyAttempts",
"ERROR_VEHICLE_NOT_IN_ACCOUNT": "vehicleNotInAccount",
"ERROR_G1_NO_SUBSCRIPTION": "SXM40004", // G1 Error Codes
"ERROR_G1_STOLEN_VEHICLE": "SXM40005",
"ERROR_G1_INVALID_PIN": "SXM40006",
"ERROR_G1_SERVICE_ALREADY_STARTED": "SXM40009",
"ERROR_G1_PIN_LOCKED": "SXM40017",
}
// TODO: Get back and add error wrapper
// var apiErrors = map[string]string{
// "ERROR_SOA_403": "403-soa-unableToParseResponseBody", // G2 Error Codes
// "ERROR_INVALID_CREDENTIALS": "InvalidCredentials",
// "ERROR_SERVICE_ALREADY_STARTED": "ServiceAlreadyStarted",
// "ERROR_INVALID_ACCOUNT": "invalidAccount",
// "ERROR_PASSWORD_WARNING": "passwordWarning",
// "ERROR_ACCOUNT_LOCKED": "accountLocked",
// "ERROR_NO_VEHICLES": "noVehiclesOnAccount",
// "ERROR_NO_ACCOUNT": "accountNotFound",
// "ERROR_TOO_MANY_ATTEMPTS": "tooManyAttempts",
// "ERROR_VEHICLE_NOT_IN_ACCOUNT": "vehicleNotInAccount",
// "ERROR_G1_NO_SUBSCRIPTION": "SXM40004", // G1 Error Codes
// "ERROR_G1_STOLEN_VEHICLE": "SXM40005",
// "ERROR_G1_INVALID_PIN": "SXM40006",
// "ERROR_G1_SERVICE_ALREADY_STARTED": "SXM40009",
// "ERROR_G1_PIN_LOCKED": "SXM40017",
// }
// 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 OPL_MIL PANPM-TUIRWAOC PWAAADWWAP RAB_MIL RCC REARBRK RES RESCC RHSF RPOI RPOIA RTGU RVFS SRH_MIL SRS_MIL TEL_MIL TIF_35 TIR_33 TLD TPMS_MIL VALET VDC_MIL WASH_MIL g3
// 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 SRS_MIL TEL_MIL TIF_35 TIR_33 TPMS_MIL VDC_MIL WASH_MIL g2
@ -132,51 +134,51 @@ var features = map[string]string{
"VALET": "Valet Parking",
}
var errors = map[string]string{
"ABS_MIL": "Anti-Lock Braking System",
"AHBL_MIL": "Automatic Headlight Beam Leveler",
"ATF_MIL": "Automatic Transmission Oil Temperature",
"AWD_MIL": "Symmetrical Full-Time AWD",
"BSDRCT_MIL": "Blind-Spot Detection",
"CEL_MIL": "Check Engine Light",
"EBD_MIL": "Electronic Brake Force Distribution",
"EOL_MIL": "Engine Oil Level",
"EPAS_MIL": "Electric Power Assisted Steering",
"EPB_MIL": "Parking Brake",
"ESS_MIL": "EyeSight Exclusive Advanced Driver-Assist System",
"ISS_MIL": "iss",
"OPL_MIL": "Oil Pressure",
"RAB_MIL": "Reverse Auto Braking",
"SRH_MIL": "Steering Responsive Headlights",
"SRS_MIL": "Airbag System",
"TEL_MIL": "telematics",
"TPMS_MIL": "tpms",
"VDC_MIL": "Vehicle Dynamics Control",
"WASH_MIL": "Windshield Washer Fluid Level",
}
var modelCodes = map[string]string{
"PDL": "Subaru Outback Touring XT",
"LDJ": "Subaru Outback Limited XT",
"KDF": "Outback 2.5i Limited",
"LDD": "Outback Premium",
"PDG": "Outback Touring",
"KFB": "Forester Base Model",
"HFJ": "Forester 2.5i Touring",
"KFJ": "Forester Touring",
"KAF": "Legacy 2.5i Limited",
"KLF": "Impreza 2.0i Sport",
"LRD": "Crosstrek Premium",
"KRD": "Crosstrek 2.0i Premium",
"PCL": "Ascent Limited 7-Passenger",
}
// var errors = map[string]string{
// "ABS_MIL": "Anti-Lock Braking System",
// "AHBL_MIL": "Automatic Headlight Beam Leveler",
// "ATF_MIL": "Automatic Transmission Oil Temperature",
// "AWD_MIL": "Symmetrical Full-Time AWD",
// "BSDRCT_MIL": "Blind-Spot Detection",
// "CEL_MIL": "Check Engine Light",
// "EBD_MIL": "Electronic Brake Force Distribution",
// "EOL_MIL": "Engine Oil Level",
// "EPAS_MIL": "Electric Power Assisted Steering",
// "EPB_MIL": "Parking Brake",
// "ESS_MIL": "EyeSight Exclusive Advanced Driver-Assist System",
// "ISS_MIL": "iss",
// "OPL_MIL": "Oil Pressure",
// "RAB_MIL": "Reverse Auto Braking",
// "SRH_MIL": "Steering Responsive Headlights",
// "SRS_MIL": "Airbag System",
// "TEL_MIL": "telematics",
// "TPMS_MIL": "tpms",
// "VDC_MIL": "Vehicle Dynamics Control",
// "WASH_MIL": "Windshield Washer Fluid Level",
// }
// var modelCodes = map[string]string{
// "PDL": "Subaru Outback Touring XT",
// "LDJ": "Subaru Outback Limited XT",
// "KDF": "Outback 2.5i Limited",
// "LDD": "Outback Premium",
// "PDG": "Outback Touring",
// "KFB": "Forester Base Model",
// "HFJ": "Forester 2.5i Touring",
// "KFJ": "Forester Touring",
// "KAF": "Legacy 2.5i Limited",
// "KLF": "Impreza 2.0i Sport",
// "LRD": "Crosstrek Premium",
// "KRD": "Crosstrek 2.0i Premium",
// "PCL": "Ascent Limited 7-Passenger",
// }
var badValues = map[string]any{
"remainingFuelPercent": 101,
"tyreStatusFrontLeft": "UNKNOWN",
"tyreStatusFrontRight": "UNKNOWN",
"tyreStatusRearLeft": "UNKNOWN",
"tyreStatusRearRight": "UNKNOWN",
}
// var badValues = map[string]any{
// "remainingFuelPercent": 101,
// "tyreStatusFrontLeft": "UNKNOWN",
// "tyreStatusFrontRight": "UNKNOWN",
// "tyreStatusRearLeft": "UNKNOWN",
// "tyreStatusRearRight": "UNKNOWN",
// }
const (
GET = "GET"

View File

@ -2,7 +2,6 @@ package mysubaru
import (
"encoding/json"
"log/slog"
)
// Response .
@ -14,14 +13,14 @@ type Response 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
}
// 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
// }
// Unmarshal .
// func (r *Response) Unmarshal(b []byte) {}

View File

@ -10,29 +10,29 @@ import (
"time"
)
var parts = map[string]map[string][]string{
"door": {
"suffix": {"position", "status"},
"position1": {"front", "rear", "boot", "enginehood"},
"position2": {"right", "left"},
},
"window": {
"suffix": {"status"},
"position1": {"front", "rear", "sunroof"},
"position2": {"right", "left"},
},
"tire": {
"prefix": {"status"},
"position1": {"front", "rear"},
"position2": {"right", "left"},
},
"tyre": {
"prefix": {"pressure"},
"suffix": {"psi", "unit"},
"position1": {"front", "rear"},
"position2": {"right", "left"},
},
}
// var parts = map[string]map[string][]string{
// "door": {
// "suffix": {"position", "status"},
// "position1": {"front", "rear", "boot", "enginehood"},
// "position2": {"right", "left"},
// },
// "window": {
// "suffix": {"status"},
// "position1": {"front", "rear", "sunroof"},
// "position2": {"right", "left"},
// },
// "tire": {
// "prefix": {"status"},
// "position1": {"front", "rear"},
// "position2": {"right", "left"},
// },
// "tyre": {
// "prefix": {"pressure"},
// "suffix": {"psi", "unit"},
// "position1": {"front", "rear"},
// "position2": {"right", "left"},
// },
// }
// Vehicle .
type Vehicle struct {
@ -618,7 +618,6 @@ func (v *Vehicle) GetVehicleStatus() {
val.Field(i).Interface() == "" ||
val.Field(i).Interface() == 0 ||
val.Field(i).Interface() == float64(0) ||
(val.Field(i).Interface() == 101 && typeOfS.Field(i).Name == "RemainingFuelPercent") ||
val.Field(i).Interface() == nil {
continue
}
@ -976,9 +975,9 @@ func (v *Vehicle) getAPIGen() string {
// isPINRequired .
// Return if a vehicle with an active remote service subscription exists.
func (v *Vehicle) isPINRequired() bool {
return v.getRemoteOptionsStatus()
}
// func (v *Vehicle) isPINRequired() bool {
// return v.getRemoteOptionsStatus()
// }
// isEV .
// Get whether the specified VIN is an Electric Vehicle.
@ -992,29 +991,29 @@ func (v *Vehicle) getRemoteOptionsStatus() bool {
return contains(v.SubscriptionFeatures, FEATURE_REMOTE)
}
// getRemoteStartStatus .
// Get whether the specified VIN has remote engine start service available.
func (v *Vehicle) getRemoteStartStatus() bool {
return contains(v.Features, FEATURE_REMOTE_START)
}
// // getRemoteStartStatus .
// // Get whether the specified VIN has remote engine start service available.
// func (v *Vehicle) getRemoteStartStatus() bool {
// return contains(v.Features, FEATURE_REMOTE_START)
// }
// getSafetyStatus .
// Get whether the specified VIN is has an active Starlink Safety Plus service plan.
func (v *Vehicle) getSafetyStatus() bool {
return contains(v.SubscriptionFeatures, FEATURE_SAFETY)
}
// // getSafetyStatus .
// // Get whether the specified VIN is has an active Starlink Safety Plus service plan.
// func (v *Vehicle) getSafetyStatus() bool {
// return contains(v.SubscriptionFeatures, FEATURE_SAFETY)
// }
// getSubscriptionStatus .
// Get whether the specified VIN has an active service plan.
func (v *Vehicle) getSubscriptionStatus() bool {
return contains(v.SubscriptionFeatures, FEATURE_ACTIVE)
}
// // getSubscriptionStatus .
// // Get whether the specified VIN has an active service plan.
// func (v *Vehicle) getSubscriptionStatus() bool {
// return contains(v.SubscriptionFeatures, FEATURE_ACTIVE)
// }
// getVehicleName .
// Get the nickname of a specified VIN.
func (v *Vehicle) getVehicleName() string {
return v.CarName
}
// // getVehicleName .
// // Get the nickname of a specified VIN.
// func (v *Vehicle) getVehicleName() string {
// return v.CarName
// }
// func getClimateData() {}
// func saveClimateSettings() {}