ukBaz / python-bluezero

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

Method to determinate current/negotiated MTU for connection #397

Closed vovagorodok closed 11 months ago

vovagorodok commented 11 months ago

I'm working on https://github.com/vovagorodok/ArduinoBleOTA library to support BLE software uploading for microcontrollers.

Is here easy way to determinate MTU connection size or negotiate it. With this information I'll simplify protocol a lot.

class Central should contain this method?

vovagorodok commented 11 months ago

In bleak found some workaround for BlueZ https://github.com/hbldh/bleak/blob/8a720ab835932c5a4f423fee157b300ca6021a6e/examples/mtu_size.py#L29

ukBaz commented 11 months ago

The goal of Bluezero was/is to provide a simplified API to people that want to use Bluetooth functionality in their code on Linux. The Bluezero development team accepts that as the user becomes more experienced they may not need Bluezero and will use BlueZ on its own.

I think your use case might be one such example. I suspect that you want the quickest throughput possible so would want to use AcquireWrite which is also not supported in the library.

For writing a client I would have thought Bleak was a better solution for you as it is cross platform.

vovagorodok commented 11 months ago

I already have script in bluezero: https://github.com/vovagorodok/ArduinoBleOTA/blob/main/tools/uploader.py and application in flutter https://github.com/vovagorodok/ble_ota_app.

I have plans to create additional script in Bleak, but haven't time for this moment. Quickest throughput is not most important for this moment (12kB/s is enough for this moment)

Important for me is to create simple and explicit protocol. Currently by protocol Peripheral send MTU size instead of get information about it on Central side directly.

Is here any way to get MTU size information on Central side using bluezero?

ukBaz commented 11 months ago

Since BlueZ 5.62 there has been a property on the GATT characteristic. https://git.kernel.org/pub/scm/bluetooth/bluez.git/tree/doc/gatt-api.txt?h=5.62#n297

I think that is what the following thread is about: https://github.com/bluez/bluez/issues/199

To access this in Bluezero the GATT file would need to be updated in a similar way to the other read-only properties. e.g: https://github.com/ukBaz/python-bluezero/blob/6db02adc16daeafd913b2cdf3d8e46ad10ccda2b/bluezero/GATT.py#L122-L130

If you didn't want to change the library you can access it by delving inside of the Central device. e.g:

from bluezero import central
from bluezero import constants
from bluezero import dbus_tools

LED_SRV = 'E95DD91D-251D-470A-A062-FA1922DFA9A8'
LED_TEXT = 'E95D93EE-251D-470A-A062-FA1922DFA9A8'

remote_device = central.Central('E1:4B:6C:22:56:F0')
led_text = remote_device.add_characteristic(LED_SRV, LED_TEXT)

remote_device.connect()

mtu = dbus_tools.dbus_to_python(led_text.characteristic_props.Get(constants.GATT_CHRC_IFACE, 'MTU'))
print(mtu)

content = b'test#'
if len(content) > mtu:
    print("error!!")
else:
    led_text.write_value(b'test#')
remote_device.disconnect()
vovagorodok commented 11 months ago

Hmm, I thought the MTU is a device property, not a characteristic

ukBaz commented 11 months ago

Hmm, I thought the MTU is a device property, not a characteristic

I think there is the L2CAP PDU which is typically 27 bytes and is set at the device level. Then there is then the ATT MTU which is typically 23 bytes and set for the characteristic. When I ran the experiment above I got a value of 23 bytes so I suspect it is the ATT MTU that it is being reported.

Anyway, I'm not sure what your point is with your statement. Bluezero's goal is to make getting started with BlueZ's D-Bus API easier. Bluezero can only build on what is made available by BlueZ. Your use-case feels like it is quite an advanced use-case and so possibly out of scope for this library.

I don't have your hardware or the time to dive in to this. If you do similar experiment to the one above, do you get a value larger than 23 bytes which is set by your peripheral? Isn't knowing the size what you need so you can split your writes up?

What help do you need from me?

vovagorodok commented 11 months ago

I just was curious why MTU is characteristic prop. As I see BlueZ request max possible MTU during connection.

My issue is solved by creating tx attribute with max possible size (MAX_MTU - 3 (WRITE_OPERATIOM_OVERHEAD)) in peripheral side.

Your example fully show how to get current MTU size. Lets close this issue. Thanks!