I will ask one of the developers to respond when they have a chance.
1 of 1 people found this helpful
If blecm_getAvailableTxBuffers() is not zero you can call bleprofile_sendNotification and data will be certainly queued. Check speed_test.c for example.
Just to mention:
"Notifications" are unreliable. There is not any guarantee that Notification was received on client (Android, for instance). If you want to use a reliable approach: it would be "Indication". But this is not supported on WICED Sense FW, as for my knowledge.
So, there are two issues:
a) do not override Notification when in progress on device itself: I am a bit confused: if I see the code in wiced_sense_tx_opportunity_notice I would assume it is synchronous: if new Notification generated and kicked off to be sent (via timer) - code should progress when all Notification bytes are sent (the function call comes back, a synchronous function call). But I might be wrong. It might be possible that sending Notification message is asynchronous: it is just scheduled and if a new one should be sent, it might overwrite buffers of the previous one. No clue. Why there is not a semaphore around it or a clear comment that the call doing the Notification to be sent is "asynchronous"?
b) Even on server/device side all is fine, no guarantee that client (Android) will really receive all Notifications. It remains asynchronous between server and client: if client sends fast Notifications, it can happen that client will get just few of them, not in sequence, some lost in between. No flow control on Notifications, no back pressure between client (host) and server (device). Device has no clue if delivered properly, if and what is lost.
"Indication" (if supported on FW, I think it is not) would be better: it will send a new one just if previous one was acknowledged It will not send a new Indication if previous one was not acknowledged. But Notifications can overrun the client.
1 of 1 people found this helpful
You are indeed right. The notification is unreliable. Meanwhile it is guaranteed that if server radio sent the notification the client's radio receives it (or connection is lost). If your Android has enough CPU power to read data over UART and give to your application you should be good. Considering that your Android CPU is at least 50 times more powerful that of 20736 and UART is at least 3mbps with Bluetooth max of about 80kbps the probability is pretty low that you will miss a notification. This is all subject to your application being able to queue notification for transmission (see my previous post).
The indications are indeed supported by the FW. You just need to modify your database to change properties of your characteristic and use sendIndication function instead of sendNotification. Meanwhile you can send at least 4 notifications during one connection event. You can send only 1 indication over 2 connection events because each indication requires confirmation from the client. If connection interval is set to 6 frames (7.5 msec) the maximum you can send using notifications is 4 notifications * 20 bytes / 7.5 msec.Using indications it is 8 times less (1 * 20 / 15).
Cool, thank you.
Very helpful to me, to know that Indications are supported (even a code change needed, not generic just by changing the service definition). I like stuff like BGScript where defining an Indication will do automatically the handling of it. Here, I have to make sure changing from Notification to Indication on service and characteristic definition goes along with source code change - very hard to understand and to figure out (without any example or guideline doc).
You can check hello_sensor for example. It can send both. The client decides if it wants to receive notifications or indications by writing 0x01 or 0x02 into Characteristic Client Configuration descriptor of the characteristic.
Upps, I am lost.
I was talking about the WICED Sense FW. And what I see on code:
- sure, CCC bit 0 is for Nofication, bit 1 for Indication (as per BLE definition)
- But never mind: any value written, even 0x04 (invalid, reserved bit set) - it enables just the Notification to send
- I have never seen that bit 0 or bit 1 is evaluated, just if CCC value is not 0
- and I have verified: even you write 0x10 (invalid code) - it enables the Notification.
I do not see any FW code where it checks if Notification or Indication, just != 0.
If database allows only notifications to be set, there is no reason to check if the value is 0x01 or 0x02. Check hello_sensor application, maybe it will give you some clue.
sure, if 0x01 or 0x02 does not matter really if something needs to be sent. But where is the code to expect, to receive the ACK for an Indication (if I have written 0x02 instead of 0x01)?
And why 0x02 on CCC written is not denied if Characteristic is defined as Notification (what I see with a scanner)?
I would assume - I cannot subscribe to an "Indication" if not announced as such one.
Where is the code to make sure, if on "Indication" mode, the ACK was received before next Indication?
I do not see anything. So I assume, just Notifications are supported.
On the server side you need to have characteristic with indicate property. Something like
CHARACTERISTIC_UUID128 (0x0029, HANDLE_HELLO_SENSOR_VALUE_NOTIFY, UUID_HELLO_CHARACTERISTIC_NOTIFY,
LEGATTDB_CHAR_PROP_READ | LEGATTDB_CHAR_PROP_INDICATE,
Characteristic will need to have a client configuration descriptor, so that client can allow indications. Something like
LEGATTDB_PERM_READABLE | LEGATTDB_PERM_WRITE_REQ, 2),
In the write handler you need to process writes into the descriptor. You can also verify that client wrote 0x02
if ((len == 2) && (handle == HANDLE_HELLO_SENSOR_CLIENT_CONFIGURATION_DESCRIPTOR))
hello_sensor_hostinfo.characteristic_client_configuration = attrPtr + (attrPtr << 8);
if (hello_sensor_hostinfo.characteristic_client_configuration == CCC_INDICATION)
When you need to send data you need to verify that you have not sent indications. Because you cannot send more than 1 at a time.
hello_sensor_indication_sent = TRUE;
bleprofile_sendIndication(HANDLE_HELLO_SENSOR_VALUE_NOTIFY, (UINT8 *)db_pdu.pdu, db_pdu.len, hello_sensor_indication_cfm);
>> If blecm_getAvailableTxBuffers() is not zero you can call bleprofile_sendNotification and data will be certainly
>> queued. Check speed_test.c for example
Actually, our application has been checking blecm_getAvailableTxBuffers() and
ensuring TX buffer availability before calling bleprofile_sendNotification().
My gut feeling is there seems to be a max allowed number of Notification data queueing.
Data sent with bleprofile_sendNotification() after around 15 calling doesn't seem to go through over the air.
We are setting 50 TX buffers with blecm_setAvailableTxBuffers() during application init.
Do you really need to queue 50 transmissions? As you probably know 20736 does not have that much RAM. I suspect you running out of the buffers. You may try to play with memory pools used by the device. See
WICED-Smart-SDK\Wiced-Smart\tier2\brcm\libraries\inc\thread_and_mem_mgmt.h. But it might be better to figure out how not to use that much RAM.
We are queueing up to 20 Notification data at this moment even though setting 50 TX buffers.
This is Slave side of our use case and still enough RAM is left since there is not much codes.
I don't know how much memory is allocated per TX buffers.
Even if assuming 40 bytes each, 50 buffers are just 2K bytes of memory.