Skip to content

fix(bridge): BLE 桥广播设备状态通知 + 查询合成回包 + 状态缓存持久化 - #58

Open
lizuyi-6 wants to merge 2 commits into
AhakeyAI:mainfrom
lizuyi-6:fix/ble-bridge-status-broadcast
Open

fix(bridge): BLE 桥广播设备状态通知 + 查询合成回包 + 状态缓存持久化#58
lizuyi-6 wants to merge 2 commits into
AhakeyAI:mainfrom
lizuyi-6:fix/ble-bridge-status-broadcast

Conversation

@lizuyi-6

@lizuyi-6 lizuyi-6 commented Aug 30, 2026

Copy link
Copy Markdown

问题

在 Windows 上用 纯蓝牙 连接 AhaKey-X1 时,eternal-dev 分支的新客户端(1.5.3)永远显示"等待设备/未连接",拿不到电量、拨杆等任何设备状态。排查发现是 BLE 桥接器与新客户端的契约断裂,共三层问题:

  1. 状态通知不广播:TcpServer.OnBleNotify 收到键盘的 13 字节设备状态通知后只更新内存缓存就返回,不广播给 TCP 客户端。而新客户端 BleManager.shouldAcceptDeviceInfo 只认 USB 连接、不再采信缓存的 DEVICE_INFO 应答,只接受实时广播的 BleNotify 状态帧——这个包桥从来不发,于是 BLE 模式死锁在"等待设备"。
  2. 键盘固件在 BLE 下不应答状态查询:实测(USB 有线时会应答,蓝牙不会)键盘只在状态变化时主动推送。只做广播的话,客户端每 2 秒的状态查询拿不到回包,其 5 秒新鲜度判定(firmwareStatusFresh)会失败,稳态下反复显示断开。
  3. 重启后全 0 缓存是危险默认态:桥重启后 _deviceStatus 为全 0,而 SwitchState=0 在协议语义里是"自动批准"——Python hooks(query_devices_info)此时会把所有 PermissionRequest 判为放行。

修复(均在 BLE_tcp_bridge/TcpServer.cs)

  • 状态通知在更新缓存的同时,随其它通知一起广播给所有 TCP 客户端;
  • 收到状态查询帧(AA BB 00 CC DD)时,除转发键盘外,用缓存合成一帧状态广播应答,客户端轮询链路始终有新鲜回包;
  • 每次状态更新落盘到 exe 同目录 device_status.cache(逗号分隔 8 字段),启动时回放,消灭全 0 窗口。

另附一个编译修复(BLE_tcp_driver.csproj):添加 Microsoft.NETFramework.ReferenceAssemblies(仅编译期,PrivateAssets=All),没有装 .NET 4.7.2 Developer Pack、只有 VS Build Tools 的机器也能 msbuild -restore 直接编译。

兼容性

  • QueryDeviceInfo(0x4 缓存查询)行为不变,现有 Python hooks 与 1.0.x 客户端不受影响;
  • 旧客户端会多收到 0x81 状态广播包,走其原有的通知处理逻辑,实测 1.0.0 也可以借此获得实时刷新;
  • 缓存文件读写均带 try/catch,失败时回退到原有行为。

实测环境

Windows 11 + AhaKey-X1(蓝牙连接,固件 1.0):

  • 1.5.3 客户端 BLE 模式:已连接、电量实时、拨杆变化秒级刷新,稳态持续收包不掉线;
  • 监听客户端可收到键盘拨杆变化推送的实时 0x81 帧;
  • 桥重启后立即报出上次真实状态(不再全 0)。

后续如果固件侧能让 BLE 也应答状态查询,第 2 条合成回包可以去掉;持久化缓存则建议长期保留。

Microsoft.NETFramework.ReferenceAssemblies 仅在编译期使用(PrivateAssets=All),
不影响运行时产物; 只有 VS Build Tools 而没装 targeting pack 的机器
也能直接 msbuild -restore 通过。
三个问题:

1. 桥收到键盘 13 字节设备状态通知后只更新内存缓存, 不广播给 TCP 客户端。
   eternal-dev 上的新客户端(1.5.3)按设计只信任实时广播的状态帧,
   不再采信缓存的 DEVICE_INFO 应答, 导致 BLE 模式下永远"等待设备"。
   现在状态通知在更新缓存的同时随其它通知一起广播。

2. 实测键盘固件在 BLE 下不应答状态查询(AA BB 00 CC DD), 只在状态变化时
   主动推送(USB 有线时会应答)。仅做广播的话, 稳态下客户端的
   5 秒新鲜度判定会失败并显示断开。现在桥收到状态查询帧时,
   除转发给键盘外, 用缓存合成一帧状态广播应答, 客户端 2 秒轮询
   始终有新鲜回包。

3. 桥重启后内存缓存为全 0, 而 SwitchState=0 在协议语义里是"自动批准",
   Python hooks(query_devices_info)此时会把所有 PermissionRequest 判为放行。
   现在每次状态更新落盘到 exe 同目录 device_status.cache, 启动时回放。

已在 Windows 11 + AhaKey-X1(蓝牙连接)实测: 1.5.3 客户端 BLE 模式
已连接/电量实时/拨杆变化秒级刷新, 稳态不掉线; 0x83 缓存查询行为不变,
现有 hooks 与 1.0.x 客户端不受影响(多收的 0x81 包走原有通知处理逻辑)。
@ZephyrKeXiner

Copy link
Copy Markdown
Member

Hi @eternal904,
请关注一下这条PR。

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants