在我们的自定义配置文件中,我们有一个由客户端/中心设备在空中编写的特征。这个特征在user_custs1_def.h中定义为CHAR_LEN为254(这是它应该达到的最大大小)。在测试中,我们发现只要新的写入值在长度上等于或小于之前的写入值,那么一切都可以正常工作。但是,如果新值比先前写入的值长(即使新值仍然比初始的CHAR_LEN 254短得多),写入就会失败,系统的行为开始变得不稳定。例如,对该特性进行较长时间的写入后,该特性就不能通过空中读取,与客户机的连接变得不稳定。
在编写较长的字符串的情况下,custs1_task.c中的gattc_write_req_ind_handler()函数从未被调用,因此问题发生在代码的这一点之前。
我们如何实现所需的功能?也就是说,一个可以从客户端获取任何值(最多254字节)的可写特征,而不管该特征的当前内容是什么?
设备:
嗨mkelwood,
似乎写一个比之前写的价值更大的特征值,不是问题,我不能复制它。在DSPS中,你可以有你想要的功能,所以请检查这些特性是如何在这个项目中实现的。
谢谢,PM_Dialog
你好PM_Dialog,
谢谢你的回复。我有一些额外的信息。我对这个问题的最初结论是错误的;并不是比以前写的时间长导致了这个问题。相反,它的写入长度大于(MTU - 3)字节,这需要写入长特征值过程(蓝牙规范5.0 Vol 3 Part G section 4.9.4)。
我已经附上了OTA捕获文件显示问题的截图。DA14585为从设备(GATT服务器)。目标特征有处理53。在连接和发现之后,我向特征写入一个短值(长度小于MTU - 3),它成功了(参见帧4468和4473)。我读回了正确的值(帧6926和6932)。然后我尝试写一个21字节长的值(比MTU - 3多一个字节)。GATT客户端发送一个Prepare write Request(帧7334,突出显示的帧),没有来自DA14585的响应。奴隶现在是破碎的和无反应的。
我已经尝试将目标特征权限设置为WRITE_REQ和WRITE_COMMAND。附加的捕获具有WRITE_REQ权限。使用WRITE_COMMAND, GATT客户端不会让我写一个长值到特征(它抱怨坏参数)。
所以我现在的问题是,为什么写长特征值程序不工作?为什么DA14585不响应准备写响应?我是否需要做任何特殊的事情来支持从GATT服务器端准备写/执行写序列?
谢谢你的帮助!
我更新到SDK 6.0.10.511;写长特征值的问题仍然存在。设备无法响应来自中央的Prepare Write Request,设备在断开/重新连接之前是无响应的。
嗨mkelwood,
如果您不使用或不想使用MTU交换,您应该实现写长特征值作为SDK的ble_app_peripheral示例中的实现。请看看SDK的这个例子。如果要写入的特征值的长度大于20字节,则会触发user_catch_rest_hndl()函数中的user_svc1_long_val_att_info_req_handler()。如果长度小于20字节,将执行user_svc1_long_val_wr_ind_handler()。因此,如果希望在不进行MTU交换的情况下发送超过20个字节,则应该执行与ble_app_peripheral示例中的user_svc1_long_val_att_info_req_handler()函数相同的实现。因为你这样做,主服务器将发送一个“准备写请求”,从服务器将响应一个“准备写响应”。否则,如果您希望执行一个简单的写请求并发送超过20个字节,则应该增加MTU大小。
谢谢,PM_Dialog
谢谢PM_Dialog提供的这些信息!我已经按照您的建议实现了att_info_req_handler代码,这解决了写长特征值的问题。wr_ind_handler在接收到EXECUTE WRITE命令后仍然被调用;这是预期和首选的行为。
我从来没有想到att_info_req_handler是编写长特征的代码。即使看到ble_app_peripheral应用程序中的代码,我也不会在这个和Prepare Write/Execute Write序列之间建立连接。我在Dialog或Riviera Waves的文档中都找不到这方面的文档。我希望有更好的文档关于这些更模糊的回调。
嗨mkelwood,
很高兴你把问题解决了。
谢谢,PM_Dialog