# Jx_stdio_CANFD

Jx_stdio_CANFD 是一个 CANFD/UDP 桥接工具，用于让上位机通过 UDP 与下位机
CANFD 调试通道通信。客户正常使用时不需要输入命令，解压发布包后双击
`启动CANFD桥接.bat` 即可进入配置向导并启动桥接。

当前支持的 CANFD 设备：

- PEAK PCAN，基于 `python-can`
- 创芯科技 ControlCANFD，运行时 DLL 位于 `CX_V1.21/x64/ControlCANFD.dll`
- 周立功 ZCAN，运行时 DLL 位于 `ZLG_lib/zlgcan_x64/zlgcan.dll`

创芯和周立功适配流程参考了已验证可用的烧录上位机项目：
`E:\Jx_boot_drive\host\host_upgrader`。该项目在本工程中仅作为只读参考。

## 客户使用方式

### 使用前准备

客户电脑需要先安装：

1. Python 3.11 或更高版本，并勾选安装 Windows Python 启动器 `py`
2. 对应 CAN 盒官方驱动：
   - PCAN：安装 PEAK 官方驱动
   - 创芯科技 200U：安装创芯 ControlCANFD 驱动
   - 周立功：安装 ZLG 驱动

发布包不包含 Python 安装包，也不会自动安装 CAN 盒驱动。

### 启动方法

解压发布包后，直接双击：

```text
启动CANFD桥接.bat
```

首次启动时，脚本会自动完成以下步骤：

1. 在当前目录创建 `.venv` 本地运行环境
2. 检查并修复缺失的 `pip`
3. 从 `wheels` 目录离线安装本工具和 Python 依赖
4. 打开 CANFD/UDP 桥接配置向导

后续再次启动时，会复用已经创建好的 `.venv`，直接进入配置向导。

### 配置向导

正常使用时，直接运行工具即可：

```powershell
jx-canfd
```

Windows 客户通常不需要输入上面的命令，双击 `启动CANFD桥接.bat` 即可。

向导会依次询问：

1. CANFD 设备类型：周立功、创芯科技或 PCAN
2. CANFD 通道：可选择通道 0 或通道 1
3. CANFD 速率：默认 `1M + 5M`，也可选择 `1M + 4M`、`1M + 2M` 或 `1M + 1M`
4. 模组 ID：默认 `1`，范围 `1..127`
5. 桥接转发端口：默认 `9000`
6. JxServoStudio 接收端口：默认 `9001`

向导不会扫描后台设备，也不会要求客户选择 CANFD 型号。周立功和创芯设备内部默认
按 `USBCANFD_200U` 兼容模式打开，只根据客户选择的通道 0 或 1 访问设备；PCAN 的
通道 0/1 分别对应 `PCAN_USBBUS1` 和 `PCAN_USBBUS2`。

配置完成后，工具会打印需要在 JxServoStudio UDP 界面中填写的 IP 和端口。
同一台电脑运行时，JxServoStudio 目标地址固定使用 `127.0.0.1`：

- JxServoStudio 本地端口：`9001`
- JxServoStudio 对端端口：`9000`

桥接工具可以接收来自临时 UDP 源端口的命令，但回传数据始终发送到
JxServoStudio 的接收端口 `9001`，临时源端口不会改变回传目标。

如果 JxServoStudio 的 UDP 端口暂时没有打开或刚关闭，Windows 可能返回
`WinError 10054`。工具会把该事件作为可恢复 UDP 状态处理，桥接会继续运行，
不会因此主动退出。

当桥接程序正常退出、按下 `Ctrl+C` 或关闭控制台窗口时，工具会尝试发送命令，
将下位机调试通道切回 USB。

## 常用诊断命令

以下命令主要用于现场排查和开发调试。客户正常使用时优先双击启动脚本。

列出已知或可检测的 CANFD 通道：

```powershell
jx-canfd list
jx-canfd list --adapter pcan
jx-canfd list --adapter zlg
jx-canfd list --adapter cx
```

打开指定通道并打印设备能力信息：

```powershell
jx-canfd probe --config configs\pcan.example.yaml
jx-canfd probe --config configs\zlg.example.yaml
jx-canfd probe --config configs\cx.example.yaml
```

接收 CANFD 报文：

```powershell
jx-canfd dump --config configs\zlg.example.yaml
jx-canfd dump --adapter pcan --channel PCAN_USBBUS1 --count 10
```

发送一帧 CANFD 报文：

```powershell
jx-canfd send --config configs\zlg.example.yaml --id 0x123 --data "01 02 03 04"
```

启动 UDP 桥接：

```powershell
jx-canfd udp-bridge --config configs\udp_bridge.zlg.example.yaml --module-id 1 --udp-bind-port 9000 --verbose
```

只测试下位机调试握手，不启动 UDP 桥接：

```powershell
jx-canfd udp-bridge --config configs\udp_bridge.zlg.example.yaml --module-id 1 --handshake-only --verbose
```

## 调试握手协议

桥接启动后，默认会先发送固件调试握手命令。该握手与较早的
`JXCF/JXUS/JXER` ASCII 握手不兼容。

默认 CANFD 桥接 ID：

- 上位机到设备：`0x791`
- 设备到上位机：`0x790`

握手命令：

