#!/usr/bin/env python3 # -*- coding: utf-8 -*- """ 测试 MT6 RFID 读卡器协议函数(大端序版本) """ import sys import os # 添加 PySimpleGUI 目录到路径 sys.path.insert(0, os.path.join(os.path.dirname(os.path.abspath(__file__)), 'PySimpleGUI')) # 导入协议函数 from rfid_tester import ( calc_outer_checksum, build_setreq_frame, parse_getres_frame, cmd_get_version, cmd_factory_reset, cmd_read_format, cmd_set_format, cmd_buzzer, cmd_rf_power, cmd_set_power, cmd_set_mode, cmd_read_epc, cmd_select_card, cmd_write_epc, ) def test_calc_outer_checksum(): """测试校验和计算""" print("\n=== 测试校验和计算 ===") # 根据文档,读版本号命令 # Data Length: 00 01 (大端序) # Data: c0 data_len = bytes([0x00, 0x01]) data = bytes([0xc0]) checksum = calc_outer_checksum(data_len, data) print(f"读版本号校验和: 0x{checksum:02x} (期望: 0xc1)") assert checksum == 0xc1, f"校验和计算错误: 期望 0xc1, 实际 0x{checksum:02x}" # 打开蜂鸣器 # Data Length: 00 02 (大端序) # Data: cd 01 data_len = bytes([0x00, 0x02]) data = bytes([0xcd, 0x01]) checksum = calc_outer_checksum(data_len, data) print(f"打开蜂鸣器校验和: 0x{checksum:02x} (期望: 0xce)") assert checksum == 0xce, f"校验和计算错误: 期望 0xce, 实际 0x{checksum:02x}" # 设置功率=8 # Data Length: 00 02 (大端序) # Data: cc 08 data_len = bytes([0x00, 0x02]) data = bytes([0xcc, 0x08]) checksum = calc_outer_checksum(data_len, data) print(f"设置功率=8校验和: 0x{checksum:02x} (期望: 0xc6)") assert checksum == 0xc6, f"校验和计算错误: 期望 0xc6, 实际 0x{checksum:02x}" print("校验和测试通过!") def test_build_setreq_frame(): """测试帧构建(大端序)""" print("\n=== 测试帧构建(大端序)===") # 测试读版本号命令 cmd = cmd_get_version() frame = build_setreq_frame(cmd) # 大端序: 01 00 00 00 00 00 06 00 02 00 01 c0 c1 03 expected = bytes([0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x06, 0x00, 0x02, 0x00, 0x01, 0xc0, 0xc1, 0x03]) print(f"读版本号帧 (前14字节): {frame[:14].hex()}") print(f"期望: {expected.hex()}") assert frame[:14] == expected, f"读版本号帧不匹配" assert len(frame) == 256, f"帧长度应为256字节,实际为{len(frame)}" print("读版本号帧测试通过!") # 测试打开蜂鸣器命令 cmd = cmd_buzzer(True) frame = build_setreq_frame(cmd) # 大端序: 01 00 00 00 00 00 07 00 02 00 02 cd 01 ce 03 expected = bytes([0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x07, 0x00, 0x02, 0x00, 0x02, 0xcd, 0x01, 0xce, 0x03]) print(f"打开蜂鸣器帧 (前15字节): {frame[:15].hex()}") print(f"期望: {expected.hex()}") assert frame[:15] == expected, f"打开蜂鸣器帧不匹配" print("打开蜂鸣器帧测试通过!") # 测试关闭蜂鸣器命令 cmd = cmd_buzzer(False) frame = build_setreq_frame(cmd) # 大端序: 01 00 00 00 00 00 07 00 02 00 02 cd 00 cf 03 expected = bytes([0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x07, 0x00, 0x02, 0x00, 0x02, 0xcd, 0x00, 0xcf, 0x03]) print(f"关闭蜂鸣器帧 (前15字节): {frame[:15].hex()}") print(f"期望: {expected.hex()}") assert frame[:15] == expected, f"关闭蜂鸣器帧不匹配" print("关闭蜂鸣器帧测试通过!") # 测试设置功率命令 cmd = cmd_set_power(8) frame = build_setreq_frame(cmd) # 大端序: 01 00 00 00 00 00 07 00 02 00 02 cc 08 c6 03 expected = bytes([0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x07, 0x00, 0x02, 0x00, 0x02, 0xcc, 0x08, 0xc6, 0x03]) print(f"设置功率=8帧 (前15字节): {frame[:15].hex()}") print(f"期望: {expected.hex()}") assert frame[:15] == expected, f"设置功率帧不匹配" print("设置功率帧测试通过!") # 测试设置被动模式命令 cmd = cmd_set_mode(2) frame = build_setreq_frame(cmd) # 大端序: 01 00 00 00 00 00 07 00 02 00 02 0f 02 0f 03 expected = bytes([0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x07, 0x00, 0x02, 0x00, 0x02, 0x0f, 0x02, 0x0f, 0x03]) print(f"设置被动模式帧 (前15字节): {frame[:15].hex()}") print(f"期望: {expected.hex()}") assert frame[:15] == expected, f"设置模式帧不匹配" print("设置模式帧测试通过!") # 测试读取 EPC 命令 cmd = cmd_read_epc() frame = build_setreq_frame(cmd) # Data: ce bb 00 22 00 00 22 7e (8 bytes) # Frame Length: 00 0d (大端序, 13) # Data Length: 00 08 (大端序) # Checksum: 00 ^ 08 ^ ce ^ bb ^ 00 ^ 22 ^ 00 ^ 00 ^ 22 ^ 7e = 03 expected = bytes([0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x0d, 0x00, 0x02, 0x00, 0x08, 0xce, 0xbb, 0x00, 0x22, 0x00, 0x00, 0x22, 0x7e, 0x03, 0x03]) print(f"读取EPC帧 (前21字节): {frame[:21].hex()}") print(f"期望: {expected.hex()}") assert frame[:21] == expected, f"读取EPC帧不匹配" print("读取EPC帧测试通过!") # 测试打开射频命令 cmd = cmd_rf_power(True) frame = build_setreq_frame(cmd) # Data: 90 01 (2 bytes) # Data Length: 00 02 # Frame Length: 00 07 # Checksum: 00 ^ 02 ^ 90 ^ 01 = 93 expected = bytes([0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x07, 0x00, 0x02, 0x00, 0x02, 0x90, 0x01, 0x93, 0x03]) print(f"打开射频帧 (前15字节): {frame[:15].hex()}") print(f"期望: {expected.hex()}") assert frame[:15] == expected, f"打开射频帧不匹配" print("打开射频帧测试通过!") def test_parse_getres_frame(): """测试响应帧解析(大端序)""" print("\n=== 测试响应帧解析(大端序)===") # 模拟读版本号成功的响应 version_str = b"MT6_RF915_RW" response = bytearray() response.append(0x03) # Report ID response.extend([0x00, 0x00, 0x00, 0x00]) # Fixed frame_len = 2 + 2 + 1 + len(version_str) + 1 # constant + data_len + status + version + checksum response.extend(frame_len.to_bytes(2, 'big')) # Frame Length (大端序) response.extend([0x00, 0x02]) # Constant data_len = 1 + len(version_str) response.extend(data_len.to_bytes(2, 'big')) # Data Length (大端序) response.append(0x00) # Status = 成功 response.extend(version_str) # Version string # 计算校验和 checksum = calc_outer_checksum(data_len.to_bytes(2, 'big'), bytes([0x00]) + version_str) response.append(checksum) response.append(0x03) # End Marker result = parse_getres_frame(bytes(response)) assert result is not None, "解析失败" status, data = result print(f"状态: 0x{status:02x} (期望: 0x00)") print(f"数据: {data}") assert status == 0x00, f"状态应为 0x00,实际为 0x{status:02x}" assert data.decode('ascii').startswith("MT6"), "版本字符串应包含 MT6" print("响应帧解析测试通过!") def test_command_functions(): """测试命令生成函数""" print("\n=== 测试命令生成函数 ===") # 测试读版本号命令 cmd = cmd_get_version() print(f"读版本号命令: {cmd.hex()}") assert cmd == bytes([0xc0]), f"读版本号命令应为 c0" # 测试恢复出厂设置命令 cmd = cmd_factory_reset() print(f"恢复出厂设置命令: {cmd.hex()}") assert cmd == bytes([0xcf]), f"恢复出厂设置命令应为 cf" # 测试读取格式命令 cmd = cmd_read_format() print(f"读取格式命令: {cmd.hex()}") assert cmd == bytes([0x83]), f"读取格式命令应为 83" # 测试设置格式命令 cmd = cmd_set_format() print(f"设置格式命令: {cmd.hex()}") assert cmd == bytes([0x82, 0x0f, 0x00, 0x00, 0x00, 0x01, 0x01, 0x01, 0x00]), f"设置格式命令不匹配" # 测试蜂鸣器命令 cmd = cmd_buzzer(True) print(f"打开蜂鸣器命令: {cmd.hex()}") assert cmd == bytes([0xcd, 0x01]), f"打开蜂鸣器命令应为 cd 01" cmd = cmd_buzzer(False) print(f"关闭蜂鸣器命令: {cmd.hex()}") assert cmd == bytes([0xcd, 0x00]), f"关闭蜂鸣器命令应为 cd 00" # 测试射频电源命令 cmd = cmd_rf_power(True) print(f"打开射频命令: {cmd.hex()}") assert cmd == bytes([0x90, 0x01]), f"打开射频命令应为 90 01" cmd = cmd_rf_power(False) print(f"关闭射频命令: {cmd.hex()}") assert cmd == bytes([0x90, 0x00]), f"关闭射频命令应为 90 00" # 测试设置功率命令 cmd = cmd_set_power(5) print(f"设置功率=5命令: {cmd.hex()}") assert cmd == bytes([0xcc, 0x05]), f"设置功率=5命令应为 cc 05" # 测试设置模式命令 cmd = cmd_set_mode(1) print(f"设置单标签巡查模式命令: {cmd.hex()}") assert cmd == bytes([0x0f, 0x01]), f"设置单标签巡查模式命令应为 0f 01" cmd = cmd_set_mode(2) print(f"设置被动模式命令: {cmd.hex()}") assert cmd == bytes([0x0f, 0x02]), f"设置被动模式命令应为 0f 02" # 测试读取 EPC 命令 cmd = cmd_read_epc() print(f"读取EPC命令: {cmd.hex()}") assert cmd == bytes([0xce, 0xbb, 0x00, 0x22, 0x00, 0x00, 0x22, 0x7e]), f"读取EPC命令不匹配" # 测试选中卡命令(验证校验和计算包含Internal Length) epc_data = bytes([0x11, 0x22]) cmd = cmd_select_card(epc_data) print(f"选中卡命令 (EPC=1122): {cmd.hex()}") # 根据协议: ce bb 00 0c 00 09 01 00 00 00 20 10 00 11 22 79 7e # Checksum = 00+0c+00+09+01+00+00+00+20+10+00+11+22 mod 256 = 79 expected = bytes([0xce, 0xbb, 0x00, 0x0c, 0x00, 0x09, 0x01, 0x00, 0x00, 0x00, 0x20, 0x10, 0x00, 0x11, 0x22, 0x79, 0x7e]) assert cmd == expected, f"选中卡命令不匹配: 期望 {expected.hex()}, 实际 {cmd.hex()}" print("命令生成函数测试通过!") def test_epc_operations(): """测试EPC操作命令""" print("\n=== 测试EPC操作命令 ===") # 测试选中卡命令 epc_data = bytes([0x11, 0x22]) cmd = cmd_select_card(epc_data) print(f"选中卡命令: {cmd.hex()}") # 验证结构: ce bb + Card Op Command + Internal Length(大端) + Payload + Checksum + 7e assert cmd[0:2] == bytes([0xce, 0xbb]), "Command/Magic不正确" assert cmd[2:4] == bytes([0x00, 0x0c]), "Card Op Command不正确" assert cmd[4:6] == bytes([0x00, 0x09]), "Internal Length应为00 09 (大端序)" assert cmd[-1] == 0x7e, "End Marker应为7e" print("选中卡命令测试通过!") # 测试写入EPC命令 old_epc_crc = bytes([0xca, 0x9e]) # 大端序 new_epc = bytes([0x11, 0x23]) cmd = cmd_write_epc(old_epc_crc, new_epc) print(f"写入EPC命令: {cmd.hex()}") # 验证结构 assert cmd[0:2] == bytes([0xce, 0xbb]), "Command/Magic不正确" assert cmd[2:4] == bytes([0x00, 0x49]), "Card Op Command不正确" assert cmd[-1] == 0x7e, "End Marker应为7e" print("写入EPC命令测试通过!") def main(): """主测试函数""" print("=" * 60) print("MT6 RFID 读卡器协议函数测试(大端序版本)") print("=" * 60) try: test_calc_outer_checksum() test_build_setreq_frame() test_parse_getres_frame() test_command_functions() test_epc_operations() print("\n" + "=" * 60) print("所有测试通过!") print("=" * 60) return 0 except AssertionError as e: print(f"\n测试失败: {e}") return 1 except Exception as e: print(f"\n测试出错: {e}") import traceback traceback.print_exc() return 1 if __name__ == '__main__': sys.exit(main())