feat: redesign and lots of progress

This commit is contained in:
2026-04-26 22:43:22 +02:00
parent 16ac66471a
commit 82ea8125e1
24 changed files with 1095 additions and 1315 deletions

View File

@ -1,6 +1,8 @@
import 'dart:async';
import 'package:anyhow/anyhow.dart';
import 'package:flutter/foundation.dart'
show TargetPlatform, defaultTargetPlatform;
import 'package:flutter_riverpod/flutter_riverpod.dart';
import 'package:flutter_reactive_ble/flutter_reactive_ble.dart'
hide ConnectionStatus, Result, Logger;
@ -173,9 +175,6 @@ class BluetoothController {
(currentState.$1 == ConnectionStatus.connected ||
currentState.$1 == ConnectionStatus.connecting)) {
log.info('Already connected or connecting to $deviceId.');
if (currentState.$1 == ConnectionStatus.connected) {
unawaited(_requestMtuOnConnect(deviceId));
}
return Ok(null);
}
@ -191,6 +190,7 @@ class BluetoothController {
try {
await _connectionStateSubscription?.cancel();
_updateConnectionState(ConnectionStatus.connecting, deviceId);
final connectionResult = Completer<Result<void>>();
_connectionStateSubscription = _ble
.connectToDevice(
@ -199,12 +199,21 @@ class BluetoothController {
servicesWithCharacteristicsToDiscover:
servicesWithCharacteristicsToDiscover,
)
.listen((update) {
.listen((update) async {
switch (update.connectionState) {
case DeviceConnectionState.connected:
_connectedDeviceId = deviceId;
_updateConnectionState(ConnectionStatus.connected, deviceId);
unawaited(_requestMtuOnConnect(deviceId));
if (!connectionResult.isCompleted) {
final mtuResult = await _requestInitialMtu(deviceId);
if (mtuResult.isErr()) {
log.warning(
'Initial MTU request failed for $deviceId: '
'${mtuResult.unwrapErr()}',
);
}
connectionResult.complete(Ok(null));
}
break;
case DeviceConnectionState.connecting:
_updateConnectionState(ConnectionStatus.connecting, deviceId);
@ -214,14 +223,31 @@ class BluetoothController {
break;
case DeviceConnectionState.disconnected:
_cleanUpConnection();
if (!connectionResult.isCompleted) {
connectionResult.complete(
bail('Failed to connect to $deviceId: disconnected'),
);
}
break;
}
}, onError: (Object error, StackTrace st) {
log.severe('Failed to connect to $deviceId: $error', error, st);
_cleanUpConnection();
if (!connectionResult.isCompleted) {
connectionResult.complete(
bail('Failed to connect to $deviceId: $error'),
);
}
});
return Ok(null);
try {
return await connectionResult.future.timeout(timeout);
} on TimeoutException {
await _connectionStateSubscription?.cancel();
_connectionStateSubscription = null;
_cleanUpConnection();
return bail('Timed out connecting to $deviceId');
}
} catch (e) {
_cleanUpConnection();
return bail('Failed to connect to $deviceId: $e');
@ -301,7 +327,7 @@ class BluetoothController {
{int mtu = defaultMtu}) async {
final result = await requestMtuAndGetValue(deviceId, mtu: mtu);
if (result.isErr()) {
return bail(result.unwrapErr());
return Err(result.unwrapErr());
}
return Ok(null);
}
@ -310,6 +336,10 @@ class BluetoothController {
{int mtu = defaultMtu}) async {
try {
final negotiatedMtu = await _ble.requestMtu(deviceId: deviceId, mtu: mtu);
if (negotiatedMtu <= 0) {
return bail(
'Error requesting MTU $mtu for $deviceId: negotiated invalid MTU $negotiatedMtu');
}
log.info(
'MTU negotiated for $deviceId: requested $mtu, got $negotiatedMtu');
return Ok(negotiatedMtu);
@ -318,12 +348,11 @@ class BluetoothController {
}
}
Future<void> _requestMtuOnConnect(String deviceId) async {
final mtuResult = await requestMtu(deviceId, mtu: defaultMtu);
if (mtuResult.isErr()) {
log.warning(
'MTU request after connect failed for $deviceId: ${mtuResult.unwrapErr()}');
Future<Result<void>> _requestInitialMtu(String deviceId) async {
if (defaultTargetPlatform != TargetPlatform.android) {
return Ok(null);
}
return requestMtu(deviceId, mtu: defaultMtu);
}
Stream<List<int>> subscribeToCharacteristic(