App 2.22.0: Overview style Cockpit, segmented rings and a power trace
A third Overview style beside Tiles and Dashboard: rings for battery, power (zero at the top, regeneration anticlockwise in green) with the speed and gear inside, and 5-minute usage with a tick for the average since start; below, the power of the last two minutes, the clock, climate and odometer. Unread values light nothing and show "—"; the trace leaves gaps (PowerTrace, unit-tested). Emulator only. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01LhzAVaUyqcw5PkGjz4mWW6
This commit is contained in:
@@ -67,6 +67,7 @@ public class MainActivity extends AppCompatActivity {
|
||||
private View logPane;
|
||||
private View vehiclePane;
|
||||
private View dashboardPane;
|
||||
private View cockpitPane;
|
||||
private View consumptionPane;
|
||||
private View chargingPane;
|
||||
/** Display, battery, charging price and Wi-Fi. */
|
||||
@@ -244,6 +245,7 @@ public class MainActivity extends AppCompatActivity {
|
||||
serverPane = inflatePane(R.layout.pane_server);
|
||||
vehiclePane = inflatePane(R.layout.pane_vehicle);
|
||||
dashboardPane = inflatePane(R.layout.pane_dashboard);
|
||||
cockpitPane = inflatePane(R.layout.pane_cockpit);
|
||||
// The Overview page holds both styles; Settings → Overview style picks the one shown.
|
||||
android.widget.FrameLayout overviewPage = new android.widget.FrameLayout(this);
|
||||
overviewPage.setLayoutParams(new android.view.ViewGroup.LayoutParams(
|
||||
@@ -251,6 +253,7 @@ public class MainActivity extends AppCompatActivity {
|
||||
android.view.ViewGroup.LayoutParams.MATCH_PARENT));
|
||||
overviewPage.addView(vehiclePane);
|
||||
overviewPage.addView(dashboardPane);
|
||||
overviewPage.addView(cockpitPane);
|
||||
consumptionPane = inflatePane(R.layout.pane_consumption);
|
||||
chargingPane = inflatePane(R.layout.pane_charging);
|
||||
settingsPane = inflatePane(R.layout.pane_settings);
|
||||
@@ -261,6 +264,7 @@ public class MainActivity extends AppCompatActivity {
|
||||
UpdateLog.noteVersion(this, BuildConfig.VERSION_NAME);
|
||||
bindVehiclePane();
|
||||
bindDashboard();
|
||||
bindCockpit();
|
||||
bindConsumptionPane();
|
||||
bindChargingPane();
|
||||
bindServerPane();
|
||||
@@ -1307,6 +1311,8 @@ public class MainActivity extends AppCompatActivity {
|
||||
showEstimate(vehRangeAverage, vehRangeAverageNote, vehUsageAverage, vehUsageAverageNote,
|
||||
average, getString(R.string.usage_last_5_min), R.string.range_waiting);
|
||||
dashTripKm = trip == null ? null : trip.distanceKm;
|
||||
cockpitTrip = trip;
|
||||
cockpitAverage = average;
|
||||
if (dashUsage != null) dashUsage.setText(average == null ? "—"
|
||||
: String.format(java.util.Locale.US, "%.1f kWh/100 km", average.kwhPer100Km));
|
||||
}
|
||||
@@ -1427,22 +1433,30 @@ public class MainActivity extends AppCompatActivity {
|
||||
/** Kilometres since start, from the range estimator; null until it has a distance. */
|
||||
private Double dashTripKm;
|
||||
|
||||
private boolean dashboardStyle() {
|
||||
return "DASHBOARD".equals(prefs.getString(PREF_OVERVIEW_STYLE, "TILES"));
|
||||
/** The stored values of the Overview styles, in the order of the drop-down. */
|
||||
private static final String[] OVERVIEW_STYLES = { "TILES", "DASHBOARD", "COCKPIT" };
|
||||
|
||||
/** The chosen style's index in {@link #OVERVIEW_STYLES}; anything unknown is Tiles. */
|
||||
private int overviewStyle() {
|
||||
String style = prefs.getString(PREF_OVERVIEW_STYLE, "TILES");
|
||||
for (int i = 0; i < OVERVIEW_STYLES.length; i++) if (OVERVIEW_STYLES[i].equals(style)) return i;
|
||||
return 0;
|
||||
}
|
||||
|
||||
private void applyOverviewStyle() {
|
||||
boolean dash = dashboardStyle();
|
||||
dashboardPane.setVisibility(dash ? View.VISIBLE : View.GONE);
|
||||
vehiclePane.setVisibility(dash ? View.GONE : View.VISIBLE);
|
||||
int style = overviewStyle();
|
||||
vehiclePane.setVisibility(style == 0 ? View.VISIBLE : View.GONE);
|
||||
dashboardPane.setVisibility(style == 1 ? View.VISIBLE : View.GONE);
|
||||
cockpitPane.setVisibility(style == 2 ? View.VISIBLE : View.GONE);
|
||||
}
|
||||
|
||||
/** Tiles (the cards) or Dashboard (gauges); both are fed on every reading. */
|
||||
/** Tiles (the cards), Dashboard (gauges) or Cockpit (rings); all are fed on every reading. */
|
||||
private void bindOverviewStyle() {
|
||||
String[] labels = { getString(R.string.overview_style_tiles), getString(R.string.overview_style_dashboard) };
|
||||
bindChoices(settingsPane.findViewById(R.id.overview_style_choices), labels, dashboardStyle() ? 1 : 0,
|
||||
String[] labels = { getString(R.string.overview_style_tiles), getString(R.string.overview_style_dashboard),
|
||||
getString(R.string.overview_style_cockpit) };
|
||||
bindChoices(settingsPane.findViewById(R.id.overview_style_choices), labels, overviewStyle(),
|
||||
position -> {
|
||||
prefs.edit().putString(PREF_OVERVIEW_STYLE, position == 1 ? "DASHBOARD" : "TILES").apply();
|
||||
prefs.edit().putString(PREF_OVERVIEW_STYLE, OVERVIEW_STYLES[position]).apply();
|
||||
applyOverviewStyle();
|
||||
});
|
||||
}
|
||||
@@ -1461,9 +1475,69 @@ public class MainActivity extends AppCompatActivity {
|
||||
dashBattery.configure(0f, 100f, 25f, 5, getString(R.string.dash_unit_battery));
|
||||
dashBattery.setEndLabels("E", "F");
|
||||
dashBattery.setWarnBelow(20f);
|
||||
}
|
||||
|
||||
// ---------- Cockpit (Overview style) ----------
|
||||
|
||||
/** Power over the last two minutes, a slot per second. */
|
||||
private final PowerTrace cockpitTrace = new PowerTrace(120_000, 120);
|
||||
private RingView cockpitBattery, cockpitPower, cockpitUsage;
|
||||
private TraceView cockpitTraceView;
|
||||
private TextView cockpitClimate, cockpitOdometer;
|
||||
/** From the range estimator: since start and the last 5 minutes; null until known. */
|
||||
private RangeEstimator.Estimate cockpitTrip, cockpitAverage;
|
||||
|
||||
private void bindCockpit() {
|
||||
cockpitBattery = cockpitPane.findViewById(R.id.cockpit_battery);
|
||||
cockpitPower = cockpitPane.findViewById(R.id.cockpit_power);
|
||||
cockpitUsage = cockpitPane.findViewById(R.id.cockpit_usage);
|
||||
cockpitTraceView = cockpitPane.findViewById(R.id.cockpit_trace);
|
||||
cockpitClimate = cockpitPane.findViewById(R.id.cockpit_climate);
|
||||
cockpitOdometer = cockpitPane.findViewById(R.id.cockpit_odometer);
|
||||
cockpitBattery.configure(0f, 100f, 40);
|
||||
cockpitBattery.setWarnBelow(20f);
|
||||
cockpitBattery.setBigScale(0.36f);
|
||||
cockpitBattery.setScaleLabels("0", null, "100");
|
||||
cockpitPower.setCentred(-50f, 150f, 60);
|
||||
cockpitPower.setTopPill(true);
|
||||
cockpitPower.setBigScale(0.44f);
|
||||
cockpitPower.setScaleLabels("−50", "0", "150 kW");
|
||||
cockpitUsage.configure(0f, 30f, 40);
|
||||
cockpitUsage.setBigScale(0.36f);
|
||||
cockpitUsage.setScaleLabels("0", null, "30");
|
||||
applyOverviewStyle();
|
||||
}
|
||||
|
||||
/** The rings and the strip; every value null-safe ("—", nothing lit, gaps in the trace). */
|
||||
private void showCockpit(EnergySnapshot s) {
|
||||
if (cockpitPower == null) return;
|
||||
java.util.Locale us = java.util.Locale.US;
|
||||
Float soc = s.getSocPercent();
|
||||
cockpitBattery.setValue(soc, getString(R.string.cockpit_battery),
|
||||
soc == null ? null : String.format(us, "%.0f", soc), "%",
|
||||
fmt(s.getRangeKm(), "%.0f km"), null);
|
||||
|
||||
Float power = s.getBatteryPowerKw();
|
||||
Float speed = s.getSpeedKmh();
|
||||
Boolean parked = s.getParked();
|
||||
cockpitPower.setValue(power, parked == null ? "—" : parked ? "P" : "D",
|
||||
speed == null ? null : String.format(us, "%.0f", speed), getString(R.string.dash_unit_kmh),
|
||||
power == null ? "—" : String.format(us, "%.1f kW", power), null);
|
||||
cockpitTrace.add(android.os.SystemClock.elapsedRealtime(), power);
|
||||
cockpitTraceView.setValues(cockpitTrace.snapshot());
|
||||
|
||||
RangeEstimator.Estimate now = cockpitAverage, trip = cockpitTrip;
|
||||
cockpitUsage.setValue(now == null ? null : (float) now.kwhPer100Km, getString(R.string.cockpit_usage),
|
||||
now == null ? null : String.format(us, "%.1f", now.kwhPer100Km), getString(R.string.cockpit_usage_unit),
|
||||
trip == null ? getString(R.string.cockpit_usage_trip, "—")
|
||||
: getString(R.string.cockpit_usage_trip, String.format(us, "%.1f", trip.kwhPer100Km)),
|
||||
trip == null ? null : String.format(us, "%.1f km", trip.distanceKm));
|
||||
cockpitUsage.setMarker(trip == null ? null : (float) trip.kwhPer100Km);
|
||||
|
||||
cockpitClimate.setText(fmt(s.getClimate().getDriverTargetCelsius(), "%.0f °C"));
|
||||
cockpitOdometer.setText(fmt(s.getOdometerKm(), "%,.0f km"));
|
||||
}
|
||||
|
||||
/** The gauges and the strip; every value null-safe ("—", no needle). */
|
||||
private void showDashboard(EnergySnapshot s) {
|
||||
if (dashPower == null) return;
|
||||
@@ -1504,6 +1578,7 @@ public class MainActivity extends AppCompatActivity {
|
||||
vehTireRl.setText(unit.format(s.getTirePressures().getRearLeftKpa()));
|
||||
vehTireRr.setText(unit.format(s.getTirePressures().getRearRightKpa()));
|
||||
showDashboard(s);
|
||||
showCockpit(s);
|
||||
} catch (Throwable ignored) {
|
||||
// Leave the last good reading on screen.
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user