mirror of
https://github.com/pybricks/pybricks-code.git
synced 2026-09-12 17:45:22 +00:00
add firmware flash failure reasons
This commit is contained in:
@@ -1,6 +1,7 @@
|
||||
// SPDX-License-Identifier: MIT
|
||||
// Copyright (c) 2020-2021 The Pybricks Authors
|
||||
|
||||
import { FirmwareMetadata, FirmwareReaderError } from '@pybricks/firmware';
|
||||
import { Action } from 'redux';
|
||||
import { assert } from '../utils';
|
||||
|
||||
@@ -12,6 +13,8 @@ export enum FlashFirmwareActionType {
|
||||
FlashFirmware = 'flashFirmware.action.flashFirmware',
|
||||
/** Flashing started. */
|
||||
DidStart = 'flashFirmware.action.didStart',
|
||||
/** Flashing was not able to start. */
|
||||
DidFailToStart = 'flashFirmware.action.didFailStart',
|
||||
/** Firmware flash progress. */
|
||||
DidProgress = 'flashFirmware.action.didProgress',
|
||||
/** Flashing finished successfully. */
|
||||
@@ -20,6 +23,116 @@ export enum FlashFirmwareActionType {
|
||||
DidFailToFinish = 'flashFirmware.action.didFailToFinish',
|
||||
}
|
||||
|
||||
export enum MetadataProblem {
|
||||
Missing = 'metadata.missing',
|
||||
NotSupported = 'metadata.notSupported',
|
||||
}
|
||||
|
||||
export enum HubError {
|
||||
UnknownCommand = 'hubError.unknownCommand',
|
||||
EraseFailed = 'hubError.eraseFailed',
|
||||
InitFailed = 'hubError.initFailed',
|
||||
CountMismatch = 'hubError.countMismatch',
|
||||
ChecksumMismatch = 'hubError.checksumMismatch',
|
||||
}
|
||||
|
||||
function isHubError(arg: unknown): arg is HubError {
|
||||
if (typeof arg !== 'string') {
|
||||
return false;
|
||||
}
|
||||
return Object.keys(HubError).includes(arg);
|
||||
}
|
||||
|
||||
type Reason<T> = {
|
||||
reason: T;
|
||||
};
|
||||
|
||||
export enum FailToStartReasonType {
|
||||
/** Connecting to the hub failed. */
|
||||
FailedToConnect = 'flashFirmware.failToStart.reason.failedToConnect',
|
||||
/** The is no firmware available that matches the connected hub. */
|
||||
NoFirmware = 'flashFirmware.failToStart.reason.noFirmware',
|
||||
/** The provided firmware.zip does not match the connected hub. */
|
||||
DeviceMismatch = 'flashFirmware.failToStart.reason.deviceMismatch',
|
||||
/** There was a problem with the zip file. */
|
||||
ZipError = 'flashFirmware.failToStart.reason.zipError',
|
||||
/** Metadata property is missing or invalid. */
|
||||
BadMetadata = 'flashFirmware.failToStart.reason.badMetadata',
|
||||
/** The main.py file failed to compile. */
|
||||
FailedToCompile = 'flashFirmware.failToStart.reason.failedToCompile',
|
||||
/** The combined firmware-base.bin and main.mpy are too big. */
|
||||
FirmwareSize = 'flashFirmware.failToStart.reason.firmwareSize',
|
||||
/** An unexpected error occurred. */
|
||||
Unknown = 'flashFirmware.failToStart.reason.unknown',
|
||||
}
|
||||
|
||||
export type FailToStartReasonFailedToConnect = Reason<FailToStartReasonType.FailedToConnect>;
|
||||
|
||||
export type FailToStartReasonNoFirmware = Reason<FailToStartReasonType.NoFirmware>;
|
||||
|
||||
export type FailToStartReasonDeviceMismatch = Reason<FailToStartReasonType.DeviceMismatch>;
|
||||
|
||||
export type FailToStartReasonZipError = Reason<FailToStartReasonType.ZipError> & {
|
||||
err: FirmwareReaderError;
|
||||
};
|
||||
|
||||
export type FailToStartReasonBadMetadata = Reason<FailToStartReasonType.BadMetadata> & {
|
||||
property: keyof FirmwareMetadata;
|
||||
problem: MetadataProblem;
|
||||
};
|
||||
|
||||
export type FailToStartReasonFirmwareSize = Reason<FailToStartReasonType.FirmwareSize>;
|
||||
|
||||
export type FailToStartReasonFailedToCompile = Reason<FailToStartReasonType.FailedToCompile>;
|
||||
|
||||
export type FailToStartReasonUnknown = Reason<FailToStartReasonType.Unknown> & {
|
||||
err: Error;
|
||||
};
|
||||
|
||||
export type FailToStartReason =
|
||||
| FailToStartReasonFailedToConnect
|
||||
| FailToStartReasonNoFirmware
|
||||
| FailToStartReasonDeviceMismatch
|
||||
| FailToStartReasonZipError
|
||||
| FailToStartReasonBadMetadata
|
||||
| FailToStartReasonFirmwareSize
|
||||
| FailToStartReasonFailedToCompile
|
||||
| FailToStartReasonUnknown;
|
||||
|
||||
export enum FailToFinishReasonType {
|
||||
/** Waiting for a response from the hub took too long. */
|
||||
TimedOut = 'flashFirmware.failToFinish.reason.timedOut',
|
||||
/** Something went wrong with the BLE connection. */
|
||||
BleError = 'flashFirmware.failToFinish.reason.bleError',
|
||||
/** The BLE connection was lost before flashing completed. */
|
||||
Disconnected = 'flashFirmware.failToFinish.reason.disconnected',
|
||||
/** The hub sent a response indicating a problem. */
|
||||
HubError = 'flashFirmware.failToFinish.reason.hubError',
|
||||
/** An unexpected error occurred. */
|
||||
Unknown = 'flashFirmware.failToFinish.reason.unknown',
|
||||
}
|
||||
|
||||
export type FailToFinishReasonTimedOut = Reason<FailToFinishReasonType.TimedOut>;
|
||||
|
||||
export type FailToFinishReasonBleError = Reason<FailToFinishReasonType.BleError>;
|
||||
|
||||
export type FailToFinishReasonDisconnected = Reason<FailToFinishReasonType.Disconnected>;
|
||||
|
||||
export type FailToFinishReasonHubError = Reason<FailToFinishReasonType.HubError> & {
|
||||
hubError: HubError;
|
||||
};
|
||||
|
||||
export type FailToFinishReasonUnknown = Reason<FailToFinishReasonType.Unknown> & {
|
||||
err: Error;
|
||||
};
|
||||
|
||||
export type FailToFinishReason =
|
||||
| FailToFinishReasonTimedOut
|
||||
| FailToFinishReasonBleError
|
||||
| FailToFinishReasonDisconnected
|
||||
| FailToFinishReasonHubError
|
||||
| FailToFinishReasonUnknown;
|
||||
|
||||
/**
|
||||
* Action that flashes firmware to a hub.
|
||||
*/
|
||||
@@ -47,6 +160,94 @@ export function didStart(): FlashFirmwareDidStartAction {
|
||||
return { type: FlashFirmwareActionType.DidStart };
|
||||
}
|
||||
|
||||
/** Action that indicates flashing did not start because of an error. */
|
||||
export type FlashFirmwareDidFailToStartAction = Action<FlashFirmwareActionType.DidFailToStart> & {
|
||||
reason: FailToStartReason;
|
||||
};
|
||||
|
||||
export function didFailToStart(
|
||||
reason: FailToStartReasonType.ZipError,
|
||||
err: FirmwareReaderError,
|
||||
): FlashFirmwareDidFailToStartAction;
|
||||
|
||||
export function didFailToStart(
|
||||
reason: FailToStartReasonType.BadMetadata,
|
||||
property: keyof FirmwareMetadata,
|
||||
problem: MetadataProblem,
|
||||
): FlashFirmwareDidFailToStartAction;
|
||||
|
||||
export function didFailToStart(
|
||||
reason: FailToStartReasonType.Unknown,
|
||||
err: Error,
|
||||
): FlashFirmwareDidFailToStartAction;
|
||||
|
||||
export function didFailToStart(
|
||||
reason: Exclude<
|
||||
FailToStartReasonType,
|
||||
| FailToStartReasonType.ZipError
|
||||
| FailToStartReasonType.BadMetadata
|
||||
| FailToStartReasonType.Unknown
|
||||
>,
|
||||
): FlashFirmwareDidFailToStartAction;
|
||||
|
||||
/**
|
||||
* Action that indicates flashing did not start because of an error.
|
||||
* @param total The total number of bytes to be flashed.
|
||||
*/
|
||||
export function didFailToStart(
|
||||
reason: FailToStartReasonType,
|
||||
arg1?: string | Error,
|
||||
arg2?: MetadataProblem,
|
||||
): FlashFirmwareDidFailToStartAction {
|
||||
if (reason === FailToStartReasonType.ZipError) {
|
||||
// istanbul ignore if: programmer error give wrong arg
|
||||
if (!(arg1 instanceof FirmwareReaderError)) {
|
||||
throw new Error('missing or invalid err');
|
||||
}
|
||||
return {
|
||||
type: FlashFirmwareActionType.DidFailToStart,
|
||||
reason: { reason, err: arg1 },
|
||||
};
|
||||
}
|
||||
|
||||
if (reason === FailToStartReasonType.BadMetadata) {
|
||||
// istanbul ignore if: programmer error give wrong arg
|
||||
if (
|
||||
arg1 !== 'metadata-version' &&
|
||||
arg1 !== 'firmware-version' &&
|
||||
arg1 !== 'device-id' &&
|
||||
arg1 !== 'checksum-type' &&
|
||||
arg1 !== 'mpy-abi-version' &&
|
||||
arg1 !== 'mpy-cross-options' &&
|
||||
arg1 !== 'user-mpy-offset' &&
|
||||
arg1 !== 'max-firmware-size'
|
||||
) {
|
||||
throw new Error('missing or invalid property');
|
||||
}
|
||||
// istanbul ignore if: programmer error give wrong arg
|
||||
if (arg2 === undefined) {
|
||||
throw new Error('missing or invalid problem');
|
||||
}
|
||||
return {
|
||||
type: FlashFirmwareActionType.DidFailToStart,
|
||||
reason: { reason, property: arg1, problem: arg2 },
|
||||
};
|
||||
}
|
||||
|
||||
if (reason === FailToStartReasonType.Unknown) {
|
||||
// istanbul ignore if: programmer error give wrong arg
|
||||
if (!(arg1 instanceof Error)) {
|
||||
throw new Error('missing or invalid err');
|
||||
}
|
||||
return {
|
||||
type: FlashFirmwareActionType.DidFailToStart,
|
||||
reason: { reason, err: arg1 },
|
||||
};
|
||||
}
|
||||
|
||||
return { type: FlashFirmwareActionType.DidFailToStart, reason: { reason } };
|
||||
}
|
||||
|
||||
/** Action that indicates current firmware flashing progress. */
|
||||
export type FlashFirmwareDidProgressAction = Action<FlashFirmwareActionType.DidProgress> & {
|
||||
/** The current progress (0 to 1). */
|
||||
@@ -71,11 +272,55 @@ export function didFinish(): FlashFirmwareDidFinishAction {
|
||||
}
|
||||
|
||||
/** Action that indicates that flashing failed. */
|
||||
export type FlashFirmwareDidFailToFinishAction = Action<FlashFirmwareActionType.DidFailToFinish>;
|
||||
export type FlashFirmwareDidFailToFinishAction = Action<FlashFirmwareActionType.DidFailToFinish> & {
|
||||
reason: FailToFinishReason;
|
||||
};
|
||||
|
||||
export function didFailToFinish(
|
||||
reason: FailToFinishReasonType.HubError,
|
||||
hubError: HubError,
|
||||
): FlashFirmwareDidFailToFinishAction;
|
||||
|
||||
export function didFailToFinish(
|
||||
reason: FailToFinishReasonType.Unknown,
|
||||
err: Error,
|
||||
): FlashFirmwareDidFailToFinishAction;
|
||||
|
||||
export function didFailToFinish(
|
||||
reason: Exclude<
|
||||
FailToFinishReasonType,
|
||||
FailToFinishReasonType.HubError | FailToFinishReasonType.Unknown
|
||||
>,
|
||||
): FlashFirmwareDidFailToFinishAction;
|
||||
|
||||
/** Action that indicates that flashing failed. */
|
||||
export function didFailToFinish(): FlashFirmwareDidFailToFinishAction {
|
||||
return { type: FlashFirmwareActionType.DidFailToFinish };
|
||||
export function didFailToFinish(
|
||||
reason: FailToFinishReasonType,
|
||||
arg1?: HubError | Error,
|
||||
): FlashFirmwareDidFailToFinishAction {
|
||||
if (reason === FailToFinishReasonType.HubError) {
|
||||
// istanbul ignore if: programmer error give wrong arg
|
||||
if (!isHubError(arg1)) {
|
||||
throw new Error('missing or invalid err');
|
||||
}
|
||||
return {
|
||||
type: FlashFirmwareActionType.DidFailToFinish,
|
||||
reason: { reason, hubError: arg1 },
|
||||
};
|
||||
}
|
||||
|
||||
if (reason === FailToFinishReasonType.Unknown) {
|
||||
// istanbul ignore if: programmer error give wrong arg
|
||||
if (!(arg1 instanceof Error)) {
|
||||
throw new Error('missing or invalid err');
|
||||
}
|
||||
return {
|
||||
type: FlashFirmwareActionType.DidFailToFinish,
|
||||
reason: { reason, err: arg1 },
|
||||
};
|
||||
}
|
||||
|
||||
return { type: FlashFirmwareActionType.DidFailToFinish, reason: { reason } };
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -84,6 +329,7 @@ export function didFailToFinish(): FlashFirmwareDidFailToFinishAction {
|
||||
export type FlashFirmwareAction =
|
||||
| FlashFirmwareFlashAction
|
||||
| FlashFirmwareDidStartAction
|
||||
| FlashFirmwareDidFailToStartAction
|
||||
| FlashFirmwareDidProgressAction
|
||||
| FlashFirmwareDidFinishAction
|
||||
| FlashFirmwareDidFailToFinishAction;
|
||||
|
||||
Reference in New Issue
Block a user