Skip to content

Conversation

@jamesarich
Copy link
Collaborator

@jamesarich jamesarich commented Dec 4, 2025

This pull request introduces significant improvements to the firmware update workflow, device connection handling, and codebase maintainability. The main highlights are the addition of new update methods (BLE OTA and USB File Transfer), enhanced UI messaging for firmware updates, new service and repository methods for device transport and DFU reboot, and utility functions for radio transport identification. These changes collectively improve user experience, device management, and code clarity.

Firmware Update Workflow Enhancements:

  • Added new firmware update methods (BLE OTA and USB File Transfer), including UI support for selecting update methods and saving firmware files to DFU drives.
  • Introduced FirmwareFileHandler for robust file operations (download, extraction, copy) related to firmware updates.
  • Improved UI messaging with new strings for update progress, instructions, and method details.

Device Connection and Service Improvements:

  • Added support for rebooting devices to DFU mode via a new AIDL method and service implementation.
  • Implemented transport identification for device connections, with service and repository methods to set and retrieve the current transport (BLE, Serial, TCP, etc.).

Codebase Maintenance and Utility Functions:

  • Added utility extension functions to RadioPrefs for transport type identification (isBle, isSerial, etc.).
  • Updated Detekt baseline for the firmware feature to suppress generic exception warnings.
Screen_recording_20251204_144308.mp4

This commit introduces support for updating firmware via USB DFU for devices that require it (e.g., those based on the RP2040). The update process now differentiates between OTA (Bluetooth) and USB updates based on the connection transport and device hardware properties.

- **Differentiate Update Paths**: The `FirmwareUpdateViewModel` now checks the connection transport. If connected via "Serial" and the device requires DFU, it initiates the USB update flow; otherwise, it proceeds with the existing OTA update process.
- **Implement USB DFU Flow**:
    - Added a `rebootToDfu()` command, which is sent to the device to put it into bootloader mode.
    - The app downloads the appropriate `.uf2` firmware file.
    - It then waits for the device to reappear as a mass storage device (DFU drive).
    - Once the drive is detected, the firmware file is copied to it to complete the update.
- **Service Layer Updates**:
    - The `ServiceRepository` now tracks the current `connectionTransport` (e.g., "Serial", "Bluetooth").
    - A `rebootToDfu()` function has been added to `IMeshService.aidl` and implemented in `MeshService` to send the required admin packet.
- **UI Feedback**: Added new string resources to inform the user about the status of the USB DFU process, such as "Rebooting to DFU...", "Waiting for DFU device...", and "Copying firmware...".

Signed-off-by: James Rich <[email protected]>
This commit refactors the USB DFU firmware update process to be more robust and user-friendly. Instead of attempting to automatically detect and write to the DFU drive, the app now prompts the user to save the `.uf2` file via the system file picker. This approach avoids issues with file system permissions and unreliable drive detection.

Key changes:
- **Modified USB DFU Flow**: The update process now downloads the `.uf2` file, reboots the device into DFU mode, and then uses `ActivityResultContracts.CreateDocument` to ask the user where to save the firmware file.
- **New UI State**: Introduced `AwaitingFileSave` state to handle the user interaction for saving the file.
- **Device Detachment Detection**: Added logic to listen for the `USB_DEVICE_DETACHED` broadcast, providing feedback that the flashing process has started.
- **Connection Type Logic**: The ViewModel now uses helpers from `RadioPrefs` (`isSerial()`, `isBle()`) to determine the connection type and initiate the correct update flow (USB DFU vs. OTA).
- **URL Update**: Changed the base URL for firmware downloads to point to `raw.githubusercontent.com` for more direct access.
- **Removed Automatic DFU Drive Search**: The problematic and unreliable logic for automatically finding the DFU drive has been removed.
- **Cleanup**: Refactored validation logic and removed unused methods.

Signed-off-by: James Rich <[email protected]>
This commit refactors the `FirmwareUpdateViewModel` to improve clarity and maintainability by separating the firmware update logic into dedicated handler classes for Over-the-Air (OTA) and USB updates. It also introduces a `FirmwareFileHandler` to encapsulate all file-related operations.

- **`FirmwareFileHandler`**: New class to manage downloading, extracting, and copying firmware files. This centralizes file operations previously handled within the ViewModel.
- **`OtaUpdateHandler` and `UsbUpdateHandler`**: New classes that encapsulate the specific logic for BLE OTA and USB firmware updates, respectively. They use a new `FirmwareRetriever` class to fetch the correct firmware files.
- **`FirmwareUpdateViewModel`**:
    - Now delegates update tasks to `OtaUpdateHandler` and `UsbUpdateHandler`.
    - Determines the update method (BLE or USB) based on the current connection and passes this information to the UI.
    - Logic for starting updates from a local file now uses the `OtaUpdateHandler`.
- **UI Changes (`FirmwareUpdateScreen` and `ReadyState`)**:
    - The UI now displays the determined update method (e.g., "BLE OTA" or "USB File Transfer") with a corresponding icon.
    - The bootloader warning is now only shown for BLE connections that require it.
    - The disclaimer dialog is now aware of the update method and only shows BLE-specific content (like the Chirpy warning) when appropriate.

