execute method
Future<VtjCommandResult<EnterDfuBootloaderResult> >
execute(
- BluetoothCharacteristic writeCharacteristic,
- BluetoothCharacteristic replyCharacteristic
override
Custom execute that handles device reboot behavior.
The device will disconnect after entering DFU mode, so we treat timeout and connection errors as success.
Implementation
@override
Future<VtjCommandResult<EnterDfuBootloaderResult>> execute(
BluetoothCharacteristic writeCharacteristic,
BluetoothCharacteristic replyCharacteristic,
) async {
final completer = Completer<VtjCommandResult<EnterDfuBootloaderResult>>();
late StreamSubscription subscription;
try {
await replyCharacteristic.read();
subscription = replyCharacteristic.lastValueStream.listen((data) {
if (data.isNotEmpty && data[0] == commandId) {
final result = parseResponse(Uint8List.fromList(data));
subscription.cancel();
if (!completer.isCompleted) {
completer.complete(result);
}
}
});
if (!replyCharacteristic.isNotifying) {
await replyCharacteristic.setNotifyValue(true);
}
final request = buildRequest();
await writeCharacteristic.write(request, withoutResponse: false);
// Shorter timeout - device will reboot
return await completer.future.timeout(
const Duration(seconds: 5),
onTimeout: () {
subscription.cancel();
// Timeout is expected as device reboots
return const VtjCommandResult.success(EnterDfuBootloaderResult.success());
},
);
} catch (e) {
subscription.cancel();
if (!completer.isCompleted) {
// Connection errors are expected as device reboots
if (e.toString().contains('disconnect') ||
e.toString().contains('connection')) {
return const VtjCommandResult.success(EnterDfuBootloaderResult.success());
}
return VtjCommandResult.failure('Command failed: $e', null);
}
return completer.future;
}
}