80 lines
2.6 KiB
JavaScript
80 lines
2.6 KiB
JavaScript
/**
|
|
* Universal OTA Bundle Creator
|
|
* Packs FW (Provider.bin) and WWW (www_v*.bin) into a single .bundle file.
|
|
*/
|
|
|
|
import { readFileSync, writeFileSync, readdirSync, existsSync, mkdirSync } from 'fs';
|
|
import { resolve, dirname } from 'path';
|
|
import { fileURLToPath } from 'url';
|
|
|
|
const __dirname = dirname(fileURLToPath(import.meta.url));
|
|
const projectRoot = resolve(__dirname, '..');
|
|
const providerRoot = resolve(projectRoot, '..');
|
|
const binDir = resolve(projectRoot, 'bin');
|
|
|
|
// Paths
|
|
const fwFile = resolve(providerRoot, 'build', 'Provider.bin');
|
|
const bundleDir = resolve(projectRoot, 'bundles');
|
|
|
|
if (!existsSync(bundleDir)) {
|
|
mkdirSync(bundleDir, { recursive: true });
|
|
}
|
|
|
|
console.log('--- Universal Bundle Packaging ---');
|
|
|
|
// 1. Find the latest www.bin with proper semantic version sorting
|
|
const binFiles = readdirSync(binDir)
|
|
.filter(f => f.startsWith('www_v') && f.endsWith('.bin'))
|
|
.sort((a, b) => {
|
|
const getParts = (s) => {
|
|
const m = s.match(/v(\d+)\.(\d+)\.(\d+)/);
|
|
return m ? m.slice(1).map(Number) : [0, 0, 0];
|
|
};
|
|
const [aMajor, aMinor, aRev] = getParts(a);
|
|
const [bMajor, bMinor, bRev] = getParts(b);
|
|
return (bMajor - aMajor) || (bMinor - aMinor) || (bRev - aRev);
|
|
});
|
|
|
|
if (binFiles.length === 0) {
|
|
console.error('Error: No www_v*.bin found in frontend/bin/. Run "npm run ota:package" first.');
|
|
process.exit(1);
|
|
}
|
|
|
|
const wwwFile = resolve(binDir, binFiles[0]);
|
|
|
|
if (!existsSync(fwFile)) {
|
|
console.error(`Error: Firmware binary not found at ${fwFile}. Run "idf.py build" first.`);
|
|
process.exit(1);
|
|
}
|
|
|
|
try {
|
|
console.log(`Packing Firmware: ${fwFile}`);
|
|
console.log(`Packing Frontend: ${wwwFile}`);
|
|
|
|
const fwBuf = readFileSync(fwFile);
|
|
const wwwBuf = readFileSync(wwwFile);
|
|
|
|
// Create 12-byte header
|
|
// Magic: BNDL (4 bytes)
|
|
// FW Size: uint32 (4 bytes)
|
|
// WWW Size: uint32 (4 bytes)
|
|
const header = Buffer.alloc(12);
|
|
header.write('BNDL', 0);
|
|
header.writeUInt32LE(fwBuf.length, 4);
|
|
header.writeUInt32LE(wwwBuf.length, 8);
|
|
|
|
const bundleBuf = Buffer.concat([header, fwBuf, wwwBuf]);
|
|
const outputFile = resolve(bundleDir, `universal_v${binFiles[0].replace('www_v', '').replace('.bin', '')}.bundle`);
|
|
|
|
writeFileSync(outputFile, bundleBuf);
|
|
|
|
console.log('-------------------------------');
|
|
console.log(`Success: Bundle created at ${outputFile}`);
|
|
console.log(`Total size: ${(bundleBuf.length / 1024 / 1024).toFixed(2)} MB`);
|
|
console.log('-------------------------------');
|
|
|
|
} catch (e) {
|
|
console.error('Error creating bundle:', e.message);
|
|
process.exit(1);
|
|
}
|