From 7868b255f4bc29ccf595e8c59195438cc08d0773 Mon Sep 17 00:00:00 2001 From: Oliver Bagge Date: Fri, 2 Jan 2026 16:40:33 +0100 Subject: [PATCH] update device connection exceptions --- example/lib/main.dart | 31 +++++++++++++++++++++--- example/pubspec.lock | 24 ++++++++++++------ example/pubspec.yaml | 1 + lib/open_earable_flutter.dart | 26 ++++++++++++++++---- lib/src/exceptions/device_exception.dart | 15 ++++++++++++ 5 files changed, 80 insertions(+), 17 deletions(-) create mode 100644 lib/src/exceptions/device_exception.dart diff --git a/example/lib/main.dart b/example/lib/main.dart index fc19a96..d33bf6b 100644 --- a/example/lib/main.dart +++ b/example/lib/main.dart @@ -2,6 +2,7 @@ import 'dart:async'; import 'package:example/widgets/button_state_widget.dart'; import 'package:example/widgets/fota/firmware_update.dart'; +import 'package:flutter_platform_widgets/flutter_platform_widgets.dart'; import 'package:open_earable_flutter/open_earable_flutter.dart'; import 'package:example/global_theme.dart'; import 'package:flutter/material.dart'; @@ -152,9 +153,30 @@ class MyAppState extends State { trailing: _buildTrailingWidget(device.id, Theme.of(context).colorScheme.secondary), onTap: () async { - Wearable wearable = await _wearableManager - .connectToDevice(device); - provider.setSelectedPeripheral(wearable); + try { + Wearable wearable = await _wearableManager + .connectToDevice(device); + provider.setSelectedPeripheral(wearable); + } catch (e) { + String message = _wearableManager + .deviceErrorMessage(e, device.name); + if (context.mounted) { + showPlatformDialog( + context: context, + builder: (context) => PlatformAlertDialog( + title: PlatformText('Connection Error'), + content: PlatformText(message), + actions: [ + PlatformDialogAction( + onPressed: () => + Navigator.of(context).pop(), + child: PlatformText('OK'), + ), + ], + ), + ); + } + } }, ), if (index != discoveredDevices.length - 1) @@ -246,7 +268,8 @@ class MyAppState extends State { if (_connectedDevice is ButtonManager) GroupedBox( title: "Button State", - child: ButtonStateWidget(buttonManager: _connectedDevice as ButtonManager), + child: ButtonStateWidget( + buttonManager: _connectedDevice as ButtonManager), ), if (_connectedDevice is FrequencyPlayer) GroupedBox( diff --git a/example/pubspec.lock b/example/pubspec.lock index dc169aa..231d77d 100644 --- a/example/pubspec.lock +++ b/example/pubspec.lock @@ -45,10 +45,10 @@ packages: dependency: transitive description: name: characters - sha256: f71061c654a3380576a52b451dd5532377954cf9dbd272a78fc8479606670803 + sha256: faf38497bda5ead2a8c7615f4f7939df04333478bf32e4173fcb06d428b5716b url: "https://pub.dev" source: hosted - version: "1.4.0" + version: "1.4.1" clock: dependency: transitive description: @@ -182,6 +182,14 @@ packages: url: "https://pub.dev" source: hosted version: "6.0.0" + flutter_platform_widgets: + dependency: "direct main" + description: + name: flutter_platform_widgets + sha256: "22a86564cb6cc0b93637c813ca91b0b1f61c2681a31e0f9d77590c1fa9f12020" + url: "https://pub.dev" + source: hosted + version: "9.0.0" flutter_plugin_android_lifecycle: dependency: transitive description: @@ -292,18 +300,18 @@ packages: dependency: transitive description: name: matcher - sha256: dc58c723c3c24bf8d3e2d3ad3f2f9d7bd9cf43ec6feaa64181775e60190153f2 + sha256: "12956d0ad8390bbcc63ca2e1469c0619946ccb52809807067a7020d57e647aa6" url: "https://pub.dev" source: hosted - version: "0.12.17" + version: "0.12.18" material_color_utilities: dependency: transitive description: name: material_color_utilities - sha256: f7142bb1154231d7ea5f96bc7bde4bda2a0945d2806bb11670e30b850d56bdec + sha256: "9c337007e82b1889149c82ed242ed1cb24a66044e30979c44912381e9be4c48b" url: "https://pub.dev" source: hosted - version: "0.11.1" + version: "0.13.0" mcumgr_flutter: dependency: "direct main" description: @@ -560,10 +568,10 @@ packages: dependency: transitive description: name: test_api - sha256: ab2726c1a94d3176a45960b6234466ec367179b87dd74f1611adb1f3b5fb9d55 + sha256: "19a78f63e83d3a61f00826d09bc2f60e191bf3504183c001262be6ac75589fb8" url: "https://pub.dev" source: hosted - version: "0.7.7" + version: "0.7.8" tuple: dependency: transitive description: diff --git a/example/pubspec.yaml b/example/pubspec.yaml index a3e5773..2f208cc 100644 --- a/example/pubspec.yaml +++ b/example/pubspec.yaml @@ -42,6 +42,7 @@ dependencies: # Use with the CupertinoIcons class for iOS style icons. cupertino_icons: ^1.0.2 flutter_colorpicker: ^1.1.0 + flutter_platform_widgets: ^9.0.0 meta: ^1.16.0 bloc: ^9.1.0 flutter_svg: ^2.0.17 diff --git a/lib/open_earable_flutter.dart b/lib/open_earable_flutter.dart index 48bb10f..b357438 100644 --- a/lib/open_earable_flutter.dart +++ b/lib/open_earable_flutter.dart @@ -4,6 +4,7 @@ import 'dart:async'; import 'package:logger/logger.dart'; import 'package:meta/meta.dart'; +import 'package:open_earable_flutter/src/exceptions/device_exception.dart'; import 'package:open_earable_flutter/src/models/devices/cosinuss_one_factory.dart'; import 'package:open_earable_flutter/src/models/devices/esense_factory.dart'; import 'package:open_earable_flutter/src/models/devices/open_earable_factory.dart'; @@ -193,7 +194,7 @@ class WearableManager { }) async { if (_connectedIds.contains(device.id)) { logger.w('Device ${device.id} is already connected'); - throw Exception('Device is already connected'); + throw AlreadyConnectedException(); } _connectingStreamController.add(device); @@ -226,9 +227,9 @@ class WearableManager { } _connectedIds.remove(device.id); await _bleManager.disconnect(device.id); - throw Exception('Device is currently not supported'); + throw UnsupportedDeviceException(); } else { - throw Exception('Failed to connect to device'); + throw ConnectionFailedException(); } } @@ -252,12 +253,25 @@ class WearableManager { ); connectedWearables.add(wearable); } catch (e) { - logger.e('Failed to connect to system device ${device.id}: $e'); + logger.e( + 'Failed to connect to system device ${device.id}: ${deviceErrorMessage(e, device.name)}', + ); } } return connectedWearables; } + String deviceErrorMessage(dynamic e, String deviceName) { + return switch (e) { + UnsupportedDeviceException _ => 'Device "$deviceName" is not supported.', + AlreadyConnectedException _ => + 'Device "$deviceName" is already connected.', + ConnectionFailedException _ => + 'Failed to connect to device "$deviceName". Please try again.', + _ => e.toString(), + }; + } + void addPairingRule(PairingRule rule) { _pairingManager.addRule(rule); } @@ -292,7 +306,9 @@ class WearableManager { try { await connectToDevice(discoveredDevice); } catch (e) { - logger.e('Error auto connecting device ${discoveredDevice.id}: $e'); + logger.e( + 'Error auto connecting device ${discoveredDevice.id}: ${deviceErrorMessage(e, discoveredDevice.name)}', + ); } } }); diff --git a/lib/src/exceptions/device_exception.dart b/lib/src/exceptions/device_exception.dart new file mode 100644 index 0000000..f409352 --- /dev/null +++ b/lib/src/exceptions/device_exception.dart @@ -0,0 +1,15 @@ +sealed class DeviceException implements Exception { + const DeviceException(); +} + +class UnsupportedDeviceException extends DeviceException { + const UnsupportedDeviceException(); +} + +class AlreadyConnectedException extends DeviceException { + const AlreadyConnectedException(); +} + +class ConnectionFailedException extends DeviceException { + const ConnectionFailedException(); +}