fengqiangboy / flutter-nordic-dfu

Flutter Nordic dfu
MIT License
109 stars 76 forks source link

Buttonless DFU not working on iOS #3

Closed jthansen closed 5 years ago

jthansen commented 5 years ago

I am unable to get DFU to work with iOS. I believe it has to deal with the device id being different in iOS with Flutter Blue. Since iOS creates their own UUID instead of using the MAC address like Android.

fengqiangboy commented 5 years ago

Did NRFConnect worked?

jthansen commented 5 years ago

Yeah, that works on iOS. Is there something I need to add with iOS as opposed to Android?

This code works with Android and then with iOS I get a PlatformException thrown.

Future<bool> performDfu() async {
    dfuRunning = true;
    try {
      var s = await FlutterNordicDfu.startDfu(device.id.id,'assets/file.zip',
        fileInAsset: true,
        enableUnsafeExperimentalButtonlessServiceInSecureDfu: true,
        progressListener:
        DefaultDfuProgressListenerAdapter(onProgressChangedHandle: (
            deviceAddress,
            percent,
            speed,
            avgSpeed,
            currentPart,
            partsTotal,
            ) {
          print('deviceAddress: $deviceAddress, percent: $percent');
        }),
      );
      print(s);
      dfuRunning = false;
      return true; 
    } catch (e) {
      dfuRunning = false;
      print(e);
      return false;
    }
  }
fengqiangboy commented 5 years ago

Can you paste more log that console print?

jthansen commented 5 years ago
[VERBOSE-2:ui_dart_state.cc(148)] Unhandled Exception: PlatformException(DFU_FAILED, Device address: 502CCB90-5B67-4287-3C7F-A17AD3124958, null)
#0      StandardMethodCodec.decodeEnvelope (package:flutter/src/services/message_codecs.dart:564:7)
#1      MethodChannel.invokeMethod (package:flutter/src/services/platform_channel.dart:302:33)
<asynchronous suspension>
#2      FlutterNordicDfu.startDfu (package:flutter_nordic_dfu/flutter_nordic_dfu.dart:141:27)
<asynchronous suspension>
#3      _x.performDfu (package:xxx/widgets/x.dart:1137:38)
<asynchronous suspension>
#4      System._updateFirmwareTapped.<anonymous closure> (package:xxx/screens/more/settings/system.dart:57:18)
#5      _InkResponseState._handleTap (package:flutter/src/material/ink_well.dart:511:14)
#6      _InkResponseState.build.<anonymous closure> (package:flutter/src/material/ink_well.dart:566:30)
#7      GestureRecognizer.invokeCallback (package:flutter/src/gestures/recognizer.dart:166:24)
#8      TapGestureRecognizer._checkUp (package:flutter/src/gestures/tap.dart:240:9)
#9      TapGestureRecognizer.acceptGesture (package:flutter/src/gestures/tap.dart:211:7)
#10     GestureArenaManager.sweep (package:flutter/src/gestures/arena.dart:156:27)
#11     _WidgetsFlutterBinding&BindingBase&GestureBinding.handleEvent (package:flutter/src/gestures/binding.dart:225:20)
#12     _WidgetsFlutterBinding&BindingBase&GestureBinding.dispatchEvent (package:flutter/src/gestures/binding.dart:199:22)
#13     _WidgetsFlutterBinding&BindingBase&GestureBinding._handlePointerEvent (package:flutter/src/gestures/binding.dart:156:7)
#14     _WidgetsFlutterBinding&BindingBase&GestureBinding._flushPointerEventQueue (package:flutter/src/gestures/binding.dart:102:7)
#15     _WidgetsFlutterBinding&BindingBase&GestureBinding._handlePointerDataPacket (package:flutter/src/gestures/binding.dart:86:7)
#16     _rootRunUnary (dart:async/zone.dart:1136:13)
#17     _CustomZone.runUnary (dart:async/zone.dart:1029:19)
#18     _CustomZone.runUnaryGuarded (dart:async/zone.dart:931:7)
#19     _invoke1 (dart:ui/hooks.dart:233:10)
#20     _dispatchPointerDataPacket (dart:ui/hooks.dart:154:5)
fengqiangboy commented 5 years ago

Sorry, I can't find the problem by this log message, can you try to use IOS-Pods-DFU-Library? And tell me the right code, I will compare them with my DFU platform code. Thx~

jthansen commented 5 years ago

I got the iOS DFU library to work with this code, nRF Toolbox Repo. I had to change: @objc public var alternativeAdvertisingNameEnabled from true to false. I tried changing that property in your plugin but it still didn't work. Are you calling the DFU initiator differently? They have this for their DFU function:

func performDFU() {
        self.disableOtherButtons()
        progress.isHidden = false
        progressLabel.text = nil
        progressLabel.isHidden = false
        uploadStatus.isHidden = false
        uploadButton.isEnabled = false

        self.registerObservers()

        // To start the DFU operation the DFUServiceInitiator must be used
        let initiator = DFUServiceInitiator(centralManager: centralManager!, target: selectedPeripheral!)
        initiator.forceDfu = UserDefaults.standard.bool(forKey: "dfu_force_dfu")
        initiator.packetReceiptNotificationParameter = UInt16(UserDefaults.standard.integer(forKey: "dfu_number_of_packets"))
        initiator.logger = self
        initiator.delegate = self
        initiator.progressDelegate = self
        initiator.enableUnsafeExperimentalButtonlessServiceInSecureDfu = true
        dfuController = initiator.with(firmware: selectedFirmware!).start()
        uploadButton.setTitle("Cancel", for: UIControlState())
        uploadButton.isEnabled = true
    }

Have you accomplished buttonless DFU with this plugin yet?

fengqiangboy commented 5 years ago

Yes, we use dfuInitiator.start(targetWithIdentifier: uuid) to start dfu

jthansen commented 5 years ago

It's working today with a different unit. So I'm not sure what was all wrong.