mirror of
https://github.com/SlimeVR/SlimeVR-Server.git
synced 2026-04-06 02:01:58 +02:00
12
gui/.env
12
gui/.env
@@ -1,8 +1,8 @@
|
||||
# VITE_FIRMWARE_TOOL_URL=https://fw-tool-api.slimevr.io
|
||||
# VITE_FIRMWARE_TOOL_S3_URL=https://fw-tool-bucket.slimevr.io
|
||||
# FIRMWARE_TOOL_SCHEMA_URL=https://fw-tool-api.slimevr.io/api-json
|
||||
VITE_FIRMWARE_TOOL_URL=https://fw-tool-api.slimevr.io
|
||||
VITE_FIRMWARE_TOOL_S3_URL=https://fw-tool-bucket.slimevr.io
|
||||
FIRMWARE_TOOL_SCHEMA_URL=https://fw-tool-api.slimevr.io/api-json
|
||||
|
||||
|
||||
VITE_FIRMWARE_TOOL_URL=http://localhost:3000
|
||||
VITE_FIRMWARE_TOOL_S3_URL=http://localhost:9099
|
||||
FIRMWARE_TOOL_SCHEMA_URL=http://localhost:3000/api-json
|
||||
# VITE_FIRMWARE_TOOL_URL=http://localhost:3000
|
||||
# VITE_FIRMWARE_TOOL_S3_URL=http://localhost:9000
|
||||
# FIRMWARE_TOOL_SCHEMA_URL=http://localhost:3000/api-json
|
||||
|
||||
@@ -25,7 +25,6 @@
|
||||
"@tauri-apps/plugin-store": "^2.0.0",
|
||||
"@tweenjs/tween.js": "^25.0.0",
|
||||
"@twemoji/svg": "^15.0.0",
|
||||
"ajv": "^8.17.1",
|
||||
"browser-fs-access": "^0.35.0",
|
||||
"classnames": "^2.5.1",
|
||||
"flatbuffers": "22.10.26",
|
||||
|
||||
@@ -89,7 +89,6 @@ board_type-WEMOSD1MINI = Wemos D1 Mini
|
||||
board_type-TTGO_TBASE = TTGO T-Base
|
||||
board_type-ESP01 = ESP-01
|
||||
board_type-SLIMEVR = SlimeVR
|
||||
board_type-SLIMEVR_V1_2 = SlimeVR v1.2
|
||||
board_type-LOLIN_C3_MINI = Lolin C3 Mini
|
||||
board_type-BEETLE32C3 = Beetle ESP32-C3
|
||||
board_type-ESP32C3DEVKITM1 = Espressif ESP32-C3 DevKitM-1
|
||||
@@ -384,8 +383,7 @@ tracker-settings-name_section-label = Tracker name
|
||||
tracker-settings-forget = Forget tracker
|
||||
tracker-settings-forget-description = Removes the tracker from the SlimeVR Server and prevents it from connecting until the server is restarted. The configuration of the tracker won't be lost.
|
||||
tracker-settings-forget-label = Forget tracker
|
||||
tracker-settings-update-unavailable-v2 = No releases found
|
||||
tracker-settings-update-incompatible = Cannot update. Incompatible board
|
||||
tracker-settings-update-unavailable = Cannot be updated (DIY)
|
||||
tracker-settings-update-low-battery = Cannot update. Battery lower than 50%
|
||||
tracker-settings-update-up_to_date = Up to date
|
||||
tracker-settings-update-blocked = Update not available. No other releases available
|
||||
|
||||
@@ -3,7 +3,7 @@ import { Typography } from '@/components/commons/Typography';
|
||||
import { QueryClient, QueryClientProvider } from '@tanstack/react-query';
|
||||
import {
|
||||
FirmwareToolContextC,
|
||||
provideFirmwareTool,
|
||||
useFirmwareToolContext,
|
||||
} from '@/hooks/firmware-tool';
|
||||
import { AddImusStep } from './AddImusStep';
|
||||
import { SelectBoardStep } from './SelectBoardStep';
|
||||
@@ -15,87 +15,63 @@ import { SelectFirmwareStep } from './SelectFirmwareStep';
|
||||
import { BuildStep } from './BuildStep';
|
||||
import { FlashingMethodStep } from './FlashingMethodStep';
|
||||
import { FlashingStep } from './FlashingStep';
|
||||
import { FlashBtnStep } from './FlashBtnStep';
|
||||
import { FirmwareUpdateMethod } from 'solarxr-protocol';
|
||||
import { useMemo } from 'react';
|
||||
import {
|
||||
useGetHealth,
|
||||
useGetIsCompatibleVersion,
|
||||
} from '@/firmware-tool-api/firmwareToolComponents';
|
||||
import { SelectSourceSetep } from './steps/SelectSourceStep';
|
||||
import { BoardDefaultsStep } from './steps/BoardDefaultsStep';
|
||||
|
||||
function FirmwareToolContent() {
|
||||
const { l10n } = useLocalization();
|
||||
const context = provideFirmwareTool();
|
||||
const { isError, isLoading: isInitialLoading, refetch } = useGetHealth({});
|
||||
const compatibilityCheckEnabled = !!__VERSION_TAG__;
|
||||
const { isLoading: isCompatibilityLoading, data: compatibilityData } =
|
||||
useGetIsCompatibleVersion(
|
||||
{ pathParams: { version: __VERSION_TAG__ } },
|
||||
{ enabled: compatibilityCheckEnabled }
|
||||
);
|
||||
|
||||
const isLoading = isInitialLoading || isCompatibilityLoading;
|
||||
const isCompatible =
|
||||
!compatibilityCheckEnabled || (compatibilityData?.success ?? false);
|
||||
const context = useFirmwareToolContext();
|
||||
const { isError, isGlobalLoading: isLoading, retry, isCompatible } = context;
|
||||
|
||||
const steps = useMemo(() => {
|
||||
const steps = [
|
||||
{
|
||||
id: 'SelectSource',
|
||||
component: SelectSourceSetep,
|
||||
title: l10n.getString('firmware_tool-step-select_source'),
|
||||
id: 'SelectBoard',
|
||||
component: SelectBoardStep,
|
||||
title: l10n.getString('firmware_tool-board_step'),
|
||||
},
|
||||
{
|
||||
component: BoardDefaultsStep,
|
||||
title: l10n.getString('firmware_tool-step-board_defaults'),
|
||||
component: BoardPinsStep,
|
||||
title: l10n.getString('firmware_tool-board_pins_step'),
|
||||
},
|
||||
{
|
||||
component: AddImusStep,
|
||||
title: l10n.getString('firmware_tool-add_imus_step'),
|
||||
},
|
||||
{
|
||||
id: 'SelectFirmware',
|
||||
component: SelectFirmwareStep,
|
||||
title: l10n.getString('firmware_tool-select_firmware_step'),
|
||||
},
|
||||
{
|
||||
component: FlashingMethodStep,
|
||||
id: 'FlashingMethod',
|
||||
title: l10n.getString('firmware_tool-flash_method_step'),
|
||||
},
|
||||
{
|
||||
component: BuildStep,
|
||||
title: l10n.getString('firmware_tool-build_step'),
|
||||
},
|
||||
{
|
||||
component: FlashingStep,
|
||||
title: l10n.getString('firmware_tool-flashing_step'),
|
||||
},
|
||||
// {
|
||||
// component: BoardPinsStep,
|
||||
// title: l10n.getString('firmware_tool-board_pins_step'),
|
||||
// },
|
||||
// {
|
||||
// component: AddImusStep,
|
||||
// title: l10n.getString('firmware_tool-add_imus_step'),
|
||||
// },
|
||||
// {
|
||||
// id: 'SelectFirmware',
|
||||
// component: SelectFirmwareStep,
|
||||
// title: l10n.getString('firmware_tool-select_firmware_step'),
|
||||
// },
|
||||
// {
|
||||
// component: FlashingMethodStep,
|
||||
// id: 'FlashingMethod',
|
||||
// title: l10n.getString('firmware_tool-flash_method_step'),
|
||||
// },
|
||||
// {
|
||||
// component: BuildStep,
|
||||
// title: l10n.getString('firmware_tool-build_step'),
|
||||
// },
|
||||
// {
|
||||
// component: FlashingStep,
|
||||
// title: l10n.getString('firmware_tool-flashing_step'),
|
||||
// },
|
||||
];
|
||||
|
||||
// if (
|
||||
// context.defaultConfig?.needBootPress &&
|
||||
// context.selectedDevices?.find(
|
||||
// ({ type }) => type === FirmwareUpdateMethod.SerialFirmwareUpdate
|
||||
// )
|
||||
// ) {
|
||||
// steps.splice(5, 0, {
|
||||
// component: FlashBtnStep,
|
||||
// title: l10n.getString('firmware_tool-flashbtn_step'),
|
||||
// });
|
||||
// }
|
||||
if (
|
||||
context.defaultConfig?.needBootPress &&
|
||||
context.selectedDevices?.find(
|
||||
({ type }) => type === FirmwareUpdateMethod.SerialFirmwareUpdate
|
||||
)
|
||||
) {
|
||||
steps.splice(5, 0, {
|
||||
component: FlashBtnStep,
|
||||
title: l10n.getString('firmware_tool-flashbtn_step'),
|
||||
});
|
||||
}
|
||||
return steps;
|
||||
}, [
|
||||
/* context.defaultConfig?.needBootPress, context.selectedDevices */ l10n,
|
||||
]);
|
||||
|
||||
const retry = async () => {
|
||||
await refetch();
|
||||
};
|
||||
}, [context.defaultConfig?.needBootPress, context.selectedDevices, l10n]);
|
||||
|
||||
return (
|
||||
<FirmwareToolContextC.Provider value={context}>
|
||||
|
||||
@@ -26,9 +26,7 @@ export function FlashBtnStep({
|
||||
{l10n.getString('firmware_tool-flashbtn_step-description')}
|
||||
</Typography>
|
||||
{defaultConfig?.boardConfig.type ===
|
||||
boardTypeToFirmwareToolBoardType[BoardType.SLIMEVR] ||
|
||||
defaultConfig?.boardConfig.type ===
|
||||
boardTypeToFirmwareToolBoardType[BoardType.SLIMEVR_V1_2] ? (
|
||||
boardTypeToFirmwareToolBoardType[BoardType.SLIMEVR] ? (
|
||||
<>
|
||||
<Typography variant="standard" whitespace="whitespace-pre">
|
||||
{l10n.getString('firmware_tool-flashbtn_step-board_SLIMEVR')}
|
||||
|
||||
@@ -1,173 +0,0 @@
|
||||
import { useLocalization } from '@fluent/react';
|
||||
import { Typography } from '@/components/commons/Typography';
|
||||
import { useFirmwareTool } from '@/hooks/firmware-tool';
|
||||
import {} from '@/firmware-tool-api/firmwareToolComponents';
|
||||
import { SomeJSONSchema } from 'ajv/dist/types/json-schema';
|
||||
import { useEffect } from 'react';
|
||||
|
||||
const refToKey = (ref: string) => ref.substring('#/$defs/'.length);
|
||||
|
||||
type ComponentNode = { label: string } & (
|
||||
| {
|
||||
type: 'checkbox';
|
||||
value: boolean;
|
||||
}
|
||||
| {
|
||||
type: 'dropdown';
|
||||
items: string[];
|
||||
value: string;
|
||||
}
|
||||
| {
|
||||
type: 'text';
|
||||
value: string;
|
||||
}
|
||||
| {
|
||||
type: 'group';
|
||||
name: string;
|
||||
childrens: ComponentNode[];
|
||||
}
|
||||
| {
|
||||
type: 'list';
|
||||
childrens: ComponentNode[];
|
||||
}
|
||||
);
|
||||
|
||||
const handleNode = (
|
||||
defs: SomeJSONSchema['$defs'],
|
||||
node: SomeJSONSchema,
|
||||
data: any,
|
||||
parentNode: SomeJSONSchema | null = null
|
||||
): ComponentNode[] => {
|
||||
const components: ComponentNode[] = [];
|
||||
if (!node) return [];
|
||||
|
||||
if (node.$ref) {
|
||||
return handleNode(defs, defs![refToKey(node.$ref)], data, node);
|
||||
}
|
||||
if (node.type === 'object') {
|
||||
if (
|
||||
node.oneOf &&
|
||||
Array.isArray(node.oneOf) &&
|
||||
node.discriminator?.propertyName
|
||||
) {
|
||||
const discriminator = node.discriminator.propertyName;
|
||||
const selected = node.oneOf.find((o) => {
|
||||
if (
|
||||
o.$ref &&
|
||||
defs![refToKey(o.$ref)].properties[discriminator].const ===
|
||||
data[discriminator]
|
||||
) {
|
||||
return true;
|
||||
}
|
||||
|
||||
if (
|
||||
o.type === 'object' &&
|
||||
o.properties[discriminator].const === data[discriminator]
|
||||
) {
|
||||
console.log(data);
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
});
|
||||
components.push(...handleNode(defs, selected, data, node));
|
||||
} else if (node.properties) {
|
||||
const childs: ComponentNode[] = [];
|
||||
for (const property of Object.keys(node.properties)) {
|
||||
childs.push(
|
||||
...handleNode(defs, node.properties[property], data[property], node)
|
||||
);
|
||||
}
|
||||
components.push({
|
||||
type: 'group',
|
||||
name: node.description,
|
||||
childrens: childs,
|
||||
label: node.description ?? parentNode?.description ?? 'nothing o',
|
||||
});
|
||||
} else {
|
||||
throw 'unknown object';
|
||||
}
|
||||
}
|
||||
if (node.type === 'boolean') {
|
||||
components.push({
|
||||
type: 'checkbox',
|
||||
label: node.description ?? parentNode?.description ?? 'nothing b',
|
||||
value: data,
|
||||
});
|
||||
}
|
||||
if (node.type === 'array') {
|
||||
if (!Array.isArray(data)) throw 'not an array';
|
||||
const childs: ComponentNode[] = [];
|
||||
data.forEach((d) => {
|
||||
childs.push(...handleNode(defs, node.items, d, node));
|
||||
});
|
||||
components.push({
|
||||
type: 'list',
|
||||
childrens: childs,
|
||||
label: node.description ?? parentNode?.description ?? 'nothing a',
|
||||
});
|
||||
}
|
||||
if (node.type === 'string') {
|
||||
if (node.enum) {
|
||||
components.push({
|
||||
type: 'dropdown',
|
||||
label: node.description ?? parentNode?.description ?? 'nothing e',
|
||||
items: node.enum,
|
||||
value: data,
|
||||
});
|
||||
} else {
|
||||
components.push({
|
||||
type: 'text',
|
||||
label: node.description ?? parentNode?.description ?? 'nothing s',
|
||||
value: data,
|
||||
});
|
||||
}
|
||||
}
|
||||
if (node.type === 'number') {
|
||||
components.push({
|
||||
type: 'text',
|
||||
label: node.description ?? parentNode?.description ?? 'nothing n',
|
||||
value: data,
|
||||
});
|
||||
}
|
||||
return components;
|
||||
};
|
||||
|
||||
export function BoardDefaultsStep({
|
||||
nextStep,
|
||||
goTo,
|
||||
}: {
|
||||
nextStep: () => void;
|
||||
prevStep: () => void;
|
||||
goTo: (id: string) => void;
|
||||
}) {
|
||||
const { l10n } = useLocalization();
|
||||
const { selectedSource } = useFirmwareTool();
|
||||
|
||||
useEffect(() => {
|
||||
if (!selectedSource) return;
|
||||
const d = selectedSource?.default?.schema as any as SomeJSONSchema;
|
||||
if (!d.$defs) throw 'no defs';
|
||||
const t = refToKey(d.properties.defaults.additionalProperties.$ref);
|
||||
if (!t) throw 'unable to get defaults ref';
|
||||
const boardConfig = d.$defs[t];
|
||||
const boardValues = d.$defs[refToKey(boardConfig.properties.values.$ref)];
|
||||
const data = selectedSource.default?.defaults.values as any;
|
||||
console.log(
|
||||
// selectedSource.default?.defaults.values
|
||||
JSON.stringify(handleNode(d.$defs, boardValues, data), null, 2)
|
||||
);
|
||||
}, [selectedSource]);
|
||||
|
||||
return (
|
||||
<>
|
||||
<div className="flex flex-col w-full">
|
||||
<div className="flex flex-grow flex-col gap-4">
|
||||
<Typography>
|
||||
{l10n.getString('firmware_tool-board_step-description')}
|
||||
</Typography>
|
||||
</div>
|
||||
<div className="my-4"></div>
|
||||
</div>
|
||||
</>
|
||||
);
|
||||
}
|
||||
@@ -1,234 +0,0 @@
|
||||
import { Localized, useLocalization } from '@fluent/react';
|
||||
import { Typography } from '@/components/commons/Typography';
|
||||
import { LoaderIcon, SlimeState } from '@/components/commons/icon/LoaderIcon';
|
||||
import { useFirmwareTool } from '@/hooks/firmware-tool';
|
||||
import classNames from 'classnames';
|
||||
import { Button } from '@/components/commons/Button';
|
||||
import {
|
||||
fetchGetFirmwareBoardDefaults,
|
||||
useGetFirmwareSources,
|
||||
} from '@/firmware-tool-api/firmwareToolComponents';
|
||||
import { useEffect, useMemo, useState } from 'react';
|
||||
|
||||
function Selector({
|
||||
text,
|
||||
active,
|
||||
disabled,
|
||||
official,
|
||||
onClick,
|
||||
}: {
|
||||
text: string;
|
||||
active: boolean;
|
||||
official?: boolean;
|
||||
disabled?: boolean;
|
||||
onClick: () => void;
|
||||
}) {
|
||||
return (
|
||||
<div
|
||||
className={classNames(
|
||||
'p-3 rounded-md hover:bg-background-50 w-full cursor-pointer relative',
|
||||
{
|
||||
'bg-background-50 text-background-10': active, // FIXME: use selected source
|
||||
'bg-background-60': !active,
|
||||
'bg-background-80 text-background-50': disabled,
|
||||
}
|
||||
)}
|
||||
onClick={() => {
|
||||
if (!disabled) onClick();
|
||||
}}
|
||||
>
|
||||
{official && (
|
||||
<div className="absolute px-2 py-0.5 rounded-md bg-accent-background-20 -top-2 -right-2">
|
||||
<Typography>Official</Typography>
|
||||
</div>
|
||||
)}
|
||||
{text}
|
||||
</div>
|
||||
);
|
||||
}
|
||||
|
||||
export function SelectSourceSetep({
|
||||
nextStep,
|
||||
goTo,
|
||||
}: {
|
||||
nextStep: () => void;
|
||||
prevStep: () => void;
|
||||
goTo: (id: string) => void;
|
||||
}) {
|
||||
const { l10n } = useLocalization();
|
||||
const { setSelectedSource, selectedSource } = useFirmwareTool();
|
||||
const [partialBoard, setPartialBoard] = useState<{
|
||||
source?: string;
|
||||
version?: string;
|
||||
board?: string;
|
||||
}>();
|
||||
const { isFetching, data: sources } = useGetFirmwareSources({});
|
||||
|
||||
const { possibleBoards, possibleVersions, sourcesGroupped } = useMemo(() => {
|
||||
return {
|
||||
sourcesGroupped: sources?.reduce(
|
||||
(curr, source) => {
|
||||
if (!curr.find(({ name }) => source.source === name))
|
||||
curr.push({
|
||||
name: source.source,
|
||||
official: source.official,
|
||||
disabled:
|
||||
!partialBoard?.board ||
|
||||
!source.availableBoards.includes(partialBoard.board),
|
||||
});
|
||||
return curr;
|
||||
},
|
||||
[] as { name: string; official: boolean; disabled: boolean }[]
|
||||
),
|
||||
possibleBoards: sources?.reduce((curr, source) => {
|
||||
const unknownBoards = source.availableBoards.filter(
|
||||
(b) => !curr.includes(b)
|
||||
);
|
||||
curr.push(...unknownBoards);
|
||||
return curr;
|
||||
}, [] as string[]),
|
||||
possibleVersions: sources?.reduce(
|
||||
(curr, source) => {
|
||||
if (!curr.find(({ name }) => source.version === name))
|
||||
curr.push({
|
||||
disabled:
|
||||
!partialBoard?.board ||
|
||||
!source.availableBoards.includes(partialBoard.board) ||
|
||||
source.source !== partialBoard.source,
|
||||
name: source.version,
|
||||
});
|
||||
|
||||
return curr;
|
||||
},
|
||||
[] as { name: string; disabled: boolean }[]
|
||||
),
|
||||
};
|
||||
}, [sources, partialBoard]);
|
||||
|
||||
useEffect(() => {
|
||||
if (partialBoard?.source && partialBoard.board && partialBoard.version) {
|
||||
const params = {
|
||||
board: partialBoard.board,
|
||||
source: partialBoard.source,
|
||||
version: partialBoard.version,
|
||||
};
|
||||
fetchGetFirmwareBoardDefaults({
|
||||
queryParams: params,
|
||||
}).then((board) =>
|
||||
setSelectedSource({
|
||||
source: params,
|
||||
default: board,
|
||||
})
|
||||
);
|
||||
}
|
||||
}, [partialBoard]);
|
||||
|
||||
const formatSource = (name: string, official: boolean) => {
|
||||
return !official ? name : name.substring(name.indexOf('/') + 1);
|
||||
};
|
||||
|
||||
return (
|
||||
<>
|
||||
<div className="flex flex-col w-full">
|
||||
<div className="flex flex-grow flex-col gap-4">
|
||||
<Typography>
|
||||
{l10n.getString('firmware_tool-board_step-description')}
|
||||
</Typography>
|
||||
</div>
|
||||
<div className="my-4">
|
||||
{!isFetching && (
|
||||
<>
|
||||
<div className="grid grid-cols-3 gap-4">
|
||||
<div className="flex flex-col gap-2 w-full">
|
||||
<Typography variant="section-title">Board Type</Typography>
|
||||
<div className="flex flex-col gap-2">
|
||||
{possibleBoards?.map((board) => (
|
||||
<Selector
|
||||
active={partialBoard?.board === board}
|
||||
key={`${board}`}
|
||||
onClick={() => {
|
||||
setPartialBoard({ board });
|
||||
}}
|
||||
text={board}
|
||||
></Selector>
|
||||
))}
|
||||
</div>
|
||||
</div>
|
||||
<div className="flex flex-col gap-2 w-full">
|
||||
<Typography variant="section-title">
|
||||
Firmware Source
|
||||
</Typography>
|
||||
<div className="flex flex-col gap-2">
|
||||
{sourcesGroupped?.map(({ name, official, disabled }) => (
|
||||
<Selector
|
||||
active={partialBoard?.source === name}
|
||||
disabled={disabled}
|
||||
key={`${name}`}
|
||||
official={official}
|
||||
onClick={() => {
|
||||
setPartialBoard((curr) => ({
|
||||
...curr,
|
||||
source: name,
|
||||
}));
|
||||
}}
|
||||
text={formatSource(name, official)}
|
||||
></Selector>
|
||||
))}
|
||||
</div>
|
||||
</div>
|
||||
<div className="flex flex-col gap-2 w-full">
|
||||
<Typography variant="section-title">
|
||||
Firmware Version
|
||||
</Typography>
|
||||
<div className="flex flex-col gap-2">
|
||||
{possibleVersions?.map(({ name, disabled }) => (
|
||||
<Selector
|
||||
active={partialBoard?.version === name}
|
||||
disabled={disabled}
|
||||
key={`${name}`}
|
||||
onClick={() => {
|
||||
setPartialBoard((curr) => ({
|
||||
...curr,
|
||||
version: name,
|
||||
}));
|
||||
}}
|
||||
text={name}
|
||||
></Selector>
|
||||
))}
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<div className="flex justify-end">
|
||||
<Localized id="firmware_tool-next_step">
|
||||
<Button
|
||||
variant="primary"
|
||||
disabled={!selectedSource}
|
||||
onClick={() => {
|
||||
// if (
|
||||
// selectedSource?.default?.defaults.flashingRules
|
||||
// .shouldOnlyUseDefaults
|
||||
// ) {
|
||||
// goTo('SelectFirmware');
|
||||
// } else {
|
||||
nextStep();
|
||||
// }
|
||||
}}
|
||||
></Button>
|
||||
</Localized>
|
||||
</div>
|
||||
</>
|
||||
)}
|
||||
|
||||
{isFetching && (
|
||||
<div className="flex justify-center flex-col items-center gap-3 h-44">
|
||||
<LoaderIcon slimeState={SlimeState.JUMPY}></LoaderIcon>
|
||||
<Localized id="firmware_tool-loading">
|
||||
<Typography></Typography>
|
||||
</Localized>
|
||||
</div>
|
||||
)}
|
||||
</div>
|
||||
</div>
|
||||
</>
|
||||
);
|
||||
}
|
||||
@@ -3,7 +3,6 @@ import { Typography } from '@/components/commons/Typography';
|
||||
import { getTrackerName } from '@/hooks/tracker';
|
||||
import { ComponentProps, useEffect, useMemo, useRef, useState } from 'react';
|
||||
import {
|
||||
BoardType,
|
||||
DeviceDataT,
|
||||
DeviceIdTableT,
|
||||
FirmwareUpdateMethod,
|
||||
@@ -40,8 +39,6 @@ interface FirmwareUpdateForm {
|
||||
selectedDevices: { [key: string]: boolean };
|
||||
}
|
||||
|
||||
type SelectedDeviceWithBoard = SelectedDevice & { board: BoardType };
|
||||
|
||||
interface UpdateStatus {
|
||||
status: FirmwareUpdateStatus;
|
||||
type: FirmwareUpdateMethod;
|
||||
@@ -199,34 +196,21 @@ export function FirmwareUpdate() {
|
||||
};
|
||||
}, []);
|
||||
|
||||
const queueFlashing = (selectedDevices: SelectedDeviceWithBoard[]) => {
|
||||
const queueFlashing = (selectedDevices: SelectedDevice[]) => {
|
||||
clear();
|
||||
pendingDevicesRef.current = selectedDevices;
|
||||
const firmwareFile = currentFirmwareRelease?.firmwareFile;
|
||||
if (!firmwareFile) throw new Error('invalid state - no firmware file');
|
||||
const requests = getFlashingRequests(
|
||||
selectedDevices,
|
||||
[{ isFirmware: true, firmwareId: '', url: firmwareFile, offset: 0 }],
|
||||
{ wifi: undefined, alonePage: false, progress: 0 }, // we do not use serial
|
||||
null // we do not use serial
|
||||
);
|
||||
|
||||
if (!currentFirmwareRelease)
|
||||
throw new Error('invalid state - no fw release');
|
||||
|
||||
const groupedByBoard = selectedDevices.reduce((curr, device) => {
|
||||
const boards = curr.get(device.board) ?? [];
|
||||
boards.push(device);
|
||||
curr.set(device.board, boards);
|
||||
return curr;
|
||||
}, new Map<BoardType, SelectedDeviceWithBoard[]>());
|
||||
for (const [board, devices] of groupedByBoard) {
|
||||
if (board === BoardType.UNKNOWN) continue;
|
||||
const firmwareFile = currentFirmwareRelease.firmwareFiles[board];
|
||||
if (!firmwareFile) continue;
|
||||
const requests = getFlashingRequests(
|
||||
devices,
|
||||
[{ isFirmware: true, firmwareId: '', url: firmwareFile, offset: 0 }],
|
||||
{ wifi: undefined, alonePage: false, progress: 0 }, // we do not use serial
|
||||
null // we do not use serial
|
||||
);
|
||||
|
||||
requests.forEach((req) => {
|
||||
sendRPCPacket(RpcMessage.FirmwareUpdateRequest, req);
|
||||
});
|
||||
}
|
||||
requests.forEach((req) => {
|
||||
sendRPCPacket(RpcMessage.FirmwareUpdateRequest, req);
|
||||
});
|
||||
};
|
||||
|
||||
const trackerWithErrors = useMemo(
|
||||
@@ -297,12 +281,11 @@ export function FirmwareUpdate() {
|
||||
{
|
||||
type: FirmwareUpdateMethod.OTAFirmwareUpdate,
|
||||
deviceId: id,
|
||||
board: device.hardwareInfo?.officialBoardType ?? BoardType.UNKNOWN,
|
||||
deviceNames: deviceNames(device, l10n),
|
||||
},
|
||||
];
|
||||
},
|
||||
[] as SelectedDeviceWithBoard[]
|
||||
[] as SelectedDevice[]
|
||||
);
|
||||
if (!selectedDevices)
|
||||
throw new Error('invalid state - no selected devices');
|
||||
|
||||
@@ -170,7 +170,11 @@ export function TrackerSettingsPage() {
|
||||
currentFirmwareRelease &&
|
||||
tracker?.device?.hardwareInfo &&
|
||||
checkForUpdate(currentFirmwareRelease, tracker?.device);
|
||||
const updateUnavailable = needUpdate === null;
|
||||
const updateUnavailable =
|
||||
tracker?.device?.hardwareInfo?.officialBoardType !== BoardType.SLIMEVR ||
|
||||
!semver.valid(
|
||||
tracker?.device?.hardwareInfo?.firmwareVersion?.toString() ?? 'none'
|
||||
);
|
||||
|
||||
return (
|
||||
<form
|
||||
@@ -212,19 +216,12 @@ export function TrackerSettingsPage() {
|
||||
</Typography>
|
||||
<Typography>-</Typography>
|
||||
{updateUnavailable && (
|
||||
<Localized id="tracker-settings-update-unavailable-v2">
|
||||
<Typography>No releases found</Typography>
|
||||
<Localized id="tracker-settings-update-unavailable">
|
||||
<Typography>Cannot be updated (DIY)</Typography>
|
||||
</Localized>
|
||||
)}
|
||||
{!updateUnavailable && (
|
||||
<>
|
||||
{needUpdate === 'unavailable' && (
|
||||
<Localized id="tracker-settings-update-incompatible">
|
||||
<Typography>
|
||||
Cannot be updated, Incompatible board
|
||||
</Typography>
|
||||
</Localized>
|
||||
)}
|
||||
{needUpdate === 'blocked' && (
|
||||
// This happens only if no update is available and or the user is not in the current stagged
|
||||
<Localized id="tracker-settings-update-blocked">
|
||||
|
||||
@@ -4,10 +4,7 @@
|
||||
* @version 0.0.1
|
||||
*/
|
||||
import * as reactQuery from '@tanstack/react-query';
|
||||
import {
|
||||
useFirmwareToolContext,
|
||||
FirmwareToolContext,
|
||||
} from './firmwareToolContext';
|
||||
import { useFirmwareToolContext, FirmwareToolContext } from './firmwareToolContext';
|
||||
import type * as Fetcher from './firmwareToolFetcher';
|
||||
import { firmwareToolFetch } from './firmwareToolFetcher';
|
||||
import type * as Schemas from './firmwareToolSchemas';
|
||||
@@ -30,16 +27,7 @@ export const fetchGetIsCompatibleVersion = (
|
||||
signal?: AbortSignal
|
||||
) =>
|
||||
firmwareToolFetch<
|
||||
| {
|
||||
success: true;
|
||||
}
|
||||
| {
|
||||
success: false;
|
||||
reason: {
|
||||
message: string;
|
||||
versions: string;
|
||||
};
|
||||
},
|
||||
Schemas.VerionCheckResponse,
|
||||
GetIsCompatibleVersionError,
|
||||
undefined,
|
||||
{},
|
||||
@@ -50,51 +38,20 @@ export const fetchGetIsCompatibleVersion = (
|
||||
/**
|
||||
* Is this api compatible with the server version given
|
||||
*/
|
||||
export const useGetIsCompatibleVersion = <
|
||||
TData =
|
||||
| {
|
||||
success: true;
|
||||
}
|
||||
| {
|
||||
success: false;
|
||||
reason: {
|
||||
message: string;
|
||||
versions: string;
|
||||
};
|
||||
},
|
||||
>(
|
||||
export const useGetIsCompatibleVersion = <TData = Schemas.VerionCheckResponse>(
|
||||
variables: GetIsCompatibleVersionVariables,
|
||||
options?: Omit<
|
||||
reactQuery.UseQueryOptions<
|
||||
| {
|
||||
success: true;
|
||||
}
|
||||
| {
|
||||
success: false;
|
||||
reason: {
|
||||
message: string;
|
||||
versions: string;
|
||||
};
|
||||
},
|
||||
Schemas.VerionCheckResponse,
|
||||
GetIsCompatibleVersionError,
|
||||
TData
|
||||
>,
|
||||
'queryKey' | 'queryFn' | 'initialData'
|
||||
>
|
||||
) => {
|
||||
const { fetcherOptions, queryOptions, queryKeyFn } =
|
||||
useFirmwareToolContext(options);
|
||||
const { fetcherOptions, queryOptions, queryKeyFn } = useFirmwareToolContext(options);
|
||||
return reactQuery.useQuery<
|
||||
| {
|
||||
success: true;
|
||||
}
|
||||
| {
|
||||
success: false;
|
||||
reason: {
|
||||
message: string;
|
||||
versions: string;
|
||||
};
|
||||
},
|
||||
Schemas.VerionCheckResponse,
|
||||
GetIsCompatibleVersionError,
|
||||
TData
|
||||
>({
|
||||
@@ -110,6 +67,504 @@ export const useGetIsCompatibleVersion = <
|
||||
});
|
||||
};
|
||||
|
||||
export type GetFirmwaresError = Fetcher.ErrorWrapper<undefined>;
|
||||
|
||||
export type GetFirmwaresResponse = Schemas.FirmwareDTO[];
|
||||
|
||||
export type GetFirmwaresVariables = FirmwareToolContext['fetcherOptions'];
|
||||
|
||||
/**
|
||||
* List all the built firmwares
|
||||
*/
|
||||
export const fetchGetFirmwares = (
|
||||
variables: GetFirmwaresVariables,
|
||||
signal?: AbortSignal
|
||||
) =>
|
||||
firmwareToolFetch<GetFirmwaresResponse, GetFirmwaresError, undefined, {}, {}, {}>({
|
||||
url: '/firmwares',
|
||||
method: 'get',
|
||||
...variables,
|
||||
signal,
|
||||
});
|
||||
|
||||
/**
|
||||
* List all the built firmwares
|
||||
*/
|
||||
export const useGetFirmwares = <TData = GetFirmwaresResponse>(
|
||||
variables: GetFirmwaresVariables,
|
||||
options?: Omit<
|
||||
reactQuery.UseQueryOptions<GetFirmwaresResponse, GetFirmwaresError, TData>,
|
||||
'queryKey' | 'queryFn' | 'initialData'
|
||||
>
|
||||
) => {
|
||||
const { fetcherOptions, queryOptions, queryKeyFn } = useFirmwareToolContext(options);
|
||||
return reactQuery.useQuery<GetFirmwaresResponse, GetFirmwaresError, TData>({
|
||||
queryKey: queryKeyFn({
|
||||
path: '/firmwares',
|
||||
operationId: 'getFirmwares',
|
||||
variables,
|
||||
}),
|
||||
queryFn: ({ signal }) =>
|
||||
fetchGetFirmwares({ ...fetcherOptions, ...variables }, signal),
|
||||
...options,
|
||||
...queryOptions,
|
||||
});
|
||||
};
|
||||
|
||||
export type PostFirmwaresBuildError = Fetcher.ErrorWrapper<{
|
||||
status: 400;
|
||||
payload: Schemas.VersionNotFoundExeption;
|
||||
}>;
|
||||
|
||||
export type PostFirmwaresBuildVariables = {
|
||||
body: Schemas.CreateBuildFirmwareDTO;
|
||||
} & FirmwareToolContext['fetcherOptions'];
|
||||
|
||||
/**
|
||||
* Build a firmware from the requested configuration
|
||||
*/
|
||||
export const fetchPostFirmwaresBuild = (
|
||||
variables: PostFirmwaresBuildVariables,
|
||||
signal?: AbortSignal
|
||||
) =>
|
||||
firmwareToolFetch<
|
||||
Schemas.BuildResponseDTO,
|
||||
PostFirmwaresBuildError,
|
||||
Schemas.CreateBuildFirmwareDTO,
|
||||
{},
|
||||
{},
|
||||
{}
|
||||
>({ url: '/firmwares/build', method: 'post', ...variables, signal });
|
||||
|
||||
/**
|
||||
* Build a firmware from the requested configuration
|
||||
*/
|
||||
export const usePostFirmwaresBuild = (
|
||||
options?: Omit<
|
||||
reactQuery.UseMutationOptions<
|
||||
Schemas.BuildResponseDTO,
|
||||
PostFirmwaresBuildError,
|
||||
PostFirmwaresBuildVariables
|
||||
>,
|
||||
'mutationFn'
|
||||
>
|
||||
) => {
|
||||
const { fetcherOptions } = useFirmwareToolContext();
|
||||
return reactQuery.useMutation<
|
||||
Schemas.BuildResponseDTO,
|
||||
PostFirmwaresBuildError,
|
||||
PostFirmwaresBuildVariables
|
||||
>({
|
||||
mutationFn: (variables: PostFirmwaresBuildVariables) =>
|
||||
fetchPostFirmwaresBuild({ ...fetcherOptions, ...variables }),
|
||||
...options,
|
||||
});
|
||||
};
|
||||
|
||||
export type GetFirmwaresBuildStatusIdPathParams = {
|
||||
id: string;
|
||||
};
|
||||
|
||||
export type GetFirmwaresBuildStatusIdError = Fetcher.ErrorWrapper<undefined>;
|
||||
|
||||
export type GetFirmwaresBuildStatusIdVariables = {
|
||||
pathParams: GetFirmwaresBuildStatusIdPathParams;
|
||||
} & FirmwareToolContext['fetcherOptions'];
|
||||
|
||||
/**
|
||||
* Get the build status of a firmware
|
||||
* This is a SSE (Server Sent Event)
|
||||
* you can use the web browser api to check for the build status and update the ui in real time
|
||||
*/
|
||||
export const fetchGetFirmwaresBuildStatusId = (
|
||||
variables: GetFirmwaresBuildStatusIdVariables,
|
||||
signal?: AbortSignal
|
||||
) =>
|
||||
firmwareToolFetch<
|
||||
Schemas.ObservableType,
|
||||
GetFirmwaresBuildStatusIdError,
|
||||
undefined,
|
||||
{},
|
||||
{},
|
||||
GetFirmwaresBuildStatusIdPathParams
|
||||
>({
|
||||
url: '/firmwares/build-status/{id}',
|
||||
method: 'get',
|
||||
...variables,
|
||||
signal,
|
||||
});
|
||||
|
||||
/**
|
||||
* Get the build status of a firmware
|
||||
* This is a SSE (Server Sent Event)
|
||||
* you can use the web browser api to check for the build status and update the ui in real time
|
||||
*/
|
||||
export const useGetFirmwaresBuildStatusId = <TData = Schemas.ObservableType>(
|
||||
variables: GetFirmwaresBuildStatusIdVariables,
|
||||
options?: Omit<
|
||||
reactQuery.UseQueryOptions<
|
||||
Schemas.ObservableType,
|
||||
GetFirmwaresBuildStatusIdError,
|
||||
TData
|
||||
>,
|
||||
'queryKey' | 'queryFn' | 'initialData'
|
||||
>
|
||||
) => {
|
||||
const { fetcherOptions, queryOptions, queryKeyFn } = useFirmwareToolContext(options);
|
||||
return reactQuery.useQuery<
|
||||
Schemas.ObservableType,
|
||||
GetFirmwaresBuildStatusIdError,
|
||||
TData
|
||||
>({
|
||||
queryKey: queryKeyFn({
|
||||
path: '/firmwares/build-status/{id}',
|
||||
operationId: 'getFirmwaresBuildStatusId',
|
||||
variables,
|
||||
}),
|
||||
queryFn: ({ signal }) =>
|
||||
fetchGetFirmwaresBuildStatusId({ ...fetcherOptions, ...variables }, signal),
|
||||
...options,
|
||||
...queryOptions,
|
||||
});
|
||||
};
|
||||
|
||||
export type GetFirmwaresBoardsError = Fetcher.ErrorWrapper<undefined>;
|
||||
|
||||
export type GetFirmwaresBoardsResponse = string[];
|
||||
|
||||
export type GetFirmwaresBoardsVariables = FirmwareToolContext['fetcherOptions'];
|
||||
|
||||
/**
|
||||
* List all the possible board types
|
||||
*/
|
||||
export const fetchGetFirmwaresBoards = (
|
||||
variables: GetFirmwaresBoardsVariables,
|
||||
signal?: AbortSignal
|
||||
) =>
|
||||
firmwareToolFetch<
|
||||
GetFirmwaresBoardsResponse,
|
||||
GetFirmwaresBoardsError,
|
||||
undefined,
|
||||
{},
|
||||
{},
|
||||
{}
|
||||
>({ url: '/firmwares/boards', method: 'get', ...variables, signal });
|
||||
|
||||
/**
|
||||
* List all the possible board types
|
||||
*/
|
||||
export const useGetFirmwaresBoards = <TData = GetFirmwaresBoardsResponse>(
|
||||
variables: GetFirmwaresBoardsVariables,
|
||||
options?: Omit<
|
||||
reactQuery.UseQueryOptions<
|
||||
GetFirmwaresBoardsResponse,
|
||||
GetFirmwaresBoardsError,
|
||||
TData
|
||||
>,
|
||||
'queryKey' | 'queryFn' | 'initialData'
|
||||
>
|
||||
) => {
|
||||
const { fetcherOptions, queryOptions, queryKeyFn } = useFirmwareToolContext(options);
|
||||
return reactQuery.useQuery<
|
||||
GetFirmwaresBoardsResponse,
|
||||
GetFirmwaresBoardsError,
|
||||
TData
|
||||
>({
|
||||
queryKey: queryKeyFn({
|
||||
path: '/firmwares/boards',
|
||||
operationId: 'getFirmwaresBoards',
|
||||
variables,
|
||||
}),
|
||||
queryFn: ({ signal }) =>
|
||||
fetchGetFirmwaresBoards({ ...fetcherOptions, ...variables }, signal),
|
||||
...options,
|
||||
...queryOptions,
|
||||
});
|
||||
};
|
||||
|
||||
export type GetFirmwaresVersionsError = Fetcher.ErrorWrapper<undefined>;
|
||||
|
||||
export type GetFirmwaresVersionsResponse = Schemas.ReleaseDTO[];
|
||||
|
||||
export type GetFirmwaresVersionsVariables = FirmwareToolContext['fetcherOptions'];
|
||||
|
||||
/**
|
||||
* List all the possible versions to build a firmware from
|
||||
*/
|
||||
export const fetchGetFirmwaresVersions = (
|
||||
variables: GetFirmwaresVersionsVariables,
|
||||
signal?: AbortSignal
|
||||
) =>
|
||||
firmwareToolFetch<
|
||||
GetFirmwaresVersionsResponse,
|
||||
GetFirmwaresVersionsError,
|
||||
undefined,
|
||||
{},
|
||||
{},
|
||||
{}
|
||||
>({ url: '/firmwares/versions', method: 'get', ...variables, signal });
|
||||
|
||||
/**
|
||||
* List all the possible versions to build a firmware from
|
||||
*/
|
||||
export const useGetFirmwaresVersions = <TData = GetFirmwaresVersionsResponse>(
|
||||
variables: GetFirmwaresVersionsVariables,
|
||||
options?: Omit<
|
||||
reactQuery.UseQueryOptions<
|
||||
GetFirmwaresVersionsResponse,
|
||||
GetFirmwaresVersionsError,
|
||||
TData
|
||||
>,
|
||||
'queryKey' | 'queryFn' | 'initialData'
|
||||
>
|
||||
) => {
|
||||
const { fetcherOptions, queryOptions, queryKeyFn } = useFirmwareToolContext(options);
|
||||
return reactQuery.useQuery<
|
||||
GetFirmwaresVersionsResponse,
|
||||
GetFirmwaresVersionsError,
|
||||
TData
|
||||
>({
|
||||
queryKey: queryKeyFn({
|
||||
path: '/firmwares/versions',
|
||||
operationId: 'getFirmwaresVersions',
|
||||
variables,
|
||||
}),
|
||||
queryFn: ({ signal }) =>
|
||||
fetchGetFirmwaresVersions({ ...fetcherOptions, ...variables }, signal),
|
||||
...options,
|
||||
...queryOptions,
|
||||
});
|
||||
};
|
||||
|
||||
export type GetFirmwaresImusError = Fetcher.ErrorWrapper<undefined>;
|
||||
|
||||
export type GetFirmwaresImusResponse = Schemas.Imudto[];
|
||||
|
||||
export type GetFirmwaresImusVariables = FirmwareToolContext['fetcherOptions'];
|
||||
|
||||
/**
|
||||
* List all the possible imus to use
|
||||
*/
|
||||
export const fetchGetFirmwaresImus = (
|
||||
variables: GetFirmwaresImusVariables,
|
||||
signal?: AbortSignal
|
||||
) =>
|
||||
firmwareToolFetch<
|
||||
GetFirmwaresImusResponse,
|
||||
GetFirmwaresImusError,
|
||||
undefined,
|
||||
{},
|
||||
{},
|
||||
{}
|
||||
>({ url: '/firmwares/imus', method: 'get', ...variables, signal });
|
||||
|
||||
/**
|
||||
* List all the possible imus to use
|
||||
*/
|
||||
export const useGetFirmwaresImus = <TData = GetFirmwaresImusResponse>(
|
||||
variables: GetFirmwaresImusVariables,
|
||||
options?: Omit<
|
||||
reactQuery.UseQueryOptions<GetFirmwaresImusResponse, GetFirmwaresImusError, TData>,
|
||||
'queryKey' | 'queryFn' | 'initialData'
|
||||
>
|
||||
) => {
|
||||
const { fetcherOptions, queryOptions, queryKeyFn } = useFirmwareToolContext(options);
|
||||
return reactQuery.useQuery<GetFirmwaresImusResponse, GetFirmwaresImusError, TData>({
|
||||
queryKey: queryKeyFn({
|
||||
path: '/firmwares/imus',
|
||||
operationId: 'getFirmwaresImus',
|
||||
variables,
|
||||
}),
|
||||
queryFn: ({ signal }) =>
|
||||
fetchGetFirmwaresImus({ ...fetcherOptions, ...variables }, signal),
|
||||
...options,
|
||||
...queryOptions,
|
||||
});
|
||||
};
|
||||
|
||||
export type GetFirmwaresBatteriesError = Fetcher.ErrorWrapper<undefined>;
|
||||
|
||||
export type GetFirmwaresBatteriesResponse = string[];
|
||||
|
||||
export type GetFirmwaresBatteriesVariables = FirmwareToolContext['fetcherOptions'];
|
||||
|
||||
/**
|
||||
* List all the battery types
|
||||
*/
|
||||
export const fetchGetFirmwaresBatteries = (
|
||||
variables: GetFirmwaresBatteriesVariables,
|
||||
signal?: AbortSignal
|
||||
) =>
|
||||
firmwareToolFetch<
|
||||
GetFirmwaresBatteriesResponse,
|
||||
GetFirmwaresBatteriesError,
|
||||
undefined,
|
||||
{},
|
||||
{},
|
||||
{}
|
||||
>({ url: '/firmwares/batteries', method: 'get', ...variables, signal });
|
||||
|
||||
/**
|
||||
* List all the battery types
|
||||
*/
|
||||
export const useGetFirmwaresBatteries = <TData = GetFirmwaresBatteriesResponse>(
|
||||
variables: GetFirmwaresBatteriesVariables,
|
||||
options?: Omit<
|
||||
reactQuery.UseQueryOptions<
|
||||
GetFirmwaresBatteriesResponse,
|
||||
GetFirmwaresBatteriesError,
|
||||
TData
|
||||
>,
|
||||
'queryKey' | 'queryFn' | 'initialData'
|
||||
>
|
||||
) => {
|
||||
const { fetcherOptions, queryOptions, queryKeyFn } = useFirmwareToolContext(options);
|
||||
return reactQuery.useQuery<
|
||||
GetFirmwaresBatteriesResponse,
|
||||
GetFirmwaresBatteriesError,
|
||||
TData
|
||||
>({
|
||||
queryKey: queryKeyFn({
|
||||
path: '/firmwares/batteries',
|
||||
operationId: 'getFirmwaresBatteries',
|
||||
variables,
|
||||
}),
|
||||
queryFn: ({ signal }) =>
|
||||
fetchGetFirmwaresBatteries({ ...fetcherOptions, ...variables }, signal),
|
||||
...options,
|
||||
...queryOptions,
|
||||
});
|
||||
};
|
||||
|
||||
export type GetFirmwaresDefaultConfigBoardPathParams = {
|
||||
board:
|
||||
| 'BOARD_SLIMEVR'
|
||||
| 'BOARD_NODEMCU'
|
||||
| 'BOARD_WROOM32'
|
||||
| 'BOARD_WEMOSD1MINI'
|
||||
| 'BOARD_TTGO_TBASE'
|
||||
| 'BOARD_ESP01'
|
||||
| 'BOARD_LOLIN_C3_MINI'
|
||||
| 'BOARD_BEETLE32C3'
|
||||
| 'BOARD_ES32C3DEVKITM1';
|
||||
};
|
||||
|
||||
export type GetFirmwaresDefaultConfigBoardError = Fetcher.ErrorWrapper<undefined>;
|
||||
|
||||
export type GetFirmwaresDefaultConfigBoardVariables = {
|
||||
pathParams: GetFirmwaresDefaultConfigBoardPathParams;
|
||||
} & FirmwareToolContext['fetcherOptions'];
|
||||
|
||||
/**
|
||||
* Gives the default pins / configuration of a given board
|
||||
*/
|
||||
export const fetchGetFirmwaresDefaultConfigBoard = (
|
||||
variables: GetFirmwaresDefaultConfigBoardVariables,
|
||||
signal?: AbortSignal
|
||||
) =>
|
||||
firmwareToolFetch<
|
||||
Schemas.DefaultBuildConfigDTO,
|
||||
GetFirmwaresDefaultConfigBoardError,
|
||||
undefined,
|
||||
{},
|
||||
{},
|
||||
GetFirmwaresDefaultConfigBoardPathParams
|
||||
>({
|
||||
url: '/firmwares/default-config/{board}',
|
||||
method: 'get',
|
||||
...variables,
|
||||
signal,
|
||||
});
|
||||
|
||||
/**
|
||||
* Gives the default pins / configuration of a given board
|
||||
*/
|
||||
export const useGetFirmwaresDefaultConfigBoard = <
|
||||
TData = Schemas.DefaultBuildConfigDTO,
|
||||
>(
|
||||
variables: GetFirmwaresDefaultConfigBoardVariables,
|
||||
options?: Omit<
|
||||
reactQuery.UseQueryOptions<
|
||||
Schemas.DefaultBuildConfigDTO,
|
||||
GetFirmwaresDefaultConfigBoardError,
|
||||
TData
|
||||
>,
|
||||
'queryKey' | 'queryFn' | 'initialData'
|
||||
>
|
||||
) => {
|
||||
const { fetcherOptions, queryOptions, queryKeyFn } = useFirmwareToolContext(options);
|
||||
return reactQuery.useQuery<
|
||||
Schemas.DefaultBuildConfigDTO,
|
||||
GetFirmwaresDefaultConfigBoardError,
|
||||
TData
|
||||
>({
|
||||
queryKey: queryKeyFn({
|
||||
path: '/firmwares/default-config/{board}',
|
||||
operationId: 'getFirmwaresDefaultConfigBoard',
|
||||
variables,
|
||||
}),
|
||||
queryFn: ({ signal }) =>
|
||||
fetchGetFirmwaresDefaultConfigBoard({ ...fetcherOptions, ...variables }, signal),
|
||||
...options,
|
||||
...queryOptions,
|
||||
});
|
||||
};
|
||||
|
||||
export type GetFirmwaresIdPathParams = {
|
||||
id: string;
|
||||
};
|
||||
|
||||
export type GetFirmwaresIdError = Fetcher.ErrorWrapper<{
|
||||
status: 404;
|
||||
payload: Schemas.HttpException;
|
||||
}>;
|
||||
|
||||
export type GetFirmwaresIdVariables = {
|
||||
pathParams: GetFirmwaresIdPathParams;
|
||||
} & FirmwareToolContext['fetcherOptions'];
|
||||
|
||||
/**
|
||||
* Get the inforamtions about a firmware from its id
|
||||
* also provide more informations than the simple list, like pins and imus and files
|
||||
*/
|
||||
export const fetchGetFirmwaresId = (
|
||||
variables: GetFirmwaresIdVariables,
|
||||
signal?: AbortSignal
|
||||
) =>
|
||||
firmwareToolFetch<
|
||||
Schemas.FirmwareDetailDTO,
|
||||
GetFirmwaresIdError,
|
||||
undefined,
|
||||
{},
|
||||
{},
|
||||
GetFirmwaresIdPathParams
|
||||
>({ url: '/firmwares/{id}', method: 'get', ...variables, signal });
|
||||
|
||||
/**
|
||||
* Get the inforamtions about a firmware from its id
|
||||
* also provide more informations than the simple list, like pins and imus and files
|
||||
*/
|
||||
export const useGetFirmwaresId = <TData = Schemas.FirmwareDetailDTO>(
|
||||
variables: GetFirmwaresIdVariables,
|
||||
options?: Omit<
|
||||
reactQuery.UseQueryOptions<Schemas.FirmwareDetailDTO, GetFirmwaresIdError, TData>,
|
||||
'queryKey' | 'queryFn' | 'initialData'
|
||||
>
|
||||
) => {
|
||||
const { fetcherOptions, queryOptions, queryKeyFn } = useFirmwareToolContext(options);
|
||||
return reactQuery.useQuery<Schemas.FirmwareDetailDTO, GetFirmwaresIdError, TData>({
|
||||
queryKey: queryKeyFn({
|
||||
path: '/firmwares/{id}',
|
||||
operationId: 'getFirmwaresId',
|
||||
variables,
|
||||
}),
|
||||
queryFn: ({ signal }) =>
|
||||
fetchGetFirmwaresId({ ...fetcherOptions, ...variables }, signal),
|
||||
...options,
|
||||
...queryOptions,
|
||||
});
|
||||
};
|
||||
|
||||
export type GetHealthError = Fetcher.ErrorWrapper<undefined>;
|
||||
|
||||
export type GetHealthVariables = FirmwareToolContext['fetcherOptions'];
|
||||
@@ -118,10 +573,7 @@ export type GetHealthVariables = FirmwareToolContext['fetcherOptions'];
|
||||
* Gives the status of the api
|
||||
* this endpoint will always return true
|
||||
*/
|
||||
export const fetchGetHealth = (
|
||||
variables: GetHealthVariables,
|
||||
signal?: AbortSignal
|
||||
) =>
|
||||
export const fetchGetHealth = (variables: GetHealthVariables, signal?: AbortSignal) =>
|
||||
firmwareToolFetch<boolean, GetHealthError, undefined, {}, {}, {}>({
|
||||
url: '/health',
|
||||
method: 'get',
|
||||
@@ -133,15 +585,14 @@ export const fetchGetHealth = (
|
||||
* Gives the status of the api
|
||||
* this endpoint will always return true
|
||||
*/
|
||||
export const useGetHealth = <TData = boolean,>(
|
||||
export const useGetHealth = <TData = boolean>(
|
||||
variables: GetHealthVariables,
|
||||
options?: Omit<
|
||||
reactQuery.UseQueryOptions<boolean, GetHealthError, TData>,
|
||||
'queryKey' | 'queryFn' | 'initialData'
|
||||
>
|
||||
) => {
|
||||
const { fetcherOptions, queryOptions, queryKeyFn } =
|
||||
useFirmwareToolContext(options);
|
||||
const { fetcherOptions, queryOptions, queryKeyFn } = useFirmwareToolContext(options);
|
||||
return reactQuery.useQuery<boolean, GetHealthError, TData>({
|
||||
queryKey: queryKeyFn({
|
||||
path: '/health',
|
||||
@@ -155,252 +606,54 @@ export const useGetHealth = <TData = boolean,>(
|
||||
});
|
||||
};
|
||||
|
||||
export type GetFirmwareSourcesError = Fetcher.ErrorWrapper<undefined>;
|
||||
|
||||
export type GetFirmwareSourcesResponse = Schemas.FirmwareSource[];
|
||||
|
||||
export type GetFirmwareSourcesVariables = FirmwareToolContext['fetcherOptions'];
|
||||
|
||||
/**
|
||||
* List all the sources you can build a firmware from
|
||||
*/
|
||||
export const fetchGetFirmwareSources = (
|
||||
variables: GetFirmwareSourcesVariables,
|
||||
signal?: AbortSignal
|
||||
) =>
|
||||
firmwareToolFetch<
|
||||
GetFirmwareSourcesResponse,
|
||||
GetFirmwareSourcesError,
|
||||
undefined,
|
||||
{},
|
||||
{},
|
||||
{}
|
||||
>({ url: '/firmware/sources', method: 'get', ...variables, signal });
|
||||
|
||||
/**
|
||||
* List all the sources you can build a firmware from
|
||||
*/
|
||||
export const useGetFirmwareSources = <TData = GetFirmwareSourcesResponse,>(
|
||||
variables: GetFirmwareSourcesVariables,
|
||||
options?: Omit<
|
||||
reactQuery.UseQueryOptions<
|
||||
GetFirmwareSourcesResponse,
|
||||
GetFirmwareSourcesError,
|
||||
TData
|
||||
>,
|
||||
'queryKey' | 'queryFn' | 'initialData'
|
||||
>
|
||||
) => {
|
||||
const { fetcherOptions, queryOptions, queryKeyFn } =
|
||||
useFirmwareToolContext(options);
|
||||
return reactQuery.useQuery<
|
||||
GetFirmwareSourcesResponse,
|
||||
GetFirmwareSourcesError,
|
||||
TData
|
||||
>({
|
||||
queryKey: queryKeyFn({
|
||||
path: '/firmware/sources',
|
||||
operationId: 'getFirmwareSources',
|
||||
variables,
|
||||
}),
|
||||
queryFn: ({ signal }) =>
|
||||
fetchGetFirmwareSources({ ...fetcherOptions, ...variables }, signal),
|
||||
...options,
|
||||
...queryOptions,
|
||||
});
|
||||
};
|
||||
|
||||
export type GetFirmwareBoardDefaultsQueryParams = {
|
||||
source: string;
|
||||
board: string;
|
||||
version: string;
|
||||
};
|
||||
|
||||
export type GetFirmwareBoardDefaultsError = Fetcher.ErrorWrapper<undefined>;
|
||||
|
||||
export type GetFirmwareBoardDefaultsVariables = {
|
||||
queryParams: GetFirmwareBoardDefaultsQueryParams;
|
||||
} & FirmwareToolContext['fetcherOptions'];
|
||||
|
||||
/**
|
||||
* Fet the defaults of a specific board on a specific firmware
|
||||
*/
|
||||
export const fetchGetFirmwareBoardDefaults = (
|
||||
variables: GetFirmwareBoardDefaultsVariables,
|
||||
signal?: AbortSignal
|
||||
) =>
|
||||
firmwareToolFetch<
|
||||
Schemas.FirmwareBoardDefaultsNullable,
|
||||
GetFirmwareBoardDefaultsError,
|
||||
undefined,
|
||||
{},
|
||||
GetFirmwareBoardDefaultsQueryParams,
|
||||
{}
|
||||
>({ url: '/firmware/board-defaults', method: 'get', ...variables, signal });
|
||||
|
||||
/**
|
||||
* Fet the defaults of a specific board on a specific firmware
|
||||
*/
|
||||
export const useGetFirmwareBoardDefaults = <
|
||||
TData = Schemas.FirmwareBoardDefaultsNullable,
|
||||
>(
|
||||
variables: GetFirmwareBoardDefaultsVariables,
|
||||
options?: Omit<
|
||||
reactQuery.UseQueryOptions<
|
||||
Schemas.FirmwareBoardDefaultsNullable,
|
||||
GetFirmwareBoardDefaultsError,
|
||||
TData
|
||||
>,
|
||||
'queryKey' | 'queryFn' | 'initialData'
|
||||
>
|
||||
) => {
|
||||
const { fetcherOptions, queryOptions, queryKeyFn } =
|
||||
useFirmwareToolContext(options);
|
||||
return reactQuery.useQuery<
|
||||
Schemas.FirmwareBoardDefaultsNullable,
|
||||
GetFirmwareBoardDefaultsError,
|
||||
TData
|
||||
>({
|
||||
queryKey: queryKeyFn({
|
||||
path: '/firmware/board-defaults',
|
||||
operationId: 'getFirmwareBoardDefaults',
|
||||
variables,
|
||||
}),
|
||||
queryFn: ({ signal }) =>
|
||||
fetchGetFirmwareBoardDefaults(
|
||||
{ ...fetcherOptions, ...variables },
|
||||
signal
|
||||
),
|
||||
...options,
|
||||
...queryOptions,
|
||||
});
|
||||
};
|
||||
|
||||
export type PostFirmwareBuildError = Fetcher.ErrorWrapper<undefined>;
|
||||
|
||||
export type PostFirmwareBuildVariables = {
|
||||
body: Schemas.BuildFirmwareBody;
|
||||
} & FirmwareToolContext['fetcherOptions'];
|
||||
|
||||
export const fetchPostFirmwareBuild = (
|
||||
variables: PostFirmwareBuildVariables,
|
||||
signal?: AbortSignal
|
||||
) =>
|
||||
firmwareToolFetch<
|
||||
Schemas.BuildStatusBasic | Schemas.BuildStatusDone,
|
||||
PostFirmwareBuildError,
|
||||
Schemas.BuildFirmwareBody,
|
||||
{},
|
||||
{},
|
||||
{}
|
||||
>({ url: '/firmware/build', method: 'post', ...variables, signal });
|
||||
|
||||
export const usePostFirmwareBuild = (
|
||||
options?: Omit<
|
||||
reactQuery.UseMutationOptions<
|
||||
Schemas.BuildStatusBasic | Schemas.BuildStatusDone,
|
||||
PostFirmwareBuildError,
|
||||
PostFirmwareBuildVariables
|
||||
>,
|
||||
'mutationFn'
|
||||
>
|
||||
) => {
|
||||
const { fetcherOptions } = useFirmwareToolContext();
|
||||
return reactQuery.useMutation<
|
||||
Schemas.BuildStatusBasic | Schemas.BuildStatusDone,
|
||||
PostFirmwareBuildError,
|
||||
PostFirmwareBuildVariables
|
||||
>({
|
||||
mutationFn: (variables: PostFirmwareBuildVariables) =>
|
||||
fetchPostFirmwareBuild({ ...fetcherOptions, ...variables }),
|
||||
...options,
|
||||
});
|
||||
};
|
||||
|
||||
export type GetFirmwareIdPathParams = {
|
||||
id: string;
|
||||
};
|
||||
|
||||
export type GetFirmwareIdError = Fetcher.ErrorWrapper<undefined>;
|
||||
|
||||
export type GetFirmwareIdVariables = {
|
||||
pathParams: GetFirmwareIdPathParams;
|
||||
} & FirmwareToolContext['fetcherOptions'];
|
||||
|
||||
/**
|
||||
* Get the inforamtions about a firmware from its id
|
||||
* also provide more informations than the simple list, like pins and imus and files
|
||||
*/
|
||||
export const fetchGetFirmwareId = (
|
||||
variables: GetFirmwareIdVariables,
|
||||
signal?: AbortSignal
|
||||
) =>
|
||||
firmwareToolFetch<
|
||||
Schemas.FirmwareWithFiles,
|
||||
GetFirmwareIdError,
|
||||
undefined,
|
||||
{},
|
||||
{},
|
||||
GetFirmwareIdPathParams
|
||||
>({ url: '/firmware/{id}', method: 'get', ...variables, signal });
|
||||
|
||||
/**
|
||||
* Get the inforamtions about a firmware from its id
|
||||
* also provide more informations than the simple list, like pins and imus and files
|
||||
*/
|
||||
export const useGetFirmwareId = <TData = Schemas.FirmwareWithFiles,>(
|
||||
variables: GetFirmwareIdVariables,
|
||||
options?: Omit<
|
||||
reactQuery.UseQueryOptions<
|
||||
Schemas.FirmwareWithFiles,
|
||||
GetFirmwareIdError,
|
||||
TData
|
||||
>,
|
||||
'queryKey' | 'queryFn' | 'initialData'
|
||||
>
|
||||
) => {
|
||||
const { fetcherOptions, queryOptions, queryKeyFn } =
|
||||
useFirmwareToolContext(options);
|
||||
return reactQuery.useQuery<
|
||||
Schemas.FirmwareWithFiles,
|
||||
GetFirmwareIdError,
|
||||
TData
|
||||
>({
|
||||
queryKey: queryKeyFn({
|
||||
path: '/firmware/{id}',
|
||||
operationId: 'getFirmwareId',
|
||||
variables,
|
||||
}),
|
||||
queryFn: ({ signal }) =>
|
||||
fetchGetFirmwareId({ ...fetcherOptions, ...variables }, signal),
|
||||
...options,
|
||||
...queryOptions,
|
||||
});
|
||||
};
|
||||
|
||||
export type QueryOperation =
|
||||
| {
|
||||
path: '/is-compatible/{version}';
|
||||
operationId: 'getIsCompatibleVersion';
|
||||
variables: GetIsCompatibleVersionVariables;
|
||||
}
|
||||
| {
|
||||
path: '/firmwares';
|
||||
operationId: 'getFirmwares';
|
||||
variables: GetFirmwaresVariables;
|
||||
}
|
||||
| {
|
||||
path: '/firmwares/build-status/{id}';
|
||||
operationId: 'getFirmwaresBuildStatusId';
|
||||
variables: GetFirmwaresBuildStatusIdVariables;
|
||||
}
|
||||
| {
|
||||
path: '/firmwares/boards';
|
||||
operationId: 'getFirmwaresBoards';
|
||||
variables: GetFirmwaresBoardsVariables;
|
||||
}
|
||||
| {
|
||||
path: '/firmwares/versions';
|
||||
operationId: 'getFirmwaresVersions';
|
||||
variables: GetFirmwaresVersionsVariables;
|
||||
}
|
||||
| {
|
||||
path: '/firmwares/imus';
|
||||
operationId: 'getFirmwaresImus';
|
||||
variables: GetFirmwaresImusVariables;
|
||||
}
|
||||
| {
|
||||
path: '/firmwares/batteries';
|
||||
operationId: 'getFirmwaresBatteries';
|
||||
variables: GetFirmwaresBatteriesVariables;
|
||||
}
|
||||
| {
|
||||
path: '/firmwares/default-config/{board}';
|
||||
operationId: 'getFirmwaresDefaultConfigBoard';
|
||||
variables: GetFirmwaresDefaultConfigBoardVariables;
|
||||
}
|
||||
| {
|
||||
path: '/firmwares/{id}';
|
||||
operationId: 'getFirmwaresId';
|
||||
variables: GetFirmwaresIdVariables;
|
||||
}
|
||||
| {
|
||||
path: '/health';
|
||||
operationId: 'getHealth';
|
||||
variables: GetHealthVariables;
|
||||
}
|
||||
| {
|
||||
path: '/firmware/sources';
|
||||
operationId: 'getFirmwareSources';
|
||||
variables: GetFirmwareSourcesVariables;
|
||||
}
|
||||
| {
|
||||
path: '/firmware/board-defaults';
|
||||
operationId: 'getFirmwareBoardDefaults';
|
||||
variables: GetFirmwareBoardDefaultsVariables;
|
||||
}
|
||||
| {
|
||||
path: '/firmware/{id}';
|
||||
operationId: 'getFirmwareId';
|
||||
variables: GetFirmwareIdVariables;
|
||||
};
|
||||
|
||||
@@ -3,96 +3,606 @@
|
||||
*
|
||||
* @version 0.0.1
|
||||
*/
|
||||
export type FirmwareSource = {
|
||||
version: string;
|
||||
source: string;
|
||||
branch?: string;
|
||||
official: boolean;
|
||||
prerelease: boolean;
|
||||
availableBoards: string[];
|
||||
};
|
||||
|
||||
export type FirmwareBoardDefaults = {
|
||||
schema: void;
|
||||
defaults: BoardDefaults;
|
||||
};
|
||||
|
||||
export type BoardDefaults = {
|
||||
values: void;
|
||||
editable: string[];
|
||||
flashingRules: {
|
||||
applicationOffset: number;
|
||||
needBootPress: boolean;
|
||||
needManualReboot: boolean;
|
||||
shouldOnlyUseDefaults: boolean;
|
||||
export type VerionCheckResponse = {
|
||||
success: boolean;
|
||||
reason?: {
|
||||
message: string;
|
||||
versions: string;
|
||||
};
|
||||
};
|
||||
|
||||
export type BoardDefaultsQuery = {
|
||||
source: string;
|
||||
board: string;
|
||||
version: string;
|
||||
};
|
||||
|
||||
export type BuildStatusBasic = {
|
||||
/**
|
||||
* Root object declaring a built firmware
|
||||
* this object contains:
|
||||
* - the status of the build
|
||||
* - the the repository and commit used as source
|
||||
*/
|
||||
export type FirmwareDTO = {
|
||||
/**
|
||||
* UUID of the firmware
|
||||
*
|
||||
* @format uuid
|
||||
*/
|
||||
id: string;
|
||||
status:
|
||||
| 'QUEUED'
|
||||
/**
|
||||
* Id of the firmware version used.
|
||||
* Usually the commit id of the source
|
||||
* used to build the firmware
|
||||
*/
|
||||
releaseId: string;
|
||||
/**
|
||||
* Current status of the build
|
||||
* this value will change during the build
|
||||
* process
|
||||
*
|
||||
* BUILDING -> DONE \\ the firmwrare is build and ready
|
||||
* -> FAILED \\ the build failled and will be garbage collected
|
||||
*/
|
||||
buildStatus:
|
||||
| 'CREATING_BUILD_FOLDER'
|
||||
| 'DOWNLOADING_SOURCE'
|
||||
| 'EXTRACTING_SOURCE'
|
||||
| 'BUILDING'
|
||||
| 'SAVING'
|
||||
| 'ERROR';
|
||||
};
|
||||
|
||||
export type BuildStatusDone = {
|
||||
id: string;
|
||||
status: 'DONE';
|
||||
files: {
|
||||
filePath: string;
|
||||
offset: number;
|
||||
isFirmware: boolean;
|
||||
firmwareId: string;
|
||||
}[];
|
||||
};
|
||||
|
||||
export type BuildFirmwareBody = {
|
||||
source: string;
|
||||
board: string;
|
||||
version: string;
|
||||
values: void;
|
||||
};
|
||||
|
||||
export type FirmwareWithFiles = {
|
||||
id: string;
|
||||
release_id: string;
|
||||
status:
|
||||
| 'QUEUED'
|
||||
| 'CREATING_BUILD_FOLDER'
|
||||
| 'DOWNLOADING_SOURCE'
|
||||
| 'EXTRACTING_SOURCE'
|
||||
| 'DOWNLOADING_FIRMWARE'
|
||||
| 'EXTRACTING_FIRMWARE'
|
||||
| 'SETTING_UP_DEFINES'
|
||||
| 'BUILDING'
|
||||
| 'SAVING'
|
||||
| 'DONE'
|
||||
| 'ERROR';
|
||||
/**
|
||||
* The repository and branch used as source of the firmware
|
||||
*/
|
||||
buildVersion: string;
|
||||
/**
|
||||
* The date of creation of this firmware build
|
||||
*
|
||||
* @format date-time
|
||||
*/
|
||||
createdAt: string;
|
||||
/**
|
||||
* @format date-time
|
||||
*/
|
||||
updatedAt: string;
|
||||
files: {
|
||||
filePath: string;
|
||||
offset: number;
|
||||
isFirmware: boolean;
|
||||
firmwareId: string;
|
||||
}[];
|
||||
};
|
||||
|
||||
export type FirmwareBoardDefaultsNullable = {
|
||||
schema: void;
|
||||
defaults: BoardDefaults;
|
||||
} | null;
|
||||
export type BuildResponseDTO = {
|
||||
/**
|
||||
* Id of the firmware
|
||||
*
|
||||
* @format uuid
|
||||
*/
|
||||
id: string;
|
||||
/**
|
||||
* Build status of the firmware
|
||||
*/
|
||||
status:
|
||||
| 'CREATING_BUILD_FOLDER'
|
||||
| 'DOWNLOADING_FIRMWARE'
|
||||
| 'EXTRACTING_FIRMWARE'
|
||||
| 'SETTING_UP_DEFINES'
|
||||
| 'BUILDING'
|
||||
| 'SAVING'
|
||||
| 'DONE'
|
||||
| 'ERROR';
|
||||
/**
|
||||
* List of built firmware files, only set if the build succeeded
|
||||
*/
|
||||
firmwareFiles?: FirmwareFileDTO[];
|
||||
};
|
||||
|
||||
export type FirmwareFileDTO = {
|
||||
/**
|
||||
* Url to the file
|
||||
*/
|
||||
url: string;
|
||||
/**
|
||||
* Address of the partition
|
||||
*/
|
||||
offset: number;
|
||||
/**
|
||||
* Is this file the main firmware
|
||||
*/
|
||||
isFirmware: boolean;
|
||||
/**
|
||||
* Id of the linked firmware
|
||||
*
|
||||
* @format uuid
|
||||
*/
|
||||
firmwareId: string;
|
||||
};
|
||||
|
||||
export type CreateBuildFirmwareDTO = {
|
||||
/**
|
||||
* Repository of the firmware used
|
||||
*/
|
||||
version: string;
|
||||
/**
|
||||
* Board config, used to declare the pins used by the board
|
||||
*/
|
||||
boardConfig: CreateBoardConfigDTO;
|
||||
/**
|
||||
* Imu config, list of all the imus used and their pins
|
||||
*
|
||||
* @minItems 1
|
||||
*/
|
||||
imusConfig: CreateImuConfigDTO[];
|
||||
};
|
||||
|
||||
export type CreateBoardConfigDTO = {
|
||||
/**
|
||||
* Type of the board
|
||||
*/
|
||||
type:
|
||||
| 'BOARD_SLIMEVR'
|
||||
| 'BOARD_NODEMCU'
|
||||
| 'BOARD_WROOM32'
|
||||
| 'BOARD_WEMOSD1MINI'
|
||||
| 'BOARD_TTGO_TBASE'
|
||||
| 'BOARD_ESP01'
|
||||
| 'BOARD_LOLIN_C3_MINI'
|
||||
| 'BOARD_BEETLE32C3'
|
||||
| 'BOARD_ES32C3DEVKITM1';
|
||||
/**
|
||||
* Pin address of the indicator LED
|
||||
*/
|
||||
ledPin: string;
|
||||
/**
|
||||
* Is the indicator LED enabled
|
||||
*/
|
||||
enableLed: boolean;
|
||||
/**
|
||||
* Is the led inverted
|
||||
*/
|
||||
ledInverted: boolean;
|
||||
/**
|
||||
* Pin address of the battery indicator
|
||||
*/
|
||||
batteryPin: string;
|
||||
/**
|
||||
* Type of battery
|
||||
*/
|
||||
batteryType: 'BAT_EXTERNAL' | 'BAT_INTERNAL' | 'BAT_MCP3021' | 'BAT_INTERNAL_MCP3021';
|
||||
/**
|
||||
* Array of the different battery resistors, [indicator, SHIELD_R1, SHIELD_R2]
|
||||
*
|
||||
* @minItems 3
|
||||
* @maxItems 3
|
||||
*/
|
||||
batteryResistances: number[];
|
||||
};
|
||||
|
||||
export type CreateImuConfigDTO = {
|
||||
/**
|
||||
* Type of the imu
|
||||
*/
|
||||
type:
|
||||
| 'IMU_BNO085'
|
||||
| 'IMU_MPU9250'
|
||||
| 'IMU_MPU6500'
|
||||
| 'IMU_BNO080'
|
||||
| 'IMU_BNO055'
|
||||
| 'IMU_BNO086'
|
||||
| 'IMU_MPU6050'
|
||||
| 'IMU_BMI160'
|
||||
| 'IMU_ICM20948'
|
||||
| 'IMU_BMI270';
|
||||
/**
|
||||
* Pin address of the imu int pin
|
||||
* not all imus use it
|
||||
*/
|
||||
intPin: string | null;
|
||||
/**
|
||||
* Rotation of the imu in degrees
|
||||
*/
|
||||
rotation: number;
|
||||
/**
|
||||
* Pin address of the scl pin
|
||||
*/
|
||||
sclPin: string;
|
||||
/**
|
||||
* Pin address of the sda pin
|
||||
*/
|
||||
sdaPin: string;
|
||||
/**
|
||||
* Is this imu optionnal
|
||||
* Allows for extensions to be unplugged
|
||||
*/
|
||||
optional: boolean;
|
||||
};
|
||||
|
||||
export type VersionNotFoundExeption = {
|
||||
cause: void;
|
||||
name: string;
|
||||
message: string;
|
||||
stack?: string;
|
||||
};
|
||||
|
||||
/**
|
||||
* A representation of any set of values over any amount of time. This is the most basic building block
|
||||
* of RxJS.
|
||||
*/
|
||||
export type ObservableType = {
|
||||
/**
|
||||
* @deprecated true
|
||||
*/
|
||||
source?: Observableany;
|
||||
/**
|
||||
* @deprecated true
|
||||
*/
|
||||
operator?: OperatoranyType;
|
||||
};
|
||||
|
||||
/**
|
||||
* A representation of any set of values over any amount of time. This is the most basic building block
|
||||
* of RxJS.
|
||||
*/
|
||||
export type Observableany = {
|
||||
/**
|
||||
* @deprecated true
|
||||
*/
|
||||
source?: Observableany;
|
||||
/**
|
||||
* @deprecated true
|
||||
*/
|
||||
operator?: Operatoranyany;
|
||||
};
|
||||
|
||||
/**
|
||||
* *
|
||||
*/
|
||||
export type Operatoranyany = {};
|
||||
|
||||
/**
|
||||
* *
|
||||
*/
|
||||
export type OperatoranyType = {};
|
||||
|
||||
export type ReleaseDTO = {
|
||||
/**
|
||||
* id of the release, usually the commit id
|
||||
*/
|
||||
id: string;
|
||||
/**
|
||||
* url of the release
|
||||
*/
|
||||
url: string;
|
||||
/**
|
||||
* name of the release
|
||||
*/
|
||||
name: string;
|
||||
/**
|
||||
* url of the source archive
|
||||
*/
|
||||
zipball_url: string;
|
||||
/**
|
||||
* Is this release a pre release
|
||||
*/
|
||||
prerelease: boolean;
|
||||
/**
|
||||
* Is this release a draft
|
||||
*/
|
||||
draft: boolean;
|
||||
};
|
||||
|
||||
export type Imudto = {
|
||||
/**
|
||||
* Type of the imu
|
||||
*/
|
||||
type:
|
||||
| 'IMU_BNO085'
|
||||
| 'IMU_MPU9250'
|
||||
| 'IMU_MPU6500'
|
||||
| 'IMU_BNO080'
|
||||
| 'IMU_BNO055'
|
||||
| 'IMU_BNO086'
|
||||
| 'IMU_MPU6050'
|
||||
| 'IMU_BMI160'
|
||||
| 'IMU_ICM20948'
|
||||
| 'IMU_BMI270';
|
||||
/**
|
||||
* Does that imu type require a int pin
|
||||
*/
|
||||
hasIntPin: boolean;
|
||||
/**
|
||||
* First address of the imu
|
||||
*/
|
||||
imuStartAddress: number;
|
||||
/**
|
||||
* Increment of the address for each new imus
|
||||
*/
|
||||
addressIncrement: number;
|
||||
};
|
||||
|
||||
export type DefaultBuildConfigDTO = {
|
||||
/**
|
||||
* Default config of the selected board
|
||||
* contains all the default pins information about the selected board
|
||||
*/
|
||||
boardConfig: CreateBoardConfigDTO;
|
||||
/**
|
||||
* Inform the flashing utility that the user need to press the boot (or Flash) button
|
||||
* on the tracker
|
||||
*/
|
||||
needBootPress?: boolean;
|
||||
/**
|
||||
* Inform the flashing utility that the board will need a reboot after
|
||||
* being flashed
|
||||
*/
|
||||
needManualReboot?: boolean;
|
||||
/**
|
||||
* Will use the default values and skip the customisation options
|
||||
*/
|
||||
shouldOnlyUseDefaults?: boolean;
|
||||
/**
|
||||
* List of the possible imus pins, usually only two items will be sent
|
||||
*
|
||||
* @minItems 1
|
||||
*/
|
||||
imuDefaults: IMUDefaultDTO[];
|
||||
/**
|
||||
* Gives the offset of the firmare file in the eeprom. Used for flashing
|
||||
*/
|
||||
application_offset: number;
|
||||
};
|
||||
|
||||
export type IMUDefaultDTO = {
|
||||
/**
|
||||
* Type of the imu
|
||||
*/
|
||||
type?:
|
||||
| 'IMU_BNO085'
|
||||
| 'IMU_MPU9250'
|
||||
| 'IMU_MPU6500'
|
||||
| 'IMU_BNO080'
|
||||
| 'IMU_BNO055'
|
||||
| 'IMU_BNO086'
|
||||
| 'IMU_MPU6050'
|
||||
| 'IMU_BMI160'
|
||||
| 'IMU_ICM20948'
|
||||
| 'IMU_BMI270';
|
||||
/**
|
||||
* Pin address of the imu int pin
|
||||
* not all imus use it
|
||||
*/
|
||||
intPin: string | null;
|
||||
/**
|
||||
* Rotation of the imu in degrees
|
||||
*/
|
||||
rotation?: number;
|
||||
/**
|
||||
* Pin address of the scl pin
|
||||
*/
|
||||
sclPin: string;
|
||||
/**
|
||||
* Pin address of the sda pin
|
||||
*/
|
||||
sdaPin: string;
|
||||
/**
|
||||
* Is this imu optionnal
|
||||
* Allows for extensions to be unplugged
|
||||
*/
|
||||
optional: boolean;
|
||||
};
|
||||
|
||||
export type BoardConfigDTONullable = {
|
||||
/**
|
||||
* Unique id of the board config, used for relations
|
||||
*
|
||||
* @format uuid
|
||||
*/
|
||||
id: string;
|
||||
/**
|
||||
* Type of the board
|
||||
*/
|
||||
type:
|
||||
| 'BOARD_SLIMEVR'
|
||||
| 'BOARD_NODEMCU'
|
||||
| 'BOARD_WROOM32'
|
||||
| 'BOARD_WEMOSD1MINI'
|
||||
| 'BOARD_TTGO_TBASE'
|
||||
| 'BOARD_ESP01'
|
||||
| 'BOARD_LOLIN_C3_MINI'
|
||||
| 'BOARD_BEETLE32C3'
|
||||
| 'BOARD_ES32C3DEVKITM1';
|
||||
/**
|
||||
* Pin address of the indicator LED
|
||||
*/
|
||||
ledPin: string;
|
||||
/**
|
||||
* Is the indicator LED enabled
|
||||
*/
|
||||
enableLed: boolean;
|
||||
/**
|
||||
* Is the led inverted
|
||||
*/
|
||||
ledInverted: boolean;
|
||||
/**
|
||||
* Pin address of the battery indicator
|
||||
*/
|
||||
batteryPin: string;
|
||||
/**
|
||||
* Type of battery
|
||||
*/
|
||||
batteryType: 'BAT_EXTERNAL' | 'BAT_INTERNAL' | 'BAT_MCP3021' | 'BAT_INTERNAL_MCP3021';
|
||||
/**
|
||||
* Array of the different battery resistors, [indicator, SHIELD_R1, SHIELD_R2]
|
||||
*
|
||||
* @minItems 3
|
||||
* @maxItems 3
|
||||
*/
|
||||
batteryResistances: number[];
|
||||
/**
|
||||
* Id of the linked firmware, used for relations
|
||||
*
|
||||
* @format uuid
|
||||
*/
|
||||
firmwareId: string;
|
||||
};
|
||||
|
||||
export type FirmwareDetailDTO = {
|
||||
/**
|
||||
* Pins informations about the board
|
||||
*/
|
||||
boardConfig: BoardConfigDTONullable;
|
||||
/**
|
||||
* List of the declared imus, and their pin configuration
|
||||
*
|
||||
* @minItems 1
|
||||
*/
|
||||
imusConfig: ImuConfigDTO[];
|
||||
/**
|
||||
* List of the built files / partitions with their url and offsets
|
||||
*/
|
||||
firmwareFiles: FirmwareFileDTO[];
|
||||
/**
|
||||
* UUID of the firmware
|
||||
*
|
||||
* @format uuid
|
||||
*/
|
||||
id: string;
|
||||
/**
|
||||
* Id of the firmware version used.
|
||||
* Usually the commit id of the source
|
||||
* used to build the firmware
|
||||
*/
|
||||
releaseId: string;
|
||||
/**
|
||||
* Current status of the build
|
||||
* this value will change during the build
|
||||
* process
|
||||
*
|
||||
* BUILDING -> DONE \\ the firmwrare is build and ready
|
||||
* -> FAILED \\ the build failled and will be garbage collected
|
||||
*/
|
||||
buildStatus:
|
||||
| 'CREATING_BUILD_FOLDER'
|
||||
| 'DOWNLOADING_FIRMWARE'
|
||||
| 'EXTRACTING_FIRMWARE'
|
||||
| 'SETTING_UP_DEFINES'
|
||||
| 'BUILDING'
|
||||
| 'SAVING'
|
||||
| 'DONE'
|
||||
| 'ERROR';
|
||||
/**
|
||||
* The repository and branch used as source of the firmware
|
||||
*/
|
||||
buildVersion: string;
|
||||
/**
|
||||
* The date of creation of this firmware build
|
||||
*
|
||||
* @format date-time
|
||||
*/
|
||||
createdAt: string;
|
||||
};
|
||||
|
||||
export type BoardConfigDTO = {
|
||||
/**
|
||||
* Unique id of the board config, used for relations
|
||||
*
|
||||
* @format uuid
|
||||
*/
|
||||
id: string;
|
||||
/**
|
||||
* Type of the board
|
||||
*/
|
||||
type:
|
||||
| 'BOARD_SLIMEVR'
|
||||
| 'BOARD_NODEMCU'
|
||||
| 'BOARD_WROOM32'
|
||||
| 'BOARD_WEMOSD1MINI'
|
||||
| 'BOARD_TTGO_TBASE'
|
||||
| 'BOARD_ESP01'
|
||||
| 'BOARD_LOLIN_C3_MINI'
|
||||
| 'BOARD_BEETLE32C3'
|
||||
| 'BOARD_ES32C3DEVKITM1';
|
||||
/**
|
||||
* Pin address of the indicator LED
|
||||
*/
|
||||
ledPin: string;
|
||||
/**
|
||||
* Is the indicator LED enabled
|
||||
*/
|
||||
enableLed: boolean;
|
||||
/**
|
||||
* Is the led inverted
|
||||
*/
|
||||
ledInverted: boolean;
|
||||
/**
|
||||
* Pin address of the battery indicator
|
||||
*/
|
||||
batteryPin: string;
|
||||
/**
|
||||
* Type of battery
|
||||
*/
|
||||
batteryType: 'BAT_EXTERNAL' | 'BAT_INTERNAL' | 'BAT_MCP3021' | 'BAT_INTERNAL_MCP3021';
|
||||
/**
|
||||
* Array of the different battery resistors, [indicator, SHIELD_R1, SHIELD_R2]
|
||||
*
|
||||
* @minItems 3
|
||||
* @maxItems 3
|
||||
*/
|
||||
batteryResistances: number[];
|
||||
/**
|
||||
* Id of the linked firmware, used for relations
|
||||
*
|
||||
* @format uuid
|
||||
*/
|
||||
firmwareId: string;
|
||||
};
|
||||
|
||||
export type ImuConfigDTO = {
|
||||
/**
|
||||
* Unique id of the config
|
||||
* this probably will never be shown to the user as it is moslty use for relations
|
||||
*
|
||||
* @format uuid
|
||||
*/
|
||||
id: string;
|
||||
/**
|
||||
* Type of the imu
|
||||
*/
|
||||
type:
|
||||
| 'IMU_BNO085'
|
||||
| 'IMU_MPU9250'
|
||||
| 'IMU_MPU6500'
|
||||
| 'IMU_BNO080'
|
||||
| 'IMU_BNO055'
|
||||
| 'IMU_BNO086'
|
||||
| 'IMU_MPU6050'
|
||||
| 'IMU_BMI160'
|
||||
| 'IMU_ICM20948'
|
||||
| 'IMU_BMI270';
|
||||
/**
|
||||
* Rotation of the imu in degrees
|
||||
*/
|
||||
rotation: number;
|
||||
/**
|
||||
* Pin address of the imu int pin
|
||||
* not all imus use it
|
||||
*/
|
||||
intPin: string | null;
|
||||
/**
|
||||
* Pin address of the scl pin
|
||||
*/
|
||||
sclPin: string;
|
||||
/**
|
||||
* Pin address of the sda pin
|
||||
*/
|
||||
sdaPin: string;
|
||||
/**
|
||||
* Is this imu optionnal
|
||||
* Allows for extensions to be unplugged
|
||||
*/
|
||||
optional: boolean;
|
||||
/**
|
||||
* id of the linked firmware, used for relations
|
||||
*
|
||||
* @format uuid
|
||||
*/
|
||||
firmwareId: string;
|
||||
};
|
||||
|
||||
/**
|
||||
* Defines the base Nest HTTP exception, which is handled by the default
|
||||
* Exceptions Handler.
|
||||
*/
|
||||
export type HttpException = {
|
||||
cause: void;
|
||||
name: string;
|
||||
message: string;
|
||||
stack?: string;
|
||||
};
|
||||
|
||||
@@ -1,5 +1,20 @@
|
||||
import { createContext, useContext, useState } from 'react';
|
||||
import {
|
||||
fetchGetFirmwaresDefaultConfigBoard,
|
||||
useGetHealth,
|
||||
useGetIsCompatibleVersion,
|
||||
} from '@/firmware-tool-api/firmwareToolComponents';
|
||||
import {
|
||||
BuildResponseDTO,
|
||||
CreateBoardConfigDTO,
|
||||
CreateBuildFirmwareDTO,
|
||||
DefaultBuildConfigDTO,
|
||||
FirmwareFileDTO,
|
||||
} from '@/firmware-tool-api/firmwareToolSchemas';
|
||||
import { BoardPinsForm } from '@/components/firmware-tool/BoardPinsStep';
|
||||
import { DeepPartial } from 'react-hook-form';
|
||||
import {
|
||||
BoardType,
|
||||
DeviceIdT,
|
||||
FirmwarePartT,
|
||||
FirmwareUpdateMethod,
|
||||
@@ -10,20 +25,53 @@ import {
|
||||
SerialFirmwareUpdateT,
|
||||
} from 'solarxr-protocol';
|
||||
import { OnboardingContext } from './onboarding';
|
||||
import {
|
||||
BoardDefaults,
|
||||
FirmwareBoardDefaultsNullable,
|
||||
FirmwareSource,
|
||||
FirmwareWithFiles,
|
||||
} from '@/firmware-tool-api/firmwareToolSchemas';
|
||||
import { GetFirmwareBoardDefaultsQueryParams } from '@/firmware-tool-api/firmwareToolComponents';
|
||||
|
||||
export type PartialBuildFirmware = DeepPartial<CreateBuildFirmwareDTO>;
|
||||
export type FirmwareBuildStatus = BuildResponseDTO;
|
||||
export type SelectedDevice = {
|
||||
type: FirmwareUpdateMethod;
|
||||
deviceId: string | number;
|
||||
deviceNames: string[];
|
||||
};
|
||||
|
||||
export const boardTypeToFirmwareToolBoardType: Record<
|
||||
Exclude<
|
||||
BoardType,
|
||||
// This boards will not be handled by the firmware tool.
|
||||
// These are either impossible to compile automatically or deprecated
|
||||
| BoardType.CUSTOM
|
||||
| BoardType.SLIMEVR_DEV
|
||||
| BoardType.SLIMEVR_LEGACY
|
||||
| BoardType.OWOTRACK
|
||||
| BoardType.WRANGLER
|
||||
| BoardType.MOCOPI
|
||||
| BoardType.HARITORA
|
||||
| BoardType.DEV_RESERVED
|
||||
>,
|
||||
CreateBoardConfigDTO['type'] | null
|
||||
> = {
|
||||
[BoardType.UNKNOWN]: null,
|
||||
[BoardType.NODEMCU]: 'BOARD_NODEMCU',
|
||||
[BoardType.WROOM32]: 'BOARD_WROOM32',
|
||||
[BoardType.WEMOSD1MINI]: 'BOARD_WEMOSD1MINI',
|
||||
[BoardType.TTGO_TBASE]: 'BOARD_TTGO_TBASE',
|
||||
[BoardType.ESP01]: 'BOARD_ESP01',
|
||||
[BoardType.SLIMEVR]: 'BOARD_SLIMEVR',
|
||||
[BoardType.LOLIN_C3_MINI]: 'BOARD_LOLIN_C3_MINI',
|
||||
[BoardType.BEETLE32C3]: 'BOARD_BEETLE32C3',
|
||||
[BoardType.ESP32C3DEVKITM1]: 'BOARD_ES32C3DEVKITM1',
|
||||
[BoardType.WEMOSWROOM02]: null,
|
||||
[BoardType.XIAO_ESP32C3]: null,
|
||||
[BoardType.ESP32C6DEVKITC1]: null,
|
||||
[BoardType.GLOVE_IMU_SLIMEVR_DEV]: null,
|
||||
[BoardType.GESTURES]: null,
|
||||
};
|
||||
|
||||
export const firmwareToolToBoardType: Record<CreateBoardConfigDTO['type'], BoardType> =
|
||||
Object.fromEntries(
|
||||
Object.entries(boardTypeToFirmwareToolBoardType).map((a) => a.reverse())
|
||||
);
|
||||
|
||||
export const firmwareUpdateErrorStatus = [
|
||||
FirmwareUpdateStatus.ERROR_AUTHENTICATION_FAILED,
|
||||
FirmwareUpdateStatus.ERROR_DEVICE_NOT_FOUND,
|
||||
@@ -61,7 +109,24 @@ export const firmwareUpdateStatusLabel: Record<FirmwareUpdateStatus, string> = {
|
||||
[FirmwareUpdateStatus.ERROR_UNKNOWN]: 'firmware_update-status-ERROR_UNKNOWN',
|
||||
};
|
||||
|
||||
export type FirmwareToolContext = ReturnType<typeof provideFirmwareTool>;
|
||||
export interface FirmwareToolContext {
|
||||
selectBoard: (boardType: CreateBoardConfigDTO['type']) => Promise<void>;
|
||||
selectVersion: (version: CreateBuildFirmwareDTO['version']) => void;
|
||||
updatePins: (form: BoardPinsForm) => void;
|
||||
updateImus: (imus: CreateBuildFirmwareDTO['imusConfig']) => void;
|
||||
setBuildStatus: (buildStatus: FirmwareBuildStatus) => void;
|
||||
selectDevices: (device: SelectedDevice[] | null) => void;
|
||||
retry: () => void;
|
||||
buildStatus: FirmwareBuildStatus;
|
||||
defaultConfig: DefaultBuildConfigDTO | null;
|
||||
newConfig: PartialBuildFirmware | null;
|
||||
selectedDevices: SelectedDevice[] | null;
|
||||
isStepLoading: boolean;
|
||||
isGlobalLoading: boolean;
|
||||
isCompatible: boolean;
|
||||
isError: boolean;
|
||||
}
|
||||
|
||||
export const FirmwareToolContextC = createContext<FirmwareToolContext>(
|
||||
undefined as any
|
||||
);
|
||||
@@ -74,23 +139,97 @@ export function useFirmwareTool() {
|
||||
return context;
|
||||
}
|
||||
|
||||
export function provideFirmwareTool() {
|
||||
const [selectedSource, setSelectedSource] = useState<{
|
||||
source: GetFirmwareBoardDefaultsQueryParams;
|
||||
default: FirmwareBoardDefaultsNullable;
|
||||
}>();
|
||||
export function useFirmwareToolContext(): FirmwareToolContext {
|
||||
const [defaultConfig, setDefaultConfig] = useState<DefaultBuildConfigDTO | null>(
|
||||
null
|
||||
);
|
||||
const [selectedDevices, selectDevices] = useState<SelectedDevice[] | null>(null);
|
||||
const [newConfig, setNewConfig] = useState<PartialBuildFirmware>({});
|
||||
const [isLoading, setLoading] = useState(false);
|
||||
const { isError, isLoading: isInitialLoading, refetch } = useGetHealth({});
|
||||
const compatibilityCheckEnabled = !!__VERSION_TAG__;
|
||||
const { isLoading: isCompatibilityLoading, data: compatibilityData } =
|
||||
useGetIsCompatibleVersion(
|
||||
{ pathParams: { version: __VERSION_TAG__ } },
|
||||
{ enabled: compatibilityCheckEnabled }
|
||||
);
|
||||
const [buildStatus, setBuildStatus] = useState<FirmwareBuildStatus>({
|
||||
status: 'CREATING_BUILD_FOLDER',
|
||||
id: '',
|
||||
});
|
||||
|
||||
return {
|
||||
selectedSource,
|
||||
setSelectedSource,
|
||||
selectBoard: async (boardType: CreateBoardConfigDTO['type']) => {
|
||||
setLoading(true);
|
||||
const boardDefaults = await fetchGetFirmwaresDefaultConfigBoard({
|
||||
pathParams: { board: boardType },
|
||||
});
|
||||
setDefaultConfig(boardDefaults);
|
||||
if (boardDefaults.shouldOnlyUseDefaults) {
|
||||
setNewConfig((currConfig) => ({
|
||||
...currConfig,
|
||||
...boardDefaults,
|
||||
imusConfig: boardDefaults.imuDefaults,
|
||||
}));
|
||||
} else {
|
||||
setNewConfig((currConfig) => ({
|
||||
...currConfig,
|
||||
boardConfig: { ...currConfig.boardConfig, type: boardType },
|
||||
imusConfig: [],
|
||||
}));
|
||||
}
|
||||
setLoading(false);
|
||||
},
|
||||
updatePins: (form: BoardPinsForm) => {
|
||||
setNewConfig((currConfig) => {
|
||||
return {
|
||||
...currConfig,
|
||||
imusConfig: [...(currConfig?.imusConfig || [])],
|
||||
boardConfig: {
|
||||
...currConfig.boardConfig,
|
||||
...form,
|
||||
batteryResistances: form.batteryResistances.map((r) => Number(r)),
|
||||
},
|
||||
};
|
||||
});
|
||||
},
|
||||
updateImus: (imus: CreateBuildFirmwareDTO['imusConfig']) => {
|
||||
setNewConfig((currConfig) => {
|
||||
return {
|
||||
...currConfig,
|
||||
imusConfig: imus.map(({ rotation, ...fields }) => ({
|
||||
...fields,
|
||||
rotation: Number(rotation),
|
||||
})), // Make sure that the rotation is handled as number
|
||||
};
|
||||
});
|
||||
},
|
||||
retry: async () => {
|
||||
setLoading(true);
|
||||
await refetch();
|
||||
setLoading(false);
|
||||
},
|
||||
selectVersion: (version: CreateBuildFirmwareDTO['version']) => {
|
||||
setNewConfig((currConfig) => ({ ...currConfig, version }));
|
||||
},
|
||||
setBuildStatus,
|
||||
selectDevices,
|
||||
selectedDevices,
|
||||
buildStatus,
|
||||
defaultConfig,
|
||||
newConfig,
|
||||
isStepLoading: isLoading,
|
||||
isGlobalLoading: isInitialLoading || isCompatibilityLoading,
|
||||
isCompatible: !compatibilityCheckEnabled || (compatibilityData?.success ?? false),
|
||||
isError: isError || (!compatibilityData?.success && compatibilityCheckEnabled),
|
||||
};
|
||||
}
|
||||
|
||||
export const getFlashingRequests = (
|
||||
devices: SelectedDevice[],
|
||||
firmwareFiles: FirmwareWithFiles['files'],
|
||||
firmwareFiles: FirmwareFileDTO[],
|
||||
onboardingState: OnboardingContext['state'],
|
||||
defaultConfig: BoardDefaults | null
|
||||
defaultConfig: DefaultBuildConfigDTO | null
|
||||
) => {
|
||||
const firmware = firmwareFiles.find(({ isFirmware }) => isFirmware);
|
||||
if (!firmware) throw new Error('invalid state - no firmware to find');
|
||||
@@ -105,7 +244,7 @@ export const getFlashingRequests = (
|
||||
|
||||
const part = new FirmwarePartT();
|
||||
part.offset = 0;
|
||||
part.url = firmware.filePath;
|
||||
part.url = firmware.url;
|
||||
|
||||
const method = new OTAFirmwareUpdateT();
|
||||
method.deviceId = dId;
|
||||
@@ -128,13 +267,12 @@ export const getFlashingRequests = (
|
||||
method.deviceId = id;
|
||||
method.ssid = onboardingState.wifi.ssid;
|
||||
method.password = onboardingState.wifi.password;
|
||||
method.needManualReboot =
|
||||
defaultConfig?.flashingRules.needManualReboot ?? false;
|
||||
method.needManualReboot = defaultConfig?.needManualReboot ?? false;
|
||||
|
||||
method.firmwarePart = firmwareFiles.map(({ offset, filePath }) => {
|
||||
method.firmwarePart = firmwareFiles.map(({ offset, url }) => {
|
||||
const part = new FirmwarePartT();
|
||||
part.offset = offset;
|
||||
part.url = filePath;
|
||||
part.url = url;
|
||||
return part;
|
||||
});
|
||||
|
||||
|
||||
@@ -8,7 +8,7 @@ export interface FirmwareRelease {
|
||||
name: string;
|
||||
version: string;
|
||||
changelog: string;
|
||||
firmwareFiles: Partial<Record<BoardType, string>>;
|
||||
firmwareFile: string;
|
||||
userCanUpdate: boolean;
|
||||
}
|
||||
|
||||
@@ -89,9 +89,7 @@ export async function fetchCurrentFirmwareRelease(): Promise<FirmwareRelease | n
|
||||
const processedReleses = [];
|
||||
for (const release of releases) {
|
||||
const fwAsset = firstAsset(release.assets, 'BOARD_SLIMEVR-firmware.bin');
|
||||
const fw12Asset = firstAsset(release.assets, 'BOARD_SLIMEVR_V1_2-firmware.bin');
|
||||
if (!release.assets || (!fwAsset && !fw12Asset) /* || release.prerelease */)
|
||||
continue;
|
||||
if (!release.assets || !fwAsset /* || release.prerelease */) continue;
|
||||
|
||||
let version = release.tag_name;
|
||||
if (version.charAt(0) === 'v') {
|
||||
@@ -107,10 +105,7 @@ export async function fetchCurrentFirmwareRelease(): Promise<FirmwareRelease | n
|
||||
name: release.name,
|
||||
version,
|
||||
changelog: release.body,
|
||||
firmwareFiles: {
|
||||
[BoardType.SLIMEVR]: fwAsset.browser_download_url,
|
||||
[BoardType.SLIMEVR_V1_2]: fw12Asset.browser_download_url,
|
||||
},
|
||||
firmwareFile: fwAsset.browser_download_url,
|
||||
userCanUpdate,
|
||||
});
|
||||
|
||||
@@ -128,10 +123,7 @@ export function checkForUpdate(
|
||||
if (!currentFirmwareRelease.userCanUpdate) return 'blocked';
|
||||
|
||||
if (
|
||||
!device.hardwareInfo?.officialBoardType ||
|
||||
![BoardType.SLIMEVR, BoardType.SLIMEVR_V1_2].includes(
|
||||
device.hardwareInfo.officialBoardType
|
||||
) ||
|
||||
device.hardwareInfo?.officialBoardType !== BoardType.SLIMEVR ||
|
||||
!semver.valid(currentFirmwareRelease.version) ||
|
||||
!semver.valid(device.hardwareInfo.firmwareVersion?.toString() ?? 'none')
|
||||
) {
|
||||
|
||||
23
pnpm-lock.yaml
generated
23
pnpm-lock.yaml
generated
@@ -80,9 +80,6 @@ importers:
|
||||
'@twemoji/svg':
|
||||
specifier: ^15.0.0
|
||||
version: 15.0.0
|
||||
ajv:
|
||||
specifier: ^8.17.1
|
||||
version: 8.17.1
|
||||
browser-fs-access:
|
||||
specifier: ^0.35.0
|
||||
version: 0.35.0
|
||||
@@ -1543,9 +1540,6 @@ packages:
|
||||
ajv@6.12.6:
|
||||
resolution: {integrity: sha512-j3fVLgvTo527anyYyJOGTYJbG+vnnQYvE0m5mmkc1TK+nxAppkCLMIL0aZ4dblVCNoGShhm+kzE4ZUykBoMg4g==}
|
||||
|
||||
ajv@8.17.1:
|
||||
resolution: {integrity: sha512-B/gBuNg5SiMTrPkC+A2+cW0RszwxYmn6VYxB/inlBStS5nx6xHIt/ehKRhIMhqusl7a8LjQoZnjCs5vhwxOQ1g==}
|
||||
|
||||
ansi-escapes@4.3.2:
|
||||
resolution: {integrity: sha512-gKXj5ALrKWQLsYG9jlTRmR/xKluxHV+Z9QEwNIgCfM1/uwPMCuzVVnh5mwTd+OuBZcwSIMbqssNWRm1lE51QaQ==}
|
||||
engines: {node: '>=8'}
|
||||
@@ -2311,9 +2305,6 @@ packages:
|
||||
fast-safe-stringify@2.1.1:
|
||||
resolution: {integrity: sha512-W+KJc2dmILlPplD/H4K9l9LcAHAfPtP6BY84uVLXQ6Evcz9Lcg33Y2z1IVblT6xdY54PXYVHEv+0Wpq8Io6zkA==}
|
||||
|
||||
fast-uri@3.1.0:
|
||||
resolution: {integrity: sha512-iPeeDKJSWf4IEOasVVrknXpaBV0IApz/gp7S2bb7Z4Lljbl2MGJRqInZiUrQwV16cpzw/D3S5j5Julj/gT52AA==}
|
||||
|
||||
fastq@1.17.1:
|
||||
resolution: {integrity: sha512-sRVD3lWVIXWg6By68ZN7vho9a1pQcN/WBFaAAsDDFzlJjvoGx0P8z7V1t72grFJfJhu3YPZBuu25f7Kaw2jN1w==}
|
||||
|
||||
@@ -2870,9 +2861,6 @@ packages:
|
||||
json-schema-traverse@0.4.1:
|
||||
resolution: {integrity: sha512-xbbCH5dCYU5T8LcEhhuh7HJ88HXuW3qsI3Y0zOZFKfZEHcpWiHU/Jxzk629Brsab/mMiHQti9wMP+845RPe3Vg==}
|
||||
|
||||
json-schema-traverse@1.0.0:
|
||||
resolution: {integrity: sha512-NM8/P9n3XjXhIZn1lLhkFaACTOURQXjWhV4BA/RnOv8xvgqtqpAX9IO4mRQxSx1Rlo4tqzeqb0sOlruaOy3dug==}
|
||||
|
||||
json-stable-stringify-without-jsonify@1.0.1:
|
||||
resolution: {integrity: sha512-Bdboy+l7tA3OGW6FjyFHWkP5LuByj1Tk33Ljyq0axyzdk9//JSi2u3fP1QSmd1KNwq6VOKYGlAu87CisVir6Pw==}
|
||||
|
||||
@@ -5828,13 +5816,6 @@ snapshots:
|
||||
json-schema-traverse: 0.4.1
|
||||
uri-js: 4.4.1
|
||||
|
||||
ajv@8.17.1:
|
||||
dependencies:
|
||||
fast-deep-equal: 3.1.3
|
||||
fast-uri: 3.1.0
|
||||
json-schema-traverse: 1.0.0
|
||||
require-from-string: 2.0.2
|
||||
|
||||
ansi-escapes@4.3.2:
|
||||
dependencies:
|
||||
type-fest: 0.21.3
|
||||
@@ -6760,8 +6741,6 @@ snapshots:
|
||||
|
||||
fast-safe-stringify@2.1.1: {}
|
||||
|
||||
fast-uri@3.1.0: {}
|
||||
|
||||
fastq@1.17.1:
|
||||
dependencies:
|
||||
reusify: 1.0.4
|
||||
@@ -7316,8 +7295,6 @@ snapshots:
|
||||
|
||||
json-schema-traverse@0.4.1: {}
|
||||
|
||||
json-schema-traverse@1.0.0: {}
|
||||
|
||||
json-stable-stringify-without-jsonify@1.0.1: {}
|
||||
|
||||
json5@1.0.2:
|
||||
|
||||
@@ -56,8 +56,6 @@ enum class BoardType(val id: UInt) {
|
||||
ESP32C6DEVKITC1(19u),
|
||||
GLOVE_IMU_SLIMEVR_DEV(20u),
|
||||
GESTURES(21u),
|
||||
SLIMEVR_V1_2(22u),
|
||||
ESP32S3_SUPERMINI(23u),
|
||||
DEV_RESERVED(250u),
|
||||
;
|
||||
|
||||
@@ -86,8 +84,6 @@ enum class BoardType(val id: UInt) {
|
||||
HARITORA -> "Haritora"
|
||||
ESP32C6DEVKITC1 -> "Espressif ESP32-C6 DevKitC-1"
|
||||
GLOVE_IMU_SLIMEVR_DEV -> "SlimeVR Dev IMU Glove"
|
||||
SLIMEVR_V1_2 -> "SlimeVR v1.2"
|
||||
ESP32S3_SUPERMINI -> "ESP32-S3 SuperMini"
|
||||
DEV_RESERVED -> "Prototype"
|
||||
}
|
||||
|
||||
|
||||
Submodule solarxr-protocol updated: eed73567f7...df26226d10
Reference in New Issue
Block a user