Skip to content

Commit e38a4b4

Browse files
committed
Progress
1 parent de16acb commit e38a4b4

File tree

16 files changed

+836
-1246
lines changed

16 files changed

+836
-1246
lines changed

gui/.env

Lines changed: 6 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -1,8 +1,8 @@
1-
VITE_FIRMWARE_TOOL_URL=https://fw-tool-api.slimevr.io
2-
VITE_FIRMWARE_TOOL_S3_URL=https://fw-tool-bucket.slimevr.io
3-
FIRMWARE_TOOL_SCHEMA_URL=https://fw-tool-api.slimevr.io/api-json
1+
# VITE_FIRMWARE_TOOL_URL=https://fw-tool-api.slimevr.io
2+
# VITE_FIRMWARE_TOOL_S3_URL=https://fw-tool-bucket.slimevr.io
3+
# FIRMWARE_TOOL_SCHEMA_URL=https://fw-tool-api.slimevr.io/api-json
44

55

6-
# VITE_FIRMWARE_TOOL_URL=http://localhost:3000
7-
# VITE_FIRMWARE_TOOL_S3_URL=http://localhost:9000
8-
# FIRMWARE_TOOL_SCHEMA_URL=http://localhost:3000/api-json
6+
VITE_FIRMWARE_TOOL_URL=http://localhost:3000
7+
VITE_FIRMWARE_TOOL_S3_URL=http://localhost:9099
8+
FIRMWARE_TOOL_SCHEMA_URL=http://localhost:3000/api-json

gui/package.json

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -25,6 +25,7 @@
2525
"@tauri-apps/plugin-store": "^2.0.0",
2626
"@tweenjs/tween.js": "^25.0.0",
2727
"@twemoji/svg": "^15.0.0",
28+
"ajv": "^8.17.1",
2829
"browser-fs-access": "^0.35.0",
2930
"classnames": "^2.5.1",
3031
"flatbuffers": "22.10.26",

gui/public/i18n/en/translation.ftl

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -89,6 +89,7 @@ board_type-WEMOSD1MINI = Wemos D1 Mini
8989
board_type-TTGO_TBASE = TTGO T-Base
9090
board_type-ESP01 = ESP-01
9191
board_type-SLIMEVR = SlimeVR
92+
board_type-SLIMEVR_V1_2 = SlimeVR v1.2
9293
board_type-LOLIN_C3_MINI = Lolin C3 Mini
9394
board_type-BEETLE32C3 = Beetle ESP32-C3
9495
board_type-ESP32C3DEVKITM1 = Espressif ESP32-C3 DevKitM-1
@@ -383,7 +384,8 @@ tracker-settings-name_section-label = Tracker name
383384
tracker-settings-forget = Forget tracker
384385
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.
385386
tracker-settings-forget-label = Forget tracker
386-
tracker-settings-update-unavailable = Cannot be updated (DIY)
387+
tracker-settings-update-unavailable-v2 = No releases found
388+
tracker-settings-update-incompatible = Cannot update. Incompatible board
387389
tracker-settings-update-low-battery = Cannot update. Battery lower than 50%
388390
tracker-settings-update-up_to_date = Up to date
389391
tracker-settings-update-blocked = Update not available. No other releases available

gui/src/components/firmware-tool/FirmwareTool.tsx

