0

I am doing a firmware upgrade of a BLE peripheral device based on ESP32 from an Android central. The firmware file is sent in parts of 512 bytes each. The ESP32 device (the GATT server) sends a notification to the central (GATT client) and the central sends the next part, followed by a write command to the peripheral. Then the next notification is sent and so on.

The upgrade works, however, it takes a long time to complete (~10-12 min for a 600kB file). I sniffed the traffic with Wireshark and it turned out there are 15-20 empty PDUs between the sending of each notification by the peripheral and the start of sending the part by the central. I searched what may be the problem on the server side but could not find anything relevant.

Maybe something is happening on the Android central that delays the sending process? Or maybe I am missing something with the ESP32? Here is a Wireshark capture (I’ve underlined in red where the sending should start):

enter image description here

EDIT: I haven't added extra sleep on server and if I had, there would be no empty server PDUs, correct?

I tried what you suggested, to use just android's internal mechanism for confirmation and the download is now about 3x faster. Thank you! However, in the captures there are some strange (to me) things like a lot of 26-byte response packets from the server to the master (captures below). Why is that and is it possible to combine them into 3 packets, the way they were sent from the master?

Also, about he explanation in the link you gave:

The Bluetooth controller sends a "number of packets complete" event back to Android's Bluetooth stack over HCI which indicates that the Link Layer of the remote's device has acknowledged a packet.

I didn't quite get that. If its a Write_No_Response from the master, how does the remote device acknowledge receiving a packet? And is this Android flow control mechanism a possible explanation of my original problem with the empty packets?

enter image description here

enter image description here

peter_s
  • 55
  • 2
  • 10

1 Answers1

1

Seems like the Android device is not fast enough, or you have added an extra sleep.

Assuming the peripheral can handle the data, you can quite reliably send write commands without using a notification acknowledging scheme. See onCharacteristicWrite and onNotificationSent are being called too fast - how to acquire real outgoing data rates?. Basically just wait for onCharacteristicWrite before sending the next one.

Emil
  • 16,784
  • 2
  • 41
  • 52
  • Hi, I put my comment as an edit to the post, because there is not enough space to post it as a comment. – peter_s Nov 23 '22 at 07:54
  • It seems you are not using the "Write Without Response" write type anymore, judging from the Prepare Write Requests? Empty PDUs are always sent as a response in every connection event if the peripheral does not have anything to send. The Link Layer (which is a lower layer than ATT) acknowledges all kind of packets, you can see that in the "next expected sequence number" in the header. – Emil Nov 23 '22 at 15:45
  • Yes, I'm using Write Request with Write Response, because as I understand, this is the only way the Android stack can get a confirmation, right? I know about the empty packets, but my question is why does the server now send so many 26-byte L2CAP response packets to the client, and not combine them into several big ones? – peter_s Nov 23 '22 at 19:39
  • Also, I remember looking at some wireshark captures where the server did have Latency set, and in the capture during the latency there were only master packets, so I assumed server does not send anything while sleeping. – peter_s Nov 23 '22 at 19:47
  • Please try Write Without Response. The link layer acknowledgements are enough for the flow control. Wait for onCharacteristicWrite before you send the next packet and you will be fine. Prepare Write Requests are really stupid and inefficient since they echo back the data and the central just discards them. Make sure though the MTU is big enough for your packets. – Emil Nov 23 '22 at 19:54
  • Thanks, it's now much faster. – peter_s Nov 29 '22 at 14:33