Chapter 11: HCV DPF Regeneration (v0.8.0 update) - zymbia-carpm/garagepro_sdk GitHub Wiki
This update (SDK version 49, 0.8.0) adds DPF regeneration for Ashok Leyland heavy commercial vehicles. It is fully additive — scan, clear-codes and live-data integrations are unchanged.
A forced regeneration burns off the soot collected in the vehicle's diesel particulate filter (DPF). The SDK runs the whole procedure from one call and shows every screen itself: ECU selection, safety instructions, scanner connection, live checks of the vehicle conditions, progress with live readings, cool-down and the outcome. Your app starts it and receives one result.
Ashok Leyland only, with any of these four ECU families. The mechanic picks the ECU on the first screen, from the label on the vehicle's engine or after-treatment unit.
| ECU | System | Typical duration | Before starting, the SDK waits for |
|---|---|---|---|
| Denso A4 / A6 / H6 | Diesel injection | 30–90 min | engine above 300 rpm, vehicle stopped |
| Delphi DCM 7.1 | Diesel injection | 30–40 min | engine above 300 rpm, vehicle stopped, coolant above 70 °C |
| Albonair ACU | After-treatment | about 40 min | engine above 300 rpm, vehicle stopped |
| Cummins CM1788 ACM | After-treatment | 20–40 min | engine idling between 300 and 1000 rpm, vehicle stopped, coolant at least 60 °C |
On Denso, the mechanic also presses the blinking DPF button on the vehicle dashboard when the SDK asks, then confirms in the app.
- SDK 0.8.0 or later (see Upgrade below).
-
An authenticated session — call
GProAuthenticationexactly as in Chapter 2 first. -
A classic Bluetooth OBDII scanner. The SDK connects to it itself, using the same scanner list
as scans. Regeneration is not available on connections you pass in with
GProDeviceConnection. - Internet when the regeneration starts, to register the vehicle. Readings do not need the network while the regeneration runs.
The SDK asks for Bluetooth permissions (and offers to turn Bluetooth on) by itself. You do not need to forward permission or activity results to it.
The regeneration opens its own connection to the scanner and closes it when its screens close. Most
scanners accept one connection at a time, so if your app is still connected to the same scanner
through a GProScanProcess or GProLiveScanProcess, call forceStop() on it before starting a
regeneration.
Call GProDpfRegeneration.start(...) from an Activity:
GProDpfRegeneration.start(activity, makeName, registrationNumber, jobCardId,
new GProDpfListener() {
@Override
public void onDpfCompleted(GProDpfResult result) {
// the regeneration finished successfully
}
@Override
public void onDpfEndedEarly(GProDpfResult result) {
// the ECU ended it without completing - result.getOutcome() says how
}
@Override
public void onDpfCancelled(GProDpfResult result) {
// the mechanic stopped it, or closed the screens before it started
}
@Override
public void onDpfFailed(String message, GProDpfResult partialResult) {
// it could not start or could not continue - message says why
}
});
makeName must be Ashok Leyland (any capitalisation or spacing). registrationNumber and
jobCardId are your references for the vehicle and the job, exactly as for a scan.
To offer the option only where it applies, check the make first:
boolean supported = GProDpfRegeneration.isSupportedMake(makeName);
Starting with any other make fails straight away with onDpfFailed(...); nothing is shown.
Exactly one callback fires per start(...) call, on the main thread.
| Callback | When | result.getOutcome() |
|---|---|---|
onDpfCompleted |
The regeneration ran to completion | COMPLETED |
onDpfEndedEarly |
The ECU ended the regeneration before completing it | ENDED_EARLY |
onDpfEndedEarly |
The ECU accepted the start but never began the regeneration | DID_NOT_START |
onDpfCancelled |
The mechanic stopped it, or closed the screens before it started | CANCELLED |
onDpfFailed |
It could not start or could not continue |
FAILED (when a result is present) |
In onDpfEndedEarly, the mechanic has been advised on screen to run the procedure again.
message is ready to show to the user. partialResult tells you how far it got:
-
partialResultisnull— nothing started: the make is not Ashok Leyland, the session has expired, Bluetooth or its permission was refused, no scanner was connected, or the vehicle could not be registered. Except for the make check, which fails before any screen opens, the SDK has already shown the reason and closed its screens. -
partialResultis present — a run was recorded.partialResult.getFailureReason()is one of:
| Failure reason | Meaning | What to suggest |
|---|---|---|
GProDpfResult.FAILURE_ARM_REJECTED |
The ECU refused to start the regeneration | Check the vehicle conditions and that the right ECU was chosen |
GProDpfResult.FAILURE_SECURITY |
The ECU refused access | Try again later |
GProDpfResult.FAILURE_LINK_LOST |
The connection to the scanner or vehicle was lost | Check the scanner and try again |
| Method | Description |
|---|---|
getOutcome() |
One of the OUTCOME_* constants in the table above |
getFailureReason() |
One of the FAILURE_* constants; null unless the outcome is FAILED
|
getVariant() |
AL_DENSO_A4_A6_H6, AL_DELPHI_71_DCM, AL_ALBONAIR_ACU or AL_CUMMINS_CM1788_ACM; null if the mechanic closed the ECU selection |
getResetType() |
The same ECU as recorded on the server, e.g. DPF_AL_ALBONAIR_ACU
|
getRegenDurationMs() |
Time from the regeneration starting to the ECU ending it; 0 if it never started or was stopped first |
getPeakDpfInletC() |
Highest DPF inlet temperature seen, in °C; null on Cummins, or if no reading arrived |
getTerminalCode() |
The ECU's final status, for support; null if the ECU never reported an end |
getSampleCount() |
Readings recorded during the run |
getUploadedCount() |
Readings the server had accepted when the result was delivered |
getLocalRunId() |
This run's ID on the device; 0 if nothing was recorded |
getDpfResetBackendId() |
The run's server ID; 0 if the upload is still pending |
getUserCarModelId() |
The registered vehicle's server ID |
If your Activity may be recreated during a long regeneration, you can use an activity result instead of a listener:
startActivityForResult(
GProDpfRegeneration.createIntent(context, makeName, registrationNumber, jobCardId),
REQUEST_DPF);
@Override
protected void onActivityResult(int requestCode, int resultCode, Intent data) {
super.onActivityResult(requestCode, resultCode, data);
if (requestCode != REQUEST_DPF || data == null) return;
Bundle result = data.getBundleExtra(GProDpfRegeneration.EXTRA_RESULT); // may be null
String message = data.getStringExtra(GProDpfRegeneration.EXTRA_MESSAGE); // set on failure
switch (resultCode) {
case GProDpfRegeneration.RESULT_CODE_COMPLETED: break;
case GProDpfRegeneration.RESULT_CODE_ENDED_EARLY: break;
case GProDpfRegeneration.RESULT_CODE_CANCELLED: break;
case GProDpfRegeneration.RESULT_CODE_FAILED: break;
}
}
The result bundle carries the same values as GProDpfResult, under these keys: outcome,
failure_reason, variant, reset_type, terminal_code, regen_duration_ms (long),
sample_count, uploaded_count, backend_id, local_run_id, user_car_model_id (ints) and
peak_dpf_inlet_c (int, present only when there is a reading).
Use one form or the other for a given regeneration — start(...) with a listener, or
createIntent(...) with an activity result.
- The screen stays on while the SDK's screens are visible.
- If the mechanic leaves your app, the regeneration keeps running and a notification shows it is in progress. Tapping the notification returns to the regeneration screen.
- Notification permission (Android 13 and later) is requested when the regeneration starts. Refusing it does not stop the regeneration; the notification is simply not shown.
- Stopping — the mechanic can stop at any time. The SDK asks for confirmation, tells the ECU to end the routine and saves what was recorded.
- Cool-down — after the ECU ends the regeneration, the SDK keeps reading the temperatures for two minutes and reminds the mechanic to keep the engine idling while the exhaust cools, then shows the outcome.
Readings are saved on the device as they are captured, so a regeneration interrupted by the app
being closed does not lose them. The run and its readings are uploaded when the run ends. If the
phone is offline at that moment, getDpfResetBackendId() is 0 and the upload completes
automatically in the background later.
These are merged into your app automatically — no manifest changes are needed:
- Permissions:
FOREGROUND_SERVICE,FOREGROUND_SERVICE_CONNECTED_DEVICE,WAKE_LOCKandPOST_NOTIFICATIONS - The regeneration screens (two activities) and a foreground service of type connected device
Google Play: apps that declare foreground-service permissions must describe their use in Play Console under App content → Foreground service permissions. Declare Connected device, used to keep the diagnostic session with the OBDII scanner running for the length of a DPF regeneration.
No ProGuard / R8 rules are needed — the SDK ships its own.
The regeneration screens use a neutral style. To match your brand, define the accent colour in your
app's res/values/colors.xml:
<color name="gpro_dpf_accent">#0B5FFF</color>
Buttons, the progress ring and selected states follow it.
implementation ('com.github.zymbia-carpm:garagepro_sdk:v0.8.0') {
transitive = true
}
Fully backward compatible — no code changes are required for existing integrations.