一步步教您如何在DA14580 cust profile基础上实现大量notify的发送.docx

上传人:b****5 文档编号:12218972 上传时间:2023-04-17 格式:DOCX 页数:22 大小:729.85KB
下载 相关 举报
一步步教您如何在DA14580 cust profile基础上实现大量notify的发送.docx_第1页
第1页 / 共22页
一步步教您如何在DA14580 cust profile基础上实现大量notify的发送.docx_第2页
第2页 / 共22页
一步步教您如何在DA14580 cust profile基础上实现大量notify的发送.docx_第3页
第3页 / 共22页
一步步教您如何在DA14580 cust profile基础上实现大量notify的发送.docx_第4页
第4页 / 共22页
一步步教您如何在DA14580 cust profile基础上实现大量notify的发送.docx_第5页
第5页 / 共22页
点击查看更多>>
下载资源
资源描述

一步步教您如何在DA14580 cust profile基础上实现大量notify的发送.docx

《一步步教您如何在DA14580 cust profile基础上实现大量notify的发送.docx》由会员分享,可在线阅读,更多相关《一步步教您如何在DA14580 cust profile基础上实现大量notify的发送.docx(22页珍藏版)》请在冰豆网上搜索。

一步步教您如何在DA14580 cust profile基础上实现大量notify的发送.docx

一步步教您如何在DA14580custprofile基础上实现大量notify的发送

BDF001-一步步教您如何在DA14580custprofile基础上实现大量notify的发送

文档版本:

v0.0.1

本文主要介绍如何在DA14580SDK5.0.3的prox_reporter例子基础上添加custprofile,并最终利用notify给手机发送大量数据。

主要的内容分三个部分:

1.custprofile的添加;

2.connparamupdate代码添加;

3.大量Notify数据发送丢包严重问题缓解。

需要准备的工具:

1.DA14580开发板,或者其他可以运行代码的DA14580板子;

2.基本的软件开发环境,如Keil等;

3.支持BLE的手机或者其他平台。

以上工具是DA14580开发必备,如果没有,请自行XX相关资料解决。

准备工作完毕后,我们就可以开始了:

一、custprofile的添加。

首先我们来看看custprofile添加完毕后的结果,用lightblue搜索并与芯片建立连接后,会出现以下服务:

首先,我们打开prox_reporter工程,然后,添加custservice服务所必须文件到我们的工程中:

这几个文件分别在以下位置:

sdk\ble_stack\profiles\custom\custs\custs1.c

sdk\ble_stack\profiles\custom\custs\custs1_task.c

sdk\ble_stack\profiles\custom\custom_common.c

sdk\ble_stack\host\att\attm\attm_db_128.c

然后我们在prox_reporter\src\config文件夹中建立一个新文件user_custs_config.h并加入到工程中:

完毕后,我们在工程属性中加入一个宏定义,以便后续方便查找我们本次修改的代码,当然,你也可以不加此宏定义:

好了,现在开始我们添加代码。

首先打开user_proxr.c文件,并加入以下代码:

其中char_value我们用作存放read和write数据的地方,notify_timer作为发送notify的定时器。

在user_proxr.c文件的最后面,加入以下4个函数:

其中,user_app_on_connection用来定义连接建立后需要添加的代码;user_app_on_disconnect为连接断开后需要做的工作;user_on_db_init_complete为database初始化完毕后的接口函数;user_catch_rest_hndl我们用来处理由主机(可以是手机)往下发送的msg,这里我们用来处理CUSTS1_VAL_WRITE_IND请求。

我们来一步步添加每一个函数体:

Default_app_on_connection为系统默认的connection处理函数,我们保留它的所有功能,接下去我们开启notify_timer,利用的是app_easy_timer,这个函数是SDK5里面新的设置定时器的函数,如果用老的SDK,是没有这个函数的,可以利用其它的方法实现;函数的第一个参数1000,我们设置了定时器触发的时间为1000*10ms也就是10s,第二个参数notify_charactertistic_update为触发时调用的函数,一旦定时器到达10s,则会直接跳转到notify_charactertistic_update函数。

按照字面理解,此函数为disconnect处理函数,同样的道理,我们保留default_app_on_disconnect的所有功能,然后我们关闭之前开启的timer,因为连接端口后,再发送notify是没有任何意义的。

此函数只在database完成初始化后调用一次,这里我们设置了之前定义的char_value值到数据库中,以便主机发起read请求后能够得到有效数据。

