App 2.32.1: drop the cruise control reads; the recorder becomes general

The 2.32.0 recording (ACC set to 101, 90 and 80 km/h behind another car)
found none of it among 1,194 values: the head unit does not get the ACC
data. Removed the cruise log and the set-speed read (EVHardware is as
before 2.27.3); the finding is under "Signals the car does not provide".
The recorder stays as the Signal recorder, for finding other signals.

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 19:51:42 +01:00
co-authored by Claude Opus 5.5
parent 2e6bb9cb83
commit 703bdfd2a3
16 changed files with 84 additions and 352 deletions
@@ -172,9 +172,6 @@ object ReadFailureLog {
lastReason.put(key, reason) != reason
}
/** Why [key] last failed, or null when it answered (or was never read). */
fun reason(key: String): String? = synchronized(lock) { lastReason[key] }
/** A property that starts answering again must not silence its next failure. */
fun clear(key: String) {
synchronized(lock) { lastReason.remove(key) }
@@ -427,59 +427,6 @@ object EVHardware {
private const val PROP_CCU_ONBD_PLUG = 0x2140F43E // vendor int, AC socket
private const val PROP_CCU_OFFBD_PLUG = 0x2140F43F // vendor int, DC socket
private const val PROP_ENERGY_SINCE_CHARGE = 0x2160A1BB // vendor float kWh
/**
* `AAD_EPTCCTRGTSPD` in the head unit's `CarAdvancedAssistedDrivingManager`: by its name the
* powertrain's cruise control target speed. Unit and the value while cruise control is off
* are not established; it is passed on raw.
*/
private const val PROP_CRUISE_TARGET_SPEED = 0x2160A15B // vendor float
/**
* The other driver-assistance properties of `CarAdvancedAssistedDrivingManager` that may
* say what the adaptive cruise control is doing, read raw for the Logs tab while their
* meaning is established on the car: the operation mode of traffic-jam / intelligent
* cruise assist (`LANE_TJAICAOPMD`, by the manager 0 no request, 1 object following,
* 2 lane centre, 3 combined), the speed assist (`SPEED_ASST_SYS`, `SPEED_ASST_MODE`, by the
* manager 0 off, 2 manual limiter, 3 intelligent), the traffic-jam assist switch, and the
* object the ACC follows (`ACC_OBJ_*`: existence probability, longitudinal distance and
* relative speed).
*/
private val ACC_DEBUG_PROPS = listOf(
AccDebugProp("cc", PROP_CRUISE_TARGET_SPEED, float = true),
AccDebugProp("ica", 0x2140A12A, float = false), // AAD_LANE_TJAICAOPMD
AccDebugProp("tja", 0x2140A107, float = false), // AAD_TRAFFIC_JAM_ASST_SYS
AccDebugProp("sas", 0x2140A101, float = false), // AAD_SPEED_ASST_SYS
AccDebugProp("sam", 0x2140A102, float = false), // AAD_SPEED_ASST_MODE
AccDebugProp("obj", 0x2160A12F, float = true), // AAD_ACC_OBJ_EXIST_PRBLTY
AccDebugProp("dist", 0x2160A12C, float = true), // AAD_ACC_OBJ_LONG_RLTV_DIST
AccDebugProp("rel", 0x2160A12E, float = true), // AAD_ACC_OBJ_LONG_RLTV_SPD
)
private class AccDebugProp(val name: String, val id: Int, val float: Boolean)
/** The cruise control target speed as the car reports it, unmapped; null when unread. */
fun getCruiseTargetSpeedRaw(): Float? = supportedTelemetryRead {
getFloatPropertyCPM(PROP_CRUISE_TARGET_SPEED, AREA_GLOBAL)?.takeIf { it.isFinite() }
}
/**
* The driver-assistance properties above, one raw reading each, for debugging the adaptive
* cruise control on the car: name to value (floats to two decimals), or to "unread" with
* the reason the car gave. Read only; about eight calls, so not on the main thread.
*/
fun readAccDebug(): List<Pair<String, String>> = ACC_DEBUG_PROPS.map { prop ->
val value: Any? = supportedTelemetryRead {
if (prop.float) getFloatPropertyCPM(prop.id, AREA_GLOBAL)?.takeIf { it.isFinite() }
else readPropertyCPM(prop.id, AREA_GLOBAL, Int::class.javaObjectType) { sCpmGetIntMethod } as? Int
}
prop.name to when (value) {
is Float -> String.format(java.util.Locale.US, "%.2f", value)
null -> "unread" + (ReadFailureLog.reason(
"0x${Integer.toHexString(prop.id)}@0x${Integer.toHexString(AREA_GLOBAL)}")
?.let { " ($it)" } ?: "")
else -> value.toString()
}
}
/**
* `HVAC_AMBIENT_TEMPERATURE`, the one in-car candidate left on this firmware.
@@ -50,8 +50,6 @@ data class EnergySnapshot(
val regenLevelRaw: Int? = null,
/** The gear's raw code (MG4 SWI68: 1 P, 2 R, 3 N, 4 D); null where the car did not answer. */
val gearRaw: Int? = null,
/** Cruise control target speed as reported (`0x2160A15B`), unit not established; null unread. */
val cruiseTargetSpeedRaw: Float? = null,
) {
val hasVehicleData: Boolean
get() = socPercent != null || rangeKm != null || speedKmh != null ||
@@ -61,7 +59,7 @@ data class EnergySnapshot(
vehicleConsumedKwh != null || vehicleRegeneratedKwh != null ||
parked != null || climate.hasData || tirePressures.hasData ||
widestWindowPercent != null || driveModeRaw != null || regenLevelRaw != null ||
gearRaw != null || cruiseTargetSpeedRaw != null
gearRaw != null
}
data class TirePressureSnapshot(
@@ -29,8 +29,6 @@ interface EnergySignalSource {
fun parked(): Boolean?
/** The gear's raw code (MG4 SWI68: 1 P, 2 R, 3 N, 4 D). Null where unread. */
fun gearRaw(): Int? = null
/** The cruise control target speed, raw (unit not established). Null where unread. */
fun cruiseTargetSpeedRaw(): Float? = null
fun batteryVoltageV(): Float? = null
fun batteryCurrentA(): Float? = null
/** Widest window opening in percent; null where the firmware has no read. */
@@ -79,7 +77,6 @@ class EvHardwareEnergySignalSource(context: Context) : EnergySignalSource {
override fun vehicleRegeneratedKwh() = SaicCharging.regeneratedKwhSinceCharge()
override fun parked() = EVHardware.isVehicleInPark()
override fun gearRaw() = EVHardware.getGearRaw()
override fun cruiseTargetSpeedRaw() = EVHardware.getCruiseTargetSpeedRaw()
override fun batteryVoltageV() = EVHardware.getVendorBatteryVoltageV()
override fun batteryCurrentA() = EVHardware.getVendorBatteryCurrentA()
override fun widestWindowPercent() = SaicVehicleControl.widestWindowPercent()
@@ -161,7 +158,6 @@ class EnergyTelemetryReader(private val source: EnergySignalSource) {
driveModeRaw = source.driveModeRaw(),
regenLevelRaw = source.regenLevelRaw(),
gearRaw = source.gearRaw(),
cruiseTargetSpeedRaw = source.cruiseTargetSpeedRaw(),
)
/** Reads CP-004 candidates only when an unstable evidence capture explicitly requests them. */