Skip to content

Commit faa599e

Browse files
Add initial attempt at firmware downloads
1 parent 315c7b0 commit faa599e

File tree

2 files changed

+67
-5
lines changed

2 files changed

+67
-5
lines changed

kernel/src/constants.ts

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -4,7 +4,8 @@ export interface FirmwareOption {
44
url: string;
55
}
66

7-
export const firmwareOptions: Record<string, FirmwareOption> = {
7+
// Optionally in the future could switch to initialize with this and make it align with a recent-ish release...
8+
export const defaultFirmwareOptions: Record<string, FirmwareOption> = {
89
'auto': {
910
name: 'Auto detection',
1011
url: ''

kernel/src/services/FirmwareService.ts

Lines changed: 65 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -1,30 +1,90 @@
1-
import { firmwareOptions } from '../constants'
1+
import { FirmwareOption } from '../constants'
22
import { DeviceService } from './DeviceService';
33

44
export class FirmwareService {
55
private firmwareString: string | null = null;
66
private firmwareBlob: Blob | null = null;
77
private selectedFirmwareId: string = 'Auto';
8+
// Should make firmwareOptions a private variable and use getters to access it.
9+
// This way we can add logic to the getters if we need to in the future. Default to empty record.
10+
private firmwareOptions: Record<string, FirmwareOption> = {};
811

912
constructor(private deviceService: DeviceService) {
1013
const savedSelection = localStorage.getItem('selectedFirmwareId');
14+
// Get the firmware options from GitHub (or local files).
15+
// Maybe we'll add an explicit button for updating the firmware options in the future...
16+
// We'll initialize our private firmwareOptions here with the reqFirmwareOptionsGitHub() method.
17+
this.reqFirmwareOptionsGitHub().then((res) => {
18+
this.firmwareOptions = res;
19+
})
20+
1121
if (savedSelection) {
1222
this.selectedFirmwareId = savedSelection;
1323
} else {
1424
this.selectedFirmwareId = 'auto';
1525
}
1626
}
1727

18-
getFirmwareOptions(){
28+
// We'll use this method to fetch the firmware options from GitHub.
29+
// We could alternatively use local files in ../binaries/ so we aren't sending a request to GitHub every time.
30+
private async reqFirmwareOptionsGitHub(): Promise<Record<string, FirmwareOption>> {
31+
const releases = await fetch('https://api.github.com/repos/sparkfun/micropython/releases', {
32+
method: 'GET'
33+
});
34+
35+
if (!releases.ok) {
36+
throw new Error(`Failed to fetch releases: ${releases.status} ${releases.statusText}`);
37+
}
38+
const releasesData = await releases.json();
39+
const firmwareOptions: Record<string, FirmwareOption> = {};
40+
41+
firmwareOptions['auto'] = {
42+
name: 'Auto detection',
43+
url: ''
44+
};
45+
46+
// Take the first release and iterate through the assets to populate the firmware options.
47+
const latestRelease = releasesData[0];
48+
if (latestRelease && latestRelease.assets) {
49+
latestRelease.assets.forEach((asset: any) => {
50+
// We should make the name the full name of the asset but the key the firmwareId (the board name in lowercase with dashes and an optional "m" prefix for minimal).
51+
const firmwareName = asset.name;
52+
var firmwareId = firmwareName.replace(/\.uf2|\.zip/g, '').toLowerCase().replace(/_/g, '-');
53+
54+
if (firmwareName.startsWith('MINIMAL_')) {
55+
firmwareId = 'm-' + firmwareId.replace('minimal-', '');
56+
}
57+
const firmwareUrl = asset.browser_download_url;
58+
59+
const firmwareOption: FirmwareOption = {
60+
name: firmwareName,
61+
url: firmwareUrl
62+
};
63+
firmwareOptions[firmwareId] = firmwareOption;
64+
});
65+
}
66+
67+
// Add the local firmware option.
68+
firmwareOptions['local'] = {
69+
name: 'Local firmware upload',
70+
url: ''
71+
};
72+
1973
return firmwareOptions;
2074
}
2175

76+
// This is where we can add our logic of fetching from GitHub.
77+
// We could alternatively use local files in ../binaries/ so we aren't sending a request to GitHub every time.
78+
getFirmwareOptions(){
79+
return this.firmwareOptions;
80+
}
81+
2282
getSelectedFirmwareId(): string {
2383
return this.selectedFirmwareId;
2484
}
2585

2686
setSelectedFirmwareId(id: string): void {
27-
if (id in firmwareOptions){
87+
if (id in this.firmwareOptions) {
2888
this.selectedFirmwareId = id;
2989
this.firmwareString = null;
3090
this.firmwareBlob = null;
@@ -67,8 +127,9 @@ export class FirmwareService {
67127
return this.downloadSpecificFirmware(firmwareId);
68128
}
69129

130+
// TODO: This is where we can add our logic of fetching from GitHub
70131
private async downloadSpecificFirmware(firmwareId: string): Promise<string> {
71-
const selectedFirmware = firmwareOptions[firmwareId]
132+
const selectedFirmware = this.firmwareOptions[firmwareId]
72133
if (!selectedFirmware || !selectedFirmware.url) {
73134
throw new Error(`Invalid firmware selection or no URL for: ${firmwareId}`);
74135
}

0 commit comments

Comments
 (0)