此函数处理主机发送的消息,这里只处理CUSTS1_VAL_WRITE_IND,我们将得到的数据写入char_value,并用attmdb_att_set_value函数将数据更新到底层。

然后在user_app_on_connection上面添加timer回调函数:

此函数里面暂时只做一件事情:

开启一个10ms的定时器,回调函数是它自己,也就是说每10ms调用一次此函数。

后续我们会利用此函数来发送Notify,现在暂时留空。

好了,user_proxr.c文件的工作暂时结束,然后在user_proxr.h中添加函数声明:

接下去在user_profiles_config.h中添加代码:

修改user_config.h中的广播数据:

这个修改并不是必须的,没有这个系统也能正常工作,只是广播数据中少了custprofile信息,为了避免表里不一,还是建议修改一下吧。

刚才我们在user_proxr.c添加了user_app_on_connection、user_app_on_disconnect、user_on_db_init_complete和user_catch_rest_hndl,我们必须告诉系统我们要调用这些函数,而不是默认,所以我们需要修改user_callback_config.h:

添加头文件:

修改以下callback函数:

修改以下定义:

staticvoid(*constapp_process_catch_rest_cb)(ke_msg_id_tconstmsgid,voidconst*param,ke_task_id_tconstdest_id,ke_task_id_tconstsrc_id)=NULL;

staticvoid(*constapp_process_catch_rest_cb)(ke_msg_id_tconstmsgid,voidconst*param,ke_task_id_tconstdest_id,ke_task_id_tconstsrc_id)=(catch_rest_event_func_t)user_catch_rest_hndl;

修改完毕后我们需要编辑user_custs_config.h文件,这里代码有点多,我直接贴出来:

#ifndef_USER_CUSTS_CONFIG_H_

#define_USER_CUSTS_CONFIG_H_

#include

#include"prf_types.h"

#include"attm_db_128.h"

#include"app_prf_types.h"

#include"app_customs.h"

#defineDEF_CUST_SVC_UUID_128{0x2F,0x2A,0x93,0xA6,0xBD,0xD8,0x41,0x52,0xAC,0x0B,0x10,0x99,0x2E,0xC6,0xFE,0xED}

#defineDEF_CUST_WRITE_CHAR_UUID_128{0x10,0x11,0x12,0x13,0x14,0x15,0x16,0x17,0x18,0x19,0x1A,0x1B,0x1C,0x1D,0x1E,0x1F}

#defineDEF_CUST_READ_CHAR_UUID_128{0x20,0x21,0x22,0x23,0x24,0x25,0x26,0x27,0x28,0x29,0x2A,0x2B,0x2C,0x2D,0x2E,0x2F}

#defineDEF_CUST_NOTIFY_CHAR_UUID_128{0x30,0x31,0x32,0x33,0x34,0x35,0x36,0x37,0x38,0x39,0x3A,0x3B,0x3C,0x3D,0x3E,0x3F}

#defineDEF_CUST_CHAR_LEN20

#defineCUST_CHAR_USER_DESC"Custom"

///CUSTOMServiceDataBaseCharacteristicenum

enum

{

CUST_IDX_SVC=0,

CUST_IDX_WRITE_CHAR,

CUST_IDX_WRITE_CHAR_VAL,

CUST_IDX_READ_CHAR,

CUST_IDX_READ_CHAR_VAL,

CUST_IDX_NOTIFY_CHAR,

CUST_IDX_NOTIFY_CHAR_VAL,

CUST_IDX_NB,

};

staticconstuint8_tcustoms_att_max_size[CUST_IDX_NB]=

{

[CUST_IDX_SVC]=0,

[CUST_IDX_WRITE_CHAR]=0,

[CUST_IDX_WRITE_CHAR_VAL]=DEF_CUST_CHAR_LEN,

[CUST_IDX_READ_CHAR]=0,

[CUST_IDX_READ_CHAR_VAL]=DEF_CUST_CHAR_LEN,

[CUST_IDX_NOTIFY_CHAR]=0,

[CUST_IDX_NOTIFY_CHAR_VAL]=DEF_CUST_CHAR_LEN,

};

staticconstatt_svc_desc128_tcustom_svc=DEF_CUST_SVC_UUID_128;

staticuint8_tCUST_WRITE_CHAR_UUID_128[ATT_UUID_128_LEN]=DEF_CUST_WRITE_CHAR_UUID_128;