Signed-off-by: James Rich <[email protected]>
This commit enhances the firmware update feature to support flashing devices using local files for both BLE (ZIP) and USB (UF2) update methods.

- Implemented logic to handle file selection based on the active update method (BLE or USB).
- Added `extractFirmware` to `FirmwareFileHandler` to automatically find and extract the correct device firmware from a local ZIP archive.
- Refactored `startUpdateFromFile` in `FirmwareUpdateViewModel` to differentiate between BLE and USB update flows and initiate the appropriate process.
- Modified `OtaUpdateHandler` and `UsbUpdateHandler` to accept an optional `firmwareUri`, allowing them to use a local file instead of downloading one.
- Updated `FirmwareFileHandler` to allow copying from a `Uri` to another `Uri`, facilitating file handling for USB updates.

Signed-off-by: James Rich <[email protected]>
This commit updates the Nordic DFU options to improve reliability.

- Adds a `DATA_OBJECT_DELAY` of 400ms using `setPrepareDataObjectDelay`.
- Enables `setRestoreBond(true)` to re-establish bonding information after the update.
- Disables `setForceDfu(false)` as it is no longer needed.
- Removes the now-redundant `setPacketsReceiptNotificationsEnabled` call.

Signed-off-by: James Rich <[email protected]>
This commit refactors the firmware update process with two main changes:

- Removes the unused `getMimeType` function and its related calls from `FirmwareUpdateViewModel`. This logic was not being utilized in the file update flow.
- Disables the `setRestoreBond` option in the DFU initiator settings within `UpdateHandler`.

Signed-off-by: James Rich <[email protected]>
This commit introduces a dialog to guide the user during the USB firmware update process.

When the device reboots into DFU mode, a dialog is now displayed. It informs the user that the device will appear as a USB drive and instructs them to select the root of that drive in the upcoming file picker to save the firmware file. This change improves the user experience by providing clear, timely instructions, preventing confusion when the file picker appears.

The automatic file save trigger on entering the `AwaitingFileSave` state has been replaced with this user-acknowledged dialog flow.

Signed-off-by: James Rich <[email protected]>
This commit refactors the firmware update feature to improve UI clarity and streamline the underlying update logic.

- Displays the currently installed firmware version on the update screen.
- Changes the main update button to show the selected update method (BLE or USB) along with a corresponding icon.
- Simplifies code in `UpdateHandler.kt` and `FirmwareUpdateViewModel.kt` by using expression bodies and removing unnecessary temporary variables.
- Adds a `detekt-baseline.xml` file to suppress existing warnings related to generic exception handling.

Signed-off-by: James Rich <[email protected]>
@codecov
Copy link

codecov bot commented Dec 4, 2025

Codecov Report

❌ Patch coverage is 0% with 438 lines in your changes missing coverage. Please review.
✅ Project coverage is 0.52%. Comparing base (dbc5fd7) to head (9ffa165).
⚠️ Report is 18 commits behind head on main.

Files with missing lines Patch % Lines
...tastic/feature/firmware/FirmwareUpdateViewModel.kt 0.00% 123 Missing and 1 partial ⚠️
...eshtastic/feature/firmware/FirmwareUpdateScreen.kt 0.00% 116 Missing ⚠️
...meshtastic/feature/firmware/FirmwareFileHandler.kt 0.00% 94 Missing ⚠️
...n/org/meshtastic/feature/firmware/UpdateHandler.kt 0.00% 90 Missing ⚠️
...tlin/org/meshtastic/core/prefs/radio/RadioPrefs.kt 0.00% 5 Missing ⚠️
...meshtastic/feature/firmware/FirmwareUpdateState.kt 0.00% 3 Missing ⚠️
.../org/meshtastic/feature/settings/SettingsScreen.kt 0.00% 3 Missing ⚠️
...in/java/com/geeksville/mesh/service/MeshService.kt 0.00% 2 Missing ⚠️
...g/meshtastic/feature/settings/SettingsViewModel.kt 0.00% 1 Missing ⚠️
Additional details and impacted files
@@           Coverage Diff            @@
##            main   #3901      +/-   ##
========================================
- Coverage   0.53%   0.52%   -0.01%     
========================================
  Files        392     394       +2     
  Lines      22940   23126     +186     
  Branches    2894    2932      +38     
========================================
  Hits         122     122              
- Misses     22797   22983     +186     
  Partials      21      21              

☔ View full report in Codecov by Sentry.
📢 Have feedback on the report? Share it here.

This commit removes the `connectionTransport()` method from the `IMeshService` AIDL interface and its implementation in `MeshService`. This method was unused within the app and is no longer needed.

Additionally, a string resource related to firmware updates has been updated to remove a redundant DFU requirement message, as the check is handled elsewhere.

Signed-off-by: James Rich <[email protected]>
Copy link
Contributor

Copilot AI left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Copilot encountered an error and was unable to review this pull request. You can try again by re-requesting a review.

@jamesarich jamesarich added this to the 2.7.9 milestone Dec 5, 2025
@jamesarich jamesarich added this pull request to the merge queue Dec 6, 2025
Merged via the queue into main with commit 499ed58 Dec 6, 2025
5 of 6 checks passed
@jamesarich jamesarich deleted the feat/usb-dfu branch December 6, 2025 12:49
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

enhancement New feature or request

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants