简述

目前的adk中只有电池,心率等几个固定的gatt服务,所以如果要实现自定义的数据收发,需要再自定义一个gatt服务

使能BLE/GATT功能

首先要在config中使能gatt,如下图所示:

添加gatt服务及属性

csr adk通过gatt_custom_server_db.dbi文件,然后利用工具生成对应的gatt服务数据表,在将该服务添加一个gatt服务列表中。通常来说嵌入式设备都是作为服务器(外设设备)存在,向客户端(中心设备)提供数据,.dbi文件如下:

primary_service {uuid : UUID_CUSTOM_SERVICE,name : "CUSTOM_FIRST_SERVICE",characteristic {uuid        : UUID_CUSTOM_CHARA_WRITE,name        : "WRITE",flags       : [ FLAG_IRQ ],properties  : [ write_cmd ],size_value       : 0x14},characteristic {uuid        : UUID_CUSTOM_CHARA_READ,name        : "READ",flags       : [ FLAG_IRQ ],properties  : [ notify ],size_value       : 0x14,client_config{name  : "CUSTOM_CCC",flags : [ FLAG_IRQ , FLAG_DYNLEN ]}},characteristic {uuid        : UUID_CUSTOM_CHARA_FLOW_CTL,name        : "FLOW_CTL",flags       : [ FLAG_IRQ ],properties  : [ notify ],value       : 0x0}
},

.dbi文件在编译中会转成相应的.c与.h文件,具体可以参考battery与heartrate对应的dbi文件。上面的dbi中,我定义了一个custom 服务,服务中包含三个character,第一个用于从手机读取,第二个用于向手机发送数据,第三个是流控。

Gatt数据发送

因为我们使用的数据发送的模型是notify,所以数据的发送需要调用一下接口GattNotificationRequest()。需要注意的是cid(channel id)参数,在这里我选择的是第一个gatt连接的cid,theSink.rundata->ble.gatt[0].cid,当有多个连接时,需要注意参数选择;还有handle参数,一定要与我们custom服务中相应的handle的UUID匹配

下面是我通过串口工具发送的指令到开发板,指令解析之后,将我要发送的数据通过蓝牙发送出去

void handleGattSendData(Task t, const struct GattSendData *send_data)
{uint16 index = 0;uint16 custom_cid = theSink.rundata->ble.gatt[index].cid;if(stateManagerGetState() > deviceConnDiscoverable){GattNotificationRequest(sinkGetBleTask(), custom_cid, HANDLE_READ, send_data->data.length, send_data->data.data);UartSendStr("OK\r\n");}else{UartSendStr("ERROR\r\n");}
}

Gatt数据接收

当底层收到数据之后,会发送给sinkGattManagerMsgHandler()进行消息处理,我们的server的消息将会包含在GATT_MANAGER_SERVER_ACCESS_IND中,原始的adk没有关于这块的数据处理,这里我参加了一个接口去打印gatt的数据

static gatt_status_t custom_gatt_data_handle(void *msg)
{uint16 flags,handle;gatt_status_t status = gatt_status_success;GATT_MANAGER_SERVER_ACCESS_IND_T *pMsg = (GATT_MANAGER_SERVER_ACCESS_IND_T *)msg;flags = pMsg->flags;handle = pMsg->handle;if (flags == (ATT_ACCESS_PERMISSION | ATT_ACCESS_WRITE_COMPLETE | ATT_ACCESS_WRITE)) {if (handle == HANDLE_WRITE) {UartSendStr("+GATTDATA:");UartSendData(pMsg->value, pMsg->size_value);UartSendStr("\r\n");} else if (handle == HANDLE_CUSTOM_CCC) {} else{status = gatt_status_write_not_permitted;}} else if (flags == (ATT_ACCESS_PERMISSION | ATT_ACCESS_READ)) {}return status;
}

Ble广播数据添加

如果想要在广播数据中包含自定义的服务的uuid等信息,需要在这里添加ble的服务数据

static void updateServicesAdData(uint8* ad_data_ptr, uint16 *counter_ptr , uint16 num_services)
{if (num_services){BLE_AD_INFO(("Custom Service"));ad_data_ptr[*counter_ptr] = (0x00 & 0xFF);(*counter_ptr)++;ad_data_ptr[*counter_ptr] = (0xFF >> 8);(*counter_ptr)++;num_services--;}
}

上面我只贴出了部分代码,详细源码及相关的工具资料等,请到我的博客<csr867x入门笔记(序)>最下面的网盘链接或者github链接中下载。

