diff --git a/client.go b/client.go index e91d2b8..37e030f 100644 --- a/client.go +++ b/client.go @@ -199,6 +199,13 @@ func (c *Client) GetVehicleByVIN(vin string) *Vehicle { vehicle.Windows = make(map[string]Window) vehicle.Tires = make(map[string]Tire) vehicle.ClimateProfiles = make(map[string]ClimateProfile) + vehicle.Troubles = make(map[string]Trouble) + + if vehicle.isEV() { + vehicle.EV = true + } else { + vehicle.EV = false + } vehicle.GetVehicleStatus() vehicle.GetVehicleCondition() diff --git a/consts.go b/consts.go index 6590e75..ab41ad0 100644 --- a/consts.go +++ b/consts.go @@ -134,28 +134,29 @@ 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 troubles = 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", diff --git a/vehicle.go b/vehicle.go index c99a440..71babc6 100644 --- a/vehicle.go +++ b/vehicle.go @@ -10,6 +10,19 @@ import ( "time" ) +// VEHICLE_STATE_TYPE >> IGNITION_OFF +// DISTANCE_TO_EMPTY_FUEL >> 241 +// AVG_FUEL_CONSUMPTION >> 127 +// POSITION_SPEED_KMPH >> 0 +// POSITION_HEADING_DEGREE >> 155 +// POSITION_TIMESTAMP >> 2022-01-18T20:40:10Z +// ODOMETER >> 40223712 (meters) +// TYRE_( STATUS | PRESSURE )_( REAR | FRONT )_( LEFT | RIGHT ) >> 2275 | UNKNOWN +// SEAT_BELT_STATUS_( ( FRONT | SECOND | THIRD )_( LEFT | MIDDLE | RIGHT ) ) >> NOT_EQUIPPED | UNKNOWN | NOT_BELTED | BELTED +// SEAT_OCCUPATION_STATUS_( ( FRONT | SECOND | THIRD )_( LEFT | MIDDLE | RIGHT ) ) >> +// DOOR_( ( FRONT | REAR )_( LEFT | RIGHT ) | ENGINE_HOOD | BOOT )_LOCK_STATUS >> UNKNOWN +// DOOR_( ( FRONT | REAR )_( LEFT | RIGHT ) | ENGINE_HOOD | BOOT )_POSITION >> CLOSED +// WINDOW_( BACK | SUNROOF | ( FRONT | REAR )_( LEFT | RIGHT ) )_STATUS >> UNKNOWN | CLOSE // var parts = map[string]map[string][]string{ // "door": { // "suffix": {"position", "status"}, @@ -71,9 +84,10 @@ type Vehicle struct { LP100Km float64 // STATUS REQUEST > "avgFuelConsumptionLitersPer100Kilometers": 12.7 } ClimateProfiles map[string]ClimateProfile - Doors map[string]Door // CONDITION REQUEST > - Windows map[string]Window // CONDITION REQUEST > - Tires map[string]Tire // CONDITION AND STATUS REQUEST > + Doors map[string]Door // CONDITION REQUEST > + Windows map[string]Window // CONDITION REQUEST > + Tires map[string]Tire // CONDITION AND STATUS REQUEST > + Troubles map[string]Trouble // GeoLocation GeoLocation Updated time.Time client *Client @@ -140,6 +154,10 @@ type Tire struct { Updated time.Time } +// Warning . +type Trouble struct { +} + func (v *Vehicle) String() string { var vString string @@ -186,6 +204,7 @@ func (v *Vehicle) String() string { vString += fmt.Sprintf("%s >> %+v\n", k, v) } + vString += "=== WARNINGS =====================\n" vString += "=== FEATURES =====================\n" for i, f := range v.Features { if !strings.HasSuffix(f, "_MIL") { @@ -458,10 +477,10 @@ func (v *Vehicle) GetClimatePresets() { if len(cProfiles) > 0 { for _, cp := range cProfiles { if v.isEV() && cp.VehicleType == "phev" { - if _, ok := v.ClimateProfiles[cp.PresetType+strings.TrimSpace(cp.Name)]; ok { + if _, ok := v.ClimateProfiles[cp.PresetType+strings.ReplaceAll(cp.Name, " ", "")]; ok { v.ClimateProfiles[cp.PresetType+cp.Name] = cp } else { - if _, ok := v.ClimateProfiles[cp.PresetType+strings.TrimSpace(cp.Name)]; ok { + if _, ok := v.ClimateProfiles[cp.PresetType+strings.ReplaceAll(cp.Name, " ", "")]; ok { v.ClimateProfiles[cp.PresetType+cp.Name] = cp } else { v.ClimateProfiles[cp.PresetType+cp.Name] = cp @@ -469,10 +488,10 @@ func (v *Vehicle) GetClimatePresets() { } } if !v.isEV() && cp.VehicleType == "gas" { - if _, ok := v.ClimateProfiles[cp.PresetType+strings.TrimSpace(cp.Name)]; ok { + if _, ok := v.ClimateProfiles[cp.PresetType+strings.ReplaceAll(cp.Name, " ", "")]; ok { v.ClimateProfiles[cp.PresetType+cp.Name] = cp } else { - if _, ok := v.ClimateProfiles[cp.PresetType+strings.TrimSpace(cp.Name)]; ok { + if _, ok := v.ClimateProfiles[cp.PresetType+strings.ReplaceAll(cp.Name, " ", "")]; ok { v.ClimateProfiles[cp.PresetType+cp.Name] = cp } else { v.ClimateProfiles[cp.PresetType+cp.Name] = cp @@ -515,10 +534,10 @@ func (v *Vehicle) GetClimateQuickPresets() { v.client.logger.Error("error while parsing climate quick presets json", "request", "GetClimateQuickPresets", "error", err.Error()) } - if _, ok := v.ClimateProfiles["quick"+cp.PresetType+strings.TrimSpace(cp.Name)]; ok { - v.ClimateProfiles["quick"+cp.PresetType+strings.TrimSpace(cp.Name)] = cp + 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.TrimSpace(cp.Name)] = cp + v.ClimateProfiles["quick"+cp.PresetType+strings.ReplaceAll(cp.Name, " ", "")] = cp } v.Updated = time.Now() } else { @@ -552,13 +571,13 @@ func (v *Vehicle) GetClimateUserPresets() { if len(cProfiles) > 0 { for _, cp := range cProfiles { - if _, ok := v.ClimateProfiles[cp.PresetType+strings.TrimSpace(cp.Name)]; ok { - v.ClimateProfiles[cp.PresetType+strings.TrimSpace(cp.Name)] = cp + 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.TrimSpace(cp.Name)]; ok { - v.ClimateProfiles[cp.PresetType+strings.TrimSpace(cp.Name)] = cp + 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.TrimSpace(cp.Name)] = cp + v.ClimateProfiles[cp.PresetType+strings.ReplaceAll(cp.Name, " ", "")] = cp } } } @@ -603,8 +622,6 @@ func (v *Vehicle) GetVehicleStatus() { v.GeoLocation.Longitude = float64(vs.Longitude) v.GeoLocation.Heading = vs.Heading - // re := regexp.MustCompile(`[A-Z][^A-Z]*`) - val := reflect.ValueOf(vs) typeOfS := val.Type() @@ -620,124 +637,22 @@ func (v *Vehicle) GetVehicleStatus() { val.Field(i).Interface() == float64(0) || val.Field(i).Interface() == nil { continue + } else { + v.client.logger.Debug("parsing a car part", "field", typeOfS.Field(i).Name, "value", val.Field(i).Interface(), "type", val.Field(i).Type()) + if strings.HasPrefix(typeOfS.Field(i).Name, "door") && strings.HasSuffix(typeOfS.Field(i).Name, "Position") { + v.parseDoor("door", "Position", typeOfS.Field(i).Name, val.Field(i).Interface()) + } + if strings.HasPrefix(typeOfS.Field(i).Name, "door") && strings.HasSuffix(typeOfS.Field(i).Name, "LockStatus") { + v.parseDoor("door", "LockStatus", typeOfS.Field(i).Name, val.Field(i).Interface()) + } + if strings.HasPrefix(typeOfS.Field(i).Name, "window") && strings.HasSuffix(typeOfS.Field(i).Name, "Status") { + v.parseWindow("window", "Status", typeOfS.Field(i).Name, val.Field(i).Interface()) + } + if strings.HasPrefix(typeOfS.Field(i).Name, "tirePressure") && strings.HasSuffix(typeOfS.Field(i).Name, "Psi") { + v.parseTire("tirePressure", "Psi", typeOfS.Field(i).Name, val.Field(i).Interface()) + } } - fmt.Printf("Field: %s, Value: %v, Type: %v\n", typeOfS.Field(i).Name, val.Field(i).Interface(), val.Field(i).Type()) } - // v := reflect.ValueOf(vSta) - // values := make([]interface{}, v.NumField()) - // for i := 0; i < v.NumField(); i++ { - // values[i] = v.Field(i).Interface() - // } - - // for key, child := range respParsed.S("data").ChildrenMap() { - // fmt.Printf("key: %v, value: %v\n", key, child.Data()) - // if child.Data() == "NOT_EQUIPPED" || child.Data() == "UNKNOWN" || child.Data() == "16383" || child.Data() == "65535" || child.Data() == "None" || child.Data() == "-64.0" || child.Data() == nil { - // // fmt.Println("Skipping") - // continue - // } - // if strings.HasPrefix(key, "door") && strings.HasSuffix(key, "Position") { - // pos := strings.TrimPrefix(key, "door") - // pos = strings.TrimSuffix(pos, "Position") - // submatchall := re.FindAllString(pos, -1) - // v.client.logger.Debug("VEHICLE COND", "key", key, "data", child.Data(), "number", len(submatchall)) - - // if door, ok := v.Doors[pos]; ok { - // door.Status = child.Data().(string) - // door.Updated = time.Now() - // } else { - // door.Status = child.Data().(string) - // door.Updated = time.Now() - // v.Doors[pos] = Door{ - // Position: submatchall[0], - // Status: child.Data().(string), - // Updated: time.Now(), - // } - // if len(submatchall) >= 2 { - // if d, ok := v.Doors[pos]; ok { - // d.SubPosition = submatchall[1] - // v.Doors[pos] = d - // } - // } - // } - // } - // if strings.HasPrefix(key, "door") && strings.HasSuffix(key, "LockStatus") { - // pos := strings.TrimPrefix(key, "door") - // pos = strings.TrimSuffix(pos, "LockStatus") - // submatchall := re.FindAllString(pos, -1) - // v.client.logger.Debug("VEHICLE COND", "key", key, "data", child.Data(), "number", len(submatchall)) - - // if door, ok := v.Doors[pos]; ok { - // door.Lock = child.Data().(string) - // door.Updated = time.Now() - // } else { - // door.Lock = child.Data().(string) - // door.Updated = time.Now() - // v.Doors[pos] = Door{ - // Position: submatchall[0], - // Lock: child.Data().(string), - // Updated: time.Now(), - // } - // if len(submatchall) >= 2 { - // if d, ok := v.Doors[pos]; ok { - // d.SubPosition = submatchall[1] - // v.Doors[pos] = d - // } - // } - // } - // } - // if strings.HasPrefix(key, "window") && strings.HasSuffix(key, "Status") { - // pos := strings.TrimPrefix(key, "window") - // pos = strings.TrimSuffix(pos, "Status") - // submatchall := re.FindAllString(pos, -1) - // v.client.logger.Debug("VEHICLE COND", "key", key, "data", child.Data(), "number", len(submatchall)) - - // if window, ok := v.Windows[pos]; ok { - // window.Status = child.Data().(string) - // window.Updated = time.Now() - // } else { - // window.Status = child.Data().(string) - // window.Updated = time.Now() - // v.Windows[pos] = Window{ - // Position: submatchall[0], - // Status: child.Data().(string), - // Updated: time.Now(), - // } - // if len(submatchall) >= 2 { - // if w, ok := v.Windows[pos]; ok { - // w.SubPosition = submatchall[1] - // v.Windows[pos] = w - // } - // } - // } - // } - // if strings.HasPrefix(key, "tirePressure") && strings.HasSuffix(key, "Psi") { - // pos := strings.TrimPrefix(key, "tirePressure") - // pos = strings.TrimSuffix(pos, "Psi") - // submatchall := re.FindAllString(pos, -1) - // v.client.logger.Debug("VEHICLE COND", "key", key, "data", child.Data(), "number", len(submatchall)) - - // if tire, ok := v.Tires[pos]; ok { - // tire.PressurePsi = child.Data().(string) - // tire.Updated = time.Now() - // } else { - // tire.PressurePsi = child.Data().(string) - // tire.Updated = time.Now() - // v.Tires[pos] = Tire{ - // Position: submatchall[0], - // PressurePsi: child.Data().(string), - // Updated: time.Now(), - // } - // if len(submatchall) >= 2 { - // if t, ok := v.Tires[pos]; ok { - // t.SubPosition = submatchall[1] - // v.Tires[pos] = t - // } - // } - // } - // } - // } - - // fmt.Printf("PARTS: %+v\n", parts) v.Updated = time.Now() } } @@ -779,134 +694,24 @@ func (v *Vehicle) GetVehicleCondition() { val.Field(i).Interface() == float64(0) || val.Field(i).Interface() == nil { continue + } else { + v.client.logger.Debug("parsing a car part", "field", typeOfS.Field(i).Name, "value", val.Field(i).Interface(), "type", val.Field(i).Type()) + if strings.HasPrefix(typeOfS.Field(i).Name, "door") && strings.HasSuffix(typeOfS.Field(i).Name, "Position") { + v.parseDoor("door", "Position", typeOfS.Field(i).Name, val.Field(i).Interface()) + } + if strings.HasPrefix(typeOfS.Field(i).Name, "door") && strings.HasSuffix(typeOfS.Field(i).Name, "LockStatus") { + v.parseDoor("door", "LockStatus", typeOfS.Field(i).Name, val.Field(i).Interface()) + } + if strings.HasPrefix(typeOfS.Field(i).Name, "window") && strings.HasSuffix(typeOfS.Field(i).Name, "Status") { + v.parseWindow("window", "Status", typeOfS.Field(i).Name, val.Field(i).Interface()) + } + // if strings.HasPrefix(typeOfS.Field(i).Name, "tirePressure") { + // v.parseTire("tirePressure", "", typeOfS.Field(i).Name, val.Field(i).Interface()) + // } } - fmt.Printf("Field: %s, Value: %v, Type: %v\n", typeOfS.Field(i).Name, val.Field(i).Interface(), val.Field(i).Type()) } - - // re := regexp.MustCompile(`[A-Z][^A-Z]*`) - - // for key, child := range respParsed.S("data").S("result").ChildrenMap() { - // fmt.Printf("key: %v, value: %v\n", key, child.Data()) - // if child.Data() == "NOT_EQUIPPED" || child.Data() == "UNKNOWN" || child.Data() == "16383" || child.Data() == "65535" || child.Data() == "None" || child.Data() == "-64.0" || child.Data() == nil { - // continue - // } - // if strings.HasPrefix(key, "door") && strings.HasSuffix(key, "Position") { - // pos := strings.TrimPrefix(key, "door") - // pos = strings.TrimSuffix(pos, "Position") - // submatchall := re.FindAllString(pos, -1) - // v.client.logger.Debug("VEHICLE COND", "key", key, "data", child.Data(), "number", len(submatchall)) - - // if door, ok := v.Doors[pos]; ok { - // door.Status = child.Data().(string) - // door.Updated = time.Now() - // } else { - // door.Status = child.Data().(string) - // door.Updated = time.Now() - // v.Doors[pos] = Door{ - // Position: submatchall[0], - // Status: child.Data().(string), - // Updated: time.Now(), - // } - // if len(submatchall) >= 2 { - // if d, ok := v.Doors[pos]; ok { - // d.SubPosition = submatchall[1] - // v.Doors[pos] = d - // } - // } - // } - // } - // if strings.HasPrefix(key, "door") && strings.HasSuffix(key, "LockStatus") { - // pos := strings.TrimPrefix(key, "door") - // pos = strings.TrimSuffix(pos, "LockStatus") - // submatchall := re.FindAllString(pos, -1) - // v.client.logger.Debug("VEHICLE COND", "key", key, "data", child.Data(), "number", len(submatchall)) - - // if door, ok := v.Doors[pos]; ok { - // door.Lock = child.Data().(string) - // door.Updated = time.Now() - // } else { - // door.Lock = child.Data().(string) - // door.Updated = time.Now() - // v.Doors[pos] = Door{ - // Position: submatchall[0], - // Lock: child.Data().(string), - // Updated: time.Now(), - // } - // if len(submatchall) >= 2 { - // if d, ok := v.Doors[pos]; ok { - // d.SubPosition = submatchall[1] - // v.Doors[pos] = d - // } - // } - // } - // } - // if strings.HasPrefix(key, "window") && strings.HasSuffix(key, "Status") { - // pos := strings.TrimPrefix(key, "window") - // pos = strings.TrimSuffix(pos, "Status") - // submatchall := re.FindAllString(pos, -1) - // v.client.logger.Debug("VEHICLE COND", "key", key, "data", child.Data(), "number", len(submatchall)) - - // if window, ok := v.Windows[pos]; ok { - // window.Status = child.Data().(string) - // window.Updated = time.Now() - // } else { - // window.Status = child.Data().(string) - // window.Updated = time.Now() - // v.Windows[pos] = Window{ - // Position: submatchall[0], - // Status: child.Data().(string), - // Updated: time.Now(), - // } - // if len(submatchall) >= 2 { - // if w, ok := v.Windows[pos]; ok { - // w.SubPosition = submatchall[1] - // v.Windows[pos] = w - // } - // } - // } - // } - // if strings.HasPrefix(key, "tirePressure") && strings.HasSuffix(key, "Psi") { - // pos := strings.TrimPrefix(key, "tirePressure") - // pos = strings.TrimSuffix(pos, "Psi") - // submatchall := re.FindAllString(pos, -1) - // v.client.logger.Debug("VEHICLE COND", "key", key, "data", child.Data(), "number", len(submatchall)) - - // if tire, ok := v.Tires[pos]; ok { - // tire.PressurePsi = child.Data().(string) - // tire.Updated = time.Now() - // } else { - // tire.PressurePsi = child.Data().(string) - // tire.Updated = time.Now() - // v.Tires[pos] = Tire{ - // Position: submatchall[0], - // PressurePsi: child.Data().(string), - // Updated: time.Now(), - // } - // if len(submatchall) >= 2 { - // if t, ok := v.Tires[pos]; ok { - // t.SubPosition = submatchall[1] - // v.Tires[pos] = t - // } - // } - // } - // } - // v.Updated = time.Now() - // } + v.Updated = time.Now() } - - // VEHICLE_STATE_TYPE >> IGNITION_OFF - // DISTANCE_TO_EMPTY_FUEL >> 241 - // AVG_FUEL_CONSUMPTION >> 127 - // POSITION_SPEED_KMPH >> 0 - // POSITION_HEADING_DEGREE >> 155 - // POSITION_TIMESTAMP >> 2022-01-18T20:40:10Z - // ODOMETER >> 40223712 (meters) - // TYRE_( STATUS | PRESSURE )_( REAR | FRONT )_( LEFT | RIGHT ) >> 2275 | UNKNOWN - // SEAT_BELT_STATUS_( ( FRONT | SECOND | THIRD )_( LEFT | MIDDLE | RIGHT ) ) >> NOT_EQUIPPED | UNKNOWN | NOT_BELTED | BELTED - // SEAT_OCCUPATION_STATUS_( ( FRONT | SECOND | THIRD )_( LEFT | MIDDLE | RIGHT ) ) >> - // DOOR_( ( FRONT | REAR )_( LEFT | RIGHT ) | ENGINE_HOOD | BOOT )_LOCK_STATUS >> UNKNOWN - // DOOR_( ( FRONT | REAR )_( LEFT | RIGHT ) | ENGINE_HOOD | BOOT )_POSITION >> CLOSED - // WINDOW_( BACK | SUNROOF | ( FRONT | REAR )_( LEFT | RIGHT ) )_STATUS >> UNKNOWN | CLOSE } // GetVehicleHealth . @@ -930,6 +735,7 @@ func (v *Vehicle) GetVehicleHealth() { for i, vhi := range vh.VehicleHealthItems { v.client.logger.Debug("vehicle health item", "id", i, "item", vhi) if vhi.IsTrouble { + // if contains(troubles, vhi.FeatureCode) {} } } } else { @@ -996,6 +802,90 @@ func (v *Vehicle) getRemoteOptionsStatus() bool { return contains(v.SubscriptionFeatures, FEATURE_REMOTE) } +// parseDoor . +func (v *Vehicle) parseDoor(prefix, suffix, name string, value any) { + re := regexp.MustCompile(`[A-Z][^A-Z]*`) + pos := strings.TrimPrefix(name, prefix) + pos = strings.TrimSuffix(pos, suffix) + submatchall := re.FindAllString(pos, -1) + v.client.logger.Debug("VEHICLE COND", "key", name, "value", value, "number", len(submatchall)) + + if door, ok := v.Doors[pos]; ok { + door.Status = value.(string) + door.Updated = time.Now() + } else { + door.Status = value.(string) + door.Updated = time.Now() + v.Doors[pos] = Door{ + Position: submatchall[0], + Status: value.(string), + Updated: time.Now(), + } + if len(submatchall) >= 2 { + if d, ok := v.Doors[pos]; ok { + d.SubPosition = submatchall[1] + v.Doors[pos] = d + } + } + } +} + +// parseWindow . +func (v *Vehicle) parseWindow(prefix, suffix, name string, value any) { + re := regexp.MustCompile(`[A-Z][^A-Z]*`) + pos := strings.TrimPrefix(name, prefix) + pos = strings.TrimSuffix(pos, suffix) + submatchall := re.FindAllString(pos, -1) + v.client.logger.Debug("VEHICLE COND", "key", name, "data", value, "number", len(submatchall)) + + if window, ok := v.Windows[pos]; ok { + window.Status = value.(string) + window.Updated = time.Now() + } else { + window.Status = value.(string) + window.Updated = time.Now() + v.Windows[pos] = Window{ + Position: submatchall[0], + Status: value.(string), + Updated: time.Now(), + } + if len(submatchall) >= 2 { + if w, ok := v.Windows[pos]; ok { + w.SubPosition = submatchall[1] + v.Windows[pos] = w + } + } + } +} + +// parseTire . +func (v *Vehicle) parseTire(prefix, suffix, name string, value any) { + re := regexp.MustCompile(`[A-Z][^A-Z]*`) + pos := strings.TrimPrefix(name, prefix) + pos = strings.TrimSuffix(pos, suffix) + submatchall := re.FindAllString(pos, -1) + v.client.logger.Debug("VEHICLE COND", "key", name, "data", value, "number", len(submatchall)) + + if tire, ok := v.Tires[pos]; ok { + tire.PressurePsi = value.(string) + tire.Updated = time.Now() + } else { + tire.PressurePsi = value.(string) + tire.Updated = time.Now() + v.Tires[pos] = Tire{ + Position: submatchall[0], + PressurePsi: value.(string), + Updated: time.Now(), + } + if len(submatchall) >= 2 { + if t, ok := v.Tires[pos]; ok { + t.SubPosition = submatchall[1] + v.Tires[pos] = t + } + } + } +} + // // getRemoteStartStatus . // // Get whether the specified VIN has remote engine start service available. // func (v *Vehicle) getRemoteStartStatus() bool { @@ -1022,7 +912,6 @@ func (v *Vehicle) getRemoteOptionsStatus() bool { // func getClimateData() {} // func saveClimateSettings() {} -// func fetch() {} // "vhsId": 914631252, @@ -1038,14 +927,3 @@ func (v *Vehicle) getRemoteOptionsStatus() bool { // "tirePressureFrontRightPsi": "34", // "tirePressureRearLeftPsi": "35", // "tirePressureRearRightPsi": "34", - -// TireStatusFrontLeft string `json:"tyreStatusFrontLeft"` // "UNKNOWN" -// TireStatusFrontRight string `json:"tyreStatusFrontRight"` // "UNKNOWN" -// TireStatusRearLeft string `json:"tyreStatusRearLeft"` // "UNKNOWN" -// TireStatusRearRight string `json:"tyreStatusRearRight"` // "UNKNOWN" - -// WindowFrontLeftStatus string `json:"windowFrontLeftStatus"` // "CLOSE" -// WindowFrontRightStatus string `json:"windowFrontRightStatus"` // "CLOSE" -// WindowRearLeftStatus string `json:"windowRearLeftStatus"` // "CLOSE" -// WindowRearRightStatus string `json:"windowRearRightStatus"` // "CLOSE" -// WindowSunroofStatus string `json:"windowSunroofStatus"` // "UNKNOWN"