kevincar / bless

Cross-platform Bluetooth Low Energy Server Python Library
MIT License
86 stars 28 forks source link

Windows 10: Device does not support this function #63

Closed WouterJD closed 2 years ago

WouterJD commented 2 years ago

The problem examples/server.py does not work on an ASUS BT400 BLE dongle

Reproduction On windows 10: ..\examples\server.py

Expected behavior I hop server.py willl work, allowing to understand how to proceed.

Screenshots

Z:\Github\WouterJD\bless\wd-StartUp>..\examples\server.py
DEBUG:asyncio:Using proactor: IocpProactor
DEBUG:bless.backends.winrt.server:Creating a new service with uuid: A07498CA-AD5B-474E-940D-16F1FBE7E8CD
DEBUG:bless.backends.winrt.server:Adding service to server with uuid A07498CA-AD5B-474E-940D-16F1FBE7E8CD
DEBUG:__main__:51ff12bb-3ed8-46e5-b4f9-d64e2fec021b:
Traceback (most recent call last):
  File "Z:\Github\WouterJD\bless\examples\server.py", line 93, in <module>
    loop.run_until_complete(run(loop))
  File "C:\Users\Wouter Dubbeldam\AppData\Local\Programs\Python\Python38\lib\asyncio\base_events.py", line 612, in run_until_complete
    return future.result()
  File "Z:\Github\WouterJD\bless\examples\server.py", line 79, in run
    await server.start()
  File "\\lt-entertain\cdisk$\github\wouterjd\bless\bless\backends\winrt\server.py", line 91, in start
    service.service_provider.start_advertising(adv_parameters)
**OSError: [WinError -2147024580] Het apparaat ondersteunt de opdrachtfunctie niet**

Desktop (please complete the following information):

Additional context No additional information, using server.py out of the box.

Question though: at what moment does bless search-and-find a BLE-dongle and what messages/errors can be expected if there is no dongle or an incompatible one?

kevincar commented 2 years ago

Thanks @WouterJD,

What is your goal for using the dongle? Are you wanting to connect to other devices through it? For example, perhaps you're interested in connecting to a keyboard, mouse, phone, etc.? In which case you'd want to use bleak.

Bless uses WinRT to access windows API to broadcast bluetooth services that are searched for and picked up by other devices.

It's an interesting question though, I haven't investigated using a dongle to broadcast over if that is what you're attempting to do. Bless attempts to access your machine's bluetooth hardware here

One place to start looking is to determine if WinRT can detect the device for advertising.

WouterJD commented 2 years ago

Hi @kevincar, I want to create a trainer service to communicate with trainer software; advertise a Tacx trainer and then communicate with Zwift.

To understand bless, I execute examples/server.py which should - if I understand correctly - should educate me how to build such a server.

I started with Std Bluetooth on my laptop, but other windows implementations (node.js) require a separate dongle. Both give same result.

PS. What OS do you primarily work with?

WouterJD commented 2 years ago

Should e server.py run out-of-the-box?

WouterJD commented 2 years ago

One place to start looking is to determine if WinRT can detect the device for advertising

I've checked the links but did not find an answer yet. Physically the devices are correct, I can use them with node.js through the zadig device driver. On the system where I test, I use the std builtin hw OR the BLE dongle, which all results in the same error: "OSError: [WinError -2147024580]"

WouterJD commented 2 years ago

@kevincar Raising an issue on bleak https://github.com/hbldh/bleak/issues/739 did not help either. @dlech says: "I would suspect that the error message is telling you that the hardware is not capable of being a peripheral."

Central question is (if I may ask): on what systems do you expect (did you test) examples/server.py?

kevincar commented 2 years ago

@WouterJD

I want to create a trainer service to communicate with trainer software; advertise a Tacx trainer and then communicate with Zwift.

So to clarify, Zwift acts as the central device and Tacx acts as the peripheral device and you're attempting to use bless to broadcast/advertize Tacx from a Windows machine using the ASUS BT400 BLE dongle? You need to ensure that the ASUS BT400 is capable of broadcasting/advertising.

According to this, the ASUS BT400 is Bluetooth 4.0 compatible. It is unlikely this device is capable of what you want. I ran into this issue quite a bit 1-2 summers ago. Bluetooth Peripheral role support seems to be a rather recent feature for laptops and desktop computers, as of Bluetooth 4.2. Checkout this to see if your bluetooth adapter supports the peripheral role. As this stack overflow answer suggests, it's best to ensure that your device is Bluetooth 5.0 compatible.

Should e server.py run out-of-the-box? on what systems do you expect (did you test) examples/server.py?

Yes, if you're running on a system with peripheral role support. I've tested Bless on macOS, Windows 10, and Linux (Ubuntu on Raspberry Pi 4) and the examples/server.py run fine as long as bless is installed.

One way to check that you're actually able to do what you want is to try and run the following code on your windows machine.

# requires pip install winrt

import asyncio

from winrt.windows.devices.bluetooth import BluetoothAdapter

async def main():
    adapter = await BluetoothAdapter.get_default_async()
    print(adapter.is_peripheral_role_supported)

asyncio.run(main())

It's possible, though I haven't tested, that if your primary bluetooth adapter on your laptop does not support the peripheral role, then you can potentially access a dongle that does support it by looking up the device identifier under device manager. Then you can modify the code as such

# requires pip install winrt

import asyncio

from winrt.windows.devices.bluetooth import BluetoothAdapter

async def main():

    # Example ID
    id = "\\\\?\\USB#VID_8087&PID_0026#5&e4436ea&0&14#{92383b0e-f90e-4ac9-8d44-8c2d0d0ebda2}"
    adapter = await BluetoothAdapter.from_id_async(id)
    print(adapter.is_peripheral_role_supported)

