ukBaz / python-bluezero

A simple Python interface to Bluez
MIT License
395 stars 112 forks source link

How to: Sending long/big data #337

Closed kishangondaliya closed 3 years ago

kishangondaliya commented 3 years ago

I'm using cpu_temperature.py example from bluezero to create GATT server.

Instead of sending cpu temperature value, I'm sending random text, around 1k bytes in read_value(). Connecting to this server via nRF app and reading characteristic gives value having length of MTU.

Dosen't it be handled by bluezero or by bluez? Like data framgementation. If no, what is best way to handle this? I had read in one of the issue where author says it should be handled by bluez but I'm not experiencing that.

ukBaz commented 3 years ago

I did investigate this recently for someone else but I can't find where that was.

The MTU is the maximum packet size of one write. Where as the write long characteristic value feature, permits a client to write more than ATT_MTU-3 bytes of data into a server’s characteristic value. It works by queuing several prepare write operations, each of which includes an offset and the data itself, and then finally writing them all atomically with an execute write operation.

My understanding is that BlueZ takes care of this "under the hood" although there looks like there has been a patch recently to GATT server around long notifications: https://marc.info/?l=linux-bluetooth&m=162358076129357&w=2

When I did my testing I used the ble_uart.py example and Serial Bluetooth Terminal

kishangondaliya commented 3 years ago

I was initially using ble_uart.py example and than later shifted to cpu_temperature.py as I was facing not getting notification issue in that(not sure why). But both example are almost similar. Right now I'm using hybrid kind of thing of both.

I also read somewhere that if your data length is same at MTU, client will assume there is more data and will read value again. I also experienced same thing like, when I read value, in server, read callback was called 3 times. As I had same code of sending big buffer in read function, nRF app side I can see 3 times same value (mtu size intial buffer). So probably nRF read data first time, it was MTU size, and than it read again and again. But I did not understand why only 3 times.

So probably fragmentation should be handled by user? I'm still confused and there is no clear description of this anywhere. Also strange thing is, in above scenario, if I enable notification, I'm only getting MTU size data not same as I read.

This all thing is happening because one of my device is negotiating MTU 185 with iOS device. Same device is negotiating MTU 517 with android. So, is there any way to set MTU through bluezero?

ukBaz commented 3 years ago

read callback was called 3 times

When it gets called the three times, what is the value offset in the options? https://github.com/ukBaz/python-bluezero/blob/392a115ace80a6d7257b76708ec24b99ec9e2e5d/examples/ble_uart.py#L38-L43

You would need that value to be able to put the data together.

kishangondaliya commented 3 years ago

I think there is some missunderstanding. This flow works perfect. When I send data from device (nRF app) to server (linux machine) it works perfect even if data is tooo long.

I get issue when I'm reading value from server (linux machine) using client (nRF app).

https://github.com/ukBaz/python-bluezero/blob/392a115ace80a6d7257b76708ec24b99ec9e2e5d/examples/cpu_temperature.py#L21-L36

Here, I'm modifying code to send 1k bytes.

kishangondaliya commented 3 years ago

I did one simple experiment, used ble_uart example as it is. Started the server. Connected through nRF app. Enabled notification. Sent data more than MTU (185 in my case) from app.

Result: I can get whatever data I send from app to server. But data server sends back, I only get of MTU length. Other data is trimmed. Now I want to solve this. This is very basic thing, not sure if I'm doing something wrong or this is really an issue in bluezero or bluez.

ukBaz commented 3 years ago

Thank you for the further clarification. I believe the issue is with the underlying BlueZ functionality.

Before reporting the issue to them it might be helpful if you base your experiments on their example code: https://git.kernel.org/pub/scm/bluetooth/bluez.git/tree/test/example-gatt-server

BlueZ contact information is at: http://www.bluez.org/contact/

ukBaz commented 3 years ago

@kishangondaliya Is there likely to be any update on this? Should I close the ticket?

kishangondaliya commented 3 years ago

@ukBaz you can close this. I was not able to find root cause nor I got any help from other forums. Used the hack for now to manage the functionality.