From 849a544ffab8d5fb76446e749b9ad0c6e0fc85d0 Mon Sep 17 00:00:00 2001 From: Alex Savin Date: Thu, 5 Jun 2025 10:53:52 -0400 Subject: [PATCH] Changed the way of naming climate profiles --- mysubaru.go | 4 +- vehicle.go | 191 ++++++++++++++++++++++++++++------------------------ 2 files changed, 105 insertions(+), 90 deletions(-) diff --git a/mysubaru.go b/mysubaru.go index 8a26eca..67a51b7 100644 --- a/mysubaru.go +++ b/mysubaru.go @@ -105,7 +105,7 @@ type VehicleData struct { LicensePlate string `json:"licensePlate"` // NJ LicensePlateState string `json:"licensePlateState"` // ABCDEF SubscriptionStatus string `json:"subscriptionStatus"` // ACTIVE - SubscriptionFeatures []string `json:"subscriptionFeatures"` // "REMOTE", "SAFETY", "Retail" + SubscriptionFeatures []string `json:"subscriptionFeatures"` // "[ REMOTE ], [ SAFETY ], [ Retail | Finance3 | RetailPHEV ]"" SubscriptionPlans []string `json:"subscriptionPlans"` // [] VehicleGeoPosition GeoPosition `json:"vehicleGeoPosition"` // GeoPosition struct AccessLevel int `json:"accessLevel"` // -1 @@ -128,7 +128,7 @@ type GeoPosition struct { Longitude float64 `json:"longitude"` // -74.401375 Speed float64 `json:"speed,omitempty"` // 62 Heading int `json:"heading,omitempty"` // 155 - Timestamp string `json:"timestamp,string"` // "2021-12-22T13:14:47" + Timestamp string `json:"timestamp"` // "2021-12-22T13:14:47" } // type GeoPositionTime time.Time diff --git a/vehicle.go b/vehicle.go index e7eeef8..48cf87f 100644 --- a/vehicle.go +++ b/vehicle.go @@ -458,52 +458,57 @@ func (v *Vehicle) GetClimatePresets() { reqURL := MOBILE_API_VERSION + apiURLs["API_G2_FETCH_RES_SUBARU_PRESETS"] resp := v.client.execute(reqURL, GET, map[string]string{}, "", false) - var r Response - err := json.Unmarshal(resp, &r) - if err != nil { - v.client.logger.Error("error while parsing json", "request", "GetClimatePresets", "error", err.Error()) - } + // var r Response + // err := json.Unmarshal(resp, &r) + // if err != nil { + // v.client.logger.Error("error while parsing json", "request", "GetClimatePresets", "error", err.Error()) + // } + if r, ok := v.client.parseResponse(resp); ok { - re1 := regexp.MustCompile(`\"`) - result := re1.ReplaceAllString(string(r.Data), "") - re2 := regexp.MustCompile(`\\`) - result = re2.ReplaceAllString(result, `"`) // \u0022 + re1 := regexp.MustCompile(`\"`) + result := re1.ReplaceAllString(string(r.Data), "") + re2 := regexp.MustCompile(`\\`) + result = re2.ReplaceAllString(result, `"`) // \u0022 - var cProfiles []ClimateProfile - err = json.Unmarshal([]byte(result), &cProfiles) - if err != nil { - v.client.logger.Error("error while parsing json", "request", "GetClimatePresets", "error", err.Error()) - } - - if len(cProfiles) > 0 { - for _, cp := range cProfiles { - if v.isEV() && cp.VehicleType == "phev" { - if _, ok := v.ClimateProfiles[cp.PresetType+strings.ReplaceAll(cp.Name, " ", "")]; ok { - v.ClimateProfiles[cp.PresetType+strings.ReplaceAll(cp.Name, " ", "")] = cp - } else { - if _, ok := v.ClimateProfiles[cp.PresetType+strings.ReplaceAll(cp.Name, " ", "")]; ok { - v.ClimateProfiles[cp.PresetType+strings.ReplaceAll(cp.Name, " ", "")] = cp - } else { - v.ClimateProfiles[cp.PresetType+strings.ReplaceAll(cp.Name, " ", "")] = cp - } - } - } - if !v.isEV() && cp.VehicleType == "gas" { - if _, ok := v.ClimateProfiles[cp.PresetType+strings.ReplaceAll(cp.Name, " ", "")]; ok { - v.ClimateProfiles[cp.PresetType+strings.ReplaceAll(cp.Name, " ", "")] = cp - } else { - if _, ok := v.ClimateProfiles[cp.PresetType+strings.ReplaceAll(cp.Name, " ", "")]; ok { - v.ClimateProfiles[cp.PresetType+strings.ReplaceAll(cp.Name, " ", "")] = cp - } else { - v.ClimateProfiles[cp.PresetType+strings.ReplaceAll(cp.Name, " ", "")] = cp - } - } - } + var cProfiles []ClimateProfile + err := json.Unmarshal([]byte(result), &cProfiles) + if err != nil { + v.client.logger.Error("error while parsing json", "request", "GetClimatePresets", "error", err.Error()) } - } else { - v.client.logger.Debug("didn't find any climate presets") + + if len(cProfiles) > 0 { + for _, cp := range cProfiles { + re := regexp.MustCompile(`([A-Z])`) + cpn := re.ReplaceAllString(cp.PresetType, "_$1") + "_" + strings.ReplaceAll(cp.Name, " ", "_") + + if v.isEV() && cp.VehicleType == "phev" { + if _, ok := v.ClimateProfiles[cpn]; ok { + v.ClimateProfiles[cpn] = cp + } else { + if _, ok := v.ClimateProfiles[cpn]; ok { + v.ClimateProfiles[cpn] = cp + } else { + v.ClimateProfiles[cpn] = cp + } + } + } + if !v.isEV() && cp.VehicleType == "gas" { + if _, ok := v.ClimateProfiles[cpn]; ok { + v.ClimateProfiles[cpn] = cp + } else { + if _, ok := v.ClimateProfiles[cpn]; ok { + v.ClimateProfiles[cpn] = cp + } else { + v.ClimateProfiles[cpn] = cp + } + } + } + } + } else { + v.client.logger.Debug("couldn't find any subaru climate presets") + } + v.Updated = time.Now() } - v.Updated = time.Now() } else { v.client.logger.Error("active STARLINK Security Plus subscription required") } @@ -518,29 +523,34 @@ func (v *Vehicle) GetClimateQuickPresets() { resp := v.client.execute(reqURL, GET, map[string]string{}, "", false) // v.client.logger.Debug("http request output", "request", "GetClimateQuickPresets", "body", resp) - var r Response - err := json.Unmarshal(resp, &r) - if err != nil { - v.client.logger.Error("error while parsing json", "request", "GetClimateQuickPresets", "error", err.Error()) - } + // var r Response + // err := json.Unmarshal(resp, &r) + // if err != nil { + // v.client.logger.Error("error while parsing json", "request", "GetClimateQuickPresets", "error", err.Error()) + // } + if r, ok := v.client.parseResponse(resp); ok { - re1 := regexp.MustCompile(`\"`) - result := re1.ReplaceAllString(string(r.Data), "") - re2 := regexp.MustCompile(`\\`) - result = re2.ReplaceAllString(result, `"`) // \u0022 + re1 := regexp.MustCompile(`\"`) + result := re1.ReplaceAllString(string(r.Data), "") + re2 := regexp.MustCompile(`\\`) + result = re2.ReplaceAllString(result, `"`) // \u0022 - var cp ClimateProfile - err = json.Unmarshal([]byte(result), &cp) - if err != nil { - v.client.logger.Error("error while parsing climate quick presets json", "request", "GetClimateQuickPresets", "error", err.Error()) - } + var cp ClimateProfile + err := json.Unmarshal([]byte(result), &cp) + if err != nil { + v.client.logger.Error("error while parsing climate quick presets json", "request", "GetClimateQuickPresets", "error", err.Error()) + } - if _, ok := v.ClimateProfiles["quick"+cp.PresetType+strings.ReplaceAll(cp.Name, " ", "")]; ok { - v.ClimateProfiles["quick"+cp.PresetType+strings.ReplaceAll(cp.Name, " ", "")] = cp - } else { - v.ClimateProfiles["quick"+cp.PresetType+strings.ReplaceAll(cp.Name, " ", "")] = cp + re := regexp.MustCompile(`([A-Z])`) + cpn := re.ReplaceAllString(cp.PresetType, "_$1") + "_quick_" + strings.ReplaceAll(cp.Name, " ", "_") + + if _, ok := v.ClimateProfiles[cpn]; ok { + v.ClimateProfiles[cpn] = cp + } else { + v.ClimateProfiles[cpn] = cp + } + v.Updated = time.Now() } - v.Updated = time.Now() } else { v.client.logger.Error("active STARLINK Security Plus subscription required") } @@ -553,39 +563,44 @@ func (v *Vehicle) GetClimateUserPresets() { reqURL := MOBILE_API_VERSION + apiURLs["API_G2_FETCH_RES_USER_PRESETS"] resp := v.client.execute(reqURL, GET, map[string]string{}, "", false) - var r Response - err := json.Unmarshal(resp, &r) - if err != nil { - v.client.logger.Error("error while parsing json", "request", "GetClimateUserPresets", "error", err.Error()) - } + // var r Response + // err := json.Unmarshal(resp, &r) + // if err != nil { + // v.client.logger.Error("error while parsing json", "request", "GetClimateUserPresets", "error", err.Error()) + // } + if r, ok := v.client.parseResponse(resp); ok { - re1 := regexp.MustCompile(`\"`) - result := re1.ReplaceAllString(string(r.Data), "") - re2 := regexp.MustCompile(`\\`) - result = re2.ReplaceAllString(result, `"`) // \u0022 + re1 := regexp.MustCompile(`\"`) + result := re1.ReplaceAllString(string(r.Data), "") + re2 := regexp.MustCompile(`\\`) + result = re2.ReplaceAllString(result, `"`) // \u0022 - var cProfiles []ClimateProfile - err = json.Unmarshal([]byte(result), &cProfiles) - if err != nil { - v.client.logger.Error("error while parsing json", "request", "GetClimateUserPresets", "error", err.Error()) - } + var cProfiles []ClimateProfile + err := json.Unmarshal([]byte(result), &cProfiles) + if err != nil { + v.client.logger.Error("error while parsing json", "request", "GetClimateUserPresets", "error", err.Error()) + } - if len(cProfiles) > 0 { - for _, cp := range cProfiles { - if _, ok := v.ClimateProfiles[cp.PresetType+strings.ReplaceAll(cp.Name, " ", "")]; ok { - v.ClimateProfiles[cp.PresetType+strings.ReplaceAll(cp.Name, " ", "")] = cp - } else { - if _, ok := v.ClimateProfiles[cp.PresetType+strings.ReplaceAll(cp.Name, " ", "")]; ok { - v.ClimateProfiles[cp.PresetType+strings.ReplaceAll(cp.Name, " ", "")] = cp + if len(cProfiles) > 0 { + for _, cp := range cProfiles { + re := regexp.MustCompile(`([A-Z])`) + cpn := re.ReplaceAllString(cp.PresetType, "_$1") + "_" + strings.ReplaceAll(cp.Name, " ", "_") + + if _, ok := v.ClimateProfiles[cpn]; ok { + v.ClimateProfiles[cpn] = cp } else { - v.ClimateProfiles[cp.PresetType+strings.ReplaceAll(cp.Name, " ", "")] = cp + if _, ok := v.ClimateProfiles[cpn]; ok { + v.ClimateProfiles[cpn] = cp + } else { + v.ClimateProfiles[cpn] = cp + } } } + } else { + v.client.logger.Debug("couldn't find any user climate presets") } - } else { - v.client.logger.Debug("didn't find any user climate presets") + v.Updated = time.Now() } - v.Updated = time.Now() } else { v.client.logger.Error("active STARLINK Security Plus subscription required") } @@ -626,7 +641,7 @@ func (v *Vehicle) GetVehicleStatus() { val := reflect.ValueOf(vs) typeOfS := val.Type() - // for i := 0; i < val.NumField(); i++ { + // (?PDoor|Window|TirePressure)(?PFront|Rear|Boot|EngineHood|Sunroof)(?PLeft|Right)?(:?Position|Status|LockStatus|Psi)? for i := range val.NumField() { // v.client.logger.Debug("vehicle status >> parsing a car part", "field", typeOfS.Field(i).Name, "value", val.Field(i).Interface(), "type", val.Field(i).Type()) if slices.Contains(badValues, val.Field(i).Interface()) { @@ -675,7 +690,7 @@ func (v *Vehicle) GetVehicleCondition() { val := reflect.ValueOf(vc) typeOfS := val.Type() - // for i := 0; i < val.NumField(); i++ { + // (?PDoor|Window|TirePressure)(?PFront|Rear|Boot|EngineHood|Sunroof)(?PLeft|Right)?(:?Position|Status|LockStatus|Psi)? for i := range val.NumField() { // v.client.logger.Debug("vehicle condition >> parsing a car part", "field", typeOfS.Field(i).Name, "value", val.Field(i).Interface(), "type", val.Field(i).Type()) if slices.Contains(badValues, val.Field(i).Interface()) {