From 9cfc62f5ca135b76dac3ddd9abe52b34222a2839 Mon Sep 17 00:00:00 2001 From: Aditya Gupta Date: Tue, 2 Jul 2024 10:59:16 +0100 Subject: [PATCH] chore: suggestions --- .../bluetooth/base_ble_state.dart | 62 +++++++++++++++++++ .../bluetooth/ble_state_interface.dart | 3 - .../bluetooth/completed_state.dart | 18 ++++++ .../bluetooth/completedstate.dart | 19 ------ .../bluetooth/connect_state.dart | 38 ++++++++++++ .../bluetooth/connectstate.dart | 53 ---------------- .../{scanstate.dart => scan_state.dart} | 48 +++++++------- .../{writestate.dart => write_state.dart} | 19 ++---- .../bletoast.dart => utils/toast_utils.dart} | 40 ++---------- lib/providers/badge_message_provider.dart | 32 ++++------ 10 files changed, 163 insertions(+), 169 deletions(-) create mode 100644 lib/bademagic_module/bluetooth/base_ble_state.dart delete mode 100644 lib/bademagic_module/bluetooth/ble_state_interface.dart create mode 100644 lib/bademagic_module/bluetooth/completed_state.dart delete mode 100644 lib/bademagic_module/bluetooth/completedstate.dart create mode 100644 lib/bademagic_module/bluetooth/connect_state.dart delete mode 100644 lib/bademagic_module/bluetooth/connectstate.dart rename lib/bademagic_module/bluetooth/{scanstate.dart => scan_state.dart} (52%) rename lib/bademagic_module/bluetooth/{writestate.dart => write_state.dart} (75%) rename lib/bademagic_module/{bluetooth/bletoast.dart => utils/toast_utils.dart} (50%) diff --git a/lib/bademagic_module/bluetooth/base_ble_state.dart b/lib/bademagic_module/bluetooth/base_ble_state.dart new file mode 100644 index 000000000..ea8160fe4 --- /dev/null +++ b/lib/bademagic_module/bluetooth/base_ble_state.dart @@ -0,0 +1,62 @@ +import 'package:badgemagic/bademagic_module/bluetooth/completed_state.dart'; +import 'package:badgemagic/bademagic_module/utils/toast_utils.dart'; +import 'package:logger/logger.dart'; + +abstract class BleState { + Future process(); +} + +abstract class NormalBleState extends BleState { + final logger = Logger(); + final toast = ToastUtils(); + + Future processState(); + + @override + Future process() async { + try { + return await processState(); + } on Exception catch (e) { + return CompletedState(isSuccess: false, message: e.toString()); + } + } +} + +abstract class RetryBleState extends BleState { + final logger = Logger(); + final toast = ToastUtils(); + + final _maxRetries = 3; + + Future processState(); + + @override + Future process() async { + int attempt = 0; + Exception? lastException; + + while (attempt < _maxRetries) { + try { + return await processState(); + } on Exception catch (e) { + logger.e(e); + lastException = e; + attempt++; + if (attempt < _maxRetries) { + logger.d("Retrying ($attempt/$_maxRetries)..."); + await Future.delayed( + const Duration(seconds: 2)); // Wait before retrying + } else { + logger.e("Max retries reached. Last exception: $lastException"); + lastException = + Exception("Max retries reached. Last exception: $lastException"); + } + } + } + + // After max retries, return a CompletedState indicating failure. + return CompletedState( + isSuccess: false, + message: lastException?.toString() ?? "Unknown error"); + } +} diff --git a/lib/bademagic_module/bluetooth/ble_state_interface.dart b/lib/bademagic_module/bluetooth/ble_state_interface.dart deleted file mode 100644 index 2580e3ac7..000000000 --- a/lib/bademagic_module/bluetooth/ble_state_interface.dart +++ /dev/null @@ -1,3 +0,0 @@ -abstract class BleState { - Future processState(); -} diff --git a/lib/bademagic_module/bluetooth/completed_state.dart b/lib/bademagic_module/bluetooth/completed_state.dart new file mode 100644 index 000000000..2e2df4084 --- /dev/null +++ b/lib/bademagic_module/bluetooth/completed_state.dart @@ -0,0 +1,18 @@ +import 'package:badgemagic/bademagic_module/bluetooth/base_ble_state.dart'; + +class CompletedState extends NormalBleState { + final bool isSuccess; + final String message; + + CompletedState({required this.isSuccess, required this.message}); + + @override + Future processState() async { + if (isSuccess) { + toast.showToast(message); + } else { + toast.showErrorToast(message); + } + return null; + } +} diff --git a/lib/bademagic_module/bluetooth/completedstate.dart b/lib/bademagic_module/bluetooth/completedstate.dart deleted file mode 100644 index 334d01651..000000000 --- a/lib/bademagic_module/bluetooth/completedstate.dart +++ /dev/null @@ -1,19 +0,0 @@ -import 'package:badgemagic/bademagic_module/bluetooth/ble_state_interface.dart'; -import 'package:badgemagic/bademagic_module/bluetooth/bletoast.dart'; - -class CompletedState implements BleState { - final bool isSuccess; - final String message; - BleStateToast toast = BleStateToast(); - - CompletedState({required this.isSuccess, required this.message}); - - @override - Future processState() async { - if (isSuccess) { - toast.successToast(message); - } - toast.failureToast(message); - return null; - } -} diff --git a/lib/bademagic_module/bluetooth/connect_state.dart b/lib/bademagic_module/bluetooth/connect_state.dart new file mode 100644 index 000000000..8aba00321 --- /dev/null +++ b/lib/bademagic_module/bluetooth/connect_state.dart @@ -0,0 +1,38 @@ +import 'package:badgemagic/bademagic_module/bluetooth/write_state.dart'; +import 'package:flutter_blue_plus/flutter_blue_plus.dart'; +import 'base_ble_state.dart'; + +class ConnectState extends RetryBleState { + final ScanResult scanResult; + + ConnectState({required this.scanResult}); + + @override + Future processState() async { + bool connected = false; + + try { + await scanResult.device.connect(autoConnect: false); + BluetoothConnectionState connectionState = + await scanResult.device.connectionState.first; + + if (connectionState == BluetoothConnectionState.connected) { + connected = true; + + logger.d("Device connected"); + toast.showToast('Device connected successfully.'); + + return WriteState(device: scanResult.device); + } else { + throw Exception("Failed to connect to the device"); + } + } catch (e) { + toast.showErrorToast('Failed to connect retry'); + rethrow; + } finally { + if (!connected) { + await scanResult.device.disconnect(); + } + } + } +} diff --git a/lib/bademagic_module/bluetooth/connectstate.dart b/lib/bademagic_module/bluetooth/connectstate.dart deleted file mode 100644 index a923bc9bd..000000000 --- a/lib/bademagic_module/bluetooth/connectstate.dart +++ /dev/null @@ -1,53 +0,0 @@ -import 'package:badgemagic/bademagic_module/bluetooth/writestate.dart'; -import 'package:flutter_blue_plus/flutter_blue_plus.dart'; -import 'package:logger/logger.dart'; -import 'ble_state_interface.dart'; -import 'bletoast.dart'; - -class ConnectState implements BleState { - final ScanResult scanResult; - final Logger logger = Logger(); - final int maxRetries = 3; - BleStateToast toast = BleStateToast(); - - ConnectState({required this.scanResult}); - - @override - Future processState() async { - int attempt = 0; - bool connected = false; - - while (attempt < maxRetries && !connected) { - try { - await scanResult.device.connect(autoConnect: false); - BluetoothConnectionState connectionState = - await scanResult.device.connectionState.first; - - if (connectionState == BluetoothConnectionState.connected) { - logger.d("Device connected"); - connected = true; - toast.successToast('Device connected successfully.'); - return WriteState(device: scanResult.device); - } else { - logger.e("Failed to connect to the device"); - } - } catch (e) { - logger.e("Connection error: $e"); - attempt++; - if (attempt < maxRetries) { - logger.d("Retrying connection ($attempt/$maxRetries)..."); - await Future.delayed( - const Duration(seconds: 2)); // Wait before retrying - } else { - logger.e("Max retries reached. Connection failed."); - toast.failureToast('Failed to connect retry'); - } - } finally { - if (!connected) { - await scanResult.device.disconnect(); - } - } - } - return null; - } -} diff --git a/lib/bademagic_module/bluetooth/scanstate.dart b/lib/bademagic_module/bluetooth/scan_state.dart similarity index 52% rename from lib/bademagic_module/bluetooth/scanstate.dart rename to lib/bademagic_module/bluetooth/scan_state.dart index 7240466af..9d9b91a9e 100644 --- a/lib/bademagic_module/bluetooth/scanstate.dart +++ b/lib/bademagic_module/bluetooth/scan_state.dart @@ -1,22 +1,18 @@ import 'dart:async'; -import 'package:badgemagic/bademagic_module/bluetooth/connectstate.dart'; +import 'package:badgemagic/bademagic_module/bluetooth/connect_state.dart'; import 'package:flutter_blue_plus/flutter_blue_plus.dart'; -import 'package:logger/logger.dart'; -import 'ble_state_interface.dart'; -import 'bletoast.dart'; - -class ScanState implements BleState { - ScanResult? foundDevice; - final Logger logger = Logger(); - BleStateToast toast = BleStateToast(); +import 'base_ble_state.dart'; +class ScanState extends NormalBleState { @override Future processState() async { StreamSubscription>? subscription; - toast.successToast("Searching for device..."); + toast.showToast("Searching for device..."); Completer nextStateCompleter = Completer(); + ScanResult? foundDevice; + try { subscription = FlutterBluePlus.scanResults.listen( (results) async { @@ -26,20 +22,22 @@ class ScanState implements BleState { .contains(Guid("0000fee0-0000-1000-8000-00805f9b34fb")), ); if (foundDevice != null) { - toast.successToast('Device found. Connecting...'); - if (!nextStateCompleter.isCompleted) { - nextStateCompleter - .complete(ConnectState(scanResult: foundDevice!)); - } + toast.showToast('Device found. Connecting...'); + nextStateCompleter + .complete(ConnectState(scanResult: foundDevice!)); + } else { + nextStateCompleter + .completeError(Exception('BLE LED Device not found.')); } + } else { + nextStateCompleter + .completeError(Exception('No BLE Devices not found.')); } }, onError: (e) async { logger.e("Scan error: $e"); - toast.failureToast('Scan error occurred.'); - if (!nextStateCompleter.isCompleted) { - nextStateCompleter.complete(null); - } + toast.showErrorToast('Scan error occurred.'); + nextStateCompleter.completeError(e); }, ); @@ -49,15 +47,13 @@ class ScanState implements BleState { ); await Future.delayed(const Duration(seconds: 6)); + + return await nextStateCompleter.future; + } catch (e) { + logger.e("Exception during scanning: $e"); + throw Exception("Exception during scanning: $e"); } finally { await subscription?.cancel(); } - - if (!nextStateCompleter.isCompleted) { - nextStateCompleter.complete( - foundDevice != null ? ConnectState(scanResult: foundDevice!) : null); - } - - return nextStateCompleter.future; } } diff --git a/lib/bademagic_module/bluetooth/writestate.dart b/lib/bademagic_module/bluetooth/write_state.dart similarity index 75% rename from lib/bademagic_module/bluetooth/writestate.dart rename to lib/bademagic_module/bluetooth/write_state.dart index 71cfa36f9..750f9b80c 100644 --- a/lib/bademagic_module/bluetooth/writestate.dart +++ b/lib/bademagic_module/bluetooth/write_state.dart @@ -1,20 +1,12 @@ import 'package:badgemagic/bademagic_module/bluetooth/datagenerator.dart'; -import 'package:badgemagic/providers/cardsprovider.dart'; import 'package:flutter_blue_plus/flutter_blue_plus.dart'; -import 'package:get_it/get_it.dart'; -import 'package:logger/logger.dart'; -import 'ble_state_interface.dart'; -import 'bletoast.dart'; -import 'completedstate.dart'; +import 'base_ble_state.dart'; +import 'completed_state.dart'; -class WriteState implements BleState { +class WriteState extends NormalBleState { final BluetoothDevice device; - final Logger logger = Logger(); - GetIt getIt = GetIt.instance; - final CardProvider cardData = GetIt.instance(); DataTransferManager manager = DataTransferManager(); - BleStateToast toast = BleStateToast(); WriteState({required this.device}); @@ -53,11 +45,10 @@ class WriteState implements BleState { } } } - return CompletedState( - isSuccess: false, message: "Please use the correct Badge"); + throw Exception("Please use the correct Badge"); } catch (e) { logger.e("Failed to write characteristic: $e"); + throw Exception("Failed to write characteristic: $e"); } - return null; } } diff --git a/lib/bademagic_module/bluetooth/bletoast.dart b/lib/bademagic_module/utils/toast_utils.dart similarity index 50% rename from lib/bademagic_module/bluetooth/bletoast.dart rename to lib/bademagic_module/utils/toast_utils.dart index 0759151ba..1926879f2 100644 --- a/lib/bademagic_module/bluetooth/bletoast.dart +++ b/lib/bademagic_module/utils/toast_utils.dart @@ -2,11 +2,11 @@ import 'package:badgemagic/providers/cardsprovider.dart'; import 'package:flutter/material.dart'; import 'package:get_it/get_it.dart'; -class BleStateToast { +class ToastUtils { CardProvider contextProvider = GetIt.instance(); - //create a toast message for success state of BLE - void successToast(String message) { + // Create a toast message + void showToast(String message) { ScaffoldMessenger.of(contextProvider.getContext()!).showSnackBar( SnackBar( margin: const EdgeInsets.symmetric(horizontal: 20, vertical: 10), @@ -38,36 +38,8 @@ class BleStateToast { ); } - //show toast for failure state of BLE - void failureToast(String message) { - ScaffoldMessenger.of(contextProvider.getContext()!).showSnackBar( - SnackBar( - margin: const EdgeInsets.symmetric(horizontal: 20, vertical: 10), - elevation: 10, - duration: const Duration(seconds: 1), - content: Row( - mainAxisAlignment: MainAxisAlignment.center, - children: [ - const Image( - image: AssetImage('assets/icons/icon.png'), - height: 20, - ), - const SizedBox( - width: 10, - ), - Text( - message, - style: const TextStyle(color: Colors.black), - ) - ], - ), - backgroundColor: Colors.white, - behavior: SnackBarBehavior.floating, - shape: RoundedRectangleBorder( - borderRadius: BorderRadius.circular(10), - ), - dismissDirection: DismissDirection.startToEnd, - ), - ); + // Create a error toast + void showErrorToast(String message) { + showToast('Error: $message'); } } diff --git a/lib/providers/badge_message_provider.dart b/lib/providers/badge_message_provider.dart index 3019dcaaf..cc6f1ce41 100644 --- a/lib/providers/badge_message_provider.dart +++ b/lib/providers/badge_message_provider.dart @@ -1,8 +1,7 @@ import 'dart:io'; -import 'package:badgemagic/bademagic_module/bluetooth/ble_state_interface.dart'; -import 'package:badgemagic/bademagic_module/bluetooth/bletoast.dart'; -import 'package:badgemagic/bademagic_module/bluetooth/completedstate.dart'; -import 'package:badgemagic/bademagic_module/bluetooth/scanstate.dart'; +import 'package:badgemagic/bademagic_module/bluetooth/base_ble_state.dart'; +import 'package:badgemagic/bademagic_module/utils/toast_utils.dart'; +import 'package:badgemagic/bademagic_module/bluetooth/scan_state.dart'; import 'package:badgemagic/bademagic_module/models/data.dart'; import 'package:badgemagic/bademagic_module/models/messages.dart'; import 'package:badgemagic/bademagic_module/models/mode.dart'; @@ -16,7 +15,7 @@ import 'package:logger/logger.dart'; class BadgeMessageProvider { static final Logger logger = Logger(); CardProvider cardData = GetIt.instance(); - BleStateToast toast = BleStateToast(); + ToastUtils toast = ToastUtils(); Map modeValueMap = { 0: Mode.left, @@ -59,30 +58,23 @@ class BadgeMessageProvider { Future transferData() async { DateTime now = DateTime.now(); - BleState state = ScanState(); - while (state is! CompletedState) { - BleState? nextState = await state.processState(); - if (nextState != null) { - state = nextState; - } else { - break; - } - } - if (state is CompletedState) { - await state.processState(); // Ensure the toast is shown + BleState? state = ScanState(); + while (state != null) { + state = await state.process(); } + logger.d("Time to transfer data is = ${DateTime.now().difference(now)}"); logger.d(".......Data transfer completed......."); } Future checkAndTransfer() async { if (await FlutterBluePlus.isSupported == false) { - toast.failureToast('Bluetooth is not supported by the device'); + toast.showErrorToast('Bluetooth is not supported by the device'); return; } if (cardData.getController().text.isEmpty) { - toast.failureToast("Please enter a message"); + toast.showErrorToast("Please enter a message"); return; } @@ -91,10 +83,10 @@ class BadgeMessageProvider { await transferData(); } else { if (Platform.isAndroid) { - toast.successToast('Turning on Bluetooth...'); + toast.showToast('Turning on Bluetooth...'); await FlutterBluePlus.turnOn(); } else if (Platform.isIOS) { - toast.successToast('Please turn on Bluetooth'); + toast.showToast('Please turn on Bluetooth'); } } }