Lines changed: 68 additions & 44 deletions
Original file line numberDiff line numberDiff line change
@@ -3,7 +3,7 @@ import { Typography } from '@/components/commons/Typography';
33
import { QueryClient, QueryClientProvider } from '@tanstack/react-query';
44
import {
55
FirmwareToolContextC,
6-
useFirmwareToolContext,
6+
provideFirmwareTool,
77
} from '@/hooks/firmware-tool';
88
import { AddImusStep } from './AddImusStep';
99
import { SelectBoardStep } from './SelectBoardStep';
@@ -15,63 +15,87 @@ import { SelectFirmwareStep } from './SelectFirmwareStep';
1515
import { BuildStep } from './BuildStep';
1616
import { FlashingMethodStep } from './FlashingMethodStep';
1717
import { FlashingStep } from './FlashingStep';
18-
import { FlashBtnStep } from './FlashBtnStep';
19-
import { FirmwareUpdateMethod } from 'solarxr-protocol';
2018
import { useMemo } from 'react';
19+
import {
20+
useGetHealth,
21+
useGetIsCompatibleVersion,
22+
} from '@/firmware-tool-api/firmwareToolComponents';
23+
import { SelectSourceSetep } from './steps/SelectSourceStep';
24+
import { BoardDefaultsStep } from './steps/BoardDefaultsStep';
2125

2226
function FirmwareToolContent() {
2327
const { l10n } = useLocalization();
24-
const context = useFirmwareToolContext();
25-
const { isError, isGlobalLoading: isLoading, retry, isCompatible } = context;
28+
const context = provideFirmwareTool();
29+
const { isError, isLoading: isInitialLoading, refetch } = useGetHealth({});
30+
const compatibilityCheckEnabled = !!__VERSION_TAG__;
31+
const { isLoading: isCompatibilityLoading, data: compatibilityData } =
32+
useGetIsCompatibleVersion(
33+
{ pathParams: { version: __VERSION_TAG__ } },
34+
{ enabled: compatibilityCheckEnabled }
35+
);
36+
37+
const isLoading = isInitialLoading || isCompatibilityLoading;
38+
const isCompatible =
39+
!compatibilityCheckEnabled || (compatibilityData?.success ?? false);
2640

2741
const steps = useMemo(() => {
2842
const steps = [
2943
{
30-
id: 'SelectBoard',
31-
component: SelectBoardStep,
32-
title: l10n.getString('firmware_tool-board_step'),
33-
},
34-
{
35-
component: BoardPinsStep,
36-
title: l10n.getString('firmware_tool-board_pins_step'),
44+
id: 'SelectSource',
45+
component: SelectSourceSetep,
46+
title: l10n.getString('firmware_tool-step-select_source'),
3747
},
3848
{
39-
component: AddImusStep,
40-
title: l10n.getString('firmware_tool-add_imus_step'),
41-
},
42-
{
43-
id: 'SelectFirmware',
44-
component: SelectFirmwareStep,
45-
title: l10n.getString('firmware_tool-select_firmware_step'),
46-
},
47-
{
48-
component: FlashingMethodStep,
49-
id: 'FlashingMethod',
50-
title: l10n.getString('firmware_tool-flash_method_step'),
51-
},
52-
{
53-
component: BuildStep,
54-
title: l10n.getString('firmware_tool-build_step'),
55-
},
56-
{
57-
component: FlashingStep,
58-
title: l10n.getString('firmware_tool-flashing_step'),
49+
component: BoardDefaultsStep,
50+
title: l10n.getString('firmware_tool-step-board_defaults'),
5951
},
52+
// {
53+
// component: BoardPinsStep,
54+
// title: l10n.getString('firmware_tool-board_pins_step'),
55+
// },
56+
// {
57+
// component: AddImusStep,
58+
// title: l10n.getString('firmware_tool-add_imus_step'),
59+
// },
60+
// {
61+
// id: 'SelectFirmware',
62+
// component: SelectFirmwareStep,
63+
// title: l10n.getString('firmware_tool-select_firmware_step'),
64+
// },
65+
// {
66+
// component: FlashingMethodStep,
67+
// id: 'FlashingMethod',
68+
// title: l10n.getString('firmware_tool-flash_method_step'),
69+
// },
70+
// {
71+
// component: BuildStep,
72+
// title: l10n.getString('firmware_tool-build_step'),
73+
// },
74+
// {
75+
// component: FlashingStep,
76+
// title: l10n.getString('firmware_tool-flashing_step'),
77+
// },
6078
];
6179

62-
if (
63-
context.defaultConfig?.needBootPress &&
64-
context.selectedDevices?.find(
65-
({ type }) => type === FirmwareUpdateMethod.SerialFirmwareUpdate
66-
)
67-
) {
68-
steps.splice(5, 0, {
69-
component: FlashBtnStep,
70-
title: l10n.getString('firmware_tool-flashbtn_step'),
71-
});
72-
}
80+
// if (
81+
// context.defaultConfig?.needBootPress &&
82+
// context.selectedDevices?.find(
83+
// ({ type }) => type === FirmwareUpdateMethod.SerialFirmwareUpdate
84+
// )
85+
// ) {
86+
// steps.splice(5, 0, {
87+
// component: FlashBtnStep,
88+
// title: l10n.getString('firmware_tool-flashbtn_step'),
89+
// });
90+
// }
7391
return steps;
74-
}, [context.defaultConfig?.needBootPress, context.selectedDevices, l10n]);
92+
}, [
93+
/* context.defaultConfig?.needBootPress, context.selectedDevices */ l10n,
94+
]);
95+
96+
const retry = async () => {
97+
await refetch();
98+
};
7599

