1. 引言这篇文章是【CSR8675学习笔记:新建一个GATT server】的兄弟篇。在前述文章中讲述了如何在CSR8675上运行一个可由手机访问的自定义GATT服务器。 本文讲述了如何在QCC3003上运行一个自定义的GATT客户端,使其能如手机一样去访问运行在其他设备上的自定义的GATT服务器。 常见的自定义GATT client的应用场景是使得QCC3003能够连接一个BLE PTT遥控器,遥控器的按键可打开或关闭蓝牙对讲。 ![]() 本文介绍的方法与【QCC3003项目实战:BlueMotor6 AGHFP CVC 蓝牙对讲耳机】一起实施,可以组建一个短距无线控制的对讲设备。 2. 什么是GATT clientGATT client是一个软件概念,用于指代蓝牙BLE GATT协议中的客户端,通常作为访问者登入一个GATT server,获取服务内容,简单的模型如下: ![]() 上图中,手机端运行GATT client,嵌入式设备端运行GATT server。client向server发送请求或命令,读写server中的特征值,达到获取设备状态和操控设备的目的。 类似地,当QCC300x与PTT建立BLE连接后,QCC300x上运行的ptt GATT client即可从PTT遥控器上运行的ptt GATT server获取按键的状态。 3. 我需要怎样的GATT client首先明确我们需要通过GATT client获取怎样的服务。在本文中以一个PTT遥控器为例,我们需要获取遥控器上的按键状态。当按键数量不超过8个,单个uint8型的特征值即足够使用。 再考虑按键事件是用户的重要输入,应以最快的速度响应,同时以尽可能低的功耗维持对用户事件的关切,因此notify机制是较合适的。即当有按键事件触发时,GATT server主动向GATT client发送通知,而非由GATT client轮询。 4. 自定义GATT client的关键步骤ADK原生支持的GATT client有很多,battery client是必不可少的,其功能是读取目标设备的当前电量或接收目标设备电量变化的通知。本文提到的GATT PTT client的原型即是GATT Battery client。 GATT Battery client的源码在ADK的src/lib/gatt_battery_client路径中。为了创建GATT PTT client,需要按如下步骤操作:
5. 连接并使用BLE PTT遥控器目标板开机后自动初始化GATT client库,但还不会自动搜索PTT遥控器,需按键触发start ble bonding消息,QCC300x即进入central模式,开始快速扫描周围是否有包含PTT server的BLE peripheral,相关log如下: [code]initialise GATT Manager - with servers Calculate memory size for server tasks: +GATT=[3] +GAP=[6] +Optional=[6] GATT Server registered GATT GAP Server initialised GAP new state=[IDLE] GAP Bonded to private device=[0] GattPtt: Add PTT advertising filter GAP new event=[POWER_ON] state=[IDLE] GAP new event=[POWER_ON] state=[IDLE] GAP new event=[BONDABLE] state=[IDLE] GAP gapStartBonding GAP new state=[BONDED_SCAN_ADV] The Max Configuration for [CENTRAL] role is 1 GAP gapStartBondableConnectionTimer timeout=[60 s] GAP new event=[CENTRAL_CONNECT_ATTEMPT] state=[BONDED_SCAN_ADV][/code] QCC300x扫描到包含PTT server的设备后,开始尝试发起连接: [code]GAP Central conn attempt=[0] GAP Central conn attempt=[0] GAP new state=[BONDABLE_CONNECTING] GAP gapStopBondableConnectionTimer GAP Connect To Any Device GAP connect attempt whitelist=[0]: connect_addr=[(0) 2:5b:1529] current_addr=[(0) 2:5b:1529] permanent_addr=[(0) 2:5b:1529] GAP Scanning fast=[1] GAP Set Master Conn Attempt =[1] CL_DM_LOCAL_NAME_COMPLETE Set advertising data bondable=[0] GAP new event=[CANCELLED_ADV] state=[BONDABLE_CONNECTING] GAP event ignored in state GAP new event=[BOND_CONN_TIMEOUT] state=[BONDABLE_CONNECTING] GAP event not handled in state GAP new event=[CENTRAL_CONNECT_ATTEMPT] state=[BONDABLE_CONNECTING] GAP event not handled in state GAP new event=[SET_ADV_COMPLETE] state=[BONDABLE_CONNECTING] GAP event not handled in state The Max Configuration for [CENTRAL] role is 1 GAP Set Master Conn Attempt =[1] Mem Alloc (Gatt Client - Services): size[15] addr[1b00] Mem Alloc (Gatt Client - Discovery): size[27] addr[2100] GATT_EXCHANGE_MTU_CFM[/code] QCC300x发现PTT遥控器支持的所有首要服务,记录服务句柄,留作后续分别获取每个服务的次要服务以及特征值,可以看出获取到GATT/PTT/BAS服务: [code](Gatt Client - Connection): addr[1c1b] GATT_DISCOVER_ALL_PRIMARY_SERVICES_CFM cid[0xc0] Start[0x1] End[0x7] more[1] (Gatt Client - Connection): addr[1c1b] Gatt Client Store Discovered Service, uuid 0x1800 GATT_DISCOVER_ALL_PRIMARY_SERVICES_CFM cid[0xc0] Start[0x8] End[0x8] more[1] (Gatt Client - Connection): addr[1c1b] Gatt Client Store Discovered Service, uuid 0x1801 Gatt Client Storing GATT Service handles Mem Re-Alloc (Gatt Client - Services): size[20] addr[1b00] GATT_DISCOVER_ALL_PRIMARY_SERVICES_CFM cid[0xc0] Start[0x9] End[0xc] more[1] (Gatt Client - Connection): addr[1c1b] Gatt Client Store Discovered Service, uuid 0x5696 Gatt Client Storing PTT Service handles Mem Re-Alloc (Gatt Client - Services): size[27] addr[1b00] GATT_DISCOVER_ALL_PRIMARY_SERVICES_CFM cid[0xc0] Start[0xd] End[0xffff] more[0] (Gatt Client - Connection): addr[1c1b] Gatt Client Store Discovered Service, uuid 0x180f Gatt Client Storing BAS Service handles Mem Re-Alloc (Gatt Client - Services): size[34] addr[1b00] (Gatt Client - Connection): addr[1c1b] (Gatt Client - Size of Services): size[5] addr[1b0e] Add gatt client service; success[0] cid[0xc0] start[0x8] end[0x8] gattClientProcessSecurityRequirements: is_security_required = 0[/code] 获取所有次要服务和特征值,完成notify事件的注册: [code]GATT Discovered Service: cid[0xc0] index[0] service[6] start[0x8] end[0x8] (Gatt Client - Connection): addr[1c1b] GATT Discovered Service: cid[0xc0] index[1] service[9] start[0x9] end[0xc] (Gatt Client - Connection): addr[1c1b] (Gatt Client - Size of Services): size[12] addr[1b13] GATT_PTT_CLIENT_INIT_CFM status[0] GATT_PTT_CLIENT_READ_BTN_VAL_CFM status[2] value[0] GATT_PTT_CLIENT_SET_NOTIFICATION_ENABLE_CFM status[0] GATT Discovered Service: cid[0xc0] index[2] service[1] start[0xd] end[0xffff] (Gatt Client - Connection): addr[1c1b] (Gatt Client - Size of Services): size[19] addr[1b1a] GATT_BATTERY_CLIENT_INIT_CFM status[0] GATT_PTT_CLIENT_READ_DESCRIPTOR_CFM status[3] uuid[10498] size[0] ]GATT_BATTERY_CLIENT_READ_LEVEL_CFM status[0] level[100] GATT Battery RC level cache=[100] GATT_BATTERY_CLIENT_SET_NOTIFICATION_ENABLE_CFM status[0] GATT Primary Services Initialised GATT Client Discovery Complete Mem Free (Gatt Client): addr[2100] (Gatt Client - Connection): addr[1c1b] GAP new event=[CENTRAL_CONNECT_COMPLETE] state=[BONDABLE_CONNECTING] GAP Set Master Conn Attempt =[0] The Max Configuration for [CENTRAL] role is 1 GAP new state=[SCAN_ADV] The Max Configuration for [PERIPHERAL] role is 0 GAP new state=[SCAN_ADV] GATT_BATTERY_CLIENT_LEVEL_IND level[100] GATT Battery RC level cache=[100] GATT_BATTERY_CLIENT_READ_DESCRIPTOR_CFM status[0] uuid[10498] size[2] [0x1][0x0][/code] 当有PTT按键触发后,QCC300x可从notify事件中得知按键值的变化: [code]GATT_PTT_CLIENT_BTN_VAL_IND value[4] GATT Ptt RC value cache=[4] GATT_PTT_CLIENT_BTN_VAL_IND value[12] GATT Ptt RC value cache=[12] GATT_PTT_CLIENT_BTN_VAL_IND value[8] GATT Ptt RC value cache=[8] GATT_PTT_CLIENT_BTN_VAL_IND value[12] GATT Ptt RC value cache=[12][/code] 对应到VM代码中,当收到此IND消息后,可发送系统消息以打开/关闭对讲:
6. 总结实测PTT按键操控QCC300x进入退出对讲的延迟很短(<50ms),用户几乎感知不到。 原理上我们可以在创建的GATT service中定义更多字节数的特征值来支持更多的按键,或是主动读写GATT service来对LED/PIO进行控制。 当前PTT按键对BLE的带宽利用较低,后续有机会可尝试开发BLE串口透传功能。 来源:https://blog.csdn.net/wzz4420381/article/details/103554748 免责声明:如果侵犯了您的权益,请联系站长,我们会及时删除侵权内容,谢谢合作! |
GMT+8, 2025-12-13 17:22 , Processed in 0.315457 second(s), 13 queries , Gzip On, MemCached On.
Powered by Discuz! X3.5
© 2001-2025 Discuz! Team.