# Printer Controller 项目说明

Magicard 官方 SDK 提供多种语言(C/C++、.NET、Java 等)的 SDK，使用 Java 的原因如下: 一、 Java 能更高效率地实现我们的核心业务流程；二、这几种语言我个人对 Java 技术栈更为熟悉，便于直接调用 JNA 接口并与 JDBC 等进行集成。

## 1. 快速概览
- 主分支：`main`。所有正式构建都来自该分支。
- 运行场景：展会期间在现场 Windows 电脑上循环运行，直到活动结束手动退出。
- 业务流程：轮询 TiDB Cloud 中状态为 `printing` 的卡片 → 送卡 → 写 NFC → 打印 → 更新为 `printing_finished`。
- 前端提报时状态是 `pending`，管理员在后台点 “Print” 后才会变成 `printing`，程序再处理。

## 2. 代码结构
```
src/main/java
├── com/pingcap/PrinterControllerApplication.java  # 主流程入口
├── com/pingcap/model
│   ├── CardInfo.java
│   └── DatabaseConnectionManager.java
├── com/pingcap/reader/HCReader.java
├── com/pingcap/fuction
│   ├── HCICRF.java
│   ├── NdefMessage.java / NdefRecord.java
│   ├── PrinterUtils.java
│   └── ReaderUtils.java
└── META-INF/MANIFEST.MF
```
- 入口类：`src/main/java/com/pingcap/PrinterControllerApplication.java`（`main()` 在这里，可用来本地调试）。

## 3. 数据 & 逻辑
1. `initializePrinter()` 查找 Magicard K (V2) 打印机然后并读取序列号。
2. 通过 `printers(sn_code -> event_id)` 绑定当前打印机所属活动，后续 SQL 都带上该 `event_id`。
3. `card_info` 只取 `status='printing'` 且 `event_id` 匹配的数据，字段使用 `short_name`、`short_company`（默认打印的值是 name、company ，和用户填写的一致。但是有些公司和人名比较长，会超过卡片大小,为了适配卡片截短后再打印）。
4. 打印成功后 `updateCardStatus()` 写回 `printing_finished`，避免重复打印。

## 4. 部署步骤（每台电脑一次性）
1. 安装 JDK17、Magicard K (V2) 驱动、HC ICRF 读写器驱动；确保 USB 连接正常。
2. 把打包好的目录拷贝到电脑（通常只发 JAR + `lib/` 文件夹）。国外办公室使用预先编译好的 JAR；北美版额外把卡背面改成  
   - Slogan：`Built to Scale with Your Ambitions`  
   - URL：`tidb.io`  
   若需要其他版本，重新在 `main` 上修改常量并打包。
3. 根据电脑位置修改 `src/main/java/com/pingcap/fuction/HCICRF.java` 的 `Native.loadLibrary` 路径（见第 5 节），然后重新打包给对应办公室。

## 5. 发布与测试
```powershell
mvnw.cmd clean package -DskipTests
copy target\printer_controller-0.0.1.jar printer_controller.jar   # 可重命名方便记忆

# 目标电脑
java -jar .\printer_controller.jar
```
部署前把 `printer_controller.jar` 与 `lib/` 同级放好，即可直接通过 `java -jar` 验证。若要模拟打印，可在测试库插入一条 `status='printing'` 的记录。

## 5. DLL / 库要求
`lib/` 目录包含：
- `SDK_JShim.jar`（打印机 SDK）、`hc_icrf64.dll` + `WltRS.dll`（HC NFC 驱动）
- `jna-*.jar`、`miglayout15-swing.jar`

`HCICRF.java` 提供多个 `Native.loadLibrary` 选项，按电脑所在办公室保留一个，其余注释：
```java
// private static hcicrf epen = Native.loadLibrary("lib\\hc_icrf64", hcicrf.class); // 默认放在项目 lib/
// private static hcicrf epen = Native.loadLibrary("C:\\Users\\kenne\\Desktop\\hc_icrf64", hcicrf.class); // 北京
private static hcicrf epen = Native.loadLibrary("C:\\Users\\invic\\Documents\\hc_icrf64", hcicrf.class); // 美国
// private static hcicrf epen = Native.loadLibrary("C:\\Users\\printer\\Documents\\hc_icrf64", hcicrf.class); // 新加坡
// private static hcicrf epen = Native.loadLibrary("C:\\Users\\上海卡立\\Desktop\\hc_icrf64", hcicrf.class); // 上海
```
确保 DLL 所在目录包含 `hc_icrf64.dll` 与 `WltRS.dll`，并对运行账户可读。

## 6. 运行期间注意事项
- 程序启动后会持续输出日志：`Begin to print...`、`write NDEF tag...`、`Finished print...` 等，用来观察流程。
- 若打印机/NFC 有异常，常见信息：
  - `Open session failed` → 打印机驱动或名称不匹配。
  - `Reader initialization failed` → 串口占用或 DLL 路径错误。
  - `Failed to retrieve event ID` → `printers` 表缺少该序列号。
- 展会结束后手动 `Ctrl+C` 或关闭命令行窗口即可停止。

## 7. 交付物
移交给各办公室的内容通常只有：
```
printer_controller.jar       # 针对该地区编译好的版本
lib\                         # hc_icrf64.dll
```
将两者放在任意目录，双击或运行 `java -jar printer_controller.jar` 即可投入使用。