staticuint8_tCUST_READ_CHAR_UUID_128[ATT_UUID_128_LEN]=DEF_CUST_READ_CHAR_UUID_128;

staticuint8_tCUST_NOTIFY_CHAR_UUID_128[ATT_UUID_128_LEN]=DEF_CUST_NOTIFY_CHAR_UUID_128;

staticconststructatt_char128_desccustom_write_char={ATT_CHAR_PROP_WR,

{0,0},

DEF_CUST_WRITE_CHAR_UUID_128};

staticconststructatt_char128_desccustom_read_char={ATT_CHAR_PROP_RD,

{0,0},

DEF_CUST_READ_CHAR_UUID_128};

staticconststructatt_char128_desccustom_notify_char={ATT_CHAR_PROP_NTF|ATT_CHAR_PROP_RD,

{0,0},

DEF_CUST_NOTIFY_CHAR_UUID_128};

staticconstuint16_tatt_decl_svc=ATT_DECL_PRIMARY_SERVICE;

staticconstuint16_tatt_decl_char=ATT_DECL_CHARACTERISTIC;

staticconstuint16_tatt_decl_cfg=ATT_DESC_CLIENT_CHAR_CFG;

staticconstuint16_tatt_decl_user_desc=ATT_DESC_CHAR_USER_DESCRIPTION;

staticconststructattm_desc_128custs1_att_db[CUST_IDX_NB]=

{

//CUSTOMServiceDeclaration

[CUST_IDX_SVC]={(uint8_t*)&att_decl_svc,ATT_UUID_16_LEN,PERM(RD,ENABLE),

sizeof(custom_svc),sizeof(custom_svc),(uint8_t*)&custom_svc},

//CustomWriteCharacteristicDeclaration

[CUST_IDX_WRITE_CHAR]={(uint8_t*)&att_decl_char,ATT_UUID_16_LEN,PERM(RD,ENABLE),

sizeof(custom_write_char),sizeof(custom_write_char),(uint8_t*)&custom_write_char},

//CustomWriteCharacteristicValue

[CUST_IDX_WRITE_CHAR_VAL]={CUST_WRITE_CHAR_UUID_128,ATT_UUID_128_LEN,PERM(WR,ENABLE),

DEF_CUST_CHAR_LEN,0,NULL},

//CustomReadCharacteristicDeclaration

[CUST_IDX_READ_CHAR]={(uint8_t*)&att_decl_char,ATT_UUID_16_LEN,PERM(RD,ENABLE),

sizeof(custom_read_char),sizeof(custom_read_char),(uint8_t*)&custom_read_char},

//CustomReadCharacteristicValue

[CUST_IDX_READ_CHAR_VAL]={CUST_READ_CHAR_UUID_128,ATT_UUID_128_LEN,PERM(RD,ENABLE),

DEF_CUST_CHAR_LEN,0,NULL},

//CustomReadCharacteristicDeclaration

[CUST_IDX_NOTIFY_CHAR]={(uint8_t*)&att_decl_char,ATT_UUID_16_LEN,PERM(RD,ENABLE),

sizeof(custom_notify_char),sizeof(custom_notify_char),(uint8_t*)&custom_notify_char},

//CustomCharacteristicValue

[CUST_IDX_NOTIFY_CHAR_VAL]={CUST_NOTIFY_CHAR_UUID_128,ATT_UUID_128_LEN,PERM(RD,ENABLE)|PERM(NTF,ENABLE),

DEF_CUST_CHAR_LEN,0,NULL},

};

/*

*LOCALVARIABLES

****************************************************************************************

*/

///Custom1/2serverfunctioncallbacktable

staticconststructcust_prf_func_callbackscust_prf_funcs[]=

{

#if(BLE_CUSTOM1_SERVER)

{TASK_CUSTS1,

custs1_att_db,

CUST_IDX_NB,

#if(BLE_APP_PRESENT)

app_custs1_create_db,app_custs1_enable,

#else

NULL,NULL,

#endif

custs1_init,NULL

},

#endif

#if(BLE_CUSTOM2_SERVER)

{TASK_CUSTS2,

NULL,

0,

#if(BLE_APP_PRESENT)

app_custs2_create_db,app_custs2_enable,

#else

NULL,NULL,

#endif

custs2_init,NULL

},

#endif

{TASK_NONE,NULL,0,NULL,NULL,NULL,NULL},//DONOTMOVE.Mustalwaysbelast

};

