petzval / btferret

Python and C Bluetooth Library
MIT License
126 stars 22 forks source link

Bluetooth Classic server listening to any client? #17

Closed gregoiregentil closed 1 year ago

gregoiregentil commented 1 year ago

This is a great library. I have a case that doesn't seem to be fully supported: I would like to connect from an Android app using Bluetooth Classic. More important, the connection/pairing procedure needs to be initiated by the Android app. From my experiment, classic_server needs to know the Android remote address that it will accept connection from.

Why isn't it there a "classic_server(-1, ..." that would accept connection from any client?

The only strategy I see is to have Android to connect to BLE to btfferret, write to a characteristic or something so that btferret is aware of the Android address. Then connect from Android to classic_server(known_android_node,...)

Am I misunderstanding the library?

petzval commented 1 year ago

Thanks, this is a sensible suggestion that I have considered in the past. I'm planning a new release in the next couple of weeks, and I'll include this change if I can get it working reliably.

gregoiregentil commented 1 year ago

It's all the more important as I have just discovered that you can't get on Android its own Bluetooth Mac address (for security reasons).

petzval commented 1 year ago

Android sets a random Bluetooth address for BLE, and an Android app is not allowed to know it. But btferret can read it via le scan = b command. A BLE Android device can be included in the devices file and found via the MATCH NAME option (see 3.3 Devices file). On the other hand, an Android Classic address is fixed and can be found on the Android device via Settings/About/Status. It can also be read by a btferret device if the Android is made discoverable and classic scan = a command in btferret. The Android is then available to a btferret server. The address can be specified in the devices file. The MATCH NAME method will also work for classic connections.

gregoiregentil commented 1 year ago

On Android indeed, you can't any more get the bluetooth address programmatically as the API now returns 02:00:00:00:00:00. To my knowledge, the MATCH_NAME doesn't work with "DEVICE=*" so btferret needs to know something about Android.

For BLE, the device can be (peripheral) server and Android can connect to it as (central) client. The Android app only needs to know the BLE device name. There is no addresses or Android name involved.

Such scenario unfortunately doesn't work for Classic. Android can scan and sees the device Classic name, it can start a pairing action but btferret won't accept it as it's not in the device text file.

I believe that the scenario described is a very usual standard scenario (a phone connects to a device over Bluetooth). Bluez supports such scenario.

Is there a limitation for btferret to accept connect/pairing from any device?

petzval commented 1 year ago

btferret will accept a pairing if the Android is in the device info which can come from the devices file or from a classic scan. If the Android is discoverable it will be found by a scan and can then be paired. But I intend to add an "any device" option for classic servers.

gregoiregentil commented 1 year ago

Superb work! Thank you.