Added Locks status and tire pressure (psi and kpa)
All checks were successful
Golan Testing / testing (1.24.x, ubuntu-latest) (push) Successful in 22s

This commit is contained in:
2025-06-05 16:43:46 -04:00
parent 57e0e7899d
commit 28f650dc7d
3 changed files with 45 additions and 158 deletions

View File

@ -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()
// (?P<type>Door|Window|TirePressure)(?P<pos1>Front|Rear|Boot|EngineHood|Sunroof)(?P<pos2>Left|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()
// (?P<type>Door|Window|TirePressure)(?P<pos1>Front|Rear|Boot|EngineHood|Sunroof)(?P<pos2>Left|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 {