init repo
This commit is contained in:
228
test_protocol.py
Normal file
228
test_protocol.py
Normal file
@@ -0,0 +1,228 @@
|
||||
#!/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_buzzer,
|
||||
cmd_set_power,
|
||||
cmd_set_mode,
|
||||
cmd_read_epc,
|
||||
cmd_select_card,
|
||||
cmd_write_epc,
|
||||
)
|
||||
|
||||
|
||||
def test_calc_outer_checksum():
|
||||
"""测试校验和计算"""
|
||||
print("\n=== 测试校验和计算 ===")
|
||||
|
||||
# 根据文档,读版本号命令的校验和应该是 0xc1
|
||||
# Data Length: 01 00 (小端序)
|
||||
# Data: c0
|
||||
data_len = bytes([0x01, 0x00])
|
||||
data = bytes([0xc0])
|
||||
checksum = calc_outer_checksum(data_len, data)
|
||||
print(f"读版本号校验和: 0x{checksum:02x} (期望: 0xc1)")
|
||||
assert checksum == 0xc1, f"校验和计算错误: 期望 0xc1, 实际 0x{checksum:02x}"
|
||||
|
||||
# 打开蜂鸣器的校验和应该是 0xce
|
||||
# Data Length: 02 00
|
||||
# Data: cd 01
|
||||
data_len = bytes([0x02, 0x00])
|
||||
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的校验和应该是 0xc6
|
||||
# Data Length: 02 00
|
||||
# Data: cc 08
|
||||
data_len = bytes([0x02, 0x00])
|
||||
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 06 00 00 02 01 00 c0 c1 03
|
||||
expected = bytes([0x01, 0x00, 0x00, 0x00, 0x00, 0x06, 0x00, 0x00, 0x02, 0x01, 0x00, 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 07 00 00 02 02 00 cd 01 ce 03
|
||||
expected = bytes([0x01, 0x00, 0x00, 0x00, 0x00, 0x07, 0x00, 0x00, 0x02, 0x02, 0x00, 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 07 00 00 02 02 00 cd 00 cf 03
|
||||
expected = bytes([0x01, 0x00, 0x00, 0x00, 0x00, 0x07, 0x00, 0x00, 0x02, 0x02, 0x00, 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 07 00 00 02 02 00 cc 08 c6 03
|
||||
expected = bytes([0x01, 0x00, 0x00, 0x00, 0x00, 0x07, 0x00, 0x00, 0x02, 0x02, 0x00, 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 07 00 00 02 02 00 0f 02 0f 03
|
||||
expected = bytes([0x01, 0x00, 0x00, 0x00, 0x00, 0x07, 0x00, 0x00, 0x02, 0x02, 0x00, 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)
|
||||
print(f"读取EPC帧 (前20字节): {frame[:20].hex()}")
|
||||
# 验证帧结构
|
||||
assert frame[0] == 0x01, "Report ID 应为 0x01"
|
||||
assert frame[1:5] == b'\x00\x00\x00\x00', "固定字段应为 0x00000000"
|
||||
assert frame[7:9] == b'\x00\x02', "Constant 应为 0x0002"
|
||||
print("读取EPC帧测试通过!")
|
||||
|
||||
|
||||
def test_parse_getres_frame():
|
||||
"""测试响应帧解析"""
|
||||
print("\n=== 测试响应帧解析 ===")
|
||||
|
||||
# 模拟读版本号成功的响应
|
||||
# Report ID: 0x03
|
||||
# 响应数据: 00 + 版本字符串 "MT6_RF915_RW"
|
||||
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) # constant + data_len + status + version
|
||||
response.extend(frame_len.to_bytes(2, 'little')) # Frame Length
|
||||
response.extend([0x00, 0x02]) # Constant
|
||||
data_len = 1 + len(version_str)
|
||||
response.extend(data_len.to_bytes(2, 'little')) # Data Length
|
||||
response.append(0x00) # Status = 成功
|
||||
response.extend(version_str) # Version string
|
||||
# 计算校验和
|
||||
checksum = calc_outer_checksum(data_len.to_bytes(2, 'little'), 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_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_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命令不匹配"
|
||||
|
||||
print("命令生成函数测试通过!")
|
||||
|
||||
|
||||
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()
|
||||
|
||||
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())
|
||||
Reference in New Issue
Block a user