Files
story/web/test/ble-hardware.mjs
T

34 lines
2.4 KiB
JavaScript
Raw Normal View History

// Explicit opt-in real-hardware smoke check. Does not submit Wi-Fi or bind an account.
import { spawn } from 'node:child_process';
import { createInterface } from 'node:readline';
import { readFileSync } from 'node:fs';
import ts from 'typescript';
const label = JSON.parse(readFileSync(process.argv[2], 'utf8'));
const compiled = ts.transpileModule(readFileSync(new URL('../src/ble/security2.ts', import.meta.url), 'utf8'), { compilerOptions: { target: ts.ScriptTarget.ES2022, module: ts.ModuleKind.ESNext } }).outputText;
const { Security2 } = await import('data:text/javascript;base64,' + Buffer.from(compiled).toString('base64'));
const python = process.env.BLE_PYTHON;
if (!python) throw new Error('Set BLE_PYTHON to the ESP-IDF Python executable');
const child = spawn(python, ['../.tmp-ble-release/ble_bridge.py', 'EchoEar-' + label.device_id.slice(-6)], { stdio: ['pipe','pipe','inherit'] });
const lines = createInterface({ input: child.stdout })[Symbol.asyncIterator]();
async function receive() { const line = await lines.next(); if (line.done) throw new Error('BLE bridge ended'); const result = JSON.parse(line.value); if (result.error) throw new Error(result.error); return result; }
try {
const connected = await receive(); console.log(JSON.stringify(connected));
const security = new Security2();
async function exchange(type, data) {
const header = Buffer.from([type, data.length & 255, data.length >> 8]);
child.stdin.write(JSON.stringify({ frame: Buffer.concat([header, data]).toString('base64') }) + '\n');
const frame = Buffer.from((await receive()).frame,'base64');
if (frame[0] !== type || frame.readUInt16LE(1) + 3 !== frame.length) throw new Error('Invalid device reply');
return frame.subarray(3);
}
await security.handshake(label.device_id, label.setup_password, data => exchange(0, data));
console.log('Real ESP-IDF Security2 handshake verified');
for (const cmd of ['get_info','get_status','get_info','get_status']) {
const raw = Buffer.from(JSON.stringify({ cmd }));
const response = JSON.parse(Buffer.from(await security.decrypt(await exchange(1, await security.encrypt(raw)))).toString());
if (cmd === 'get_info' && response.device_id !== label.device_id) throw new Error('Wrong physical device');
console.log(JSON.stringify({ cmd, response }));
}
security.clear();
} finally { child.stdin.end(JSON.stringify({ close: true }) + '\n'); await new Promise(resolve => child.on('exit', resolve)); }