你好,
我们使用SDK 5.0.4的最新版本,并使用示例项目“ble_app_peripheral”创建了一个自定义概要文件,其中包含两个具有Notify属性的特征。我们定期从外部传感器接收数据,并使用通知更新数据库中相应的特征。除了确认之外,一切都正常工作。当我们逐一传送这两个特性的通知时,我们只会收到最后一个通知的确认。在移动应用程序上,数据被正确更新。在收到前一份通知的确认后,是否必须传送每一份新的通知?有没有一种方法可以跳过这种等待,而是让所有人都期待确认?
非常感谢你的回答。
设备:
嗨AngelT,
由于您正在发送两个通知,您应该收到的确认也应该是两个,一个用于每个句柄(一个用于您发送的不同特征的每个通知)。在确认前一个通知后发送下一个通知并不是强制性的,但这是最安全的方式,设备可以缓冲的通知数量有限,如果缓冲区满了,你继续发送通知,在某个时候,这些消息将存储在你的堆中,如果你继续发送通知(事实上,存储在堆上的通知不会将正确的值发送到你的中央),你的堆最终也会被填满,平台重置将会断言。因此,发送通知最安全的方式是等待确认,以避免连用。
由于MT_dialog
你好MT_dialog,
谢谢你的回答,但我们的测试显示有一点不同的行为。确认的数量(成功与否)总是等于通知的数量。问题是,当我们有两个或多个具有“Notify”属性的特征时,我们向这些特征发送了两个或多个通知(一个接一个),所有接收到的确认都是针对最后一个通知的特征。在这种情况下,我们的逻辑是否接收到每个特征的通知以及是否可以写入/通知新数据将不起作用。
顺便说一下,Dialog在DSPS项目中使用的通知方法也不适用于我们的案例。等待每一次确认都不是最好的解决方案,因为总是会有下一次
通知并降低连接的吞吐量。
嗨AngelT,
我不确定我是否完全理解这种情况,当你说一个接一个的时候,我认为在你发送通知后,你首先等待确认消息CUSTS1_VAL_NTF_CFM,然后你发送下一个相同的特征。即使您为相同的特性发送了两个通知,您也应该再次接受两个确认(fw应该响应两条CUSTS1_VAL_NTF_CFM消息)。你也可以测试这一个简单的项目和一些infastructure像ble_app_peripheral()可以使用按钮特点和发送通知通过第二个定时器和抓住这两个不同特点的确认(如下表示),您可以添加arch_set_pxact_gpio()函数,看着它通过智能片段电力分析器工具,功能应该迫使工具与垂直红线指示完成一个通知,所以你应该在每次推送后得到两条这样的线。
案例CUSTS1_VAL_NTF_CFM:
{
Struct custs1_val_ntf_cfm const *msg_param = (Struct custs1_val_ntf_cfm const *)(param);
开关(msg_param - >处理)
{
案例CUST1_IDX_ADC_VAL_1_VAL:
arch_set_pxact_gpio ();
打破;
案例CUST1_IDX_BUTTON_STATE_VAL:
arch_set_pxact_gpio ();
打破;
案例CUST1_IDX_LONG_VALUE_VAL:
打破;
默认值:
打破;
}
}打破;
由于MT_dialog
你好MT_dialog,
可能我的解释不正确。对不起。一个接一个意味着我们为第一个特征发送第一个通知,并立即为第二个特征发送第二个通知,而不需要等待第一个确认,期望稍后将为这两个通知接收2个单独的确认。是的,我们收到了这两个确认,但总是带有第二个/最后一个通知特性的句柄。这就是问题所在。
嗨AngelT,
正如我提到的,甚至,你会得到两个确认通知已经发送,如果你检查处理程序的CUSTS1_VAL_NTF_REQ custs1_val_ntf_req_handler()函数,您将看到,如果通知成功分配和放置在缓冲区有CUSTS1_VAL_NTF_CFM分配和发送到应用程序,如果你发送两个通知会有两个CUSTS1_VAL_NTF_CFM,一个用于您已更新的每个特性。如果你没有看到,在你的应用程序,当你得到CUSTS1_VAL_NTF_CFM,你检查从哪个特征的通知是从开关的情况下,我上面粘贴?您是否尝试在ble_app_peripheral这样的简单示例中复制您的问题?我能想到的唯一原因是,如果你正在经历这样的事情,你正在更新相同的特征,custs1_val_ntf_req的句柄成员在两个通知中是相同的。
由于MT_dialog
嗨MT_dialog,
这是我们预期的行为,但结果不同。同样,ALWAYS返回的确认是针对最后通知的特征。对于测试,我们使用带有两个不同特性的项目“ble_peripheral”,属性为“Notify”。根据我们的说法,问题在于变量“custs1_env”,它包含ntf_handle/ind_handle。你怎么看?我们说的对吗?
嗨AngelT,
我不知道它是如何发生的,就像我前面提到的CUSTS1_VAL_NTF_REQ处理custs1_val_ntf_req_handler()函数,这个函数如果你检查它会发送通知中央,它还将分配和发送(如果消息没有发送成功)CUSTS1_VAL_NTF_CFM,所以对于每个CUSTS1_VAL_NTF_REQ消息CUSTS1_VAL_NTF_CFM是发送(对于成功消息发送的CUSTS1_VAL_NTF_CFM将gattc_cmp_evt_handler())。在发生消息分配的custs1_val_ntf_req_handler()中,结构custs1_val_ntf_cfm填充了得到更新的句柄cfm->句柄= param->句柄(您从CUSTS1_VAL_NTF_REQ传递的句柄,此值也将更新custs1_env。ntf_enable以便从GATTC_CMP_EVT处理程序发送),因此消息CUSTS1_VAL_NTF_CFM,你将收到将有句柄参数的特征,你刚刚更新和发送通知,所以如果你发送两个CUSTS1_VAL_NTF_REQ,你将收到两个CUSTS1_VAL_NTF_CFM和句柄的消息返回将是更新的特征。这就是为什么在我上面指出的确认处理程序(开关情况)中,我正在检查我得到的每个CUSTS1_VAL_NTF_CFM的句柄。我不知道custs1_env和ntf_handle/ind_handle与它有什么关系。因为在成功发送通知的情况下,这些成员将在custs1_val_ntf_req_handler()中填充,并稍后用于发送确认消息。如果你粘贴关于我如何复制这个代码,例如,为了检查,我使用ble_app_peripheral并应用了以下mods。
在adc的同一个定时器处理程序上发送第二个通知(粘贴在第一个通知的ke_msg_send(msg)下):
/ * * /第二次通知
struct custs1_val_ntf_req* req_2 = KE_MSG_ALLOC_DYN(custs1_val_ntf_req
TASK_CUSTS1,
TASK_APP,
custs1_val_ntf_req,
DEF_CUST1_BUTTON_STATE_CHAR_LEN);
//需要采样的ADC值
静态uint16_t sample_2;
(Sample_2 <= 0xffff) ?(sample2 + 1): 0;
Req_2 ->conhdl = app_env->conhdl;
req_2->句柄= CUST1_IDX_BUTTON_STATE_VAL;
req_2->length = DEF_CUST1_BUTTON_STATE_CHAR_LEN;
memcpy(req_2->值,&sample_2, DEF_CUST1_BUTTON_STATE_CHAR_LEN);
ke_msg_send (req_2);
在user_peripherals.c文件中的user_catch_rest_hndl()中,我在CUST1_IDX_ADC_VAL_1_VAL和CUST1_IDX_BUTTON_STATE_VAL下面放置了一个arch_set_pxact_gpio(),以便从两个更新中捕获确认,即使你没有一个pro工具包来使用电源分析器,如果你放置一个断点,这两种情况应该一个接一个地发生。
由于MT_dialog
你好MT_dialog,
谢谢你这么详细的回答。这就是一个确切的例子。你是否计算了每个特征的确认次数(例如,2个通知,第一个特征1个确认,第二个特征1个确认)?如果第二次确认延迟,一切都会像你解释的那样正常工作。请参阅函数custs1_val_ntf_req_handler()中的代码。通过GATT - custs1_env发送指示。Ntf_handle = param->句柄;。第二个通知使用变量custs1_env。Ntf_handle将包含第二个特征的句柄。由于第一个确认将在第二个通知后由函数gattc_cmp_evt_handler()发送,所有确认将使用最后保存的句柄(第二个通知的句柄- cfm->handle = custs1_env.ntf_handle;)由为什么,在custs1_env的定义。ntf_hadle is written that this is the LAST handle.
最后,这种情况下的副作用是所有确认都是针对最后通知的特征,这非常令人不快。
嗨AngelT,
很抱歉,很明显你所提到的是有效的,我可以看到你所提到的正在发生,这是因为两个CUSTS1_VAL_NTF_REQ将运行,两个prf_server_send_event()将执行,但custs1_env。ntf_handle = param->句柄将只保留第二个句柄(使用断点显然是发出延迟,我想这就是为什么我可以在断开连接发生之前得到两个指示),据我所知,我也与SDK团队进行了检查,没有办法绕过这个,因为它是当前的SDK实现(GATTC_CMP_EVT消息,表示通知成功放置在缓冲区中,不包括通知发送的特征句柄,因此信息要么通过自定义配置文件任务填充,要么由应用程序本身填充),但您可以假设第一个通知已经被放置到缓冲区中以便发送。完成并推送一个额外的通知主要是为了保持缓冲区不溢出,但显然还有一个额外的用途。
如果您想这样做,您可以尝试更改custs1_env结构以及custs1_val_ntf_req_handler()处理程序,并为您发送的通知保留类似缓冲区的东西,以便跟踪您正在等待确认的特征。执行是串行的,这意味着无论哪个特征首先被通知,你都会得到确认。
由于MT_dialog
谢谢MT_dialog。
我们终于发现了真相。我希望我的问题的答案对这个论坛的所有成员都有用。我建议Dialog Semiconductyabo国际娱乐or在UM-B-050_DA1458x_Software_Developer's_Guide_1v1.pdf文档中包含这个特定的案例,因为所有示例项目都具有两个或多个属性为“Notify或Indicate”的特征。
祝你有愉快的一天。
嗨AngelT,
为了改善SDK未来版本的处理,我已经向SDK团队发出了罚单,如果你发现上面的任何答案都有帮助,请标记为已接受。
由于MT_dialog