NekoCardReader 是一个单机 PyQt6 桌面应用,约 45 个 Python 模块,按「读卡核心 → 解码字典 →
数据档案 → 分析/地图 → UI」分层。核心设计约束是:读卡核心冻结且与上层完全解耦——
分析、地图、UI 只消费已解析的 Transaction,永远不碰卡片 I/O。
┌─────────────────────────────────────────────┐
│ UI 层 (PyQt6) │
main.py ───────────────┤ 主窗口 · 刷卡页 · 统计图 · 设置 · 系统托盘 │
│ archive_widget.py 档案 LAB (分析/修复/地图) │
│ web_map.py Leaflet 地图 HTML 生成 │
│ diagnostics.py 安全诊断中心 (不开读卡器) │
└───────────────┬─────────────────────────────┘
│ 只传递已解析 Transaction
┌────────────────────────────────┼────────────────────────────────┐
▼ ▼ ▼
┌──────────────────┐ ┌──────────────────────┐ ┌──────────────────────┐
│ 数据档案层 │ │ 分析 / 导出层 │ │ 地图 / 几何层 │
│ history_store.py │◀───────▶│ trip_analytics.py │ │ map_pipeline.py (线程)│
│ SQLite v3 档案 │ │ 纯分析,零副作用 │ │ rail_route.py OSM 路由│
│ 迁移·备份·撤销 │ │ yearbook_export.py │ │ rail_geom.py 铁轨几何│
│ data_portability │ │ 年鉴 HTML │ │ map_tiles / offline │
│ DPAPI 加密备份 │ │ plugin_registry.py │ │ 瓦片 · 离线包缓存 │
└──────────────────┘ │ 后处理插件沙箱 │ └──────────────────────┘
└──────────────────────┘
▲ 解析后的 Transaction / CardData
│
┌────────┴───────────────────────────────────────────────────────────────────┐
│ 🧊 读卡核心 (冻结, SHA-256 校验) │
│ card_reader.py 统一调度; 进程锁串行访问同一台读卡器 │
│ ┌── 日本 FeliCa ────────────────────┐ ┌── 中国交通联合 (T-Union) ───────┐ │
│ │ felica64_reader.py 64位 felica.dll │ │ pboc_reader.py PC/SC + EMV / │ │
│ │ felica_suica.py Suica 块解码 │ │ JT/T 978 │ │
│ │ felica_reader.py 32位 SFCAccLib │ │ cn_read.py 子进程读卡入口 │ │
│ │ (PowerShell 桥) │ │ │ │
│ └────────────────────────────────────┘ └─────────────────────────────────┘ │
└──────────────────────────────────────────────────────────────────────────────┘
▲ 站码 / 坐标 / 线路字典
┌────────┴───────────────────────────────────────────────────────────────────┐
│ 解码字典 / 铁路网络层 │
│ 中国: cn_data(城市码) cn_lines(线路站名) cn_coords(坐标) │
│ cn_network(地铁图+换乘) cn_trips(进出站→行程段) │
│ 日本: station_data / station_db(站点码) jp_network(全国铁路网络) │
└──────────────────────────────────────────────────────────────────────────────┘
支撑: paths(打包路径) · settings(配置) · fx(汇率换算) · 诊断脚本 detect_read / diag_reader
| 层 | 模块 | 职责 |
|---|---|---|
| UI (PyQt6) | main.py |
主窗口、刷卡/统计/设置标签页、连续采集、系统托盘 |
archive_widget.py |
档案 LAB:数据质量修复、路线频次、通勤候选、三模式地图 | |
web_map.py |
生成内嵌 Leaflet 地图 HTML(高德/OSM 双底图,终端风格 UI) | |
diagnostics.py |
不打开读卡器的安全诊断中心 | |
| 🧊 读卡核心(冻结) | card_reader.py |
统一后端调度,进程锁串行访问单一读卡器 |
felica64_reader.py |
64 位 Sony felica.dll 直调,取 IDm / 余额 / 历史 |
|
felica_suica.py |
Suica/PASMO 16 字节历史块解码 | |
felica_reader.py |
旧 32 位 SFCAccLib(PowerShell 桥接)后备路径 | |
pboc_reader.py |
中国交通联合卡:PC/SC + EMV / 交通部 JT/T 978 | |
cn_read.py |
中国卡读取的独立子进程入口 | |
| 解码字典 | cn_data cn_lines cn_coords |
城市码 / 线路站名 / 站点坐标 |
cn_network cn_trips |
地铁换乘图 / 进出站配对成行程段 | |
station_db station_data jp_network |
日本站点码与全国铁路网络 | |
| 数据档案 | history_store.py |
SQLite v3 档案、v2→v3 迁移、每日备份、撤销读取 |
data_portability.py |
SQLite/JSON 导入导出、DPAPI 本地加密备份 | |
| 分析 / 导出 | trip_analytics.py |
纯分析层(频次/通勤/日历),零副作用、可离线单测 |
yearbook_export.py |
无外部依赖的交通年鉴 HTML | |
plugin_registry.py |
后处理插件沙箱,异常隔离,不进入读卡核心 | |
| 地图 / 几何 | map_pipeline.py |
地图前处理,运行在可取消的 Qt 后台线程 |
rail_route.py rail_geom.py |
OSM 最短路 + 真实铁轨几何,持久化缓存 | |
map_tiles.py offline_maps.py |
瓦片管理 / 离线缓存包 | |
| 支撑 | paths settings fx |
打包路径、配置持久化、多币种汇率换算 |
detect_read diag_reader |
独立读卡器检测 / 占用诊断脚本 |
- 读卡核心冻结 + 完整性校验:
felica64_reader / felica_suica / pboc_reader / card_reader / felica_reader五个文件锁定在 v0.2 的 SHA-256(清单.reader-core-v0.2.sha256)。任何新功能 都在上层实现,杜绝对已验证读卡路径的回归。 - 读卡与分析彻底解耦:
trip_analytics/map_pipeline的输入只有已解析的Transaction, 因此可离线单元测试,也可安全放入 Qt 后台线程而不阻塞 UI。 - 单一读卡器的并发安全:两套后端(32/64 位、中/日)通过
card_reader的进程锁串行访问, 避免同时抢占 PaSoRi。 - 响应式地图:OSM 路由与几何在后台线程计算,切卡时自动取消旧任务;相同区间命中持久化缓存 不重复请求 Overpass。
- 本地优先 / 隐私:无服务器,历史只存本机 SQLite;联网仅用于下载可缓存的线路/瓦片/汇率。
- 可扩展:后处理插件只接触解析结果,异常被隔离并汇报到诊断页,不会中断读卡。
读卡器 → card_reader (选后端, 加锁)
→ felica64_reader / pboc_reader (原生读取)
→ felica_suica / cn_trips (解码为 Transaction)
→ history_store (合并去重, 写 SQLite, 备份)
→ trip_analytics / map_pipeline (分析 + 地图, 后台线程)
→ main.py / archive_widget / web_map (渲染)