/** * OTA Packaging Script * Generates www.bin from dist/ using mklittlefs or littlefs-python. */ import { execSync } from 'child_process'; import { resolve, dirname } from 'path'; import { fileURLToPath } from 'url'; import { existsSync, readFileSync, mkdirSync, writeFileSync } from 'fs'; const __dirname = dirname(fileURLToPath(import.meta.url)); const projectRoot = resolve(__dirname, '..'); const distDir = resolve(projectRoot, 'dist'); const binDir = resolve(projectRoot, 'bin'); const versionFile = resolve(projectRoot, 'version.json'); // Ensure bin directory exists if (!existsSync(binDir)) { mkdirSync(binDir, { recursive: true }); } // Configuration matching partitions.csv (1MB = 1048576 bytes) const FS_SIZE = 1048576; const BLOCK_SIZE = 4096; const PAGE_SIZE = 256; console.log('--- OTA Packaging ---'); /** * Handle versioning: Read current version */ function getVersion() { if (existsSync(versionFile)) { try { return JSON.parse(readFileSync(versionFile, 'utf8')); } catch (e) { console.warn('Warning: Could not read version.json:', e.message); } } return { major: 0, minor: 0, revision: 0 }; } /** * Increment and save revision */ function incrementVersion(version) { try { version.revision = (version.revision || 0) + 1; writeFileSync(versionFile, JSON.stringify(version, null, 2)); console.log(`Version incremented to: ${version.major}.${version.minor}.${version.revision} for next build.`); } catch (e) { console.warn('Warning: Could not update version.json:', e.message); } } /** * Simple .env parser to load MKLITTLEFS_PATH without external dependencies */ function loadEnv() { const envPaths = [ resolve(projectRoot, '.env.local'), resolve(projectRoot, '.env') ]; for (const path of envPaths) { if (existsSync(path)) { console.log(`Loading config from: ${path}`); const content = readFileSync(path, 'utf8'); content.split('\n').forEach(line => { const [key, ...valueParts] = line.split('='); if (key && valueParts.length > 0) { const value = valueParts.join('=').trim().replace(/^["']|["']$/g, ''); process.env[key.trim()] = value; } }); } } } loadEnv(); const version = getVersion(); const versionStr = `${version.major}.${version.minor}.${version.revision}`; const outputFile = resolve(binDir, `www_v${versionStr}.bin`); if (!existsSync(distDir)) { console.error('Error: dist/ directory not found. Run "npm run build:esp32" first.'); process.exit(1); } // Try to find mklittlefs or littlefs-python const findTool = () => { // 1. Check environment variable (from manual set or .env) if (process.env.MKLITTLEFS_PATH) { if (existsSync(process.env.MKLITTLEFS_PATH)) { return process.env.MKLITTLEFS_PATH; } console.warn(`Warning: MKLITTLEFS_PATH set to ${process.env.MKLITTLEFS_PATH} but file not found.`); } // 2. Check system PATH const tools = ['mklittlefs', 'littlefs-python']; for (const tool of tools) { try { execSync(`${tool} --version`, { stdio: 'ignore' }); return tool; } catch (e) { // Not in path } } return null; }; const tool = findTool(); if (!tool) { console.error('Error: No LittleFS tool found (checked mklittlefs and littlefs-python).'); console.info('Please set MKLITTLEFS_PATH in your .env file.'); console.info('Example: MKLITTLEFS_PATH=C:\\Espressif\\tools\\mklittlefs\\v3.2.0\\mklittlefs.exe'); process.exit(1); } try { console.log(`Using tool: ${tool}`); console.log(`Packaging ${distDir} -> ${outputFile}...`); let cmd; // Check if it is the Python version or the C++ version if (tool.includes('littlefs-python')) { // Python style: littlefs-python create