diff --git a/package.json b/package.json index ecf154fa..159aeeda 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "@pybricks/pybricks-code", - "version": "1.0.0-beta.12", + "version": "1.0.0-beta.13", "license": "MIT", "author": "The Pybricks Authors", "repository": { @@ -10,7 +10,7 @@ "dependencies": { "@blueprintjs/core": "^3.41.0", "@craco/craco": "^6.1.1", - "@pybricks/firmware": "4.8.0", + "@pybricks/firmware": "4.9.0", "@pybricks/ide-docs": "1.3.1", "@pybricks/mpy-cross-v5": "^2.0.0", "@shopify/react-i18n": "^5.3.0", diff --git a/src/firmware/FlashButton.tsx b/src/firmware/FlashButton.tsx index 89e73804..c8d5d4b0 100644 --- a/src/firmware/FlashButton.tsx +++ b/src/firmware/FlashButton.tsx @@ -2,6 +2,7 @@ // Copyright (c) 2020-2021 The Pybricks Authors import { connect } from 'react-redux'; +import { HubRuntimeState } from '../hub/reducers'; import { BootloaderConnectionState } from '../lwp3-bootloader/reducers'; import * as notification from '../notifications/actions'; import { RootState } from '../reducers'; @@ -19,7 +20,9 @@ type OwnProps = Pick; const mapStateToProps = (state: RootState): StateProps => ({ tooltip: state.firmware.flashing ? TooltipId.FlashProgress : TooltipId.Flash, - enabled: state.bootloader.connection === BootloaderConnectionState.Disconnected, + enabled: + state.bootloader.connection === BootloaderConnectionState.Disconnected && + state.hub.runtime === HubRuntimeState.Disconnected, showProgress: state.firmware.flashing, progress: state.firmware.progress === null ? undefined : state.firmware.progress, }); diff --git a/src/hub/sagas.ts b/src/hub/sagas.ts index 55eedb29..cd795dcd 100644 --- a/src/hub/sagas.ts +++ b/src/hub/sagas.ts @@ -4,6 +4,7 @@ import { SagaGenerator, actionChannel, + delay, getContext, put, race, @@ -108,7 +109,19 @@ function* downloadAndRun(_action: HubDownloadAndRunAction): Generator { return; } - const checksumAction = yield* take(checksumChannel); + const { checksumAction, checksumTimeout } = yield* race({ + checksumAction: take(checksumChannel), + checksumTimeout: delay(1000), + }); + + if (checksumTimeout) { + console.error(`timeout waiting for checksum`); + yield* put(didFailToFinishDownload()); + return; + } + + defined(checksumAction); + if (checksumAction.checksum !== (0xff ^ xor8(sizeBuf))) { console.error( `bad checksum ${checksumAction.checksum} vs ${0xff ^ xor8(sizeBuf)}`, @@ -136,7 +149,20 @@ function* downloadAndRun(_action: HubDownloadAndRunAction): Generator { } // TODO: dispatch progress } - const checksumAction = yield* take(checksumChannel); + + const { checksumAction, checksumTimeout } = yield* race({ + checksumAction: take(checksumChannel), + checksumTimeout: delay(1000), + }); + + if (checksumTimeout) { + console.error(`timeout waiting for checksum`); + yield* put(didFailToFinishDownload()); + return; + } + + defined(checksumAction); + if (checksumAction.checksum !== (0xff ^ xor8(chunk))) { console.error( `bad checksum ${checksumAction.checksum} vs ${0xff ^ xor8(chunk)}`, diff --git a/yarn.lock b/yarn.lock index fa97c3e3..69e9811f 100644 --- a/yarn.lock +++ b/yarn.lock @@ -1500,10 +1500,10 @@ schema-utils "^2.6.5" source-map "^0.7.3" -"@pybricks/firmware@4.8.0": - version "4.8.0" - resolved "https://registry.yarnpkg.com/@pybricks/firmware/-/firmware-4.8.0.tgz#6f70d12800a449e4960bc02b702fa7bbd1de39de" - integrity sha512-w6owDDc/GhOm8AowR6Pnl/akbsM0PVgbK8bNzUv01P6lgP1h17IK3HWtHwv75vntPX+9SrsVf5myvny8VhY9Pg== +"@pybricks/firmware@4.9.0": + version "4.9.0" + resolved "https://registry.yarnpkg.com/@pybricks/firmware/-/firmware-4.9.0.tgz#73854a4dd2949bb2c6faf770c893ad30f9ed7fba" + integrity sha512-TJB9232CGRDfeZzKiCnKVsNwfl+zCBKQZI9a0TotzhcZIbpVe+flGZOVXNG2J6CI8GCcrED56jv9uIgZk/zLGA== dependencies: jszip "^3.5.0"