summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--lib/control/universal_ble_scanner_controller.dart76
-rw-r--r--lib/model/device/universal_ble_device.dart17
2 files changed, 93 insertions, 0 deletions
diff --git a/lib/control/universal_ble_scanner_controller.dart b/lib/control/universal_ble_scanner_controller.dart
new file mode 100644
index 0000000..dd447bd
--- /dev/null
+++ b/lib/control/universal_ble_scanner_controller.dart
@@ -0,0 +1,76 @@
+import 'dart:async';
+
+import 'package:logger/logger.dart';
+import 'package:universal_ble/universal_ble.dart';
+import 'package:uvok_epaper_badge/control/scanner_controller.dart';
+import 'package:uvok_epaper_badge/control/scanner_controller_impl.dart';
+import 'package:uvok_epaper_badge/model/device/universal_ble_device.dart';
+
+Logger logger = Logger();
+
+class UniversalBleScannerController extends ScannerControllerImpl {
+ StreamSubscription<BleDevice>? _subscription;
+ final List<BleDevice> _devices = [];
+
+ UniversalBleScannerController() {
+ // fuck this limitation, I want an instance method to be called, which doesn't
+ // work in an initializer.
+ _subscription = UniversalBle.scanStream.listen(_newDeviceAction);
+ }
+
+ void _newDeviceAction(BleDevice dev) {
+ //logger.i("Found device: ${dev.toString()}");
+ bool added = _devices.addIf(dev, (exDev) => exDev.deviceId != dev.deviceId);
+ if (added) {
+ super.setDevices(
+ _devices
+ .map((d) => UniversalBleDevice.fromDevice(d))
+ .toList(growable: false),
+ );
+ }
+ }
+
+ @override
+ Future<void> startScan({
+ Duration timeout = const Duration(seconds: 5),
+ }) async {
+ AvailabilityState state =
+ await UniversalBle.getBluetoothAvailabilityState();
+ if (state != AvailabilityState.poweredOn) return;
+
+ _devices.clear();
+ super.setDevices([]);
+ super.setStatus(ScanStatus.scanning);
+
+ await UniversalBle.startScan();
+ await Future.delayed(timeout);
+ await UniversalBle.stopScan();
+ super.setStatus(ScanStatus.finished);
+
+ logger.i("Found ${_devices.length} devices");
+ }
+
+ @override
+ Future<void> stopScan() async {
+ await UniversalBle.stopScan();
+ }
+
+ @override
+ void dispose() {
+ super.dispose();
+ stopScan().ignore();
+ _subscription?.cancel();
+ }
+}
+
+extension ListAddExt<T> on List<T> {
+ /// An element if the predicate is true only for all elements.
+ /// predicate is passed all existing elements.
+ bool addIf(T dev, bool Function(T exDev) predicate) {
+ if (every(predicate)) {
+ add(dev);
+ return true;
+ }
+ return false;
+ }
+}
diff --git a/lib/model/device/universal_ble_device.dart b/lib/model/device/universal_ble_device.dart
new file mode 100644
index 0000000..cbd6f93
--- /dev/null
+++ b/lib/model/device/universal_ble_device.dart
@@ -0,0 +1,17 @@
+import 'package:universal_ble/universal_ble.dart';
+import 'package:uvok_epaper_badge/model/device/device.dart';
+
+class UniversalBleDevice implements Device {
+ final BleDevice device;
+
+ UniversalBleDevice.fromDevice(this.device);
+
+ @override
+ String? get address => device.deviceId;
+
+ @override
+ String? get name => device.name;
+
+ @override
+ int? get rssi => device.rssi;
+}