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:调用 GATT_DiscAllChars 后的响应长度无效

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

https://e2e.ti.com/support/wireless-connectivity/bluetooth-group/bluetooth/f/bluetooth-forum/1446265/cc2340r5-invalid-response-length-after-calling-gatt_discallchars

器件型号:CC2340R5

工具与软件:

您好!

芯片组:CC2340R5

SDK:

大家好、我目前使用的 是一款 CC2340R5 EVK ( 中央 EVK )为了开发和运行 EVK 的中心作用,基本 ble SDK 被用作基础项目。

我正在使用另一个  CC2340R5 EVK ( 外设 EVK )在外设 模式下、基本 ble SDK 代码用作基本项目。

我使用 nrf connect 以外设角色运行的 EVK 的 GATT 表、该表如下所示。 收集此信息后、我断开外设与 NRF CONNECT 的连接。

 

现在、使用" 中央 EVK "我连接到" 外设 EVK"。 连接成功后、我启动服务发现调用、如下所示:

我已经使用 Log_printf 函数打印服务发现的响应、如下所示:

我已将 服务发现响应保存 在队列中。  

稍后、 我调用从队列中检索服务发现响应、然后调用 " GATT_DiscAllChars " API 如下所示。

我得到了" ATT_READ_BY_GRP_TYPE_RSP " rsp 并在解析后、我打印了" attReadByGrpTypeRsp_t "。

您可以看到、dataLen 字段包含一个非常大的数字。  

此处可能是什么问题? 因此我无法继续、请帮助我解决此问题。  

