This thread has been locked.

If you have a related question, please click the "Ask a related question" button in the top right corner. The newly created question will be automatically linked to this question.

[参考译文] CC2340R5:属性表的句柄

Guru**** 2337870 points
请注意,本文内容源自机器翻译,可能存在语法或其它翻译错误,仅供参考。如需获取准确内容,请参阅链接中的英语原文或自行翻译。

https://e2e.ti.com/support/wireless-connectivity/bluetooth-group/bluetooth/f/bluetooth-forum/1456985/cc2340r5-handle-of-attribute-table

器件型号:CC2340R5

工具与软件:

您好!

祝您新年快乐!!!

我已经使用自定义服务和特征定义了我的自定义 GATT 属性表。 一个特征具有通知属性。

当我按下按钮时、按钮状态将被通知给客户端。 我应如何获取自定义通知特征的句柄并发送 GATT 通知?

我提到了一个示例、但针对该特定特性对句柄进行了硬编码。 请提供帮助

extern uint8 value_gpio_level;    

#define Handle_char_4 46.    

void NotifyTrigger(){       

uint8_t 状态;      

 attHandleValueNoti_t Noti;      

 uint8_t len = 1;      

 Notti.pValue = GATT_BM_alloc (0、ATT_Handle_Value_Noti、len、NULL);      if (Notti.pValue!= NULL)      {         Notti.handle         = handle_char_4;Notti.len =         len;memcpy (Noti.pValue、&value_gpio、len);          //发送通知         状态= GATT_Notification (0、&Noti、false);         if (status!= Success)         {            GATT_BM_FREE ((gattMsg_t *)&Noti、ATT_Handle_Value_Noti);         }            else      {         status = bleMemAllocError;      }}    

  • 请注意,本文内容源自机器翻译,可能存在语法或其它翻译错误,仅供参考。如需获取准确内容,请参阅链接中的英语原文或自行翻译。

    您好!

    新年快乐! 您运行的是哪个 SDK 版本?

    此致!
    Nima Behmanesh

  • 请注意,本文内容源自机器翻译,可能存在语法或其它翻译错误,仅供参考。如需获取准确内容,请参阅链接中的英语原文或自行翻译。

    8_20_00_119

  • 请注意,本文内容源自机器翻译,可能存在语法或其它翻译错误,仅供参考。如需获取准确内容,请参阅链接中的英语原文或自行翻译。

    您好!

    要了解特征、您需要一些 API。 我不确定项目的作用、但代码非常可转让。 首先、您需要启动服务发现。 有多种 API 可实现这一点:

    GATT_DiscAllPrimaryServices ()

    GATT_DiscPrimaryServiceByUUID ()

    您需要在上面找到服务句柄范围、以捕获您正在寻找的特征的句柄范围。 尽管以下示例适用于外设角色、但您可以将此代码移至器件所处的任何角色:app_peripheral.c

    void Peripheral_GAPConnEventHandler(uint32 event, BLEAppUtil_msgHdr_t *pMsgData)
    {
        gapEstLinkReqEvent_t *gapMsg = ( gapEstLinkReqEvent_t * )pMsgData;
        switch(event)
        {
            case BLEAPPUTIL_LINK_ESTABLISHED_EVENT:
            {
    
                /* Check if we reach the maximum allowed number of connections */
                if(linkDB_NumActive() < linkDB_NumConns())
                {
                    /* Start advertising since there is room for more connections */
                    BLEAppUtil_advStart(peripheralAdvHandle_1, &advSetStartParamsSet_1);
                }
                else
                {
                    /* Stop advertising since there is no room for more connections */
                    BLEAppUtil_advStop(peripheralAdvHandle_1);
                }
    
                // Device Info service. Note: The UUID is in little endian. Thus we are searching for the service of 0x180A
                uint8 pUUID[] = {0x0A, 0x18};
                // This is the call to discover a primary service by UUID.
                bStatus_t status = GATT_DiscPrimaryServiceByUUID(gapMsg->connectionHandle, &pUUID, ATT_BT_UUID_SIZE, BLEAppUtil_getSelfEntity());
                if (status != SUCCESS)
                {
                    MenuModule_printf(APP_MENU_NUM_CONNS, 0, "DiscPrimaryServiceByUUID Failed: %d", status);
                }
                else
                {
                    MenuModule_printf(APP_MENU_NUM_CONNS, 0, "DiscPrimaryServiceByUUID Success.");
                }
                break;
            }
    
            case BLEAPPUTIL_LINK_TERMINATED_EVENT:
            {
                BLEAppUtil_advStart(peripheralAdvHandle_1, &advSetStartParamsSet_1);
                break;
            }
    
            default:
            {
                break;
            }
        }
    }

    请确保阅读您计划用于发现该服务的 API 的所有 API 信息。 根据所使用的内容、它们会预期不同的事件、而且过程也不同。 对于这段代码、我们将使用 GATT_DiscPrimaryServiceByUUID ()、 因此我们需要处理 ATTT_FIND_BYE_TYPE_VALUE_RSP、并且我们将收到 attFindByTypeValueRsp_t 结构。

    在 app_data.c 中、我们需要添加一些事件和一些修改。  

    1.我们需要在数据处理程序中添加适当的事件:

    /* Note that the events are of BLEAPPUTIL, but in the handler we drop the BLEAPPUTIL prefix. */
    BLEAppUtil_EventHandler_t dataGATTHandler =
    {
        .handlerType    = BLEAPPUTIL_GATT_TYPE,
        .pEventHandler  = GATT_EventHandler,
        .eventMask      = BLEAPPUTIL_ATT_FLOW_CTRL_VIOLATED_EVENT |
                          BLEAPPUTIL_ATT_MTU_UPDATED_EVENT |
                          BLEAPPUTIL_ATT_FIND_BY_TYPE_VALUE_RSP |
                          BLEAPPUTIL_ATT_READ_BY_TYPE_RSP
    };

    ATT_FIND_BY_TYPE_VALUE_RSP 是因为我们使用 GATT_DiscPrimaryServicesByUUID 查找服务的句柄。

    ATT_READ_BY_TYPE_RSP 用于服务内的属性句柄、我们通过调用 GATT_DiscAllChars()来触发此事件

    我们需要添加这些事件、并将处理这些事件的方法添加到我们的数据处理程序中:

    static void GATT_EventHandler(uint32 event, BLEAppUtil_msgHdr_t *pMsgData)
    {
      gattMsgEvent_t *gattMsg = ( gattMsgEvent_t * )pMsgData;
      switch ( gattMsg->method )
      {
        case ATT_FLOW_CTRL_VIOLATED_EVENT:
          {
              MenuModule_printf(APP_MENU_PROFILE_STATUS_LINE, 0, "GATT status: ATT flow control is violated");
          }
          break;
    
        case ATT_MTU_UPDATED_EVENT:
          {
              MenuModule_printf(APP_MENU_PROFILE_STATUS_LINE, 0, "GATT status: ATT MTU update to %d",
                                gattMsg->msg.mtuEvt.MTU);
          }
          break;
        case ATT_READ_BY_TYPE_RSP:
        {
            display_index += 1;
            attReadByTypeRsp_t *response = (attReadByTypeRsp_t *)&(gattMsg->msg.readByTypeRsp);
            MenuModule_printf(display_index, 0, "GATT status: Read by type %d", response->numPairs);
    
            for (int i = 0; i < response->numPairs; i++)
            {
                uint16_t attributeHandle = BUILD_UINT16(response->pDataList[i * response->len + 0],
                                                        response->pDataList[i * response->len + 1]);
    
                uint16_t endHandle = BUILD_UINT16(response->pDataList[i * response->len + 2],
                                                  response->pDataList[i * response->len + 3]);
    
                display_index += 1;
                MenuModule_printf(display_index, 0, "GATT status: Read by type: Handle: %x | %x", attributeHandle, endHandle);
            }
            break;
    
        }
        case ATT_FIND_BY_TYPE_VALUE_RSP:
        {
            display_index += 1;
            attFindByTypeValueRsp_t *response = (attFindByTypeValueRsp_t *)&(gattMsg->msg.findByTypeValueRsp);
            MenuModule_printf(display_index, 0, "GATT status: Find by type: numInfo %d", response->numInfo);
    
            for (int i = 0; i < response->numInfo; i++)
            {
                uint16_t attributeHandle = BUILD_UINT16(response->pHandlesInfo[i * response->numInfo + 0],
                                                        response->pHandlesInfo[i * response->numInfo + 1]);
    
                uint16_t endHandle = BUILD_UINT16(response->pHandlesInfo[i * response->numInfo + 2],
                                                  response->pHandlesInfo[i * response->numInfo + 3]);
    
                display_index += 1;
                MenuModule_printf(display_index, 0, "GATT Handle start: %x | end: %x", attributeHandle, endHandle);
    
    
                /*
                 * Note: The call to GATT_DiscAllChars will fail if called without a delay. Here is what TI recommends:
                 *      1. Store the handles, and trigger a timer which will then call GATT_DiscAllChars with the data.
                 *      2. Add a delay.
                 *
                 *  The reason a delay or timer is needed is because the BLE stack is still processing information. Thus leading
                 *  the call to GATT_DiscAllChars to return with 'bleNotReady'. For the sake of convenience the delay implementation
                 *  is provided here. However, a timer that triggers an interrupt would be a more elegant solution.
                 *
                 */
                ClockP_sleep(1);
    
                bStatus_t status = GATT_DiscAllChars(gattMsg->connHandle, attributeHandle, endHandle, BLEAppUtil_getSelfEntity());
    
                 if (status != SUCCESS)
                 {
                     display_index += 1;
                     MenuModule_printf(display_index, 0, "GATT_DiscAllChars Failed: %x", status);
                 }
            }
    
            break;
        }
    
        default:
          break;
      }
    }

    这应该可以帮助您发现特定服务的所有特征。

    这些句柄的构建方式基于 BLE 规范对它们的定义。 但是、我建议阅读代码和规范、以了解我们是如何构建属性句柄的。

    上面的代码应该是使特征发现正常运行的良好开始。 我还建议阅读我们的 GATT API、以了解更多信息:

    TI BLE5-Stack API 文档:ATT/GATT 

    此外、阅读蓝牙核心规范将可以详细了解特征发现所需的确切过程。

    希望这对您有所帮助!

    此致!

    Nima Behmanesh