76100
return (
77101
<FirmwareToolContextC.Provider value={context}>

gui/src/components/firmware-tool/FlashBtnStep.tsx

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -26,7 +26,9 @@ export function FlashBtnStep({
2626
{l10n.getString('firmware_tool-flashbtn_step-description')}
2727
</Typography>
2828
{defaultConfig?.boardConfig.type ===
29-
boardTypeToFirmwareToolBoardType[BoardType.SLIMEVR] ? (
29+
boardTypeToFirmwareToolBoardType[BoardType.SLIMEVR] ||
30+
defaultConfig?.boardConfig.type ===
31+
boardTypeToFirmwareToolBoardType[BoardType.SLIMEVR_V1_2] ? (
3032
<>
3133
<Typography variant="standard" whitespace="whitespace-pre">
3234
{l10n.getString('firmware_tool-flashbtn_step-board_SLIMEVR')}
Lines changed: 173 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,173 @@
1+
import { useLocalization } from '@fluent/react';
2+
import { Typography } from '@/components/commons/Typography';
3+
import { useFirmwareTool } from '@/hooks/firmware-tool';
4+
import {} from '@/firmware-tool-api/firmwareToolComponents';
5+
import { SomeJSONSchema } from 'ajv/dist/types/json-schema';
6+
import { useEffect } from 'react';
7+
8+
const refToKey = (ref: string) => ref.substring('#/$defs/'.length);
9+
10+
type ComponentNode = { label: string } & (
11+
| {
12+
type: 'checkbox';
13+
value: boolean;
14+
}
15+
| {
16+
type: 'dropdown';
17+
items: string[];
18+
value: string;
19+
}
20+
| {
21+
type: 'text';
22+
value: string;
23+
}
24+
| {
25+
type: 'group';
26+
name: string;
27+
childrens: ComponentNode[];
28+
}
29+
| {
30+
type: 'list';
31+
childrens: ComponentNode[];
32+
}
33+
);
34+
35+
const handleNode = (
36+
defs: SomeJSONSchema['$defs'],
37+
node: SomeJSONSchema,
38+
data: any,
39+
parentNode: SomeJSONSchema | null = null
40+
): ComponentNode[] => {
41+
const components: ComponentNode[] = [];
42+
if (!node) return [];
43+
44+
if (node.$ref) {
45+
return handleNode(defs, defs![refToKey(node.$ref)], data, node);
46+
}
47+
if (node.type === 'object') {
48+
if (
49+
node.oneOf &&
50+
Array.isArray(node.oneOf) &&
51+
node.discriminator?.propertyName
52+
) {
53+
const discriminator = node.discriminator.propertyName;
54+
const selected = node.oneOf.find((o) => {
55+
if (
56+
o.$ref &&
57+
defs![refToKey(o.$ref)].properties[discriminator].const ===
58+
data[discriminator]
59+
) {
60+
return true;
61+
}
62+
63+
if (
64+
o.type === 'object' &&
65+
o.properties[discriminator].const === data[discriminator]
66+
) {
67+
console.log(data);
68+
return true;
69+
}
70+
return false;
71+
});
72+
components.push(...handleNode(defs, selected, data, node));
73+
} else if (node.properties) {
74+
const childs: ComponentNode[] = [];
75+
for (const property of Object.keys(node.properties)) {
76+
childs.push(
77+
...handleNode(defs, node.properties[property], data[property], node)
78+
);
79+
}
80+
components.push({
81+
type: 'group',
82+
name: node.description,
83+
childrens: childs,
84+
label: node.description ?? parentNode?.description ?? 'nothing o',
85+
});
86+
} else {
87+
throw 'unknown object';
88+
}
89+
}
90+
if (node.type === 'boolean') {
91+
components.push({
92+
type: 'checkbox',
93+
label: node.description ?? parentNode?.description ?? 'nothing b',
94+
value: data,
95+
});
96+
}
97+
if (node.type === 'array') {
98+
if (!Array.isArray(data)) throw 'not an array';
99+
const childs: ComponentNode[] = [];
100+
data.forEach((d) => {
101+
childs.push(...handleNode(defs, node.items, d, node));
102+
});
103+
components.push({
104+
type: 'list',
105+
childrens: childs,
106+
label: node.description ?? parentNode?.description ?? 'nothing a',
107+
});
108+
}
109+
if (node.type === 'string') {
110+
if (node.enum) {
111+
components.push({
112+
type: 'dropdown',
113+
label: node.description ?? parentNode?.description ?? 'nothing e',
114+
items: node.enum,
115+
value: data,
116+
});
117+
} else {
118+
components.push({
119+
type: 'text',
120+
label: node.description ?? parentNode?.description ?? 'nothing s',
121+
value: data,
122+
});
123+
}
124+
}
125+
if (node.type === 'number') {
126+
components.push({
127+
type: 'text',
128+
label: node.description ?? parentNode?.description ?? 'nothing n',
129+
value: data,
130+
});
131+
}
132+
return components;
133+
};
134+
135+
export function BoardDefaultsStep({
136+
nextStep,
137+
goTo,
138+
}: {
139+
nextStep: () => void;
140+
prevStep: () => void;
141+
goTo: (id: string) => void;
142+
}) {
143+
const { l10n } = useLocalization();
144+
const { selectedSource } = useFirmwareTool();
145+
146+
useEffect(() => {
147+
if (!selectedSource) return;
148+
const d = selectedSource?.default?.schema as any as SomeJSONSchema;
149+
if (!d.$defs) throw 'no defs';
150+
const t = refToKey(d.properties.defaults.additionalProperties.$ref);
151+
if (!t) throw 'unable to get defaults ref';
152+
const boardConfig = d.$defs[t];
153+
const boardValues = d.$defs[refToKey(boardConfig.properties.values.$ref)];
154+
const data = selectedSource.default?.defaults.values as any;
155+
console.log(
156+
// selectedSource.default?.defaults.values
157+
JSON.stringify(handleNode(d.$defs, boardValues, data), null, 2)
158+
);
159+
}, [selectedSource]);
160+
161+
return (
162+
<>
163+
<div className="flex flex-col w-full">
164+
<div className="flex flex-grow flex-col gap-4">
165+
<Typography>
166+
{l10n.getString('firmware_tool-board_step-description')}
167+
</Typography>
168+
</div>
169+
<div className="my-4"></div>
170+
</div>
171+
</>
172+
);
173+
}

0 commit comments

Comments
 (0)