App 2.10.0: range since start, usage in its own cards
"Range since start" replaces the range at current power: remaining energy over the consumption since the car was switched on, standing with the climate on included. A trip starts again after 10 minutes without samples (the car was off) or when charging. The kWh/100 km for both estimates moved out of the range tiles into two cards of their own, directly below them; the overview still fits the full-screen 1920x720 display without scrolling. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01QLJfZQZeAKAwSqViTmLzki
This commit is contained in:
@@ -90,7 +90,8 @@ public class MainActivity extends AppCompatActivity {
|
||||
private TextView vehSoc, vehRange, vehPower, vehSpeed, vehOdometer,
|
||||
vehCharging, vehHvac,
|
||||
vehTireFl, vehTireFr, vehTireRl, vehTireRr,
|
||||
vehRangePower, vehRangePowerNote, vehRangeAverage, vehRangeAverageNote;
|
||||
vehRangeTrip, vehRangeTripNote, vehRangeAverage, vehRangeAverageNote,
|
||||
vehUsageTrip, vehUsageTripNote, vehUsageAverage, vehUsageAverageNote;
|
||||
|
||||
/** Usable pack capacity for the range estimates; the car does not publish it. */
|
||||
static final String USABLE_KWH_KEY = "usable_kwh";
|
||||
@@ -995,10 +996,14 @@ public class MainActivity extends AppCompatActivity {
|
||||
vehTireFr = vehiclePane.findViewById(R.id.vehicle_tire_fr);
|
||||
vehTireRl = vehiclePane.findViewById(R.id.vehicle_tire_rl);
|
||||
vehTireRr = vehiclePane.findViewById(R.id.vehicle_tire_rr);
|
||||
vehRangePower = vehiclePane.findViewById(R.id.vehicle_range_power);
|
||||
vehRangePowerNote = vehiclePane.findViewById(R.id.vehicle_range_power_note);
|
||||
vehRangeTrip = vehiclePane.findViewById(R.id.vehicle_range_trip);
|
||||
vehRangeTripNote = vehiclePane.findViewById(R.id.vehicle_range_trip_note);
|
||||
vehRangeAverage = vehiclePane.findViewById(R.id.vehicle_range_average);
|
||||
vehRangeAverageNote = vehiclePane.findViewById(R.id.vehicle_range_average_note);
|
||||
vehUsageTrip = vehiclePane.findViewById(R.id.vehicle_usage_trip);
|
||||
vehUsageTripNote = vehiclePane.findViewById(R.id.vehicle_usage_trip_note);
|
||||
vehUsageAverage = vehiclePane.findViewById(R.id.vehicle_usage_average);
|
||||
vehUsageAverageNote = vehiclePane.findViewById(R.id.vehicle_usage_average_note);
|
||||
}
|
||||
|
||||
private double usableKwh() {
|
||||
@@ -1006,31 +1011,39 @@ public class MainActivity extends AppCompatActivity {
|
||||
}
|
||||
|
||||
/**
|
||||
* The two range estimates. Both need the car to be moving on battery power; the average
|
||||
* also needs a minute or more of driving, which the service has usually collected already.
|
||||
* The range estimates since start and at the 5-minute average, each with its usage in a
|
||||
* card below it. Since start needs the car to have moved; the average needs a minute or more
|
||||
* of driving, which the service has usually collected already.
|
||||
*/
|
||||
private void refreshRangeEstimates(EnergySnapshot s) {
|
||||
RangeEstimator estimator = RangeEstimator.shared();
|
||||
long monotonicMs = android.os.SystemClock.elapsedRealtime();
|
||||
estimator.add(monotonicMs, s.getBatteryPowerKw(), s.getSpeedKmh());
|
||||
Double remaining = RangeEstimator.remainingKwh(s.getSocPercent(), usableKwh());
|
||||
showEstimate(vehRangePower, vehRangePowerNote,
|
||||
RangeEstimator.instant(remaining, s.getBatteryPowerKw(), s.getSpeedKmh()),
|
||||
R.string.range_not_driving);
|
||||
showEstimate(vehRangeAverage, vehRangeAverageNote,
|
||||
estimator.average(remaining, monotonicMs), R.string.range_waiting);
|
||||
RangeEstimator.Estimate trip = estimator.sinceStart(remaining);
|
||||
showEstimate(vehRangeTrip, vehRangeTripNote, vehUsageTrip, vehUsageTripNote, trip,
|
||||
trip == null ? "" : getString(R.string.usage_over_distance, trip.distanceKm),
|
||||
R.string.range_trip_waiting);
|
||||
showEstimate(vehRangeAverage, vehRangeAverageNote, vehUsageAverage, vehUsageAverageNote,
|
||||
estimator.average(remaining, monotonicMs), getString(R.string.usage_last_5_min),
|
||||
R.string.range_waiting);
|
||||
}
|
||||
|
||||
private void showEstimate(TextView value, TextView note, RangeEstimator.Estimate e, int whyNot) {
|
||||
private void showEstimate(TextView range, TextView rangeNote, TextView usage, TextView usageNote,
|
||||
RangeEstimator.Estimate e, String basis, int whyNot) {
|
||||
if (e == null) {
|
||||
value.setText("—");
|
||||
note.setText(whyNot);
|
||||
range.setText("—");
|
||||
rangeNote.setText(whyNot);
|
||||
usage.setText("—");
|
||||
usageNote.setText(whyNot);
|
||||
return;
|
||||
}
|
||||
// Coasting at speed costs almost nothing, which would read as thousands of km.
|
||||
value.setText(e.rangeKm > 999 ? getString(R.string.range_over, 999)
|
||||
range.setText(e.rangeKm > 999 ? getString(R.string.range_over, 999)
|
||||
: String.format(java.util.Locale.US, "%.0f km", e.rangeKm));
|
||||
note.setText(getString(R.string.range_consumption, e.kwhPer100Km));
|
||||
rangeNote.setText("");
|
||||
usage.setText(getString(R.string.range_consumption, e.kwhPer100Km));
|
||||
usageNote.setText(basis);
|
||||
}
|
||||
|
||||
/**
|
||||
|
||||
Reference in New Issue
Block a user