unicloudvn / esp_provisioning

Flutter Provisioning library for ESP-IDF ESP32 Unified provisioning
https://unicloudgroup.dev
Apache License 2.0
65 stars 52 forks source link

Please remove the hardcoded MTU #12

Open momo1 opened 3 years ago

momo1 commented 3 years ago

In TransportBle I recommend removing the hardcoded MTU await peripheral.connect(requestMtu: 512); or allowing the user to pass in a value. This higher value breaks certain BLE stacks on some phones like Samsung.

My current workaround is to connect to the device myself to short circuit TransportBle.connect() which is called by EspProv.establishSesision()

Thanks

KOYAMANI commented 3 years ago

Are you able to find wifi list with this example ?

momo1 commented 3 years ago

If you're asking if I used the author's example code then no, I didn't. If you're asking did that fix my problem then yes. The phone was terminating the BLE connection to ESP without any meaningful error message. Also, I could only get it to work by explicitly setting Bluetooth to BLE only using Nimble in menuconfig.

KOYAMANI commented 3 years ago

Is it possible to see your code or know which line did you fix to make wifi function work ? I've been stuck almost for month.

momo1 commented 3 years ago

I didn't change anything in their code. I worked around it by making their code take a different path. Here's some code to help you understand.

  Future connectToDevice(String deviceId, String pop, {int timeoutSeconds = 3600}) async {
    if (_peripheral != null && await _peripheral.isConnected()) await _peripheral.disconnectOrCancelConnection();
    _peripheral = await bleConnector.find(deviceId, timeoutSeconds: timeoutSeconds);
    final serviceUuid = await bleConnector.discoverServiceUuid(_peripheral);
    /*
     * Make sure peripheral is connected first to avoid the hardcoded MTU in the 3p lib
     * which breaks Samsung
     */
    final ble = new TransportBLE(_peripheral, serviceUUID: serviceUuid);
    final security = Security1(pop: pop);
    _espProvisioner = EspProv(transport: ble, security: security);
    await _espProvisioner.establishSession();
  }
  Future<Peripheral> find(String deviceId, {int timeoutSeconds = 30}) async {
    _log.info('Connecting to $deviceId...');
    final completer = Completer<Peripheral>();
    Future<Peripheral> retvalFuture = completer.future
        .timeout(Duration(seconds: timeoutSeconds))
        .whenComplete(() => _bleManager.stopPeripheralScan());

    await waitForBluetoothPoweredOn();
    _bleManager.startPeripheralScan().listen((scanResult) async {
      try {
        if (scanResult.peripheral.name == deviceId && !completer.isCompleted) {
          _log.info('Found device: ${scanResult.peripheral}');
          completer.complete(scanResult.peripheral);
        }
      } catch (e) {
        completer.completeError(e);
      }
    });

    return retvalFuture;
  }
  Future<String> discoverServiceUuid(Peripheral peripheral) async {
    for (var retry = 0; retry < 3; retry++) {
      _log.info('Discovering ESP Prov BLE service...');
      try {
        /*
         * !!! DO NOT TOUCH MTU !!!!!
         * iOS will just use 186 regardless
         * Samsung will break on anything larger
         * No negotiation makes transfer very slow
         */
        if (!await peripheral.isConnected()) await peripheral.connect(requestMtu: 186);
        await peripheral.discoverAllServicesAndCharacteristics();
        final services = await peripheral.services();
        for (var service in services) {
          final chars = await service.characteristics();
          for (var char in chars) {
            final descriptors = await char.descriptors();
            for (var desc in descriptors) {
              final metadata = String.fromCharCodes(await desc.read());
              if (metadata == 'proto-ver') return service.uuid;
            }
          }
        }
      } on Error {} catch (e) {}
      _log.warning('Could not find ESP Prov service. Retrying...');
      try {
        if (await peripheral.isConnected()) await peripheral.disconnectOrCancelConnection();
      } on Error {} catch (e) {
        _log.warning('Could not disconnect from device.');
      }
      await Future.delayed(Duration(seconds: 5));
    }

    throw Exception('Could not find ESP Prov service.');
  }