// One-off verification script used during development to ensure the // TS protocol codec round-trips correctly and matches the C++ side. // Not intended to ship — kept because vitest couldn't run in the // sandbox where this was bootstrapped, and a plain tsx script lets // us re-run it quickly on any machine. import { crc8, encodeFrame, FrameDecoder, MsgType, Emotion, type DecodedFrame, } from '../src/hardware/protocol.js'; function assert(cond: unknown, msg: string): void { if (!cond) { console.error(`FAIL: ${msg}`); process.exitCode = 1; } else { console.log(`ok: ${msg}`); } } // CRC reference values (also validated against Python implementation). assert(crc8(Buffer.from('123456789', 'ascii')) === 0xf4, "crc8('123456789') === 0xF4"); assert(crc8(Buffer.from([0x00])) === 0x00, 'crc8([0x00]) === 0x00'); assert(crc8(Buffer.from([0x01])) === 0x07, 'crc8([0x01]) === 0x07'); assert(crc8(Buffer.from([0xaa])) === 0x5f, 'crc8([0xAA]) === 0x5F'); // DISPLAY_EMOTION HAPPY must produce a 6-byte frame with CRC 0xDC // (matches Python reference computed in verify script). const happy = encodeFrame(MsgType.DISPLAY_EMOTION, Buffer.from([Emotion.HAPPY])); assert(happy.length === 6, 'DISPLAY_EMOTION frame length === 6'); assert(happy[0] === 0xaa, 'start byte 0xAA'); assert(happy[1] === 0x20, 'type 0x20'); assert(happy[2] === 0x00 && happy[3] === 0x01, 'length = 1'); assert(happy[4] === 0x01, 'payload = HAPPY (1)'); assert(happy[5] === 0xdc, 'CRC === 0xDC'); // Round-trip through the decoder. let received: DecodedFrame | null = null; const decoder = new FrameDecoder((f) => { received = f; }); decoder.feed(happy); assert(received !== null, 'frame emitted'); assert(received!.type === MsgType.DISPLAY_EMOTION, 'type preserved'); assert(received!.payload[0] === Emotion.HAPPY, 'payload preserved'); // Resync after corrupted CRC. received = null; const bad = Buffer.from(happy); bad[bad.length - 1] = (bad[bad.length - 1]! ^ 0xff) & 0xff; decoder.feed(bad); assert(received === null, 'bad CRC not emitted'); assert(decoder.framesDropped === 1, 'drop counter === 1'); const again = encodeFrame(MsgType.DISPLAY_EMOTION, Buffer.from([Emotion.WINK])); decoder.feed(again); assert(received !== null, 'decoder resynced'); assert((received as unknown as DecodedFrame).payload[0] === Emotion.WINK, 'resync payload ok'); console.log('\nall protocol checks passed');