# PC 工程:0x5A 授权流程说明 本文档**以 Unity PC 工程 `smart-bow-pc` 为主**,说明应用侧何时发起 `0x5A` 授权轮询、如何写特征、如何解析 Notify。 7 字节组包、累加和与加解密算法在 **`BluetoothDecryptor`** 中实现(源码位于同仓库 **`smart-bow-sdk-dll`**,PC 端通过程序集或同步脚本引用同一逻辑)。 --- ## 是否有此行为(结论) **有。** 在 PC 端当 **`CommonConfig.EnableDecryption`** 与 **`NeedDecryption`** 同时为真时,连接成功后会启动 **`PollingCoroutine`**,约每秒调用 **`SendEncrypt` → `WriteByteData`**,向外设下发 **`0x5A`~`0x5D` 的 7 字节授权请求**;收到首字节为 **`0x5a`** 的 Notify 后走 **`AUTHOR_Decrypt`**,成功后 **`StopEncrypt()`** 并 **`InitWhenConenct()`** 进入业务数据。 --- ## PC 端简要流程(用户可读) 1. 用户在 PC 用户端发起蓝牙连接并成功。 2. 若未开启上述两个配置,则直接 **`InitWhenConenct()`**,**不发送**授权帧。 3. 若已开启:PC 端约 **每 1 秒** 向写特征写入 **7 字节**(`0x5A` + 4 字节密文 + 校验 + `0x5D`)。 4. 外设解密后通过 Notify 回 **7 字节**(`0x5A` + 4 字节明文 + 校验 + `0x5D`),算法与规范附件 1、2 一致。 5. PC 校验通过后停止轮询,进入后续业务;失败时按 **`BluetoothAim`** 内逻辑可能重连。 ```mermaid sequenceDiagram participant PC as PC 用户端 Unity participant D as 蓝牙外设 PC->>D: BLE 连接成功 alt EnableDecryption && NeedDecryption loop 约每秒,直至授权成功 PC->>D: Write 7 字节授权请求 end D->>PC: Notify 7 字节应答 PC->>PC: StopEncrypt,InitWhenConenct else 未开启授权 PC->>PC: 直接 InitWhenConenct end ``` --- ## PC 工程代码路径与职责 | 职责 | PC 工程内路径 | |------|----------------| | 连接成功是否进入授权 | `Assets/BowArrow/Scripts/Bluetooth/BluetoothAim.cs`:`OnConnected`(约 399~404 行)、`OnConnected_windows1`(约 1595~1600 行)、`OnCMDBLEReady`(约 1970~1974 行) | | 每秒轮询与下发 | 同上:`PollingCoroutine`、`SendEncrypt`、`StopEncrypt` | | 收到 Notify 后校验授权 | 同上:`OnCharacteristicChanged`(约 1625~1659 行),首字节 `0x5a` 时调用 `BluetoothDecryptor.AUTHOR_Decrypt` | | Win 单路 BLE 回调绑定 | 同上:`firstBluetoothWindows.OnConnected = OnConnected_windows1` 等(搜索 `OnConnected_windows1`) | | SmartBow CMD 通道 Notify | 同上:`OnCMDBLENotify` → `OnCharacteristicChanged` | --- ## PC 端关键代码节选 **入口:连接成功后启动轮询(通用 BluetoothHelper)** ```399:404:Assets/BowArrow/Scripts/Bluetooth/BluetoothAim.cs if (CommonConfig.EnableDecryption && NeedDecryption) { // 这里验证指令,开始请求授权 // 启动轮询协程 StartCoroutine(PollingCoroutine()); } ``` **入口:Windows 单路 BLE 连接成功** ```1595:1600:Assets/BowArrow/Scripts/Bluetooth/BluetoothAim.cs if (CommonConfig.EnableDecryption && NeedDecryption) { // 这里验证指令,开始请求授权 // 启动轮询协程 StartCoroutine(PollingCoroutine()); } ``` **入口:SmartBow CMD BLE 特征就绪** ```1970:1974:Assets/BowArrow/Scripts/Bluetooth/BluetoothAim.cs if (CommonConfig.EnableDecryption && NeedDecryption) { // 这里验证指令,开始请求授权 // 启动轮询协程 StartCoroutine(PollingCoroutine()); } ``` **轮询与写入写特征** ```553:580:Assets/BowArrow/Scripts/Bluetooth/BluetoothAim.cs private IEnumerator PollingCoroutine() { // 发送请求 // SendEncrypt(); // 设置轮询标志 isPolling = true; PollingCoroutineCount = 4; uint systemTick = (uint)DateTime.Now.Ticks; while (isPolling) { // 等待一秒 yield return new WaitForSeconds(1f); SendEncrypt(systemTick); PollingCoroutineCount--; } } /// /// 1、加密字节由系统生成的随机码加密而成; /// 2、蓝牙每次断开并重新连接后,会重新生成随机加密值; /// 3、当设备未发送正确的解密信息时,APP会每秒发送1次请求,直到解密成功。 /// /// private void SendEncrypt(uint systemTick) { byte[] sendByte = BluetoothDecryptor.AUTHOR_SendReq(systemTick); Debug.Log("请求sendByte:" + BitConverter.ToString(sendByte)); WriteByteData(sendByte); } ``` **Notify:授权未通过时只处理 `0x5a` 帧** ```1625:1659:Assets/BowArrow/Scripts/Bluetooth/BluetoothAim.cs if (CommonConfig.EnableDecryption && NeedDecryption) { //Pc 版本先走校验流程 if (!BluetoothDecryptor.AUTHOR_IsDecrypt()) { if (value[0] == 0x5a) { // 从硬件读取数据 if (value != null && value.Length > 0) { Debug.Log("接收到数据:" + BitConverter.ToString(value)); BluetoothDecryptor.AUTHOR_Decrypt(value); if (BluetoothDecryptor.AUTHOR_IsDecrypt()) { Debug.Log("解密成功!"); //解密成功后 StopEncrypt(); //开始连接其他信息 InitWhenConenct(); } else { Debug.Log("解密失败!"); //SideTipView.ShowTip("设备通信失败,断开连接", Color.yellow); //断开连接等操作 if (PollingCoroutineCount <= 0) { StopEncrypt(); DoConnect(); } } } } return; } } ``` --- ## 与 SDK 的对应关系(供对照) PC 端仅调用 **`BluetoothDecryptor.AUTHOR_SendReq` / `AUTHOR_Decrypt` / `AUTHOR_IsDecrypt`**,具体算法与 7 字节布局见: `smart-bow-sdk-dll/SmartBowSDK/BluetoothDecryptor.cs`(`AUTHOR_SendReq`、`AUTHOR_Decrypt`、`CheckSum`、`AUTHOR_ImprovedEncrypt`、`AUTHOR_ImprovedDecrypt`)。 --- *详细帧格式与附件 1、2 以《蓝牙 BLE 外设设计与通信规范》为准;本文档路径:`smart-bow-pc/docs/0x5A与BLE规范对照说明.md`。*