Skip to content

Latest commit

 

History

History
157 lines (103 loc) · 6.84 KB

File metadata and controls

157 lines (103 loc) · 6.84 KB

NekoCardReader 🐱💳

本地优先的中国交通联合卡(T-Union)与日本 FeliCa(Suica / PASMO)交通档案、分析与地图应用。

一款 Windows 桌面工具(PyQt6):把交通卡里的余额、交易和行程读出来,长期本地归档, 并在内嵌地图上可视化你的通勤足迹——数据全部留在本机。

版本:v0.3 | 平台:Windows x64 | Python 3.12 | 界面语言:中文


🖼️ 界面预览

仪表盘 —— 总趋数 / 里程 / 花费 / 站点、月度趋势、最常去站点、中日国别分布:

仪表盘

行程地图 —— 在真实铁路网上高亮每段行程,支持高德 / OSM 双底图与终端风格 CRT 效果:

行程地图


✨ 主要功能

  • 读卡(核心已冻结)
    • 中国交通联合卡:通过 PC/SC 读取余额、卡号、交易与行程。
    • 日本 Suica / PASMO:使用 64 位 Sony felica.dll 读取 IDm、余额与历史(含 Apple Pay 卡)。
    • 同卡按 IDm / 卡号累计,新记录合并、旧记录去重。
  • 数据档案(v0.3):SQLite 长期归档、每日滚动备份、撤销最近一次读取、SQLite / JSON 导入导出。
  • 连续采集:贴卡即读、自动合并、等待换卡,配声音与托盘通知。
  • 档案 LAB:数据质量修复、路线频次、通勤候选、交通日历、铁路网络完成度, 以及“每次行程 / 唯一区间 / 频次热度”三种地图模式与持久化路线几何缓存。
  • 导出与离线:交通年鉴 HTML、DPAPI 加密备份、离线地图缓存包。
  • 可扩展:后处理插件、安全诊断、冻结核心完整性校验。

详细的档案 LAB、连续采集、插件与便携模式说明见文末「深入说明」。


🚀 快速开始(从源码运行)

需要 Python 3.12(64 位) 和 一台 PC/SC 读卡器(如 Sony PaSoRi RC-S380 作者目前只测试过这个)。

# 1. 克隆
git clone https://github.com/zheznanohana/NekoCardReader.git
cd NekoCardReader

# 2. 安装依赖
py -3.12 -m pip install -r requirements.txt

# 3.(可选,日本 FeliCa 才需要)放入 Sony felica.dll 
#    从本机 Sony FeliCa Library 拷到 felica_runtime\felica.dll

# 4. 运行
py -3.12 main.py

没有读卡器也可以先看界面:程序在无卡时会用内置 mock 数据渲染示例。

🏗️ 程序结构

约 45 个 Python 模块,按「读卡核心 → 解码字典 → 数据档案 → 分析/地图 → UI」分层。 核心约束:读卡核心冻结且与上层完全解耦——分析、地图、UI 只消费已解析的 Transaction, 永不触碰卡片 I/O。完整分层图、模块职责表与设计决策见 ARCHITECTURE.md

代表模块 职责
UI (PyQt6) main.py · archive_widget.py · web_map.py 主窗口、档案 LAB、Leaflet 地图
读卡核心 card_reader.py · felica64_reader.py · pboc_reader.py 中/日读卡,进程锁串行
解码字典 cn_lines/cn_coords/cn_trips · station_db · jp_network 站码/坐标/换乘/铁路网
数据档案 history_store.py · data_portability.py SQLite 档案、备份、DPAPI
分析/导出 trip_analytics.py · yearbook_export.py · plugin_registry.py 纯分析、年鉴、插件沙箱
地图/几何 map_pipeline.py · rail_route/rail_geom · offline_maps 后台路由、铁轨几何、离线包
读卡器 → card_reader → felica64/pboc_reader → felica_suica/cn_trips
       → history_store(合并去重·SQLite·备份) → trip_analytics/map_pipeline(后台线程) → UI

设计亮点:读卡核心以 SHA-256 冻结防回归;读卡与分析彻底解耦(分析层可离线单测、可入后台线程); 单一读卡器进程锁并发安全;地图路由可取消 + 持久化缓存;本地优先零服务器;插件异常沙箱隔离。


🔒 隐私

  • 数据默认全部留在本地:历史库 history_v3.sqlite3backups/ 与个人足迹不会进入 Git, 也不会上传到任何服务器。仓库里看不到作者的历史,你的历史同样只在你自己机器上。
  • 联网仅用于:下载线路 / 站点数据、地图瓦片、汇率——均可缓存到本地后离线使用。
  • 冻结的读卡核心只做读取,不改写卡片。

🧊 冻结读卡核心

稳定基线保存在 Git 标签 v0.2。v0.3 遵守「冻结读卡核心」原则,下列文件必须与 v0.2 的 SHA-256 一致(清单 .reader-core-v0.2.sha256):

felica64_reader.py · felica_suica.py · pboc_reader.py · card_reader.py · felica_reader.py

档案 LAB 的安全诊断不会打开读卡器。

🧪 测试

python -m unittest discover -s tests -v

覆盖 SQLite 迁移、累计去重、扫描撤销、站点修正、路线缓存、备份恢复、DPAPI、连续采集所依赖的 分析逻辑、年鉴、离线地图包与插件隔离。


📚 深入说明

v0.3 数据档案

  • 首次运行将 history_v2.json 无损迁移为 history_v3.sqlite3;迁移前文件保留为 history_v2.json.migrated-v0.3.bak
  • 每次读取保存解析快照、解析器版本、读到数量与新增数量。
  • raw_blocks 表与 archive_raw_blocks() 接口已就位;冻结读卡层当前未暴露原始字节, 因此暂时只保存完整解析快照。
  • 每日滚动备份,支持撤销最近一次读取、SQLite / JSON 导出与恢复前自动备份。

连续采集

在刷卡页勾选「连续采集」后开始:等待卡片 → 读取并合并新增 → 等待当前卡片移开 → 自动等待下一张。 同卡未移开不会重复写入;成功与失败会用系统提示音及托盘通知。

档案 LAB

  • 数据质量与未知站点修复(本地候选补全,修正永久覆盖后续扫描结果)。
  • 路线频次、通勤候选、交通日历与日本铁路网络完成度。
  • 地图「每次行程 / 唯一区间 / 频次热度」三种模式;路线几何持久化缓存,相同区间不重复计算 OSM 路由。
  • 地图前处理在独立 Qt 线程执行;OSM 最短路与站序兜底并行,切卡时自动取消 / 丢弃旧任务。
  • 历史表按 200 行分批填充,统计图与档案子页按需渲染,避免隐藏页面抢占主线程。
  • 交通年鉴 HTML、DPAPI 加密备份、离线地图缓存包;安全诊断、冻结核心完整性校验、后处理插件管理。

插件

插件目录:%LOCALAPPDATA%\NekoCardReader\plugins(便携模式为 data\plugins)。

PLUGIN_NAME = "example"
PLUGIN_VERSION = "1"

def postprocess(transactions, context):
    # 仅处理已经解析完成的 Transaction; 不进入读卡核心。
    return transactions

插件异常会被隔离并显示在诊断页,不会中断读卡。