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.

Supported vehicles

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.

Requirements

  • SDK 0.8.0 or later (see Upgrade below).
  • An authenticated session — call GProAuthentication exactly 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.

Step 1: Start the 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.

Step 2: Handle the result

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.

When onDpfFailed fires

message is ready to show to the user. partialResult tells you how far it got:

  • partialResult is null — 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.
  • partialResult is 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

GProDpfResult

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

Alternative: receive the result as an activity result

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.

While the regeneration runs

  • 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.

Data and uploads

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.

Manifest, permissions and Google Play

These are merged into your app automatically — no manifest changes are needed:

  • Permissions: FOREGROUND_SERVICE, FOREGROUND_SERVICE_CONNECTED_DEVICE, WAKE_LOCK and POST_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.

Customising the colour

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.

Upgrade

implementation ('com.github.zymbia-carpm:garagepro_sdk:v0.8.0') {
    transitive = true
}

Fully backward compatible — no code changes are required for existing integrations.

⚠️ **GitHub.com Fallback** ⚠️