nfcscript 0.0.10__tar.gz → 0.0.12__tar.gz
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- {nfcscript-0.0.10 → nfcscript-0.0.12}/PKG-INFO +10 -7
- {nfcscript-0.0.10 → nfcscript-0.0.12}/README.md +9 -6
- {nfcscript-0.0.10 → nfcscript-0.0.12}/pyproject.toml +2 -2
- {nfcscript-0.0.10 → nfcscript-0.0.12}/src/nfc/cli.py +0 -7
- {nfcscript-0.0.10 → nfcscript-0.0.12}/src/nfc/reader.py +5 -1
- {nfcscript-0.0.10 → nfcscript-0.0.12}/src/nfc/trace.py +23 -12
- {nfcscript-0.0.10 → nfcscript-0.0.12}/src/nfcscript.egg-info/PKG-INFO +10 -7
- {nfcscript-0.0.10 → nfcscript-0.0.12}/tests/test_trace.py +0 -8
- {nfcscript-0.0.10 → nfcscript-0.0.12}/setup.cfg +0 -0
- {nfcscript-0.0.10 → nfcscript-0.0.12}/src/nfc/__init__.py +0 -0
- {nfcscript-0.0.10 → nfcscript-0.0.12}/src/nfc/assertions.py +0 -0
- {nfcscript-0.0.10 → nfcscript-0.0.12}/src/nfc/bits.py +0 -0
- {nfcscript-0.0.10 → nfcscript-0.0.12}/src/nfc/checksum.py +0 -0
- {nfcscript-0.0.10 → nfcscript-0.0.12}/src/nfc/delay.py +0 -0
- {nfcscript-0.0.10 → nfcscript-0.0.12}/src/nfc/hex_util.py +0 -0
- {nfcscript-0.0.10 → nfcscript-0.0.12}/src/nfc/nfc_cli.py +0 -0
- {nfcscript-0.0.10 → nfcscript-0.0.12}/src/nfcscript.egg-info/SOURCES.txt +0 -0
- {nfcscript-0.0.10 → nfcscript-0.0.12}/src/nfcscript.egg-info/dependency_links.txt +0 -0
- {nfcscript-0.0.10 → nfcscript-0.0.12}/src/nfcscript.egg-info/entry_points.txt +0 -0
- {nfcscript-0.0.10 → nfcscript-0.0.12}/src/nfcscript.egg-info/requires.txt +0 -0
- {nfcscript-0.0.10 → nfcscript-0.0.12}/src/nfcscript.egg-info/top_level.txt +0 -0
- {nfcscript-0.0.10 → nfcscript-0.0.12}/tests/test_assertions.py +0 -0
- {nfcscript-0.0.10 → nfcscript-0.0.12}/tests/test_bits.py +0 -0
- {nfcscript-0.0.10 → nfcscript-0.0.12}/tests/test_checksum.py +0 -0
- {nfcscript-0.0.10 → nfcscript-0.0.12}/tests/test_cli.py +0 -0
- {nfcscript-0.0.10 → nfcscript-0.0.12}/tests/test_cli_collect.py +0 -0
- {nfcscript-0.0.10 → nfcscript-0.0.12}/tests/test_delay.py +0 -0
- {nfcscript-0.0.10 → nfcscript-0.0.12}/tests/test_hex_util.py +0 -0
- {nfcscript-0.0.10 → nfcscript-0.0.12}/tests/test_reader.py +0 -0
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
Metadata-Version: 2.4
|
|
2
2
|
Name: nfcscript
|
|
3
|
-
Version: 0.0.
|
|
3
|
+
Version: 0.0.12
|
|
4
4
|
Summary: A plugin-based core engine for DSL-style NFC testing automation.
|
|
5
5
|
Author: crthu
|
|
6
6
|
Requires-Python: >=3.14
|
|
@@ -123,14 +123,14 @@ connect()
|
|
|
123
123
|
trace.set_layer("DRIVER", True)
|
|
124
124
|
trace.set_layer("PROTOCOL", True)
|
|
125
125
|
|
|
126
|
-
#
|
|
126
|
+
# 寻卡(自动切换协议解析器)
|
|
127
127
|
card_info = active()
|
|
128
128
|
ASSERT_IS_NOT_NONE(card_info, "未扫描到卡片")
|
|
129
|
-
print(f"UID: {
|
|
129
|
+
print(f"UID: {' '.join(f'{b:02X}' for b in card_info.uid)}")
|
|
130
130
|
|
|
131
131
|
# 创建卡片实例
|
|
132
132
|
from nfctester.registry import CardRegistry
|
|
133
|
-
card = CardRegistry.create("
|
|
133
|
+
card = CardRegistry.create("mifare_classic", reader=get_reader())
|
|
134
134
|
|
|
135
135
|
# 关闭连接
|
|
136
136
|
close()
|
|
@@ -142,8 +142,8 @@ close()
|
|
|
142
142
|
from nfc import *
|
|
143
143
|
|
|
144
144
|
with session() as reader:
|
|
145
|
-
card_info = reader.
|
|
146
|
-
print(card_info)
|
|
145
|
+
card_info = reader.active()
|
|
146
|
+
print(card_info.uid)
|
|
147
147
|
# 自动断开连接
|
|
148
148
|
```
|
|
149
149
|
|
|
@@ -167,7 +167,7 @@ with session() as reader:
|
|
|
167
167
|
|------|------|
|
|
168
168
|
| `connect(port, reader_type)` | 连接读卡器 |
|
|
169
169
|
| `get_reader()` | 获取当前读卡器实例 |
|
|
170
|
-
| `active(low_layer, ignore_error, reqa_cmd)` | 寻卡,返回 uid/atq/sak |
|
|
170
|
+
| `active(low_layer, ignore_error, reqa_cmd)` | 寻卡,返回 CardInfo (uid/atq/sak),自动切换协议解析器 |
|
|
171
171
|
| `transceive(data, tx_crc, rx_crc)` | 底层帧交互 |
|
|
172
172
|
| `transceive_bits(data, last_tx_bits, tx_crc, rx_crc)` | 位控制帧交互 |
|
|
173
173
|
| `reqa()` | ISO14443-A REQA |
|
|
@@ -185,6 +185,9 @@ with session() as reader:
|
|
|
185
185
|
|------|------|
|
|
186
186
|
| `trace.set_layer(layer, enable)` | 开启/关闭追踪层 |
|
|
187
187
|
| `trace.set_level(level)` | 设置日志级别 |
|
|
188
|
+
| `trace.set_parse(level)` | 设置解析级别 (0=关闭, 1=hex+摘要) |
|
|
189
|
+
| `trace.add_sink(fn)` | 注册结构化 trace 事件回调 |
|
|
190
|
+
| `trace.remove_sink(fn)` | 移除已注册的回调 |
|
|
188
191
|
| `trace.info(msg)` / `trace.error(msg)` / `trace.warning(msg)` / `trace.success(msg)` / `trace.debug(msg)` | 输出日志 |
|
|
189
192
|
|
|
190
193
|
### assertions.py
|
|
@@ -113,14 +113,14 @@ connect()
|
|
|
113
113
|
trace.set_layer("DRIVER", True)
|
|
114
114
|
trace.set_layer("PROTOCOL", True)
|
|
115
115
|
|
|
116
|
-
#
|
|
116
|
+
# 寻卡(自动切换协议解析器)
|
|
117
117
|
card_info = active()
|
|
118
118
|
ASSERT_IS_NOT_NONE(card_info, "未扫描到卡片")
|
|
119
|
-
print(f"UID: {
|
|
119
|
+
print(f"UID: {' '.join(f'{b:02X}' for b in card_info.uid)}")
|
|
120
120
|
|
|
121
121
|
# 创建卡片实例
|
|
122
122
|
from nfctester.registry import CardRegistry
|
|
123
|
-
card = CardRegistry.create("
|
|
123
|
+
card = CardRegistry.create("mifare_classic", reader=get_reader())
|
|
124
124
|
|
|
125
125
|
# 关闭连接
|
|
126
126
|
close()
|
|
@@ -132,8 +132,8 @@ close()
|
|
|
132
132
|
from nfc import *
|
|
133
133
|
|
|
134
134
|
with session() as reader:
|
|
135
|
-
card_info = reader.
|
|
136
|
-
print(card_info)
|
|
135
|
+
card_info = reader.active()
|
|
136
|
+
print(card_info.uid)
|
|
137
137
|
# 自动断开连接
|
|
138
138
|
```
|
|
139
139
|
|
|
@@ -157,7 +157,7 @@ with session() as reader:
|
|
|
157
157
|
|------|------|
|
|
158
158
|
| `connect(port, reader_type)` | 连接读卡器 |
|
|
159
159
|
| `get_reader()` | 获取当前读卡器实例 |
|
|
160
|
-
| `active(low_layer, ignore_error, reqa_cmd)` | 寻卡,返回 uid/atq/sak |
|
|
160
|
+
| `active(low_layer, ignore_error, reqa_cmd)` | 寻卡,返回 CardInfo (uid/atq/sak),自动切换协议解析器 |
|
|
161
161
|
| `transceive(data, tx_crc, rx_crc)` | 底层帧交互 |
|
|
162
162
|
| `transceive_bits(data, last_tx_bits, tx_crc, rx_crc)` | 位控制帧交互 |
|
|
163
163
|
| `reqa()` | ISO14443-A REQA |
|
|
@@ -175,6 +175,9 @@ with session() as reader:
|
|
|
175
175
|
|------|------|
|
|
176
176
|
| `trace.set_layer(layer, enable)` | 开启/关闭追踪层 |
|
|
177
177
|
| `trace.set_level(level)` | 设置日志级别 |
|
|
178
|
+
| `trace.set_parse(level)` | 设置解析级别 (0=关闭, 1=hex+摘要) |
|
|
179
|
+
| `trace.add_sink(fn)` | 注册结构化 trace 事件回调 |
|
|
180
|
+
| `trace.remove_sink(fn)` | 移除已注册的回调 |
|
|
178
181
|
| `trace.info(msg)` / `trace.error(msg)` / `trace.warning(msg)` / `trace.success(msg)` / `trace.debug(msg)` | 输出日志 |
|
|
179
182
|
|
|
180
183
|
### assertions.py
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
[project]
|
|
2
2
|
name = "nfcscript"
|
|
3
|
-
version = "0.0.
|
|
3
|
+
version = "0.0.12"
|
|
4
4
|
description = "A plugin-based core engine for DSL-style NFC testing automation."
|
|
5
5
|
readme = "README.md"
|
|
6
6
|
requires-python = ">=3.14"
|
|
@@ -34,7 +34,7 @@ dev = [
|
|
|
34
34
|
]
|
|
35
35
|
|
|
36
36
|
[tool.bumpversion]
|
|
37
|
-
current_version = "0.0.
|
|
37
|
+
current_version = "0.0.12"
|
|
38
38
|
commit = true
|
|
39
39
|
tag = true
|
|
40
40
|
allow_dirty = true
|
|
@@ -59,8 +59,6 @@ def main():
|
|
|
59
59
|
parser.add_argument("--trace-protocol", action="store_true", help="开启 PROTOCOL 层追踪")
|
|
60
60
|
parser.add_argument("--trace-parse", type=int, default=None, choices=[0, 1, 2],
|
|
61
61
|
help="解析级别: 0=关闭 1=简单 2=复杂 (默认: NFC_TRACE_PARSE 或 1)")
|
|
62
|
-
parser.add_argument("--trace-card-type", default=None,
|
|
63
|
-
help="卡片类型标识 (默认: NFC_TRACE_CARD_TYPE)")
|
|
64
62
|
parser.add_argument("--trace-level", default="INFO", help="日志级别 (默认: INFO)")
|
|
65
63
|
|
|
66
64
|
args, extra = parser.parse_known_args()
|
|
@@ -87,7 +85,6 @@ def main():
|
|
|
87
85
|
trace_driver = os.environ.get("NFC_TRACE_DRIVER", "").lower() in ("1", "true", "yes")
|
|
88
86
|
trace_protocol = os.environ.get("NFC_TRACE_PROTOCOL", "").lower() in ("1", "true", "yes")
|
|
89
87
|
trace_parse = os.environ.get("NFC_TRACE_PARSE", "1")
|
|
90
|
-
trace_card_type = os.environ.get("NFC_TRACE_CARD_TYPE")
|
|
91
88
|
trace_width = os.environ.get("NFC_TRACE_WIDTH")
|
|
92
89
|
|
|
93
90
|
if args.trace_level != "INFO":
|
|
@@ -98,15 +95,11 @@ def main():
|
|
|
98
95
|
trace_protocol = True
|
|
99
96
|
if args.trace_parse is not None:
|
|
100
97
|
trace_parse = str(args.trace_parse)
|
|
101
|
-
if args.trace_card_type is not None:
|
|
102
|
-
trace_card_type = args.trace_card_type
|
|
103
98
|
|
|
104
99
|
trace.set_level(trace_level)
|
|
105
100
|
trace.set_layer("DRIVER", trace_driver)
|
|
106
101
|
trace.set_layer("PROTOCOL", trace_protocol)
|
|
107
102
|
trace.set_parse(_parse_level(trace_parse))
|
|
108
|
-
if trace_card_type is not None:
|
|
109
|
-
trace.set_card_type(trace_card_type)
|
|
110
103
|
if trace_width is not None:
|
|
111
104
|
os.environ["CRFT_TRACE_WIDTH"] = trace_width
|
|
112
105
|
|
|
@@ -2,6 +2,7 @@ import os
|
|
|
2
2
|
from contextlib import contextmanager
|
|
3
3
|
from nfctester.drivers.card_reader import CardInfo, TransceiveBits
|
|
4
4
|
from nfctester.registry import CardReaderRegistry
|
|
5
|
+
from nfctester.trace import trace as _trace
|
|
5
6
|
from .assertions import ASSERT_EQUAL, ASSERT_IS_NOT_NONE, ASSERT_LEN
|
|
6
7
|
from .checksum import GET_BCC
|
|
7
8
|
from .hex_util import FORMAT_HEX
|
|
@@ -146,7 +147,10 @@ def active(low_layer: bool = False, ignore_error: bool = False, reqa_cmd: int =
|
|
|
146
147
|
sak = sak_res[0] if sak_res else 0
|
|
147
148
|
break
|
|
148
149
|
|
|
149
|
-
|
|
150
|
+
info = CardInfo(uid=full_uid, atq=atq, sak=sak)
|
|
151
|
+
atqa = int.from_bytes(atq, "little")
|
|
152
|
+
_trace.set_parser(atqa, sak)
|
|
153
|
+
return info
|
|
150
154
|
|
|
151
155
|
|
|
152
156
|
def transceive(data: list[int], tx_crc: bool = True, rx_crc: bool = True) -> list[int]:
|
|
@@ -4,7 +4,8 @@ NFC Script Trace 模块
|
|
|
4
4
|
提供日志追踪控制,包装 nfctester.trace 的功能。
|
|
5
5
|
"""
|
|
6
6
|
|
|
7
|
-
from
|
|
7
|
+
from typing import Callable
|
|
8
|
+
from nfctester.trace import TraceEvent, trace as _trace
|
|
8
9
|
|
|
9
10
|
|
|
10
11
|
def set_layer(layer: str, enable: bool = True):
|
|
@@ -33,21 +34,11 @@ def set_parse(level: int = 1):
|
|
|
33
34
|
设置解析级别。
|
|
34
35
|
|
|
35
36
|
Args:
|
|
36
|
-
level: 0
|
|
37
|
+
level: 0=关闭(hex), 1=简单(hex + 摘要标签)
|
|
37
38
|
"""
|
|
38
39
|
_trace.set_parse(level)
|
|
39
40
|
|
|
40
41
|
|
|
41
|
-
def set_card_type(card_type: str):
|
|
42
|
-
"""
|
|
43
|
-
设置当前卡片类型,注入到所有协议解析器的 state 中。
|
|
44
|
-
|
|
45
|
-
Args:
|
|
46
|
-
card_type: 卡片类型标识,如 "mifare_classic_1k", "ntag213"
|
|
47
|
-
"""
|
|
48
|
-
_trace.set_card_type(card_type)
|
|
49
|
-
|
|
50
|
-
|
|
51
42
|
def info(msg: str):
|
|
52
43
|
"""输出 INFO 级别日志"""
|
|
53
44
|
_trace.info(msg)
|
|
@@ -71,3 +62,23 @@ def success(msg: str):
|
|
|
71
62
|
def debug(msg: str):
|
|
72
63
|
"""输出 DEBUG 级别日志"""
|
|
73
64
|
_trace.debug(msg)
|
|
65
|
+
|
|
66
|
+
|
|
67
|
+
def add_sink(fn: Callable[[TraceEvent], None]):
|
|
68
|
+
"""
|
|
69
|
+
注册结构化 trace 事件回调。
|
|
70
|
+
|
|
71
|
+
Args:
|
|
72
|
+
fn: 回调函数,接收 TraceEvent 对象
|
|
73
|
+
"""
|
|
74
|
+
_trace.add_sink(fn)
|
|
75
|
+
|
|
76
|
+
|
|
77
|
+
def remove_sink(fn: Callable[[TraceEvent], None]):
|
|
78
|
+
"""
|
|
79
|
+
移除结构化 trace 事件回调。
|
|
80
|
+
|
|
81
|
+
Args:
|
|
82
|
+
fn: 之前注册的回调函数
|
|
83
|
+
"""
|
|
84
|
+
_trace.remove_sink(fn)
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
Metadata-Version: 2.4
|
|
2
2
|
Name: nfcscript
|
|
3
|
-
Version: 0.0.
|
|
3
|
+
Version: 0.0.12
|
|
4
4
|
Summary: A plugin-based core engine for DSL-style NFC testing automation.
|
|
5
5
|
Author: crthu
|
|
6
6
|
Requires-Python: >=3.14
|
|
@@ -123,14 +123,14 @@ connect()
|
|
|
123
123
|
trace.set_layer("DRIVER", True)
|
|
124
124
|
trace.set_layer("PROTOCOL", True)
|
|
125
125
|
|
|
126
|
-
#
|
|
126
|
+
# 寻卡(自动切换协议解析器)
|
|
127
127
|
card_info = active()
|
|
128
128
|
ASSERT_IS_NOT_NONE(card_info, "未扫描到卡片")
|
|
129
|
-
print(f"UID: {
|
|
129
|
+
print(f"UID: {' '.join(f'{b:02X}' for b in card_info.uid)}")
|
|
130
130
|
|
|
131
131
|
# 创建卡片实例
|
|
132
132
|
from nfctester.registry import CardRegistry
|
|
133
|
-
card = CardRegistry.create("
|
|
133
|
+
card = CardRegistry.create("mifare_classic", reader=get_reader())
|
|
134
134
|
|
|
135
135
|
# 关闭连接
|
|
136
136
|
close()
|
|
@@ -142,8 +142,8 @@ close()
|
|
|
142
142
|
from nfc import *
|
|
143
143
|
|
|
144
144
|
with session() as reader:
|
|
145
|
-
card_info = reader.
|
|
146
|
-
print(card_info)
|
|
145
|
+
card_info = reader.active()
|
|
146
|
+
print(card_info.uid)
|
|
147
147
|
# 自动断开连接
|
|
148
148
|
```
|
|
149
149
|
|
|
@@ -167,7 +167,7 @@ with session() as reader:
|
|
|
167
167
|
|------|------|
|
|
168
168
|
| `connect(port, reader_type)` | 连接读卡器 |
|
|
169
169
|
| `get_reader()` | 获取当前读卡器实例 |
|
|
170
|
-
| `active(low_layer, ignore_error, reqa_cmd)` | 寻卡,返回 uid/atq/sak |
|
|
170
|
+
| `active(low_layer, ignore_error, reqa_cmd)` | 寻卡,返回 CardInfo (uid/atq/sak),自动切换协议解析器 |
|
|
171
171
|
| `transceive(data, tx_crc, rx_crc)` | 底层帧交互 |
|
|
172
172
|
| `transceive_bits(data, last_tx_bits, tx_crc, rx_crc)` | 位控制帧交互 |
|
|
173
173
|
| `reqa()` | ISO14443-A REQA |
|
|
@@ -185,6 +185,9 @@ with session() as reader:
|
|
|
185
185
|
|------|------|
|
|
186
186
|
| `trace.set_layer(layer, enable)` | 开启/关闭追踪层 |
|
|
187
187
|
| `trace.set_level(level)` | 设置日志级别 |
|
|
188
|
+
| `trace.set_parse(level)` | 设置解析级别 (0=关闭, 1=hex+摘要) |
|
|
189
|
+
| `trace.add_sink(fn)` | 注册结构化 trace 事件回调 |
|
|
190
|
+
| `trace.remove_sink(fn)` | 移除已注册的回调 |
|
|
188
191
|
| `trace.info(msg)` / `trace.error(msg)` / `trace.warning(msg)` / `trace.success(msg)` / `trace.debug(msg)` | 输出日志 |
|
|
189
192
|
|
|
190
193
|
### assertions.py
|
|
@@ -37,14 +37,6 @@ class TestSetParse:
|
|
|
37
37
|
mock_trace.set_parse.assert_called_once_with(2)
|
|
38
38
|
|
|
39
39
|
|
|
40
|
-
class TestSetCardType:
|
|
41
|
-
|
|
42
|
-
@patch("nfc.trace._trace")
|
|
43
|
-
def test_set_card_type(self, mock_trace):
|
|
44
|
-
trace.set_card_type("mifare_classic_1k")
|
|
45
|
-
mock_trace.set_card_type.assert_called_once_with("mifare_classic_1k")
|
|
46
|
-
|
|
47
|
-
|
|
48
40
|
class TestLogFunctions:
|
|
49
41
|
|
|
50
42
|
@patch("nfc.trace._trace")
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|