scanForFrame method

Future<void> scanForFrame()
inherited

Implementation

Future<void> scanForFrame() async {
  currentState = ApplicationState.scanning;
  if (mounted) setState(() {});

  // create a Future we can manually complete when Frame is found
  // or timeout occurred, but either way we can await scanForFrame synchronously
  final completer = Completer<void>();

  await BrilliantBluetooth.requestPermission();

  await _scanStream?.cancel();
  _scanStream = BrilliantBluetooth.scan().timeout(const Duration(seconds: 5),
      onTimeout: (sink) {
    // Scan timeouts can occur without having found a Frame, but also
    // after the Frame is found and being connected to, even though
    // the first step after finding the Frame is to stop the scan.
    // In those cases we don't want to change the application state back
    // to disconnected
    switch (currentState) {
      case ApplicationState.scanning:
        _log.fine('Scan timed out after 5 seconds');
        currentState = ApplicationState.disconnected;
        if (mounted) setState(() {});
        break;
      case ApplicationState.connecting:
        // found a device and started connecting, just let it play out
        break;
      case ApplicationState.connected:
      case ApplicationState.ready:
      case ApplicationState.running:
      case ApplicationState.starting:
      case ApplicationState.canceling:
        // already connected, nothing to do
        break;
      default:
        _log.fine('Unexpected state on scan timeout: $currentState');
        if (mounted) setState(() {});

      // signal that scanForFrame can now finish
      // if it hasn't already completed via the listen() path below
      if (!completer.isCompleted) {
        completer.complete();
      }
    }
  }).listen((device) async {
    _log.fine('Frame found, connecting');
    currentState = ApplicationState.connecting;
    if (mounted) setState(() {});

    await connectToScannedFrame(device);

    // signal that scanForFrame can now finish
    completer.complete();
  });

  // wait until the listen(onData) or the onTimeout is completed
  // so we can return synchronously
  await completer.future;
}