协议栈中的主机或从机的已连接事件并不表示主机与从机已准备好通讯
协议栈:BLE-CC254x-1.4.1.43908b
现象:
主机运行SimpleBLECentral,从机运行SimpleBLEPeripheral。
从机LCD已显示"Connected",说明从机已发生GAPROLE_CONNECTED事件;
主机在发生事件GAP_LINK_ESTABLISHED_EVENT且( pEvent->gap.hdr.status == SUCCESS )后,发送GATT_ReadUsingCharUUID后( simpleBLEDiscState == BLE_DISC_STATE_CHAR ),此时获得所需特征值的句柄,如果不做其他处理,simpleBLEDiscState = BLE_DISC_STATE_IDLE。按理说,此时主机从机已完成连接,可以通讯了。
问题是:此时,主机用GATT_WriteCharValue( simpleBLEConnHandle, &req, simpleBLETaskId );发送信息给从机,从机LCD未显示收到。开始以为代码有问题,反复查错,未发现问题。然后就试着重复用GATT_WriteCharValue发送信息给从机,印象里重复了57次(为了保险,重复次数后来增加到了60次),从机LCD才显示收到的信息。
需要解决的问题:如何通过事件的发生来判定主机和从机都准备好通讯了?
我也遇到同样的问题,主机获取到服务ID后,程序需要再等待一段时间(1秒内)才能与从机通信
Jun Xue,
理论上这样是没有问题的,另外你要注意GATT_WriteCharValue() 是需要等待对方回复的,不能疯狂发送。
建议你空中抓包看一下,是不是有问题。
问题是:我只想一次就发送成功!
所以想知道:主机发送GATT_ReadUsingCharUUID并在( simpleBLEDiscState == BLE_DISC_STATE_CHAR )进行句柄的处理后,立刻使用GATT_WriteCharValue() ,信息就一定能物理发送出去,只是从机还没准备好。我的判断对不对?
我没有协议分析仪,暂时无法判断。
Jun Xue,
从机不会有准备好还是没准备好的说法。只要句柄,写属性,长度都正确,就应该可以写。
建议你,不要在SimpleBLECentral_processGATTDiscEvent()函数里面去操作写。等服务查找彻底结束后再操作吧。你可以看一下central工程里面怎么通过按键去操作写的。
我只是为了叙述流程的先后,才那样写的。我没有在SimpleBLECentral_processGATTDiscEvent()函数里面去操作写!
我是看到示例程序中simpleBLEGATTDiscoveryEvent( gattMsgEvent_t *pMsg )函数在else if ( simpleBLEDiscState == BLE_DISC_STATE_CHAR )满足条件后的处理完成后,会设定simpleBLEDiscState = BLE_DISC_STATE_IDLE,判断这个BLE空闲状态表示主机/从机完成连接及特征值确认后对蓝牙的操作已完成,我就在此处使用了一个自定义的OSAL消息去处理发送单元缓冲区(几个字节)的一个信号单元。在消息处理函数中操作的GATT_WriteCharValue() 。只不过,我控制了消息处理函数进入60次才退出而已。
Y,谢谢你的回答。
在我的应用中,主机要求尽量节省电力,因此,每次的通讯建立/传送/断开的时间越短越好。所以我才提出通讯建立的判据的问题。
服务查找彻底结束后的判据是什么?不是if (simpleBLEDiscState == BLE_DISC_STATE_IDLE)么?
Y,你好!
还有一个问题:GATT_WriteCharValue() 执行后,会引起哪些事件?----你要我“注意GATT_WriteCharValue() 是需要等待对方回复的”,服务器的这个回复会触发哪些事件?
==================
此问题自我解答:
GATT_WriteCharValue() 执行后,本身不会触发事件(只要该函数返回SUCCESS,就表示请求发送成功),但从机服务器的回复会带来系统消息GATT_MSG_EVENT,见simpleBLECentral.c中的static void simpleBLECentral_ProcessOSALMsg( osal_event_hdr_t *pMsg );*pMsg包含从机回复的信息( pMsg->method == ATT_READ_RSP )或( ( pMsg->method == ATT_ERROR_RSP ) && ( pMsg->msg.errorRsp.reqOpcode == ATT_READ_REQ ) );只要收到以上信息,就表示GATT_WriteCharValue() 的处理过程完成。
试验的补充信息:
1、从机显示收到的信息是在函数simpleProfileChangeCB( uint8 paramID )里,说明只要从机接收到通过特征值传送的信息,就会有显示。
2、增加试验,将重复用GATT_WriteCharValue()发送信息给从机改为在消息处理函数中设定定时器事件去执行GATT_WriteCharValue()【只执行一次】,如果延时小于198ms从机都不会收到信息。如果设定延时大于190ms从机每次都会收到信息。
Y,你好!
你说的“从机不会有准备好还是没准备好的说法。只要句柄,写属性,长度都正确,就应该可以写。”是真的么?还是你的意思是“连接后的丢包问题不在讨论范围内”?
GATT服务实现的底层我们看不到,客户端发送的时候怎么保证服务端在读?服务端不能忙么?没有流控,又不知道服务端读的间隔参数,难不成你要客户端不停地发或设定一个不知道为何设定及如何设定时长的延时再发么?
此问题的诡异之处在于:
GATT_ReadUsingCharUUID(...)和GATT_WriteCharValue(...)都是请求从机服务器的服务,按理来说,他们的响应时间很接近。
GATT_WriteCharValue(...)是在GATT_ReadUsingCharUUID(...)触发的事件完全被处理结束后执行的。如果是一直处于连接状态且从机可以首次收到GATT_WriteCharValue(...)所写的信息并在LCD上显示之后,其后连续发送GATT_WriteCharValue(...)只要在每次收到ATT_WRITE_RSP之后,每次发送的信息都能立刻收到,感觉不到延迟。
而从机从LCD显示连接开始到可以首次收到GATT_WriteCharValue(...)所写的信息并在LCD上显示的时间间隔大约有1秒。
各种努力之后,从发现过程结束至空闲状态后,立即使用GATT_WriteCharValue(...)发送至从机成功接收的失败次数减少到了两次,第三次发送成功,前两次GATT_WriteCharValue(...)的返回值是0x16,第三次返回值是0,并且从机回复正确,从从机LCD显示已连接到从机LCD显示首次接收到的特征值,时间间隔大约是0.5秒。
初步认为,造成这种结果的原因是BLE-STACK 1.4.1未公开源码的部分存在设计缺陷。缺陷可能是以下两种情况之一:
1、刚建立连接的一段时间,从机服务器运行时因故未处于时刻准备接受数据的状态,存在无法收到数据的时间间隔,而此时间间隔未公开设定方法。
2、刚建立连接的一段时间,主机执行GATT_WriteCharValue(...)与某进程的结束存在依赖关系,造成GATT_WriteCharValue(...)的返回值是0x16。
类似的问题我也遇到了,刚建立连接获取到特征值,在几百毫秒的时间内不能进行通讯
由实验现象:GATT_WriteCharValue(...)的返回值先是0x16,几次调用后返回值变成是0x00,并且连接正常,且从机能收到信息的结果,可见:TI在此论坛的所谓专家对协议栈的了解也就半瓶水:
搜搜以前的帖子:对于此函数返回值是“0x16”的问题的回答,TI在此论坛的专家的意见一致,基本上都是:0X16表明您的设备已经断开连接。
还是希望由协议栈的开发者主导问题的回答,如果TI做不到,那就只有大家自己去反复实践摸索了。
也在关注这个问题,但我的现象跟你的不太一样。我用的是1.4.1协议栈,有大约10%的几率出现,当主机和从机建立连接后,马上GATT_WriteCharValue发送数据,就会造成从机断开连接,但是主机还没有提示。