csr867x入门之gatt使用(五)相关推荐

  1. csr867x入门笔记(序)

    本专栏的主要内容是csr867x的入门使用,主要包括环境搭建及体验,串口调试,at指令协议添加,各个蓝牙协议的使用等,最终这些例程会加入到adk里面,adk主要是基于4.1版本. 我也会把相关的资料放 ...

  2. 【OpenCV入门指南】第五篇轮廓检测 下

    上一篇<[OpenCV入门指南]第五篇轮廓检测上>介绍了cvFindContours函数和cvDrawContours函数,并作了一个简单的使用示范.本篇将展示一个实例,让大家对轮廓检测有 ...

  3. VUE—从入门到飞起(五)

    目录 路由 路由基本使用 路由规则中定义参数 路由嵌套 命名视图实现经典布局 VUE-从入门到飞起(一) VUE-从入门到飞起(二) VUE-从入门到飞起(三) VUE-从入门到飞起(四) VUE-从 ...

  4. GPU 编程入门到精通(五)之 GPU 程序优化进阶

    版权声明:本文为博主原创文章,未经博主允许不得转载. 目录(?)[+] 博主由于工作当中的需要,开始学习 GPU 上面的编程,主要涉及到的是基于 GPU 的深度学习方面的知识,鉴于之前没有接触过 GP ...

  5. 《假如编程是魔法之零基础看得懂的Python入门教程 》——(五)我的魔法竟然有了一丝逻辑

    学习目标 了解魔法世界中的结构表现--缩进 了解魔法世界的逻辑判断--if 了解魔法世界的多次逻辑判断--ifelse嵌套 了解魔法世界中的逻辑运算--且 and 与或 or 推荐 1.<备受好 ...

  6. html5游戏制作入门系列教程(五)

    我们继续这一系列文章,使用HTML5的canvas组件进行游戏开发.今天,这是相当完整的游戏例子 – 它会回顾经典的旧电脑游戏 – 坦克大战.我会教你使用阵列地图并教你如何检测活动对象(坦克)与环境( ...

  7. Python编程从入门到实践第五章部分习题

    Python编程从入门到实践第五章部分习题 5-8 5-9` names = ['admin','zhang','li','zhao','song'] for name in names:if nam ...

  8. csr867x入门之按键配置(九)

    目录 简介 配置按键触发条件 io口配置 将按键事件对应到用户事件 触发逻辑电平反转 简介 Csr支持通过ADKConfigTool.exe配置按键,给实际的开发提供了很大的方便! 打开配置工具,连接 ...

  9. csr867x入门之iis使用(八)

    目录 Csr iis接口简介 用configuration tool设置iis模式 程序运行中的iis与analog切换 Csr iis接口简介 其iis有四根线:采样率(帧时钟).位时钟.数据输出, ...

最新文章

  1. 通俗理解tf.name_scope()、tf.variable_scope()
  2. 模板特化,全特化,偏特化,全部特化,部分特化的含义
  3. Understanding SOAP
  4. 把二元查找树转变成排序的双向链表(树)
  5. Hmac - Java加密与安全
  6. 同时运行两个PHP吗,PHP-避免由两个工作人员同时运行后台作业
  7. 如何使用LVM逻辑卷
  8. Python各类图像库的图片读写方式总结
  9. 文本生成系列之transformer结构扩展(二)
  10. 彼得林奇:赚钱密码(1990年一次演讲)
  11. @EnableWebMvc引发的swagger-ui.html的灾难
  12. MikroTik RouterOS U盘安装工具netinstall的使用
  13. Excel 做统计学分析
  14. Java开发一年经验北京薪资,全网首发!
  15. android9原生体验,原生安卓必备软件 优化类原生ROM体验
  16. 高德地图红绿灯读秒是怎么实现的?(一)
  17. 【转】Linux 虚拟内存
  18. Qt大屏电子看板系统源码基础版
  19. c# 计算圆锥的体积_用C#如何编写程序计算球,圆柱和圆锥的表面积和体积? 用C#编写方法并通过方法...
  20. 2019年记录:java小白级程序员工作一年以来的经历,遇到的坎坷以及当时的心态

热门文章

  1. 虚拟化技术之docker技术详解
  2. 使用iPhone来提醒自己-日历和提醒事项
  3. 【Java版oj】逆波兰表达式求值
  4. php手术要休息多久,囊肿切除后需要休息多久
  5. 手把手教你如何远程连接云服务器(图文教程)?
  6. 鸡蛋的吃法及营养价值
  7. 记录java.util.Collections.unmodifiableList()使用
  8. JVM-对象什么时候进入老年代(实战篇)
  9. AttributeError: module 'easygui' has no attribute 'msgbox'错误
  10. 全志v3s学习笔记(8)——TF卡分区及烧录