NFC 测试脚本 DSL 执行环境,基于 nfctester 插件化架构。
uv syncnfcscript test_card.py# 指定串口
nfcscript test_card.py -p COM21
# 指定读卡器类型
nfcscript test_card.py -r acr122u
# 开启追踪层
nfcscript test_card.py --trace-driver --trace-protocol
# 设置日志级别
nfcscript test_card.py --trace-level DEBUG
# 组合使用
nfcscript test_card.py -p COM21 -r pn532 --trace-driver --trace-protocol --trace-level DEBUG# 列出所有可用卡片类型
nfc-cli --list-cards
# 连接卡片并进入交互模式
nfc-cli -c ntag224 -p COM21
# 指定读卡器类型
nfc-cli -c mifare_classic -p COM21 -r pn532
# 通过环境变量自动发现外部卡片
export NFC_CARD_PATH="../scripts/lib"
nfc-cli -c sm7 -p COM20
# 或手动指定
nfc-cli -c sm7 -p COM20 -i ../scripts/lib进入交互模式后,可以输入命令操作卡片:
> help # 显示可用命令
> auth 7 FFFFFFFFFFFF # 认证块 7
> read 10 # 读取页 10
> write 20 AABBCCDD... # 写入页 20
> quit # 退出
支持的值格式:
- 十六进制:
0xFF,0xAABBCCDD - 十进制:
7,255 - 字节串:
b'\xff\x00'
使用 -i 参数导入外部卡片模块,支持单个 .py 文件或包含 __init__.py 的目录:
# 导入单个文件
nfc-cli -c my_card -p COM20 -i /path/to/my_card.py
# 导入目录(需要有 __init__.py)
nfc-cli -c sm7 -p COM20 -i /path/to/lib外部卡片模块需要使用 @CardRegistry.register("name") 装饰器注册。
# NTAG224 认证并读取
nfc-cli -c ntag224 -p COM21
> auth 1 AABBCCDD112233445566778899001122
> read 4
# Mifare Classic 操作
nfc-cli -c mifare_classic -p COM21
> authenticate 7 FFFFFFFFFFFF
> read_block 8
> write_block 9 AABBCCDD112233445566778899001122from nfc import *
# 连接读卡器 (默认使用环境变量 NFC_PORT 或 COM20)
connect()
# 开启追踪
trace.set_layer("DRIVER", True)
trace.set_layer("PROTOCOL", True)
# 寻卡
card_info = active()
ASSERT_IS_NOT_NONE(card_info, "未扫描到卡片")
print(f"UID: {card_info['uid'].hex().upper()}")
# 创建卡片实例
from nfctester.registry import CardRegistry
card = CardRegistry.create("mifare", reader=get_reader())
# 关闭连接
close()from nfc import *
with session() as reader:
card_info = reader.find()
print(card_info)
# 自动断开连接| 模块 | 说明 |
|---|---|
reader.py |
读卡器连接与通信 |
trace.py |
日志追踪控制 |
assertions.py |
测试断言 |
bits.py |
位操作工具 |
hex_util.py |
十六进制工具 |
checksum.py |
校验工具 |
delay.py |
延时工具 |
| 函数 | 说明 |
|---|---|
connect(port, reader_type) |
连接读卡器 |
get_reader() |
获取当前读卡器实例 |
active(ll, ignore_error) |
寻卡,返回 uid/atq/sak |
transceive(data, tx_crc, rx_crc) |
底层帧交互 |
transceive_bits(data, last_tx_bits, tx_crc, rx_crc) |
位控制帧交互 |
reqa() |
ISO14443-A REQA |
wupa() |
ISO14443-A WUPA |
halt() |
ISO14443-A HALT |
select(cl_level, uid) |
ISO14443-A SELECT |
anticoll(cl_level, nvb, uid_prefix) |
ISO14443-A ANTICOLL |
field_on() / field_off() |
RF 场控制 |
session(port, reader_type) |
上下文管理器 |
close() |
断开连接 |
| 函数 | 说明 |
|---|---|
trace.set_layer(layer, enable) |
开启/关闭追踪层 |
trace.set_level(level) |
设置日志级别 |
trace.info(msg) / trace.error(msg) / trace.warning(msg) / trace.success(msg) / trace.debug(msg) |
输出日志 |
| 函数 | 说明 |
|---|---|
ASSERT_EQUAL(expected, actual, msg) |
相等断言 |
ASSERT_LEN(data, expected_len, msg) |
长度断言 |
ASSERT_IS_NOT_NONE(value, msg) |
非空断言 |
ASSERT_IS_NONE(value, msg) |
空值断言 |
| 函数 | 说明 |
|---|---|
BITS_UPDATE(val, mask, data) |
Read-Modify-Write |
BITS_SET(val, mask) |
置位 |
BITS_RESET(val, mask) |
清位 |
| 函数 | 说明 |
|---|---|
PARSE_HEX(text) |
解析 hex 字符串 |
FORMAT_HEX(data, last_bits) |
格式化为可视化 hex |
| 函数 | 说明 |
|---|---|
GET_BCC(data) |
计算异或校验 |
| 函数 | 说明 |
|---|---|
DELAY_MS(ms) |
毫秒延时 |
优先级: CLI 参数 > 内层 .env > 外层 .env > 系统环境变量 (必须配置,否则报错)
| 变量 | 说明 | 默认值 |
|---|---|---|
NFC_PORT |
串口号 | - |
NFC_READER |
读卡器类型 | - |
NFC_TRACE_LEVEL |
日志级别 | INFO |
NFC_TRACE_DRIVER |
开启 DRIVER 层追踪 | false |
NFC_TRACE_PROTOCOL |
开启 PROTOCOL 层追踪 | false |
NFC_CARD_PATH |
外部卡片模块搜索路径 (分号分隔) | - |
支持多层 .env 加载:从脚本目录向上搜索所有 .env 文件,按从外到内的顺序依次加载(内层覆盖外层同名变量)。
例如,脚本位于 /project/tests/run.py,沿途有 /project/.env 和 /project/tests/.env,加载顺序为:
/project/.env(基础配置)/project/tests/.env(覆盖基础配置中的同名变量)
在项目根目录或脚本所在目录创建 .env 文件进行持久化配置:
NFC_PORT=COM20
NFC_READER=pn532
NFC_TRACE_LEVEL=DEBUG
NFC_TRACE_DRIVER=true
NFC_TRACE_PROTOCOL=true
# 运行测试
uv run pytest
# 运行特定测试
uv run pytest tests/test_xxx.py