From a94649aa974298538b3d9ecf0028f68ae5bdca4e Mon Sep 17 00:00:00 2001 From: uvok Date: Tue, 22 Jul 2025 09:44:17 +0200 Subject: Polish scanning and connecting scan timeout. state cleanup. Use platformname --- lib/device.dart | 46 ++++++++++++++++++++++++++++++++++++++++------ lib/main.dart | 44 +++++++++++++++++++++++++++++++------------- 2 files changed, 71 insertions(+), 19 deletions(-) (limited to 'lib') diff --git a/lib/device.dart b/lib/device.dart index eb863ad..94b2899 100644 --- a/lib/device.dart +++ b/lib/device.dart @@ -1,3 +1,5 @@ +import 'dart:async'; + import 'package:flutter/material.dart'; import 'package:flutter_blue_plus/flutter_blue_plus.dart'; import 'package:logger/logger.dart'; @@ -26,13 +28,26 @@ class DeviceScreen extends StatefulWidget { } class DeviceState extends State { + String connectStatus = ""; + // ??? + StreamSubscription subs = + Stream.empty().listen((e) => ()); + bool backActive = false; + @override Widget build(BuildContext context) { return Scaffold( appBar: AppBar(title: Text("Device details")), body: Center( child: Column( - children: [ElevatedButton(onPressed: backClick, child: Text("Back"))], + spacing: 20, + children: [ + Text(connectStatus), + ElevatedButton( + onPressed: backActive ? backClick : null, + child: Text("Back"), + ), + ], ), ), ); @@ -49,20 +64,39 @@ class DeviceState extends State { } void onConnStateChange(BluetoothConnectionState event) { + setState(() { + connectStatus = event.toString(); + }); logger.i("New conn state: ${event.toString()}"); } + @override + void deactivate() { + super.deactivate(); + logger.i("Closing state"); + subs.cancel().ignore(); + widget.btDevice.disconnect().ignore(); + } + void _doConnect() async { final dev = widget.btDevice; - var subs = dev.connectionState.listen(onConnStateChange); + subs.cancel().ignore(); + subs = dev.connectionState.listen(onConnStateChange); try { logger.i("Try to connect..."); - await dev.connect(); + // connect timeout doesn't work under Linux + await dev.connect().timeout(Duration(seconds: 1)); logger.i("Connected!"); - await dev.disconnect(); - logger.i("Disonnected!"); + + connectStatus = "Connected"; + } catch (e) { + dev.disconnect().ignore(); + connectStatus = e.toString(); } finally { - subs.cancel(); + backActive = true; + if (mounted) { + setState(() {}); + } } } } diff --git a/lib/main.dart b/lib/main.dart index aef85cf..23721ac 100644 --- a/lib/main.dart +++ b/lib/main.dart @@ -80,6 +80,14 @@ class _MyHomePageState extends State { } void _doScan() async { + var system = await FlutterBluePlus.systemDevices([]); + for (var d in system) { + logger.i('${d.platformName} already connected to! ${d.remoteId}'); + // if (d.platformName == "myBleDevice") { + // await r.connect(); // must connect our app + // } + } + setState(() { scanResults.clear(); isScanning = true; @@ -95,14 +103,14 @@ class _MyHomePageState extends State { if (Platform.isAndroid) { await FlutterBluePlus.startScan( withKeywords: ["NimBLE"], - timeout: Duration(seconds: 3), + timeout: Duration(seconds: 5), ); } else { // for Linux, which can't do advNames // msd doesn't work, either???? await FlutterBluePlus.startScan( - withMsd: [MsdFilter(0xffff, data: ascii.encode("uvok"))], - timeout: Duration(seconds: 3), + //withMsd: [MsdFilter(0xffff, data: ascii.encode("uvok"))], + timeout: Duration(seconds: 5), ); } @@ -116,15 +124,16 @@ class _MyHomePageState extends State { } } - void onScanResult(results) { + void onScanResult(List results) { if (results.isNotEmpty) { - ScanResult r = results.last; // the most recently found device - logger.i( - '${r.device.remoteId}: "${r.device.advName}" / "${r.advertisementData.advName}" found!', - ); - setState(() { + //ScanResult r = results.last; // the most recently found device + for (var r in results.where((d) => d.rssi > -90)) { + logger.i( + '${r.device.remoteId}: "${r.device.platformName}" / "${r.device.advName}" / "${r.advertisementData.advName}" found!', + ); scanResults.add(r); - }); + } + setState(() {}); } } @@ -189,7 +198,9 @@ class _MyHomePageState extends State { // action in the IDE, or press "p" in the console), to see the // wireframe for each widget. mainAxisAlignment: MainAxisAlignment.center, + spacing: 24, children: [ + SizedBox(height: 15), Row( mainAxisAlignment: MainAxisAlignment.center, spacing: 15.0, @@ -212,9 +223,12 @@ class _MyHomePageState extends State { itemBuilder: (context, index) { if (index >= scanResults.length) return null; final ScanResult result = scanResults[index]; - final String name = result.device.advName.isEmpty - ? ("") - : (result.device.advName); + final String name = firstGiven([ + result.device.advName, + result.device.platformName, + "", + ]); + return ListTile( title: Text(name), subtitle: Text(result.device.remoteId.str), @@ -241,3 +255,7 @@ class _MyHomePageState extends State { ); } } + +String firstGiven(List list) { + return list.firstWhere((s) => s.isNotEmpty, orElse: () => ""); +} -- cgit v1.2.3