App 2.34.0: set the chosen drive mode again when the car starts

The car falls back to its own default mode at every start. With "Set at
start" (on by default), the service sets the mode last chosen on
Settings and confirmed by the car again, once, while the car is in P at
0 km/h, and gives up as soon as the car leaves P or after two minutes
(DriveModeWrite.atStart, unit-tested). The buttons and the start share
the write and read-back (DriveModeSetter). Not tried on the car.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01LhzAVaUyqcw5PkGjz4mWW6
This commit is contained in:
2026-10-25 20:12:11 +01:00
co-authored by Claude Opus 5.5
parent ce2ebd7f58
commit ed65c96319
13 changed files with 241 additions and 38 deletions
@@ -1333,6 +1333,34 @@ public class MainActivity extends AppCompatActivity {
final int code = DriveModeWrite.CODES[i];
settingsPane.findViewById(DRIVE_MODE_IDS[i]).setOnClickListener(v -> requestDriveMode(code));
}
SwitchMaterial atStart = settingsPane.findViewById(R.id.drive_mode_at_start_switch);
atStart.setChecked(prefs.getBoolean(DriveModeWrite.PREF_AT_START, true));
atStart.setOnCheckedChangeListener((b, checked) ->
prefs.edit().putBoolean(DriveModeWrite.PREF_AT_START, checked).apply());
String started = driveModeAtStartText();
if (started != null) ((TextView) settingsPane.findViewById(R.id.drive_mode_status)).setText(started);
}
/** The last start's result as a sentence, from "25.10. 20:31|4|APPLIED|4"; null when none. */
private String driveModeAtStartText() {
String stored = prefs.getString(DriveModeWrite.PREF_START_RESULT, null);
if (stored == null) return null;
String[] p = stored.split("\\|", -1);
if (p.length < 4) return null;
try {
String when = p[0];
String name = driveModeName(Integer.valueOf(p[1]));
Integer reported = p[3].isEmpty() ? null : Integer.valueOf(p[3]);
switch (p[2]) {
case "APPLIED": return getString(R.string.drive_mode_start_applied, when, name);
case "ALREADY": return getString(R.string.drive_mode_start_already, when, name);
case "NOT_APPLIED": return getString(R.string.drive_mode_start_not_applied, when, name, driveModeName(reported));
case "UNREAD": return getString(R.string.drive_mode_start_unread, when, name);
default: return getString(R.string.drive_mode_start_refused, when, name);
}
} catch (NumberFormatException e) {
return null;
}
}
/** The highlight follows the car's reported mode, from every reading. */
@@ -1387,20 +1415,15 @@ public class MainActivity extends AppCompatActivity {
case UNREADABLE: return getString(R.string.drive_mode_unreadable);
default: break;
}
com.evsuite.hardware.model.DriveMode mode = com.evsuite.hardware.model.DriveMode.Companion.ofRaw(code);
if (mode == null || !com.evsuite.hardware.EVHardware.INSTANCE.writeDriveModeProperty(mode)) {
return getString(R.string.drive_mode_write_failed, name);
}
Integer now = null;
for (int i = 0; i < 10; i++) {
Thread.sleep(300);
now = com.evsuite.hardware.EVHardware.INSTANCE.getDriveModeRaw();
if (now != null && now == code) break;
}
final Integer reported = now;
runOnUiThread(() -> showDriveMode(reported));
DriveModeSetter.Result result = DriveModeSetter.set(code);
if (!result.written) return getString(R.string.drive_mode_write_failed, name);
final Integer now = result.reported;
runOnUiThread(() -> showDriveMode(now));
switch (DriveModeWrite.outcome(code, now)) {
case APPLIED: return getString(R.string.drive_mode_applied, name);
case APPLIED:
// Confirmed by the car: this is the mode set again at start.
prefs.edit().putInt(DriveModeWrite.PREF_CHOSEN, code).apply();
return getString(R.string.drive_mode_applied, name);
case NOT_APPLIED: return getString(R.string.drive_mode_not_applied, name, driveModeName(now));
default: return getString(R.string.drive_mode_unread_back, name);
}