此外、我还添加了用于解析" attReadByGrpTypeRsp_t "结构。

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

    您好!

    您不应获得 ATT_READ_BY_GRP_TYPE_RSP、因为 GATT_DiscAllChars 返回使用不同结构的 ATT_READ_BY_TYPE_RSP。

    https://dev.ti.com/tirex/content/simplelink_lowpower_f3_sdk_8_10_01_02/docs/ble5stack/ble_user_guide/doxygen/ble/html/group___a_t_t___g_a_t_t.html#gac824af509fbd28c84ae6a1d1d4a1ba11

    您是否接收到 ATT_READ_BY_GRP_TYPE_RSP、而不是 ATT_READ_BY_TYPE_RSP? 您是否介意发送您的处理代码以便我进行审核?

    此致!

    Nima Behmanesh

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

    尊敬的 Nima:  

    感谢您指出这个错误。 我发布了错误的代码片段。  请在下面找到我的 GATT_EvenHandler。

    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);
              Log_printf(LogModule_App1, Log_INFO, "MTU updated to: %d", gattMsg->msg.mtuEvt.MTU);
    
          }
          break;
        case ATT_READ_BY_GRP_TYPE_RSP:
        {
    
            MenuModule_printf(APP_MENU_PROFILE_STATUS_LINE, 0, "GATT status: ATT MTU update to %d",
                              gattMsg->msg.mtuEvt.MTU);
    
            attReadByGrpTypeRsp_t *resp = (attReadByGrpTypeRsp_t *)&(gattMsg->msg.readByGrpTypeRsp);
    
            Log_printf(LogModule_App1, Log_INFO, "response len: %d", resp->len);
            Log_printf(LogModule_App1, Log_INFO, "num groups: %d", resp->numGrps);
            if(resp->len)
            {
                sendSvcDiscRsp(resp->pDataList, resp->len); // save data to queue.
            }
    
        }break;
    
        case ATT_READ_BY_TYPE_RSP :
        {
            attReadByTypeRsp_t * resp = (attReadByTypeRsp_t *)&(gattMsg->msg.readByTypeRsp);
    
    
            Log_printf(LogModule_App1, Log_INFO, "response len: %d", resp->len);
            Log_printf(LogModule_App1, Log_INFO, "numPairs: %d", resp->numPairs);
            Log_printf(LogModule_App1, Log_INFO, "dataLen: %d", resp->dataLen);
            for(int i=0; i < resp->len; i++)
            {
                Log_printf(LogModule_App1, Log_INFO, "%d", resp->pDataList[i]);
            }
        }break;
       
        default:
          break;
      }
    }

    我正在接收" ATT_READ_BY_TYPE_RSP "解析逻辑出现在上述代码片段中。

    我打印" attReadByTypeRsp_t "结构并获得 一个非常 值的  数据长度字段。  

    我还打印了" attReadByTypeRsp_t "以下内容是不同句柄搜索的结果。

    gattMsg->msg.readByTypeRsp.len = 7;
    gattMsg->msg.readByTypeRsp.numPairs = 0x05;
    gattMsg->msg.readByTypeRsp.pDataList = 0xC3、0x43、0x00、0x20;  
    gattMsg->msg.readByTypeRsp.dataLen = 0xEB11;// 很大

    0x05、0x00、 0x07 、0x00、0xC3、 0x43、0x00、0x20、0x11、0xEB

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

    您好!

    这当然很奇怪、通过读取 attReadbyTypeRsp_t 结构、您也许不需要这个字段。

    例如、我如何对其进行解析:

            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;

    您能试一下并告诉我结果吗?

    此致!
    Nima Behmanesh

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

    尊敬的 Nima:  

    我将在明天回到办公室,我将尝试这一保持你张贴。 但获得如此大的值是非常奇怪的、您能找出原因吗?

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

    Sandeep、您好!

    我需要联系 R&D、并且同样将问题复制到我这边。 您使用的 SDK 版本是什么? 我相信这是你原来的帖子遗漏的。

    此致!
    Nima Behmanesh

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

    尊敬的 Nima:  

    我当前使用的 SDK 版本是" simplelink_lowpower_f3_sdk_8_10_01_02 "。

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

    您好!

    谢谢! 我会尝试一下、然后回复给您。

    此致!
    Nima Behmanesh

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

    Sandeep、您好!

    我还在研究这件事,不会晚于星期五回复你。

    此致!
    Nima Behmanesh

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

    Sandeep、您好!

    在假期、我的回答会有点延迟。 感谢您耐心解决此问题。

    此致!
    Nima Behmanesh

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

    感谢您发送编修。 我 希望我们能尽快找到解决办法。

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

    Sandeep、您好!

    您是否介意对最新的 SDK 进行测试、以查看问题是否仍然存在?

    此致!
    Nima Behmanesh

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

    尊敬的 Nima:  

    下图显示了 SDK 与 CC27芯片组兼容。 我随身携带了 CC27开发板、并且我也在其中加载了上述代码。 我看到 CC27电路板上也出现了同样的问题。 这真的会是一个 SDK 问题吗?

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

    Sandeep、您好!

    您是否可以尝试上面粘贴的代码片段?

    此致!

    Nima Behmanesh

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

    尊敬的 Nima:  

    在我们的用例中、上述方法可能不是可行的解决方案、因为我们希望将收到的数据发送到任务并在任务中处理处理数据。  

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

    Sandeep、您好!

    解析信息的方式由蓝牙核心规范指定。 如果您需要在不同的任务中处理数据、我建议您可能按照上面所示的方式设置信息的格式、并将其放置在可以在任务之间共享的结构中。

    此致!

    Nima Behmanesh

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

    尊敬的 Nima:

    当你说" 解析信息的方式由蓝牙核心规范指定 "。 因为 strcut 有一个指针字段( pDataList )和一个数据字段,这是我的理解,这 数据 要从中读取的字节数 pDataList .

    此外、鉴于您之前已共享的代码片段、正确的做法是假设" Response->numPairs * 4. "捕获 pDataList 的全部内容?  

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

    Sandeep、您好!

    我相信这是正确的。 尽管我相信您可以直接复制代码片段、这应该会捕获所有对属性句柄。

    此致!

    Nima Behmanesh

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

    尊敬的 Nima:

    明白了。 因此、假设对于此特定事件、必须使用 numPairs 来解码数据、并且长度字段具有通常较高的值、因为它是默认设置、这是正确的吗?

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

    尊敬的 Nima:  

     在外设上、我有1个服务和5个特性、如下所示。

    我参考了上面的代码片段并从中提取了数据。 数字对为5、每个对的长度为7。

    数据如下所示。

    0x02、0x00、0x18、0x03、0x00、0x01、0xE0、
    0x06、0x00、0x18、0x07、0x00、0x02、0xE0、
    0x0A、0x00、0x18、0x0B、0x00、0x03、0xE0、
    0x0E、0x00、0x18、0x0F、0x00、0x04、0xE0、
    0x12、0x00、0x18、0x13、0x00、0x05、0xE0

    用于提取上述数据的代码片段:

    根据我的理解、前2个字节是开始句柄、字节3和4是结束句柄。 由于我知道我的器件的 UUID、因此我可以放心地说最后2个字节是 UUID。

    我看到终端句柄与启动句柄不同步。 由于 数据 字段具有 无效值、是否可能其余字段也不正确? 我从堆栈中接收到的这个数据是正确的数据吗?

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

    Sandeep、您好!

    您是否介意重新附上服务的图片? 不需要为我加载。

    我看到末尾句柄与起始句柄不同步。

    您是否介意详细说明它们不同步意味着什么?

    此致!

    Nima Behmanesh

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

    Sandeep、您好!

    在研究这件事并尝试一些东西在我的终端,我看到混淆是从哪里来的,所以我觉得需要后退,从零开始。

    首先、我之前编写的代码不完全正确。 要了解原因、我们需要查看规格。

    1.我们来看一下 ATT_READ_BY_TYPE_RSP

    因此、这里只有两个我们关心的字段: 长度 和 属性数据列表。  这会映射到我们将解析的 attReadByTypeRsp_t 结构中的两个字段。

    长度= attReadByTypeRsp_t.len

    属性数据列表= attReadByTypeRsp_t.pDataList

    接下来、这些是  我们需要该结构中的两个字段。   完全忽略 dataLen (说实话,它甚至不应该在那里)。

    另见  注释  效率模型  属性 handle-value 对。  我们没有 启动句柄 和结束句柄。  我们将获得属性的句柄以及该属性的值。 这很重要、因为现在我们必须看看 GATT。

    2.第 G 部分。通用属性配置文件第3.3.1节

    下面我们看一下  attReadByTypeRsp_t 的值部分实际上是什么样的:

    我们还进行小端字节序、因此我们需要反转要检索的 pDataList 的顺序:

     

        case ATT_READ_BY_TYPE_RSP:
        {
            attReadByTypeRsp_t att = (attReadByTypeRsp_t)gattMsg->msg.readByTypeRsp;
    
            MenuModule_printf(APP_MENU_PROFILE_STATUS_LINE + display_index, 0, "ATT_READ_BY_TYPE_RSP len: %d numPairs: %d", att.len, att.numPairs);
            display_index++;
    
            for (uint8_t i = 0; i < att.numPairs; i++)
            {
                /* This is the Attribute Handle */
                uint16_t attHandle = BUILD_UINT16(att.pDataList[i * att.len + 0], att.pDataList[i * att.len + 1]);
                MenuModule_printf(APP_MENU_PROFILE_STATUS_LINE + display_index, 0,"ATT Handle: %x", attHandle);
                display_index++;
    
                /* This is the index to the beginning of the value data AFTER the attribute handle */
                uint8_t index = i * att.len + 2;
    
                /* The characteristic value data */
                uint8_t data1 = att.pDataList[index];     // Bit field of characteristic properties
    
                uint8_t data2 = att.pDataList[index + 1]; // Second Byte of Characteristic Value Handle
                uint8_t data3 = att.pDataList[index + 2]; // First Byte of Characteristic Value Handle
    
                /* If we were using 128-bit Bluetooth UUIDs, then we would have 16 of these instead of 2. */
                uint8_t data4 = att.pDataList[index + 3]; // Second byte of UUID
                uint8_t data5 = att.pDataList[index + 4]; // First byte of UUID
    
                /* Since we are in little endian, we have to reverse the order to make the values make sense. */
                MenuModule_printf(APP_MENU_PROFILE_STATUS_LINE + display_index, 0,"UUID: %x%x Val Handle: %x%x Properties: %x", data5, data4, data3, data2, data1);
                display_index++;
            }
        }
        break;

    我在器件信息服务(UUID 0x180A)上尝试了此操作、结果是输出:

    这是合理的、尤其是如果我们考虑到 ATT_MTU 大小为27字节(len 为7、我们有3对、因此总共27字节)。 ATT_MTU 大小在您的应用程序中可能会有所不同。 我还验证了我预期的属性和 UUID 是我将获得的。

    最后、我将解析附加的映像:

    属性句柄: 0x0002、 属性: 0x18 (GATT_PROP_WRITE | GATT_PROP_NOTIFY)、 值句柄: 0x0003、 UUID: 0xE001

    我希望这对您有所帮助、如果您有任何问题、请告诉我!

    此致!

    Nima Behmanesh

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

    尊敬的 Nima:  

    非常感谢您提供有关数据包类型的详细说明。 会议内容也非常丰富。 我在我的代码中测试了上述序列、现在我能够理解这些序列。 这样、我就能够关闭客户端实施。

    再次感谢一群人、

    Sandeep