asyncio.run(main())
WouterJD commented 2 years ago

Thanks for staying with me in this; I will do the tests as soon as I can.

Currently, FortiusAnt has a BLE-implementation using node.js which uses the zadig device driver and that works; hence the device itself is capable of doing the job....

I'll be back!

kevincar commented 2 years ago

Looking at the dependency tree for your project it's likely that node is able to do what you need because of this line here.

Notice how that in this case, the code is connecting directly to a USB device and not the native Bluetooth hardware.

Unfortunately, Bless doesn't yet support BLE from USB devices, but that would be a great feature to potentially add.

WouterJD commented 2 years ago

@kevincar thanks for this analysis.

Initially, FortiusAnt broadcasts ANT+ devices and because of upcoming importance of BLE, especially because ANT+ dongles are expensive and hard-to-come-by BLE has been added.

Since there is no python library to access Bluetooth, a node.js server is built. This requires a complex installation.

I was pointed to your library, which seemed to provide a solution. Looking at the provided functions, that is the case.

The standard Bluetooth devices cannot be used by node.js through the zadig driver) but the Asus dongle can be used.


What would be required for bless to use the Asus dongle?

WouterJD commented 2 years ago

Yes, if you're running on a system with peripheral role support. I've tested Bless on macOS, Windows 10, and Linux (Ubuntu on Raspberry Pi 4) and the examples/server.py run fine as long as bless is installed.

Apart from the reason why, this is all I try: run server.py. So: what do I miss on my windows 10 system?

(why did I run into the UUID problem and you did not?)

WouterJD commented 2 years ago
# requires pip install winrt

import asyncio

from winrt.windows.devices.bluetooth import BluetoothAdapter

async def main():
    adapter = await BluetoothAdapter.get_default_async()
    print(adapter.is_peripheral_role_supported)

asyncio.run(main())

Returns False for both the builtin bluetooth device as the ASUS BLE dongle

WouterJD commented 2 years ago

Reading the microsoft docs GATT and GAP roles were introduced in Windows 10 version 1703.

My system is: Windows 10 Pro Version 20H2 Installation date 29-12-2020 Build of OS 19042.1466 Experience Windows feature experience pack 120.2212.3920.0

20H2 is newer than the mentioned 1703, so that seems not be the issue either

WouterJD commented 2 years ago

Extending the sample code as follows

# requires pip install winrt

import asyncio

from winrt.windows.devices.bluetooth import BluetoothAdapter

async def main():
    adapter = await BluetoothAdapter.get_default_async()
    # https://docs.microsoft.com/en-us/uwp/api/windows.devices.bluetooth.bluetoothadapter?view=winrt-22000
    print("are_classic_secure_connections_supported",       adapter.are_classic_secure_connections_supported)
    print("are_low_energy_secure_connections_supported",    adapter.are_low_energy_secure_connections_supported)
    print("bluetooth_address",                              adapter.bluetooth_address)
    print("device_id",                                      adapter.device_id)
    print("is_advertisement_offload_supported",             adapter.is_advertisement_offload_supported)
    print("is_central_role_supported",                      adapter.is_central_role_supported)
    print("is_classic_supported",                           adapter.is_classic_supported)
    #print("is_extended_advertising_supported",             adapter.is_extended_advertising_supported)
    print("is_low_energy_supported",                        adapter.is_low_energy_supported)
    print("is_peripheral_role_supported",                   adapter.is_peripheral_role_supported)
    #print("max_advertisement_data_length",                 adapter.max_advertisement_data_length)

asyncio.run(main())

Produces for the Builtin Bluetooth device:

are_classic_secure_connections_supported=False
are_low_energy_secure_connections_supported=True
bluetooth_address=9064778070595
device_id=\\?\USB#VID_0A5C&PID_21E6#083E8EE07A43#{92383b0e-f90e-4ac9-8d44-8c2d0d0ebda2}
is_advertisement_offload_supported=False
is_central_role_supported=True
is_classic_supported=True
is_low_energy_supported=True
is_peripheral_role_supported=False

And for the ASUS BT400:

are_classic_secure_connections_supported=False
are_low_energy_secure_connections_supported=True
bluetooth_address=102200636312728
device_id=\\?\USB#VID_0B05&PID_17CB#5CF3709F8C98#{92383b0e-f90e-4ac9-8d44-8c2d0d0ebda2}
is_advertisement_offload_supported=False
is_central_role_supported=True
is_classic_supported=True
is_low_energy_supported=True
is_peripheral_role_supported=False

which is equal for both devices (apart from the address and id)

WouterJD commented 2 years ago

According to this, the ASUS BT400 is Bluetooth 4.0 compatible. It is unlikely this device is capable of what you want. I ran into this issue quite a bit 1-2 summers ago. Bluetooth Peripheral role support seems to be a rather recent feature for laptops and desktop computers, as of Bluetooth 4.2. Checkout this to see if your bluetooth adapter supports the peripheral role. As this stack overflow answer suggests, it's best to ensure that your device is Bluetooth 5.0 compatible.

Very good advice; I have ordered a "Vues Bluetooth 5.0 USB Adapter - Bluetooth Dongle - Audio Receiver - Transmitter - Bluetooth ontvanger - Windows 10 / 8.1 / 8/7 / XP" which by reviews is confirmed to be a Bluetooth 5.0 adapter.

[How node.js manages to make the ASUS BT400 work will remain their secret]

I'll be back as soon as I have tested the new adapter.

WouterJD commented 2 years ago

It's best to ensure that your device is Bluetooth 5.0 compatible

I have received the mentioned dongle and it works. Sorry for having bothered so much; I learned a lot in the meantime.

Thanks for patience and support