diff --git a/vehicle/bluelink/types.go b/vehicle/bluelink/types.go index 02255e7db0..31b124312f 100644 --- a/vehicle/bluelink/types.go +++ b/vehicle/bluelink/types.go @@ -1,6 +1,7 @@ package bluelink import ( + "math" "strconv" "time" @@ -82,12 +83,15 @@ const ( timeOffset = " +0100" plugTypeAC = 1 + unitMiles = 3 + kmPerMile = 1.60934 ) type DrivingDistance struct { RangeByFuel struct { EvModeRange struct { Value float64 + Unit int } } } @@ -144,7 +148,11 @@ func (d VehicleStatus) FinishTime() (time.Time, error) { func (d VehicleStatus) Range() (int64, error) { if d.EvStatus != nil { if dist := d.EvStatus.DrvDistance; len(dist) == 1 { - return int64(dist[0].RangeByFuel.EvModeRange.Value), nil + value := dist[0].RangeByFuel.EvModeRange.Value + if dist[0].RangeByFuel.EvModeRange.Unit == unitMiles { + return int64(math.Round(value * kmPerMile)), nil + } + return int64(value), nil } } return 0, api.ErrNotAvailable diff --git a/vehicle/bluelink/types_test.go b/vehicle/bluelink/types_test.go new file mode 100644 index 0000000000..8697d088a2 --- /dev/null +++ b/vehicle/bluelink/types_test.go @@ -0,0 +1,98 @@ +package bluelink + +import ( + "testing" + + "github.com/evcc-io/evcc/api" + "github.com/stretchr/testify/require" +) + +func TestVehicleStatusRangeHonorsUnit(t *testing.T) { + status := VehicleStatus{ + EvStatus: &struct { + BatteryCharge bool + BatteryStatus float64 + BatteryPlugin int + RemainTime2 struct { + Atc struct { + Value int + Unit int + } + } + ChargePortDoorOpenStatus int + DrvDistance []DrivingDistance + ReservChargeInfos ReservChargeInfo + }{ + DrvDistance: []DrivingDistance{ + { + RangeByFuel: struct { + EvModeRange struct { + Value float64 + Unit int + } + }{ + EvModeRange: struct { + Value float64 + Unit int + }{ + Value: 168.4, // 168.4 miles ≈ 271 km + Unit: unitMiles, + }, + }, + }, + }, + }, + } + + got, err := status.Range() + require.NoError(t, err) + require.EqualValues(t, 271, got) +} + +func TestVehicleStatusRangeKilometersUnchanged(t *testing.T) { + status := VehicleStatus{ + EvStatus: &struct { + BatteryCharge bool + BatteryStatus float64 + BatteryPlugin int + RemainTime2 struct { + Atc struct { + Value int + Unit int + } + } + ChargePortDoorOpenStatus int + DrvDistance []DrivingDistance + ReservChargeInfos ReservChargeInfo + }{ + DrvDistance: []DrivingDistance{ + { + RangeByFuel: struct { + EvModeRange struct { + Value float64 + Unit int + } + }{ + EvModeRange: struct { + Value float64 + Unit int + }{ + Value: 168.9, + Unit: 1, + }, + }, + }, + }, + }, + } + + got, err := status.Range() + require.NoError(t, err) + require.EqualValues(t, 168, got) +} + +func TestVehicleStatusRangeNotAvailable(t *testing.T) { + got, err := VehicleStatus{}.Range() + require.ErrorIs(t, err, api.ErrNotAvailable) + require.Zero(t, got) +}