import { describe, it, expect } from 'vitest'; import { crc16Ibm } from '../src/adapters/teltonika/crc.js'; describe('crc16Ibm', () => { it('returns 0x0000 for an empty buffer', () => { expect(crc16Ibm(Buffer.alloc(0))).toBe(0x0000); }); it('matches the canonical Teltonika Codec 8 first example (0xC7CF)', () => { // Full frame (hex stream from the Teltonika doc, first example): // 000000000000003608010000016B40D8EA30010000000000000000000000000000000105021503010101425E0F01F10000601A014E0000000000000000010000C7CF // // Structure: // 00 00 00 00 preamble // 00 00 00 36 DataFieldLength = 0x36 = 54 // 08 01 ... body (CodecID through N2) — 54 bytes // 00 00 C7 CF CRC field // // CRC is computed over the 54-byte body only. const body = Buffer.from( '08' + // CodecID '01' + // N1 = 1 '0000016B40D8EA30' + // Timestamp '01' + // Priority '00000000' + // Longitude '00000000' + // Latitude '0000' + // Altitude '0000' + // Angle '00' + // Satellites '0000' + // Speed '01' + // Event IO ID '05' + // N total IO '02' + // N1 IO (1-byte values) '15' + '03' + // IO 21 = 3 '01' + '01' + // IO 1 = 1 '01' + // N2 IO (2-byte values) '42' + '5E0F' + // IO 66 = 0x5E0F '01' + // N4 IO (4-byte values) 'F1' + '0000601A' + // IO 241 = 0x0000601A '01' + // N8 IO (8-byte values) '4E' + '0000000000000000' + // IO 78 = 0 '01', // N2 = 1 'hex', ); expect(body.length).toBe(0x36); // sanity-check: must be 54 bytes expect(crc16Ibm(body)).toBe(0xc7cf); }); it('matches the second Teltonika Codec 8 example (0xF22A)', () => { // Full frame hex: // 000000000000002808010000016B40D9AD80010000000000000000000000000000000103021503010101425E100000010000F22A // Body = bytes from CodecID through N2 (0x28 = 40 bytes) const body = Buffer.from( '08' + '01' + '0000016B40D9AD80' + '01' + '00000000' + '00000000' + '0000' + '0000' + '00' + '0000' + '01' + '03' + '02' + '15' + '03' + '01' + '01' + '01' + '42' + '5E10' + '00' + '00' + '01', 'hex', ); expect(body.length).toBe(0x28); // 40 bytes expect(crc16Ibm(body)).toBe(0xf22a); }); it('produces a non-zero CRC for a single 0xFF byte', () => { expect(crc16Ibm(Buffer.from([0xff]))).not.toBe(0); }); });