fix: fix dfu id mismatch because stale notification
This commit is contained in:
@ -527,10 +527,33 @@ class FirmwareUpdateService {
|
||||
Future<DfuBootloaderStatus> _sendStartAndWaitForStatus(
|
||||
BootloaderDfuStartPayload payload, {
|
||||
required Duration timeout,
|
||||
}) {
|
||||
return _writeControlAndWaitForStatus(
|
||||
BootloaderDfuProtocol.encodeStartPayload(payload),
|
||||
}) async {
|
||||
final eventCount = _statusEventCount;
|
||||
final encodedPayload = BootloaderDfuProtocol.encodeStartPayload(payload);
|
||||
_log.fine(
|
||||
'Writing DFU START command for session ${payload.sessionId} '
|
||||
'(len=${encodedPayload.length})',
|
||||
);
|
||||
final result = await _transport.writeControl(encodedPayload);
|
||||
if (result.isErr()) {
|
||||
_log.warning('DFU START write failed: ${result.unwrapErr()}');
|
||||
throw _DfuFailure(
|
||||
'Failed to write bootloader control command: ${result.unwrapErr()}',
|
||||
);
|
||||
}
|
||||
return _waitForStatus(
|
||||
afterEventCount: eventCount,
|
||||
timeout: timeout,
|
||||
acceptStatus: (status) {
|
||||
if (status.sessionId == payload.sessionId) {
|
||||
return true;
|
||||
}
|
||||
_log.fine(
|
||||
'Ignoring stale START status for session ${status.sessionId}; '
|
||||
'waiting for session ${payload.sessionId}',
|
||||
);
|
||||
return false;
|
||||
},
|
||||
);
|
||||
}
|
||||
|
||||
@ -708,6 +731,7 @@ class FirmwareUpdateService {
|
||||
required int afterEventCount,
|
||||
required Duration timeout,
|
||||
bool recoverable = false,
|
||||
bool Function(DfuBootloaderStatus status)? acceptStatus,
|
||||
}) async {
|
||||
final deadline = DateTime.now().add(timeout);
|
||||
var observedEvents = afterEventCount;
|
||||
@ -722,7 +746,12 @@ class FirmwareUpdateService {
|
||||
'session=${_latestStatus!.sessionId}, offset=${_latestStatus!.expectedOffset}, '
|
||||
'code=${_statusLabel(_latestStatus!)}',
|
||||
);
|
||||
return _latestStatus!;
|
||||
final status = _latestStatus!;
|
||||
if (acceptStatus == null || acceptStatus(status)) {
|
||||
return status;
|
||||
}
|
||||
observedEvents = _statusEventCount;
|
||||
continue;
|
||||
}
|
||||
|
||||
final remaining = deadline.difference(DateTime.now());
|
||||
|
||||
@ -307,6 +307,33 @@ void main() {
|
||||
await transport.dispose();
|
||||
});
|
||||
|
||||
test('ignores stale previous-session status while waiting for START',
|
||||
() async {
|
||||
final image = _validImage(80);
|
||||
final transport = _FakeFirmwareUpdateTransport(
|
||||
totalBytes: image.length,
|
||||
staleStartStatusSessionId: 20,
|
||||
);
|
||||
final service = FirmwareUpdateService(
|
||||
transport: transport,
|
||||
defaultStatusTimeout: const Duration(milliseconds: 100),
|
||||
);
|
||||
|
||||
final result = await service.startUpdate(
|
||||
imageBytes: image,
|
||||
sessionId: 21,
|
||||
);
|
||||
|
||||
expect(result.isOk(), isTrue);
|
||||
expect(
|
||||
transport.controlWrites.first.first, universalShifterDfuOpcodeStart);
|
||||
expect(transport.dataWrites.first[0], 21);
|
||||
expect(service.currentProgress.state, DfuUpdateState.completed);
|
||||
|
||||
await service.dispose();
|
||||
await transport.dispose();
|
||||
});
|
||||
|
||||
test('fails with bootloader status error on rejected START', () async {
|
||||
final image = _validImage(40);
|
||||
final transport = _FakeFirmwareUpdateTransport(
|
||||
@ -410,6 +437,7 @@ class _FakeFirmwareUpdateTransport implements FirmwareUpdateTransport {
|
||||
this.suppressFirstDataStatus = false,
|
||||
this.failDataWriteAtOffsetOnce,
|
||||
this.resetSessionOnRecoveryStatus = false,
|
||||
this.staleStartStatusSessionId,
|
||||
this.suppressFinishStatus = false,
|
||||
this.disconnectAfterFinish = true,
|
||||
this.finishStatusCode = DfuBootloaderStatusCode.ok,
|
||||
@ -425,6 +453,7 @@ class _FakeFirmwareUpdateTransport implements FirmwareUpdateTransport {
|
||||
final bool suppressFirstDataStatus;
|
||||
final int? failDataWriteAtOffsetOnce;
|
||||
final bool resetSessionOnRecoveryStatus;
|
||||
final int? staleStartStatusSessionId;
|
||||
final bool suppressFinishStatus;
|
||||
final bool disconnectAfterFinish;
|
||||
final DfuBootloaderStatusCode finishStatusCode;
|
||||
@ -502,6 +531,10 @@ class _FakeFirmwareUpdateTransport implements FirmwareUpdateTransport {
|
||||
if (opcode == universalShifterDfuOpcodeStart) {
|
||||
_sessionId = payload[17];
|
||||
_expectedOffset = 0;
|
||||
final staleSessionId = staleStartStatusSessionId;
|
||||
if (staleSessionId != null) {
|
||||
_scheduleStatus(DfuBootloaderStatusCode.ok, staleSessionId, 0);
|
||||
}
|
||||
_scheduleStatus(startStatusCode, _sessionId, 0);
|
||||
} else if (opcode == universalShifterDfuOpcodeGetStatus) {
|
||||
if (resetSessionOnRecoveryStatus && _connectCount > 1) {
|
||||
|
||||
Reference in New Issue
Block a user