65 lines
2.4 KiB
TypeScript
65 lines
2.4 KiB
TypeScript
// 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');
|