13 Replies Latest reply on Nov 25, 2014 10:32 AM by VictorZ_46 Branched to a new discussion.

    Check if bleprofile_sendNotification() was successful

    mkim

      Hello,

       

      In our use case, the application in Slave side calls bleprofile_sendNotification() to send data to Master.

      Sometime we are observing Master skips connection windows consecutively which results in buffer overflow in Slave side.

       

      Since the application in Slave side keeps calling bleprofile_sendNotification() without knowing the status of

      previous notification data (i.e., without checking if the previous data actually sent over the air),

      it seems like some of notification data are being lost.

       

      1) Is there any way for the application to check if bleprofile_sendNotification() was successfully queued?

      2) What is the max number of Notification data queued in BLE stack?

      3) Anyway to check if notification TX buffer is available before calling bleprofile_sendNotification()?

       

      Thanks!!

        • 1. Re: Check if bleprofile_sendNotification() was successful
          MichaelF_56

          I will ask one of the developers to respond when they have a chance.

          • 2. Re: Check if bleprofile_sendNotification() was successful
            VictorZ_46

            If blecm_getAvailableTxBuffers() is not zero you can call bleprofile_sendNotification and data will be certainly queued.  Check speed_test.c for example.

            1 of 1 people found this helpful
            • 3. Re: Check if bleprofile_sendNotification() was successful
              userc_6396

              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.

              • 4. Re: Check if bleprofile_sendNotification() was successful
                VictorZ_46

                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).

                1 of 1 people found this helpful
                • 5. Re: Check if bleprofile_sendNotification() was successful
                  userc_6396

                  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).

                  • 6. Re: Check if bleprofile_sendNotification() was successful
                    VictorZ_46

                    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.

                    • 7. Re: Check if bleprofile_sendNotification() was successful
                      userc_6396

                      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.
                      • 8. Re: Check if bleprofile_sendNotification() was successful
                        VictorZ_46

                        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.

                        • 9. Re: Check if bleprofile_sendNotification() was successful
                          userc_6396

                          Sorry,

                          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.

                          • 10. Re: Check if bleprofile_sendNotification() was successful
                            VictorZ_46

                            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,

                                                       LEGATTDB_PERM_READABLE, 7),

                             

                            Characteristic will need to have a client configuration descriptor, so that client can allow indications.  Something like

                             

                                CHAR_DESCRIPTOR_UUID16_WRITABLE (HANDLE_HELLO_SENSOR_CLIENT_CONFIGURATION_DESCRIPTOR,

                                                                 UUID_DESCRIPTOR_CLIENT_CHARACTERISTIC_CONFIGURATION,

                                                                 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[0] + (attrPtr[1] << 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.

                             

                                    if (!hello_sensor_indication_sent)

                                    {

                                        hello_sensor_indication_sent = TRUE;

                                        bleprofile_sendIndication(HANDLE_HELLO_SENSOR_VALUE_NOTIFY, (UINT8 *)db_pdu.pdu, db_pdu.len, hello_sensor_indication_cfm);

                                    }

                            • 11. Re: Check if bleprofile_sendNotification() was successful
                              mkim

                              >> 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.

                              • 12. Re: Check if bleprofile_sendNotification() was successful
                                VictorZ_46

                                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.

                                 

                                • 13. Re: Check if bleprofile_sendNotification() was successful
                                  mkim

                                  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.