发布网友 发布时间:2023-06-22 23:00
共1个回答
热心网友 时间:2024-11-16 07:44
自动发现 CCC 是指在订阅某一个特征值的通知或指示时,可以只用特征值的 handle,不用指定 CCC 的 handle,协议栈会自动执行一个发现过程,帮我们查找的 CCC 的 handle。
那么如何使用呢?
我们先来看看正常情况下如何订阅一个特征值的通知:
这样成功订阅之后,每次 GATT Server 发生来一个通知,协议栈都会回调 nofity_function_cb() 回调函数。 但这样我们需要在 GATT 发现过程中手动查找 CCC 的 handle 并保存,稍微麻烦一点。
现在我们来看看如何用协议栈的自动发现 CCC 。
先来看看订阅参数结构体:
使能自动发现 CCC CONFIG_BT_GATT_AUTO_DISCOVER_CCC 后,该结构体多了两个参数 end_handle 和 disc_params 。
于是我们现在订阅一个特征值的通知过程如下:
这样就能够成功订阅特征值的通知了。
关键点如下:
配置内核 CONFIG_BT_GATT_AUTO_DISCOVER_CCC=y ,然后在 bt_gatt_subscribe_params 结构体里,
注意:使用自动发现 CCC 对于 end_handle 的选择需要十分注意,否则就会包含隐藏的 BUG 。自动发现 CCC 的过程找到的是 之间的第一个 CCC 的 handle 。这会导致这样的问题,若该范围内有一个 CCC,但是该特征值本身是没有 CCC 的,但是自动发现 CCC 的过程也会找到它,这就导致了错误。
因此在使用自动发现 CCC 订阅通知时,需要提前知道该特征值是否具有通知属性。如果具有通知属性,则可以直接将 end_handle 设置为 0xFFFF,不会产生任何隐藏 BUG 。
原理浅析
在整个工程里全局搜索 CONFIG_BT_GATT_AUTO_DISCOVER_CCC 就能够看到整个实现了。
核心部分为:
可以看到,在 bt_gatt_subscribe() 函数里,若开启了 CONFIG_BT_GATT_AUTO_DISCOVER_CCC 宏,并且传入参数的 ccc_handle 值为 0,则会先执行一个 GATT 发现过程,将发现得到的 CCC handle 存入参数 params 里,最后调用 gatt_write_ccc() 写服务端的 CCC 使能通知。