Skip to content

Commit

Permalink
imp: merged ios and macos to darwin, updated multi dfu support, updat…
Browse files Browse the repository at this point in the history
…ed dependencies, refactored classes
  • Loading branch information
juliansteenbakker committed Dec 18, 2024
1 parent 0ab32cb commit 6957a82
Show file tree
Hide file tree
Showing 33 changed files with 675 additions and 545 deletions.
10 changes: 8 additions & 2 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
@@ -1,5 +1,11 @@
## 6.2.1
* [Android] Updated Nordic DFU Library to version 2.7.0
## 7.0.0
* All callbacks in startDfu() have been moved to DfuEventHandler class.
* AndroidSpecialOption() and IosSpecialOption() have been deprecated in favor of AndroidOptions() and DarwinOptions().
*
* iOS and macOS implementation have been merged in one Darwin class.
* Added parallel DFU support (thanks @Flasher-MS !)
* [Android] Updated Nordic DFU Library to version 2.8.0
* [Darwin] Updated Nordic DFU Library to version 4.16.0

## 6.2.0
* [Android] Updated Nordic DFU Library to version 2.5.0
Expand Down
28 changes: 28 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -62,6 +62,34 @@ await NordicDfu().startDfu(
);
```

## Parallel DFU

Available from version 7.0.0

### Concurrent DFU Processes
- DFU operations can run simultaneously on multiple devices.
- Callbacks are triggered correctly and independently for each device.

### Interface change
- Updated `abortDfu` method to include an optional `address` parameter:
- **If an address is provided:** The DFU process for the specified device will be aborted. **(iOS only)**
- **If no address is provided:** All active DFU processes will be aborted.
- Added error handling for `abortDfu`:
- `FlutterError("INVALID_ADDRESS")` is thrown if the provided address does not match any active DFU process.
- `FlutterError("NO_ACTIVE_DFU")` is thrown if no address is provided and there are no active DFU processes.

### iOS
- ✅ Devices update in parallel.
- ✅ Callbacks set in `startDfu` are called independently for each device.
- ✅ All active DFU processes can be aborted using the `abortDfu` method without an `address`.
- ✅ DFU processes can be individually aborted using the `abortDfu` method with an `address`.

### Android
- ✅ Devices update in parallel (set limit of 8).
- ✅ Callbacks set in `startDfu` are called independently for each device.
- ✅ All active DFU processes can be aborted using the `abortDfu` method without an `address`.
- ❌ DFU processes cannot be individually aborted using the `abortDfu` method with an `address` due to current limitations in the underlying [Android-DFU-Library](https://github.com/NordicSemiconductor/Android-DFU-Library).

## Resources

- [DFU Introduction](https://infocenter.nordicsemi.com/topic/com.nordic.infocenter.sdk5.v11.0.0/examples_ble_dfu.html?cp=6_0_0_4_3_1 "BLE Bootloader/DFU")
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -28,7 +28,7 @@ private class DfuProcess(
val serviceClass: Class<out DfuBaseService>
)

private val DFU_SERVICE_CLASSES = arrayListOf<Class<out DfuBaseService>>(
private val DFU_SERVICE_CLASSES = arrayListOf(
DfuService::class.java,
DfuService2::class.java,
DfuService3::class.java,
Expand Down Expand Up @@ -77,10 +77,6 @@ class NordicDfuPlugin : FlutterPlugin, MethodCallHandler, EventChannel.StreamHan
}

override fun onListen(arguments: Any?, events: EventChannel.EventSink?) {
if (mContext != null) {
DfuServiceListenerHelper.registerProgressListener(mContext!!, mDfuProgressListener)
}

this.sink = events
}

Expand Down Expand Up @@ -234,6 +230,10 @@ class NordicDfuPlugin : FlutterPlugin, MethodCallHandler, EventChannel.StreamHan
starter.setRebootTime(rebootTime)
}

if (mContext != null) {
DfuServiceListenerHelper.registerProgressListener(mContext!!, mDfuProgressListener, address)
}

// fix notification on android 8 and above
if (startAsForegroundService == null || startAsForegroundService) {
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O && !hasCreateNotification) {
Expand Down
File renamed without changes.
File renamed without changes.
Original file line number Diff line number Diff line change
@@ -1,21 +1,33 @@
import Flutter
import UIKit
import NordicDFU
import CoreBluetooth

public class SwiftNordicDfuPlugin: NSObject, FlutterPlugin, FlutterStreamHandler, LoggerDelegate {
#if os(iOS)
import Flutter
import UIKit
#else
import AppKit
import FlutterMacOS
#endif

public class NordicDfuPlugin: NSObject, FlutterPlugin, FlutterStreamHandler, LoggerDelegate {

let registrar: FlutterPluginRegistrar
private var sink: FlutterEventSink?
private var activeDfuMap: [String: DfuProcess] = [:]

public static func register(with registrar: FlutterPluginRegistrar) {
let instance = SwiftNordicDfuPlugin(registrar)
let instance = NordicDfuPlugin(registrar)

#if os(iOS)
let messenger = registrar.messenger()
#else
let messenger = registrar.messenger
#endif

let method = FlutterMethodChannel(name: "dev.steenbakker.nordic_dfu/method", binaryMessenger: registrar.messenger())
let method = FlutterMethodChannel(name: "dev.steenbakker.nordic_dfu/method", binaryMessenger: messenger)

let event = FlutterEventChannel(name:
"dev.steenbakker.nordic_dfu/event", binaryMessenger: registrar.messenger())
"dev.steenbakker.nordic_dfu/event", binaryMessenger: messenger)

registrar.addMethodCallDelegate(instance, channel: method)
event.setStreamHandler(instance)
Expand Down Expand Up @@ -45,33 +57,28 @@ public class SwiftNordicDfuPlugin: NSObject, FlutterPlugin, FlutterStreamHandler
}

// Aborts ongoing DFU process(es)
//
// If `call.arguments["address"]` is `nil`, the method aborts all active DFU processes
// If `call.arguments["address"]` contains a specific address, the method aborts the DFU process for that address
// If `call.arguments["address"]` is nil, aborts all active DFU processes.
// If `call.arguments["address"]` contains an address, aborts the DFU process for that address.
private func abortDfu(_ call: FlutterMethodCall, _ result: @escaping FlutterResult) {
let arguments = call.arguments as? [String: Any]
let address = arguments?["address"] as? String

if address == nil {
guard let arguments = call.arguments as? [String: Any],
let address = arguments["address"] as? String else {
// Abort all DFU processes
if activeDfuMap.isEmpty {
result(FlutterError(code: "NO_ACTIVE_DFU", message: "No active DFU processes to abort", details: nil))
return
}
for (_, process) in activeDfuMap {
process.controller?.abort()
} else {
activeDfuMap.values.forEach { _ = $0.controller?.abort() } // Explicitly ignore result of `abort()`
result(nil)
}
result(nil)
return
}

// Abort DFU process for the specified address
guard let process = activeDfuMap[address!] else {
result(FlutterError(code: "INVALID_ADDRESS", message: "No DFU process found for address: \(address!).", details: nil))
guard let process = activeDfuMap[address] else {
result(FlutterError(code: "INVALID_ADDRESS", message: "No DFU process found for address: \(address).", details: nil))
return
}

process.controller?.abort()
_ = process.controller?.abort() // Explicitly ignore result of `abort()`
result(nil)
}

Expand Down Expand Up @@ -229,7 +236,7 @@ private class DfuProcess {
deviceAddress: String,
firmware: DFUFirmware,
uuid: UUID,
delegate: SwiftNordicDfuPlugin,
delegate: NordicDfuPlugin,
result: @escaping FlutterResult,
options: DfuOptions
) {
Expand All @@ -254,10 +261,10 @@ private class DfuProcess {

// Handles DFU service and progress updates for a specific device
public class DeviceScopedDFUDelegate: NSObject, DFUServiceDelegate, DFUProgressDelegate {
private let originalDelegate: SwiftNordicDfuPlugin
private let originalDelegate: NordicDfuPlugin
private let deviceAddress: String

init(delegate: SwiftNordicDfuPlugin, deviceAddress: String) {
init(delegate: NordicDfuPlugin, deviceAddress: String) {
self.originalDelegate = delegate
self.deviceAddress = deviceAddress
}
Expand Down
12 changes: 7 additions & 5 deletions ios/nordic_dfu.podspec → darwin/nordic_dfu.podspec
Original file line number Diff line number Diff line change
Expand Up @@ -3,8 +3,8 @@
#
Pod::Spec.new do |s|
s.name = 'nordic_dfu'
s.version = '1.0.0'
s.summary = 'iOS DFU plugin for flutter.'
s.version = '2.0.0'
s.summary = 'DFU plugin for flutter.'
s.description = <<-DESC
A new flutter plugin project.
DESC
Expand All @@ -15,8 +15,10 @@ A new flutter plugin project.
s.source_files = 'Classes/**/*'
s.public_header_files = 'Classes/**/*.h'
s.swift_version = '5.4'
s.dependency 'Flutter'
s.dependency 'iOSDFULibrary', '~> 4.15.3'
s.ios.deployment_target = '9.0'
s.dependency 'NordicDFU', '~> 4.16.0'
s.ios.dependency 'Flutter'
s.osx.dependency 'FlutterMacOS'
s.ios.deployment_target = '11.0'
s.osx.deployment_target = '10.14'
end

6 changes: 5 additions & 1 deletion example/analysis_options.yaml
Original file line number Diff line number Diff line change
@@ -1 +1,5 @@
include: package:lint/strict.yaml
include: package:very_good_analysis/analysis_options.yaml
analyzer:
errors:
lines_longer_than_80_chars: ignore
public_member_api_docs: ignore
2 changes: 1 addition & 1 deletion example/android/build.gradle
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,7 @@ buildscript {
}

dependencies {
classpath 'com.android.tools.build:gradle:8.1.2'
classpath 'com.android.tools.build:gradle:8.7.3'
classpath "org.jetbrains.kotlin:kotlin-gradle-plugin:$kotlin_version"
}
}
Expand Down
2 changes: 1 addition & 1 deletion example/android/gradle/wrapper/gradle-wrapper.properties
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
#Tue Oct 10 12:30:18 CEST 2023
distributionBase=GRADLE_USER_HOME
distributionPath=wrapper/dists
distributionUrl=https\://services.gradle.org/distributions/gradle-8.4-bin.zip
distributionUrl=https\://services.gradle.org/distributions/gradle-8.9-bin.zip
zipStoreBase=GRADLE_USER_HOME
zipStorePath=wrapper/dists
2 changes: 1 addition & 1 deletion example/ios/Flutter/AppFrameworkInfo.plist
Original file line number Diff line number Diff line change
Expand Up @@ -21,6 +21,6 @@
<key>CFBundleVersion</key>
<string>1.0</string>
<key>MinimumOSVersion</key>
<string>11.0</string>
<string>12.0</string>
</dict>
</plist>
2 changes: 1 addition & 1 deletion example/ios/Podfile
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
# Uncomment this line to define a global platform for your project
platform :ios, '11.0'
platform :ios, '12.0'

# CocoaPods analytics sends network stats synchronously affecting flutter build latency.
ENV['COCOAPODS_DISABLE_STATS'] = 'true'
Expand Down
Loading

0 comments on commit 6957a82

Please sign in to comment.