diff --git a/custom_components/sigmesh_gateway/hci_gateway.py b/custom_components/sigmesh_gateway/hci_gateway.py index 1c7b7be..d9149bd 100644 --- a/custom_components/sigmesh_gateway/hci_gateway.py +++ b/custom_components/sigmesh_gateway/hci_gateway.py @@ -45,15 +45,15 @@ HCI_MESH_PREFIX = b"\xe8\xff" # Mesh 数据命令头 def build_hci_command(opcode: int, payload: bytes = b"") -> bytes: """构建 HCI 命令包。 - 根据 danglo 工具日志,格式:E9 FF [OPCODE(1)] - 对于简单命令(无 payload),只有 3 字节。 + 格式:E9 FF [OPCODE(1)] [LEN(1)] [PAYLOAD...] + 长度字段始终存在,即使为 0。 """ - # 简单格式:E9 FF OPCODE - cmd = HCI_CMD_PREFIX + bytes([opcode & 0xFF]) + # E9 FF OPCODE LEN + cmd = HCI_CMD_PREFIX + bytes([opcode & 0xFF, len(payload)]) - # 如果有 payload,添加长度和数据 + # 如果有 payload,添加数据 if payload: - cmd += bytes([len(payload)]) + payload + cmd += payload return cmd @@ -138,6 +138,8 @@ class HciGateway: opcode = self._buffer[1] length = self._buffer[2] + _LOGGER.info("收到 91 响应头:opcode=0x%02X, length=%d", opcode, length) + if len(self._buffer) < 3 + length: _LOGGER.debug("数据不完整:需要 %d 字节,当前 %d 字节", 3 + length, len(self._buffer)) break # 数据不完整,等待更多 @@ -148,7 +150,11 @@ class HciGateway: # 唤醒等待的 future if opcode in self._response_futures: + _LOGGER.info("找到匹配的 future,唤醒等待的命令 0x%02X", opcode) self._response_futures[opcode].set_result(payload) + else: + _LOGGER.warning("未找到匹配的 future (opcode=0x%02X),已发送的命令有:%s", + opcode, list(self._response_futures.keys())) self._buffer.clear() return @@ -161,6 +167,8 @@ class HciGateway: opcode = self._buffer[2] length = self._buffer[3] + _LOGGER.info("收到 E8 事件头:opcode=0x%02X, length=%d", opcode, length) + if len(self._buffer) < 4 + length: _LOGGER.debug("事件数据不完整:需要 %d 字节,当前 %d 字节", 4 + length, len(self._buffer)) break # 数据不完整 @@ -173,8 +181,9 @@ class HciGateway: self._handle_event(event_data) else: - # 未知数据,清空 - _LOGGER.warning("未知 HCI 数据头:0x%02X,清空缓冲区", self._buffer[0]) + # 未知数据,打印警告并清空 + _LOGGER.warning("未知 HCI 数据头:0x%02X,缓冲区前 20 字节:%s", + self._buffer[0], self._buffer[:20].hex().upper()) self._buffer.clear() return @@ -279,3 +288,12 @@ class HciGateway: response = await self.send_command(HciGatewayOp.CFG_APPKEY, appkey) return response is not None + + async def reset_gateway(self) -> bool: + """复位网关。 + + Returns: + True 表示成功,False 表示失败 + """ + response = await self.send_command(HciGatewayOp.GATEWAY_RESET) + return response is not None diff --git a/custom_components/sigmesh_gateway/provisioning.py b/custom_components/sigmesh_gateway/provisioning.py index cf2b682..2f39e9f 100644 --- a/custom_components/sigmesh_gateway/provisioning.py +++ b/custom_components/sigmesh_gateway/provisioning.py @@ -154,11 +154,30 @@ class ProvisioningManager: self._set_state(ProvState.PROV_FAILED) return + # 1. 先配置网关密钥(如果未配置) + try: + _LOGGER.info("正在配置网关密钥...") + netkey_bytes = bytes.fromhex(self.network_key) + appkey_bytes = bytes.fromhex(self.app_key) + + # 配置网络密钥 + netkey_result = await self.serial_reader.hci.configure_netkey(netkey_bytes) + _LOGGER.info("网络密钥配置结果:%s", "成功" if netkey_result else "失败") + + # 配置应用密钥 + appkey_result = await self.serial_reader.hci.configure_appkey(appkey_bytes) + _LOGGER.info("应用密钥配置结果:%s", "成功" if appkey_result else "失败") + + # 等待网关处理 + await asyncio.sleep(0.5) + except Exception as e: + _LOGGER.error("配置网关密钥失败:%s", e) + self._set_state(ProvState.SCANNING) self._devices = {} self._scan_result = [] - # 使用 HCI 协议发送扫描命令 + # 2. 使用 HCI 协议发送扫描命令 try: _LOGGER.debug("发送 HCI 扫描命令") result = await self.serial_reader.hci.start_scanning()