- 切换到 CANFD 请求：`0x791`，数据 `AB 01 <module_id> FB`
- 切换到 CANFD 成功应答：`0x790`，数据 `AB 81 <module_id> FB`
- 切换到 CANFD 失败应答：`0x790`，数据 `AB C1 <module_id> FB`
- 切换到 USB 请求：`0x791`，数据 `AB 00 <module_id> FB`
- 切换到 USB 成功应答：`0x790`，数据 `AB 80 <module_id> FB`
- 切换到 USB 失败应答：`0x790`，数据 `AB C0 <module_id> FB`

`configs\udp_bridge.zlg.example.yaml` 中的默认 `module_id` 为 `1`。如果目标设备
使用其他模组 ID，请修改配置文件，或在命令中传入 `--module-id <id>`。

## 推荐现场排查流程

1. 关闭 ZCANPRO、PCAN-View 或其他可能占用 CAN 盒的软件
2. 连接下位机 CANFD 总线，并给设备上电
3. 先确认 CAN 盒可以打开：

   ```powershell
   jx-canfd probe --config configs\udp_bridge.zlg.example.yaml
   ```

4. 再确认固件调试握手成功：

   ```powershell
   jx-canfd udp-bridge --config configs\udp_bridge.zlg.example.yaml --module-id 1 --handshake-only --verbose
   ```

5. 最后启动 UDP 桥接：

   ```powershell
   jx-canfd udp-bridge --config configs\udp_bridge.zlg.example.yaml --module-id 1 --udp-bind-port 9000 --verbose
   ```

6. 打开 JxServoStudio 的 UDP 连接

如果需要在程序退出时主动将固件调试通道切回 USB，可以添加
`--release-usb-on-exit`。该选项会发送 `AB 00 <module_id> FB`，并等待
`AB 80 <module_id> FB` 应答。

## 开发环境安装

开发或调试源码时，可以在 Windows 上执行：

```powershell
py -3.11 -m venv .venv
.\.venv\Scripts\python -m pip install -U pip
.\.venv\Scripts\python -m pip install -e .
```

客户发布包不需要执行以上命令。

## 工程目录说明

- `jx_stdio_canfd/adapters`：PCAN、创芯和周立功 CANFD 适配器
- `jx_stdio_canfd/bridge`：UDP 到 CANFD 的桥接循环和 CANFD 分包策略
- `jx_stdio_canfd/protocol`：ANO PT V8 报文解析和校验
- `jx_stdio_canfd/transport`：通用报文、过滤器、设备能力和错误类型
- `jx_stdio_canfd/models/bus_config.py`：通用 CANFD 总线配置
- `configs`：配置文件示例
- `CX_V1.21/x64`：创芯运行时 DLL、头文件和库文件
- `ZLG_lib/zlgcan_x64`：周立功运行时 DLL 和设备数据

## 发布离线 ZIP

构建面向客户的离线 wheel ZIP：

```powershell
.\.venv\Scripts\python scripts\build_release.py
```

默认 ZIP 名称包含项目版本号和当天构建日期：

```text
dist\release\Jx_CANFD_Bridge_v<version>_<YYYYMMDD>.zip
```

如果需要手动指定内部构建日期后缀，例如 `26060612`：

```powershell
.\.venv\Scripts\python scripts\build_release.py --build-date 26060612
```

发布脚本会自动执行：

1. 运行单元测试
2. 构建本工具和 Python 依赖的离线 wheels
3. 复制启动脚本、配置文件、创芯 DLL 和周立功 DLL
4. 生成中文使用说明
5. 验证离线安装是否可用
6. 输出发布 ZIP

发布 ZIP 不包含 Python、`.git`、测试目录、开发虚拟环境或源码目录。客户仍需提前
安装发布包声明支持的 64 位 Python 版本、`py` 启动器和对应 CAN 盒驱动。

默认只构建当前 Python 解释器对应的离线 wheels。如果要让同一个 ZIP 同时支持多个
Python 小版本，需要在打包机上安装这些 Python 版本，然后显式指定：

```powershell
.\.venv\Scripts\python scripts\build_release.py --python-versions 3.11 3.12 3.13 3.14
```

也可以让脚本自动包含当前打包机上已安装的 3.11-3.14：

```powershell
.\.venv\Scripts\python scripts\build_release.py --python-versions auto
```

启动脚本会根据 `wheels` 目录自动选择匹配的 Python 版本并创建本地 `.venv`。

## 发布免 Python EXE ZIP

如果希望客户电脑不安装 Python，可以构建 PyInstaller 目录包：

```powershell
.\.venv\Scripts\python -m pip install pyinstaller
.\.venv\Scripts\python scripts\build_exe_release.py
```

输出 ZIP：

```text
dist\exe_release\Jx_CANFD_Bridge_v<version>_<YYYYMMDD>.zip
```

该 ZIP 内包含 `Jx_CANFD_Bridge.exe`、PyInstaller `_internal` 运行时、`configs`、
`CX_V1.21/x64`、`ZLG_lib/zlgcan_x64` 和 exe 专用的 `启动CANFD桥接.bat`。客户
解压后双击 `启动CANFD桥接.bat` 即可，不需要安装 Python 或执行 pip。

原来的 `scripts\build_release.py` 仍然保留，用于构建需要客户安装 Python 的离线
wheel 发布包。
