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

@ -629,7 +629,7 @@ class ShifterFirmwareUpdateTransport implements FirmwareUpdateTransport {
final connectResult =
await bluetoothController.connectById(buttonDeviceId, timeout: timeout);
if (connectResult.isErr()) {
return bail(connectResult.unwrapErr());
return Err(connectResult.unwrapErr());
}
final currentState = bluetoothController.currentConnectionState;
@ -663,7 +663,7 @@ class ShifterFirmwareUpdateTransport implements FirmwareUpdateTransport {
try {
final statusResult = await shifterService.readStatus().timeout(timeout);
if (statusResult.isErr()) {
return bail(statusResult.unwrapErr());
return Err(statusResult.unwrapErr());
}
return Ok(null);
} on TimeoutException {

View File

@ -3,6 +3,9 @@ import 'dart:async';
import 'package:abawo_bt_app/controller/bluetooth.dart';
import 'package:abawo_bt_app/model/shifter_types.dart';
import 'package:anyhow/anyhow.dart';
import 'package:logging/logging.dart';
final _log = Logger('ShifterService');
class ShifterService {
ShifterService({
@ -83,7 +86,7 @@ class ShifterService {
universalShifterGearRatiosCharacteristicUuid,
);
if (readRes.isErr()) {
return bail(readRes.unwrapErr());
return Err(readRes.unwrapErr());
}
final raw = readRes.unwrap();
@ -159,7 +162,7 @@ class ShifterService {
universalShifterStatusCharacteristicUuid,
);
if (readRes.isErr()) {
return bail(readRes.unwrapErr());
return Err(readRes.unwrapErr());
}
try {
@ -240,25 +243,34 @@ class ShifterService {
return;
}
_statusSubscription = _requireBluetooth
.subscribeToCharacteristic(
buttonDeviceId,
universalShifterControlServiceUuid,
universalShifterStatusCharacteristicUuid,
)
.listen(
(data) {
try {
final status = CentralStatus.fromCborBytes(data);
_statusController.add(status);
} catch (_) {
// Ignore malformed payloads but keep stream alive.
}
},
onError: (_) {
// Keep UI running; reconnection logic is handled elsewhere.
},
);
try {
_statusSubscription = _requireBluetooth
.subscribeToCharacteristic(
buttonDeviceId,
universalShifterControlServiceUuid,
universalShifterStatusCharacteristicUuid,
)
.listen(
(data) {
try {
final status = CentralStatus.fromCborBytes(data);
_statusController.add(status);
} catch (error, st) {
_log.warning(
'Failed to decode status notification from $buttonDeviceId: '
'bytes=${_formatBytes(data)}',
error,
st,
);
}
},
onError: (Object error, StackTrace st) {
_log.warning('Status notification stream failed', error, st);
},
);
} catch (error, st) {
_log.warning('Could not start status notifications', error, st);
}
}
Future<void> stopStatusNotifications() async {
@ -286,6 +298,12 @@ class ShifterService {
double _decodeGearRatio(int raw) {
return raw / 64.0;
}
String _formatBytes(List<int> bytes) {
return bytes
.map((byte) => byte.toRadixString(16).padLeft(2, '0'))
.join(' ');
}
}
abstract interface class DfuPreflightBluetoothAdapter {