Initial commit
This commit is contained in:
commit
a892dfb3ba
27 changed files with 6607 additions and 0 deletions
161
composables/useEspFlasher.ts
Normal file
161
composables/useEspFlasher.ts
Normal file
|
@ -0,0 +1,161 @@
|
|||
import { ESPLoader, Transport, type FlashOptions } from 'esptool-js';
|
||||
import { serial } from "web-serial-polyfill";
|
||||
|
||||
|
||||
|
||||
|
||||
export const useEspFlasher = (term) => {
|
||||
const isConnected = ref(false);
|
||||
const flashProgress = ref(0);
|
||||
const status = ref('');
|
||||
const error = ref('');
|
||||
|
||||
const espLoaderTerminal = {
|
||||
clean() {
|
||||
term.clear();
|
||||
},
|
||||
writeLine(data) {
|
||||
term.writeln(data);
|
||||
},
|
||||
write(data) {
|
||||
term.write(data);
|
||||
},
|
||||
};
|
||||
|
||||
let port = null;
|
||||
let espLoader: ESPLoader = null;
|
||||
let transport: Transport;
|
||||
|
||||
const SERIAL_FILTERS: SerialPortFilter[] = [
|
||||
{ usbVendorId: 0x1a86 }, // QinHeng Electronics CH340
|
||||
{ usbVendorId: 0x303a } // Espressif USB JTAG/serial debug unit
|
||||
];
|
||||
|
||||
const connect = async () => {
|
||||
try {
|
||||
if (transport) {
|
||||
await disconnect();
|
||||
}
|
||||
const serialLib = !navigator.serial && navigator.usb ? serial : navigator.serial;
|
||||
|
||||
if (port === null) {
|
||||
port = await serialLib.requestPort({
|
||||
filters: SERIAL_FILTERS
|
||||
});
|
||||
|
||||
// await port.open({ baudRate: 115200 });
|
||||
|
||||
transport = new Transport(port, true);
|
||||
}
|
||||
|
||||
espLoader = new ESPLoader({
|
||||
transport,
|
||||
baudrate: 115200,
|
||||
terminal: espLoaderTerminal,
|
||||
logger: (message: string) => {
|
||||
status.value = "LOG: " + message;
|
||||
}
|
||||
});
|
||||
|
||||
// await espLoader.connect();
|
||||
// await espLoader.sync();
|
||||
|
||||
const chipInfo = await espLoader.main();
|
||||
status.value = `Connected to ${chipInfo}`;
|
||||
|
||||
// await espLoader.loadStub();
|
||||
|
||||
isConnected.value = true;
|
||||
error.value = '';
|
||||
} catch (err: any) {
|
||||
error.value = err.message;
|
||||
isConnected.value = false;
|
||||
await disconnect();
|
||||
}
|
||||
};
|
||||
|
||||
const flash = async (manifest: FirmwareManifest, eraseFlash: boolean) => {
|
||||
if (!espLoader || !isConnected.value) {
|
||||
error.value = 'Not connected to device';
|
||||
return;
|
||||
}
|
||||
|
||||
try {
|
||||
const build = manifest.builds[0];
|
||||
|
||||
if (eraseFlash) {
|
||||
status.value = 'Erasing flash...';
|
||||
await espLoader.eraseFlash();
|
||||
}
|
||||
|
||||
const fileArray = [];
|
||||
|
||||
status.value = `Flashing ${manifest.name}...`;
|
||||
|
||||
for (const part of build.parts) {
|
||||
const response = await fetch(part.path);
|
||||
const uint8Array = new Uint8Array(await response.arrayBuffer());
|
||||
const buffer = Array.from(uint8Array)
|
||||
.map(byte => String.fromCharCode(byte))
|
||||
.join('');
|
||||
fileArray.push({ data: buffer, address: part.offset });
|
||||
}
|
||||
|
||||
const flashOptions: FlashOptions = {
|
||||
fileArray: fileArray,
|
||||
flashSize: "keep",
|
||||
eraseAll: false,
|
||||
compress: true,
|
||||
reportProgress: (fileIndex, written, total) => {
|
||||
flashProgress.value = Math.round((written / total) * 100);
|
||||
},
|
||||
} as FlashOptions;
|
||||
|
||||
await espLoader.writeFlash(
|
||||
flashOptions
|
||||
);
|
||||
|
||||
status.value = 'Flash complete!';
|
||||
flashProgress.value = 100;
|
||||
espLoader.hardReset();
|
||||
} catch (err: any) {
|
||||
error.value = err.message;
|
||||
}
|
||||
};
|
||||
|
||||
const disconnect = async () => {
|
||||
if (transport) {
|
||||
await transport.disconnect();
|
||||
transport = null;
|
||||
}
|
||||
if (espLoader) {
|
||||
espLoader = null;
|
||||
}
|
||||
isConnected.value = false;
|
||||
status.value = '';
|
||||
port = null;
|
||||
flashProgress.value = 0;
|
||||
};
|
||||
|
||||
const reset = async() => {
|
||||
// console.log(transport)
|
||||
// // if (transport) {
|
||||
// await transport.setDTR(false);
|
||||
// await new Promise((resolve) => setTimeout(resolve, 100));
|
||||
// await transport.setDTR(true);
|
||||
// //}
|
||||
await espLoader.hardReset();
|
||||
await disconnect();
|
||||
}
|
||||
|
||||
return {
|
||||
isConnected,
|
||||
flashProgress,
|
||||
status,
|
||||
error,
|
||||
connect,
|
||||
flash,
|
||||
disconnect,
|
||||
reset
|
||||
};
|
||||
};
|
29
composables/useManifest.ts
Normal file
29
composables/useManifest.ts
Normal file
|
@ -0,0 +1,29 @@
|
|||
import type { FirmwareManifest } from '~/types/manifest';
|
||||
|
||||
export const useManifest = () => {
|
||||
const getManifest = async(
|
||||
deviceType: string,
|
||||
customize: boolean,
|
||||
hasFrontlight: boolean,
|
||||
displayColors: string
|
||||
): FirmwareManifest => {
|
||||
|
||||
const response = await fetch(`/${deviceType}.json`);
|
||||
const baseManifest: FirmwareManifest = await response.json();
|
||||
|
||||
if (customize) {
|
||||
// Add NVS partition based on settings
|
||||
const nvsVariant = `${hasFrontlight ? 'frontlight_' : ''}${displayColors}`;
|
||||
baseManifest.builds[0].parts.push({
|
||||
path: `firmware_v3/nvs/${nvsVariant}.bin`,
|
||||
offset: "0x9000"
|
||||
});
|
||||
}
|
||||
|
||||
return baseManifest;
|
||||
};
|
||||
|
||||
return {
|
||||
getManifest
|
||||
};
|
||||
};
|
20
composables/useTheme.ts
Normal file
20
composables/useTheme.ts
Normal file
|
@ -0,0 +1,20 @@
|
|||
export const useTheme = () => {
|
||||
const theme = ref('light');
|
||||
|
||||
onMounted(() => {
|
||||
// Check system preference
|
||||
const darkModeMediaQuery = window.matchMedia('(prefers-color-scheme: dark)');
|
||||
|
||||
const updateTheme = (e: MediaQueryListEvent | MediaQueryList) => {
|
||||
theme.value = e.matches ? 'dark' : 'light';
|
||||
document.documentElement.setAttribute('data-theme', theme.value);
|
||||
};
|
||||
|
||||
darkModeMediaQuery.addEventListener('change', updateTheme);
|
||||
updateTheme(darkModeMediaQuery);
|
||||
});
|
||||
|
||||
return {
|
||||
theme
|
||||
};
|
||||
};
|
Loading…
Add table
Add a link
Reference in a new issue