diff --git a/mysubaru.go b/mysubaru.go index 67a51b7..8e178a8 100644 --- a/mysubaru.go +++ b/mysubaru.go @@ -192,7 +192,7 @@ type VehicleStatus struct { 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 | 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 diff --git a/utils.go b/utils.go index 62377f8..2a7ffa4 100644 --- a/utils.go +++ b/utils.go @@ -58,6 +58,7 @@ func vinCheck(vin string) (bool, string) { return valid, retVin } +// transcodeDigits . func transcodeDigits(vin string) int { var digitSum = 0 var code int diff --git a/vehicle.go b/vehicle.go index 5a80766..831865d 100644 --- a/vehicle.go +++ b/vehicle.go @@ -11,19 +11,6 @@ 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"}, @@ -155,12 +142,12 @@ type Tire struct { // Status string } -// Warning . +// Trouble . type Trouble struct { + Description string } func (v *Vehicle) String() string { - var vString string vString += "=== INFORMATION =====================\n" vString += "Nickname: " + v.CarNickname + "\n" @@ -205,7 +192,11 @@ func (v *Vehicle) String() string { vString += fmt.Sprintf("%s >> %+v\n", k, v) } - vString += "=== WARNINGS =====================\n" + vString += "=== TROUBLES =====================\n" + for k, v := range v.Troubles { + vString += fmt.Sprintf("%s >> %+v\n", k, v) + } + vString += "=== FEATURES =====================\n" for i, f := range v.Features { if !strings.HasSuffix(f, "_MIL") { @@ -613,7 +604,7 @@ func (v *Vehicle) GetVehicleStatus() { v.DistanceToEmpty.Kilometers = vs.DistanceToEmptyFuelKilometers v.DistanceToEmpty.Miles10s = vs.DistanceToEmptyFuelMiles10s v.DistanceToEmpty.Kilometers10s = vs.DistanceToEmptyFuelKilometers10s - if vs.RemainingFuelPercent > 0 && vs.RemainingFuelPercent <= 100 { + if vs.RemainingFuelPercent > 0 && vs.RemainingFuelPercent <= 101 { v.DistanceToEmpty.Percentage = vs.RemainingFuelPercent } v.FuelConsumptionAvg.MPG = float64(vs.AvgFuelConsumptionMpg) @@ -626,22 +617,15 @@ func (v *Vehicle) GetVehicleStatus() { val := reflect.ValueOf(vs) typeOfS := val.Type() - // (?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()) { continue } else { - if strings.HasPrefix(typeOfS.Field(i).Name, "Door") && strings.HasSuffix(typeOfS.Field(i).Name, "Position") { - v.parseParts(typeOfS.Field(i).Name, val.Field(i).Interface()) - } - // if strings.HasPrefix(typeOfS.Field(i).Name, "Door") && strings.HasSuffix(typeOfS.Field(i).Name, "LockStatus") { - // v.parseLock("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.parseParts(typeOfS.Field(i).Name, val.Field(i).Interface()) - } - if strings.HasPrefix(typeOfS.Field(i).Name, "TirePressure") && strings.HasSuffix(typeOfS.Field(i).Name, "Psi") { + if strings.HasPrefix(typeOfS.Field(i).Name, "Door") && strings.HasSuffix(typeOfS.Field(i).Name, "Position") || + strings.HasPrefix(typeOfS.Field(i).Name, "Door") && strings.HasSuffix(typeOfS.Field(i).Name, "LockStatus") || + strings.HasPrefix(typeOfS.Field(i).Name, "Window") && strings.HasSuffix(typeOfS.Field(i).Name, "Status") || + strings.HasPrefix(typeOfS.Field(i).Name, "TirePressure") && strings.HasSuffix(typeOfS.Field(i).Name, "Psi") { v.parseParts(typeOfS.Field(i).Name, val.Field(i).Interface()) } } @@ -675,23 +659,18 @@ func (v *Vehicle) GetVehicleCondition() { val := reflect.ValueOf(vc) typeOfS := val.Type() - // (?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()) { continue } else { - if strings.HasPrefix(typeOfS.Field(i).Name, "Door") && strings.HasSuffix(typeOfS.Field(i).Name, "Position") { + if strings.HasPrefix(typeOfS.Field(i).Name, "Door") && strings.HasSuffix(typeOfS.Field(i).Name, "Position") || + strings.HasPrefix(typeOfS.Field(i).Name, "Door") && strings.HasSuffix(typeOfS.Field(i).Name, "LockStatus") || + strings.HasPrefix(typeOfS.Field(i).Name, "Window") && strings.HasSuffix(typeOfS.Field(i).Name, "Status") { v.parseParts(typeOfS.Field(i).Name, val.Field(i).Interface()) } - if strings.HasPrefix(typeOfS.Field(i).Name, "Window") && strings.HasSuffix(typeOfS.Field(i).Name, "Status") { - v.parseParts(typeOfS.Field(i).Name, val.Field(i).Interface()) - } - // if strings.HasPrefix(typeOfS.Field(i).Name, "TirePressure") && !strings.HasSuffix(typeOfS.Field(i).Name, "Unit") { - // v.parseTire("TirePressure", "", typeOfS.Field(i).Name, val.Field(i).Interface()) - // } - // if strings.HasPrefix(typeOfS.Field(i).Name, "Door") && strings.HasSuffix(typeOfS.Field(i).Name, "LockStatus") { - // v.parseLock("Door", "LockStatus", typeOfS.Field(i).Name, val.Field(i).Interface()) + // if strings.HasPrefix(typeOfS.Field(i).Name, "TirePressure") { + // v.parseParts(typeOfS.Field(i).Name, val.Field(i).Interface()) // } } } @@ -805,15 +784,26 @@ func (v *Vehicle) parseParts(name string, value any) { switch grps[1] { case "Door", "door": if d, ok := v.Doors[pn]; ok { - d.Status = value.(string) + if grps[4] == "Position" { + d.Status = value.(string) + } + if grps[4] == "LockStatus" { + d.Lock = value.(string) + } d.Updated = time.Now() v.Doors[pn] = d } else { - v.Doors[pn] = Door{ + d = Door{ Position: grps[2], - Status: value.(string), Updated: time.Now(), } + if grps[4] == "Position" { + d.Status = value.(string) + } + if grps[4] == "LockStatus" { + d.Lock = value.(string) + } + v.Doors[pn] = d if len(grps) >= 2 { if d, ok := v.Doors[pn]; ok { d.SubPosition = grps[3] @@ -841,133 +831,29 @@ func (v *Vehicle) parseParts(name string, value any) { } case "Tire", "tire": if t, ok := v.Tires[pn]; ok { - t.PressurePsi = value.(int) + if grps[4] == "Psi" { + t.PressurePsi = value.(int) + } else { + t.Pressure = int(value.(float64)) + } t.Updated = time.Now() v.Tires[pn] = t } else { - v.Tires[pn] = Tire{ + t = Tire{ Position: grps[2], - PressurePsi: value.(int), + SubPosition: grps[3], Updated: time.Now(), } - if len(grps) >= 2 { - if t, ok := v.Tires[pn]; ok { - t.SubPosition = grps[3] - v.Tires[pn] = t - } + if grps[4] == "Psi" { + t.PressurePsi = value.(int) + } else { + t.Pressure = int(value.(float64)) } + v.Tires[pn] = t } } } -// parseLock . -// func (v *Vehicle) parseLock(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("door lock status", "key", name, "value", value, "number", len(submatchall)) - -// if d, ok := v.Doors[pos]; ok { -// d.Lock = value.(string) -// d.Updated = time.Now() -// v.Doors[pos] = d -// } else { -// v.Doors[pos] = Door{ -// Position: submatchall[0], -// Lock: 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 w, ok := v.Windows[pos]; ok { -// w.Status = value.(string) -// w.Updated = time.Now() -// v.Windows[pos] = w -// } else { -// 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 -// } -// } -// } -// } - -// parseTirePsi . -// func (v *Vehicle) parseTirePsi(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 t, ok := v.Tires[pos]; ok { -// t.PressurePsi = value.(int) -// t.Updated = time.Now() -// v.Tires[pos] = t -// } else { -// v.Tires[pos] = Tire{ -// Position: submatchall[0], -// PressurePsi: value.(int), -// Updated: time.Now(), -// } -// if len(submatchall) >= 2 { -// if t, ok := v.Tires[pos]; ok { -// t.SubPosition = submatchall[1] -// v.Tires[pos] = t -// } -// } -// } -// } - -// 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 t, ok := v.Tires[pos]; ok { -// t.Pressure = int(value.(float64)) -// t.Updated = time.Now() -// v.Tires[pos] = t -// } else { -// v.Tires[pos] = Tire{ -// Position: submatchall[0], -// Pressure: int(value.(float64)), -// 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 {