import { describe, it, expect } from 'vitest'; import { buildRowsFromPayload } from '../src/processor/index.js'; describe('Processor Logic', () => { const basePayload = { ts_ms: 1700000000000, hotel_id: 1001, room_id: '8001', device_id: 'dev_001', direction: '上报', cmd_word: '0x36', frame_id: 1, udp_raw: '3601...', sys_lock_status: 0, report_count: 0, fault_count: 0 }; it('should validate required fields', () => { expect(() => buildRowsFromPayload({})).toThrow(); expect(() => buildRowsFromPayload({ ...basePayload, ts_ms: undefined })).toThrow(); }); it('should handle 0x36 Status Report with device list', () => { const payload = { ...basePayload, direction: '上报', cmd_word: '0x36', report_count: 2, device_list: [ { dev_type: 1, dev_addr: 10, dev_loop: 1, dev_data: 100 }, { dev_type: 1, dev_addr: 11, dev_loop: 2, dev_data: 0 } ] }; const rows = buildRowsFromPayload(payload); expect(rows).toHaveLength(2); expect(rows[0].action_type).toBe('36上报'); expect(rows[0].dev_addr).toBe(10); expect(rows[1].dev_addr).toBe(11); expect(rows[0].details.device_list).toHaveLength(2); }); it('should handle 0x36 Fault Report', () => { const payload = { ...basePayload, direction: '上报', cmd_word: '0x36', fault_count: 1, fault_list: [ { dev_type: 1, dev_addr: 10, dev_loop: 1, error_type: 2, error_data: 5 } ] }; const rows = buildRowsFromPayload(payload); expect(rows).toHaveLength(1); expect(rows[0].action_type).toBe('36上报'); expect(rows[0].error_type).toBe(2); }); it('should handle 0x36 Mixed Report (Status + Fault)', () => { const payload = { ...basePayload, direction: '上报', cmd_word: '0x36', report_count: 1, fault_count: 1, device_list: [{ dev_type: 1, dev_addr: 10, dev_loop: 1, dev_data: 100 }], fault_list: [{ dev_type: 1, dev_addr: 10, dev_loop: 1, error_type: 2, error_data: 5 }] }; const rows = buildRowsFromPayload(payload); expect(rows).toHaveLength(2); // 1 status + 1 fault }); it('should handle 0x0F Control Command', () => { const payload = { ...basePayload, direction: '下发', cmd_word: '0x0F', control_list: [ { dev_type: 1, dev_addr: 10, dev_loop: 1, type_l: 1, type_h: 2 } ] }; const rows = buildRowsFromPayload(payload); expect(rows).toHaveLength(1); expect(rows[0].action_type).toBe('0F下发'); expect(rows[0].type_l).toBe(1); expect(rows[0].type_h).toBe(2); expect(rows[0].dev_loop).toBe(1); }); it('should handle 0x0F ACK', () => { const payload = { ...basePayload, direction: '上报', cmd_word: '0x0F' }; const rows = buildRowsFromPayload(payload); expect(rows).toHaveLength(1); expect(rows[0].action_type).toBe('0FACK'); }); it('should fallback when lists are empty for 0x36', () => { const payload = { ...basePayload, direction: '上报', cmd_word: '0x36', device_list: [], fault_list: [] }; const rows = buildRowsFromPayload(payload); expect(rows).toHaveLength(1); expect(rows[0].action_type).toBe('36上报'); expect(rows[0].dev_type).toBeNull(); }); });