diff --git a/CHANGELOG.md b/CHANGELOG.md index 672e86f..655a228 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,5 +1,6 @@ #### 2.0.3 (2025-04-08) - adjust TrainingPeaks Virtual key mapping (#12) +- attempt to reconnect device if connection is lost #### 2.0.2 (2025-04-07) - fix bluetooth scan issues on older Android devices by asking for location permission diff --git a/lib/bluetooth/connection.dart b/lib/bluetooth/connection.dart index 0ff1e2a..46ff044 100644 --- a/lib/bluetooth/connection.dart +++ b/lib/bluetooth/connection.dart @@ -56,6 +56,7 @@ class Connection { Future performScanning() async { isScanning.value = true; + _actionStreams.add(LogNotification('Scanning for devices...')); // does not work on web, may not work on Windows if (!kIsWeb && !Platform.isWindows) { @@ -126,11 +127,21 @@ class Connection { final actionSubscription = bleDevice.actionStream.listen((data) { _actionStreams.add(data); }); - final connectionStateSubscription = UniversalBle.connectionStream(bleDevice.device.deviceId).listen(( - state, - ) async { + final connectionStateSubscription = UniversalBle.connectionStream(bleDevice.device.deviceId).listen((state) { bleDevice.isConnected = state.isConnected; _connectionStreams.add(bleDevice); + if (!bleDevice.isConnected) { + devices.remove(bleDevice); + _streamSubscriptions[bleDevice]?.cancel(); + _streamSubscriptions.remove(bleDevice); + _connectionSubscriptions[bleDevice]?.cancel(); + _connectionSubscriptions.remove(bleDevice); + _lastScanResult.clear(); + // try reconnect + if (!isScanning.value) { + performScanning(); + } + } }); _connectionSubscriptions[bleDevice] = connectionStateSubscription; diff --git a/lib/bluetooth/devices/base_device.dart b/lib/bluetooth/devices/base_device.dart index 46e71e0..4122cd4 100644 --- a/lib/bluetooth/devices/base_device.dart +++ b/lib/bluetooth/devices/base_device.dart @@ -241,12 +241,17 @@ abstract class BaseDevice { actionStreamInternal.add(LogNotification('Buttons released')); _longPressTimer?.cancel(); } else { - _longPressTimer?.cancel(); - _longPressTimer = Timer.periodic(const Duration(milliseconds: 250), (timer) async { - for (final action in buttonsClicked) { - actionStreamInternal.add(LogNotification(await actionHandler.performAction(action))); - } - }); + if (!(buttonsClicked.singleOrNull == ZwiftButton.onOffLeft || + buttonsClicked.singleOrNull == ZwiftButton.onOffRight)) { + // we don't want to trigger the long press timer for the on/off buttons + _longPressTimer?.cancel(); + _longPressTimer = Timer.periodic(const Duration(milliseconds: 250), (timer) async { + for (final action in buttonsClicked) { + actionStreamInternal.add(LogNotification(await actionHandler.performAction(action))); + } + }); + } + for (final action in buttonsClicked) { actionStreamInternal.add(LogNotification(await actionHandler.performAction(action))); }