summaryrefslogtreecommitdiff
path: root/lib
diff options
context:
space:
mode:
authoruvok2025-07-30 13:14:38 +0200
committeruvok2025-07-30 13:14:38 +0200
commit4311e39e65de3ed10f145e556085e7fb238e6e60 (patch)
tree1073ff3a3cdd561087bc4d5b7620e49183741a1f /lib
parent9536bfa04db171aee987f042dccc4c2f16fa0f29 (diff)
Add implementations of BLE controller
q&d
Diffstat (limited to 'lib')
-rw-r--r--lib/control/flutter_blue_plus_scanner_controller.dart44
-rw-r--r--lib/first_where_ext.dart9
-rw-r--r--lib/model/flutter_blue_plus_device.dart30
3 files changed, 83 insertions, 0 deletions
diff --git a/lib/control/flutter_blue_plus_scanner_controller.dart b/lib/control/flutter_blue_plus_scanner_controller.dart
new file mode 100644
index 0000000..b6f9dfc
--- /dev/null
+++ b/lib/control/flutter_blue_plus_scanner_controller.dart
@@ -0,0 +1,44 @@
+import 'dart:async';
+import 'package:badge/control/scanner_controller_impl.dart';
+import 'package:badge/model/flutter_blue_plus_device.dart';
+import 'package:badge/model/device.dart';
+import 'package:badge/control/scanner_controller.dart';
+import 'package:flutter_blue_plus/flutter_blue_plus.dart';
+
+class FlutterBluePlusScannerController extends ScannerControllerImpl {
+ final StreamController<List<Device>> _scanResultsController =
+ StreamController<List<Device>>.broadcast();
+
+ @override
+ Stream<List<Device>> get scanResultsStream => _scanResultsController.stream;
+
+ @override
+ Future<void> startScan({
+ Duration timeout = const Duration(seconds: 5),
+ }) async {
+ stopScan();
+ super.setStatus(ScanStatus.scanning);
+
+ var subscription = FlutterBluePlus.scanResults.listen((results) {
+ List<Device> devices = results
+ .map((d) => FlutterBluePlusDevice.fromScan(d))
+ .toList();
+ _scanResultsController.add(devices);
+ });
+ // either this, or the cancel in the finally block, should do the same?
+ FlutterBluePlus.cancelWhenScanComplete(subscription);
+ await FlutterBluePlus.startScan(timeout: Duration(seconds: 5));
+ await FlutterBluePlus.isScanning.where((val) => val == false).first;
+ }
+
+ @override
+ Future<void> stopScan() async {
+ await FlutterBluePlus.stopScan();
+ }
+
+ @override
+ void dispose() {
+ stopScan().ignore();
+ _scanResultsController.close();
+ }
+}
diff --git a/lib/first_where_ext.dart b/lib/first_where_ext.dart
new file mode 100644
index 0000000..7e297ff
--- /dev/null
+++ b/lib/first_where_ext.dart
@@ -0,0 +1,9 @@
+extension FirstWhereExt<T> on List<T> {
+ /// The first element satisfying [test], or `null` if there are none.
+ T? firstWhereOrNull(bool Function(T element) test) {
+ for (final element in this) {
+ if (test(element)) return element;
+ }
+ return null;
+ }
+}
diff --git a/lib/model/flutter_blue_plus_device.dart b/lib/model/flutter_blue_plus_device.dart
new file mode 100644
index 0000000..8a3619b
--- /dev/null
+++ b/lib/model/flutter_blue_plus_device.dart
@@ -0,0 +1,30 @@
+import 'package:badge/model/device.dart';
+import 'package:flutter_blue_plus/flutter_blue_plus.dart';
+
+class FlutterBluePlusDevice implements Device {
+ final ScanResult scanResult;
+
+ @override
+ String? get address => scanResult.device.remoteId.str;
+
+ @override
+ String? get name => firstGiven([
+ scanResult.device.advName,
+ scanResult.device.platformName,
+ "<Unknown>",
+ ]);
+
+ @override
+ int? get rssi => scanResult.rssi;
+
+ FlutterBluePlusDevice._(this.scanResult);
+
+ static FlutterBluePlusDevice fromScan(ScanResult scanResult) {
+ var bleDevice = FlutterBluePlusDevice._(scanResult);
+ return bleDevice;
+ }
+}
+
+String firstGiven(List<String> list) {
+ return list.firstWhere((s) => s.isNotEmpty, orElse: () => "");
+}