一、GATT服务注册模型不匹配

现象

iot_connect_sdk 调用 BleGattsStartServiceEx 传入属性列表动态注册GATT服务(OHOS标准流程),但CH585的WCH协议栈使用 GATTServApp_RegisterService 注册静态属性表。直接调用动态注册API会导致服务注册失败或属性表损坏。

根因

两种GATT注册模型的差异:

维度 IOTC SDK (OHOS标准) WCH协议栈
注册方式 运行时动态传入属性列表 编译时静态定义属性表
UUID类型 运行时指定 编译时固定
回调绑定 属性列表中携带函数指针 通过handle匹配统一回调
注册API BleGattsStartServiceEx GATTServApp_RegisterService

解决方案:预注册固定服务,仅提取write回调

Peripheral_Init 中预注册固定的 ble_hw_service(128-bit UUID),BleGattsStartServiceEx 不实际注册服务,仅从IOTC传入的属性列表中提取write回调函数指针:

/* ohos_bt_gatt_server.c — BleGattsStartServiceEx */
BleGattServiceWrite gwriteFunc = NULL;  /* 全局变量: IOTC注册的write回调 */

int BleGattsStartServiceEx(int *srvcHandle, BleGattService *srvcInfo)
{
    /* 从属性列表索引[1]提取IOTC注册的write回调 */
    gwriteFunc = srvcInfo->attrList[1].func.write;
    if (gwriteFunc == NULL) {
        PRINT("ERR gwriteFunc\n");
    }

    /* 不实际注册GATT服务 — 已由ble_hw_service预注册 */
    return OHOS_BT_STATUS_SUCCESS;
}

ble_hw_service 的静态属性表在 ble_hw_service.c 中定义,包含6项属性(Primary Service、TX Characteristic Declaration、TX Value、CCCD、RX Characteristic Declaration、RX Value),使用固定的128-bit UUID:

Service: 15f1e600-a277-43fc-a484-dd39ef8a9100
├── TX (15f1e601): INDICATE | READ, CCCD支持
└── RX (15f1e602): WRITE | WRITE_NO_RSP

二、连接参数未优化导致吞吐低下

现象

BLE连接建立后使用默认连接参数(interval可能高达数秒),SPEKE协商报文传输延迟严重,协商超时。

解决方案:连接后主动发起参数更新

/* peripheral.c — 连接参数更新定时器 */
/* 在 Peripheral_LinkEstablished 中启动 */
tmos_start_task(Peripheral_TaskID, SBP_PARAM_UPDATE_EVT, SBP_PARAM_UPDATE_DELAY);
/* SBP_PARAM_UPDATE_DELAY = 6.25ms, 延迟后发起更新避免连接建立阶段不稳定 */

/* peripheral.c — SBP_PARAM_UPDATE_EVT 处理 */
if (events & SBP_PARAM_UPDATE_EVT) {
    GAPRole_PeripheralConnParamUpdateReq(peripheralConnList.connHandle,
        DEFAULT_DESIRED_MIN_CONN_INTERVAL,  /* 6 = 7.5ms */
        DEFAULT_DESIRED_MAX_CONN_INTERVAL,  /* 100 = 125ms */
        DEFAULT_DESIRED_SLAVE_LATENCY,      /* 0 */
        DEFAULT_DESIRED_CONN_TIMEOUT,       /* 3200 = 32s */
        Peripheral_TaskID);
    return (events ^ SBP_PARAM_UPDATE_EVT);
}

/* 同时切换到2M PHY提升吞吐 */
if (events & SBP_PHY_UPDATE_EVT) {
    GAPRole_UpdatePHY(peripheralConnList.connHandle, 0,
        GAP_PHY_BIT_LE_2M, GAP_PHY_BIT_LE_2M, 0);
    return (events ^ SBP_PHY_UPDATE_EVT);
}

三、CCCD未配置时Indication发送失败

现象

IOTC SDK在App端尚未使能CCCD时发送Indication,GATT_Indication 返回错误,且分配的缓冲区泄漏。

根因

BLE Indication要求对端先通过CCCD(Client Characteristic Configuration Descriptor)使能Indication后才能发送。若CCCD未配置,GATT_Indication 会返回错误,但调用方可能未释放已分配的缓冲区。

解决方案:发送前检查CCCD状态,失败时释放缓冲区

/* ble_hw_service.c — ble_hw_indicate */
bStatus_t ble_hw_indicate(uint16_t connHandle, attHandleValueInd_t *pIndicate, uint8_t taskId)
{
    uint16_t value = GATTServApp_ReadCharCfg(connHandle, ble_hw_tx_cccd);

    /* 检查CCCD是否开启INDICATE */
    if (value & GATT_CLIENT_CFG_INDICATE) {
        pIndicate->handle = ble_hw_profile_table[2].handle;
        return GATT_Indication(connHandle, pIndicate, FALSE, taskId);
    }
    return bleIncorrectMode;  /* CCCD未配置 */
}

/* ble_safe_api.c — Exec_SendIndication, 失败时释放缓冲区 */
static int32_t Exec_SendIndication(void *arg)
{
    ParamSendIndication *p = (ParamSendIndication *)arg;
    attHandleValueInd_t indi;
    indi.len = p->len;
    indi.pValue = GATT_bm_alloc(peripheralConnList.connHandle,
                                ATT_HANDLE_VALUE_IND, indi.len, NULL, 0);
    if (indi.pValue) {
        tmos_memcpy(indi.pValue, p->data, indi.len);
        ret = ble_hw_indicate(peripheralConnList.connHandle, &indi, Peripheral_TaskID);
        if (ret) {
            GATT_bm_free((gattMsg_t *)&indi, ATT_HANDLE_VALUE_IND);  /* 失败立即释放 */
        }
    }
    return ret;
}
Logo

社区规范:仅讨论OpenHarmony相关问题。

更多推荐