Initial commit

This commit is contained in:
Djuri 2024-12-07 17:48:13 +01:00
commit a892dfb3ba
27 changed files with 6607 additions and 0 deletions

View 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
};
};

View 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
View 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
};
};