///@}USER_CONFIG

#endif//_USER_CUSTS_CONFIG_H_

以上代码主要添加了CUST_IDX_WRITE_CHAR、CUST_IDX_READ_CHAR、CUST_IDX_NOTIFY_CHAR等属性,如果需要增加其他属性如Indication,则可以按照它的样子添加即可:

可以在上图中的CUST_IDX_NOTIFY_CHAR_VAL后面添加相关定义,这里就不展开说明了。

当然,不仅仅是上图的一个地方要添加,其他相关地方也需要。

全部添加完毕后,编译并烧录到芯片运行,应该就能实现一开始所描述的功能。

二、connparamupdate代码添加

由于本次测试需要将conninterval设置为最快7.5ms,所以,增加连接参数同步代码比较重要,本次修改都在user_proxr.c中进行:

首先在头部添加以下代码:

其中红框中的部分为连接参数,此参数IOS会毫无疑问拒绝同步,如果你测试的是ISO手机,则请修改为IOS支持的连接参数规则。

然后在文件最后加上以下代码:

最后在user_app_on_connection函数中添加timer启动函数,以便在每次连接建立后APP_PARAM_UPDT_TIMEOUT时间内发起参数同步请求:

到此,同步参数代码添加完成。

接下去我们来添加Notify发送代码,来测试Notify发送。

我们在user_proxr.c中定义以下两个变量:

data_buff为发送数据,p_data为发送指针,我们的目的是将data_buff[400]这个数据包通过20个notify发送出去,每个notify的长度为20.

我们在前面写的notify_charactertistic_update函数中添加以下发送代码:

该代码的意思是当p_data小于20时会往底层写入发送数据,大于20就停止写入,也就是分了20包将数据发送出去。

最后,我们为了能重复测试,在CUSTS1_VAL_WRITE_IND中加入p_data清零代码,以实现当手机给DA14580做任何写入操作时,会重新发送20个Notify,此代码仅仅是为了方便测试。

最后,增加宏定义:

好了,编译,运行,让我们看看效果。

从抓包的结果来看,很明显,丢了地14号的包。

看来这样直接发是不可靠的,那么问题来了,如何让Notify更可靠呢?

三、大量Notify数据发送丢包严重问题缓解

这一部分是本文的重点,像前面的直接用attmdb_att_set_value和prf_server_send_event两个函数往底层写入notify数据包的方法,在对付小量的数据时是可以的,但是,如果遇到大量的数据,则这样做很容易丢包(前面我们才发了20个包就发现了,那么发200个呢,2000个呢)。

现在我们来修改代码解决此问题:

这里我们要用到cust1profile中的一个函数进行发送--custs1_val_ntf_req_handler,它在custs1_task.c中。

我们通过调用此函数来发送我们的Notify数据,我们删除刚刚在notify_charactertistic_update添加的代码并增加以下代码:

这里我们看到两个新函数,cust1_ntf_send_not_complete和app_custs1_val_ntf_upd_chars。

cust1_ntf_send_not_complete是我们自定义的,当底层还未完全接受上一个notify包的时候,他会返回一个ture,当底层已经接受了所有的notify,则会返回一个false;app_custs1_val_ntf_upd_chars是我们新写的发送函数,在user_proxr.c中来添加它的函数体:

这个函数会给系统发送一个req,系统收到后会调用我们前面提到的custs1_val_ntf_req_handler。

接下去,我们要对SDK中的文件做一些修改,按照以下位置一步步修改:

代码添加完毕后,记得添加宏定义:

这里强调一下,强烈建议加上TK_CUST_TEST这个宏定义,因为以上修改的代码都是在SDK中公共部分修改的,这里改掉了,其他工程也会被修改掉,所以为了不让其他工程崩溃,还是建议加上!

全部添加完毕后,编译运行,丢包的现象应该会消失或者缓解,因为notify这个东西是没有反馈的,成功与否取决于很多因素。

为了方便大家调试,我会将此代码放在我的个人网站上(),用户可以去下载,如遇到访问密码,请尝试:

bdf0001snowywind

 

版本修改记录:

时间

版本

内容

修改者

2016.08.25

V0.0.1

文件创建

 

展开阅读全文
相关资源
猜你喜欢
相关搜索

当前位置:首页 > 求职职场 > 笔试

copyright@ 2008-2022 冰豆网网站版权所有

经营许可证编号:鄂ICP备2022015515号-1