-
Notifications
You must be signed in to change notification settings - Fork 304
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
MacOS: scanning in new thread raises BleakError("Bluetooth device is turned off") #206
Comments
I have seen this same behavior on my Mac, trying to solve a similar
problem.
…On Mon, May 25, 2020 at 10:28 AM Dan Halbert ***@***.***> wrote:
- bleak version: 0.6.4
- Python version: 3.8.2
- Operating System: MacOS 10.15.4
- BlueZ version (bluetoothctl -v) in case of Linux:
Trying to do scanning in a new thread raises BleakError("Bluetooth device
is turned off"). Run the program below with and without --thread. In the
latter case, the error is raised, but the program works fine with
everything in the same thread.
Using BleakScanner rather than discover has the same problem.
This program runs fine on Linux with BlueZ.
This sounds sort of like #93 <#93>
and #125 <#125>, but those were
BlueZ problems. This stackoverflow Q&A may also be of interest, though I
don't know corebluetooth well enough to confirm:
https://stackoverflow.com/questions/48958267/how-can-i-use-corebluetooth-for-python-without-giving-up-the-main-thread
The reason I'm using a second thread is that I'm re-implementing an
existing non-async BLE API using bleak. I was using a fresh thread for
the bleak async side of things, and a janus queue to pass back scanning
results.
import asynciofrom bleak import discoverfrom threading import Threadimport argparse
parser = argparse.ArgumentParser()parser.add_argument('--thread', action='store_true')args = parser.parse_args()
async def scan():
devices = await discover()
for d in devices:
print(d)
def run():
asyncio.run(scan(), debug=True)
if args.thread:
print("in separate thread")
t = Thread(target=run)
t.start()
t.join()else:
print("in main thread")
loop = asyncio.get_event_loop()
loop.run_until_complete(scan())
—
You are receiving this because you are subscribed to this thread.
Reply to this email directly, view it on GitHub
<#206>, or unsubscribe
<https://github.com/notifications/unsubscribe-auth/AAVJBSN3OS2TJEPYOV7Z2M3RTKTFHANCNFSM4NJVTWUQ>
.
|
Relates to #105. On macOS , one should try to avoid using several threads/event loops in bleak, since the use of a global This needs to be put into the documentation about the macOS backend. |
I have the same problem. Even when using a different process for bleak, I get the same error. I tried both "spawn" and "fork". Do I understand it correctly that it is therefore not possible to execute bluetooth actions in the background of your program, e.g. waiting for a BLE notify while showing a loading bar to the user/running a gui? Maybe you could point us in the right direction for a fix? |
More data: even just a new event loop (as you implied/mentioned) causes the problem, without using a new thread. Using import asyncio
from bleak import discover
from threading import Thread
import argparse
parser = argparse.ArgumentParser()
parser.add_argument('--thread', action='store_true')
parser.add_argument('--run_until_complete', action='store_true')
parser.add_argument('--run', action='store_true')
args = parser.parse_args()
async def scan():
devices = await discover()
for d in devices:
print(d)
def run():
asyncio.run(scan(), debug=True)
if args.thread:
print("in separate thread")
t = Thread(target=run)
t.start()
t.join()
if args.run_until_complete:
print("run_until_complete in main thread")
loop = asyncio.get_event_loop()
loop.run_until_complete(scan())
if args.run:
print("run in main thread")
asyncio.run(scan()) |
Looking at bleak/bleak/backends/corebluetooth/__init__.py Lines 26 to 27 in 9c87ac0
I think a simple fix would be to lazily create the singleton when it's actually referenced for the first time, and have it use either the current event loop at that time, or perhaps optionally the loop passed in to I'll see if I can work up a PR for this. I see several un-merged corebluetooth PR's, but they don't appear to change how the singleton is created. |
@dhalbert I tried a few variations of the "changing which thread owns the singleton" approach without much success. Unfortunately I didn't have much time and can't be sure of the cause of the failure. Good luck! I hope you're able to find a solution |
I'm encountering the same issue. Is there a reason to use a global |
@superfashi I think a manager per client can probably work ok based on some threads in Apple's forums. Right now both discovery and clients use the shared Application. There are some minor potential benefits, like allowing peripherals to be cached for faster connecting, although this isn't done in the released version. There would be other ways around this too, like having a client's |
The following code doesn't even seem to work, which I found really confusing: import asyncio
async def run():
from bleak import discover
print(await discover())
loop = asyncio.get_event_loop()
loop.run_until_complete(run()) |
This issue will be worked on 2020-06-30, so any additional information that can be added here before that is very welcome. |
I'm not sure how useful this would be, but I'll explain the context for my original report. We are using bleak to (partially) reimplement The more identically things work on the these four platforms, the better. We want a single program to be runnable across all four. Obviously some things don't work, such as acting as a peripheral. We also have issues with scanning: the bluez kernel support does de-duplication of advertisements, which is undesirable when advertising is used for changing data transmissions, so we have to use privileged
We are very grateful for bleak, which has allowed us to provide this cross-platform support without having to deal with the native libraries on each platform. |
I had the same error as the title of this issue without using threads. The changes I made in pybricks@26ab00f and pybricks@0b37282 fixed the issue for me. But ideally it would be nice to get rid of the global (@dhalbert in case you haven't seen, it looks like BlueZ is getting better advertisement support: https://github.com/bluez/bluez/blob/master/doc/advertisement-monitor-api.txt - might be good to make sure it does what is needed while it is still experimental) |
I also ran into this issue and fought with it quite a bit. I was able to
get the error to go away after some hackery, but was never actually able to
achieve full functionality of bleak in a thread. Happy to help any way I
can, this is also a high priority item for me. I was planning to knock it
out in July if you don't come up with a fix by then.
…On Wed, Jun 24, 2020 at 8:24 AM David Lechner ***@***.***> wrote:
I had the same error as the title of this issue without using threads. The
changes I made in ***@***.***
<pybricks@26ab00f>
and ***@***.***
<pybricks@0b37282>
fixed the issue for me. But ideally it would be nice to get rid of the
global CBAPP object. It causes other os-specific quirks like #111
<#111>.
***@***.*** <https://github.com/dhalbert> in case you haven't seen, it
looks like BlueZ is getting better advertisement support:
https://github.com/bluez/bluez/blob/master/doc/advertisement-monitor-api.txt
- might be good to make sure it does what is needed while it is still
experimental)
—
You are receiving this because you commented.
Reply to this email directly, view it on GitHub
<#206 (comment)>, or
unsubscribe
<https://github.com/notifications/unsubscribe-auth/AAVJBSMFLIGY5LGJL7BTGTLRYILDHANCNFSM4NJVTWUQ>
.
--
*Chad Spensky*
*Founder and CEO*
*Allthenticate, Inc.*
|
This removes the global Application() class in the corebluetooth backend. Instead, a new central manager is created for each scanner object. Since an instance of the `Application()` was created on module import, it could interfere with other code like introspection tools that don't actually want to run `bleak`. This also fixes running `bleak` in threads (hbldh#206).
FYI, I've added pybricks@1b04383 and pybricks@f11a2e1 to our fork which gets the example program in #206 (comment) working in the thread. Still a bit of work left to do to reconcile it with the other proposes changes to the corebluetooth backend, but it probably wouldn't hurt to try it out if anyone is interested. |
This removes the global Application() class in the corebluetooth backend. Instead, a new central manager is created for each scanner object. Since an instance of the `Application()` was created on module import, it could interfere with other code like introspection tools that don't actually want to run `bleak`. This also fixes running `bleak` in threads (hbldh#206).
This removes the global Application() class in the corebluetooth backend. Instead, a new central manager is created for each scanner object. Since an instance of the `Application()` was created on module import, it could interfere with other code like introspection tools that don't actually want to run `bleak`. This also fixes running `bleak` in threads (hbldh#206).
This removes the global Application() class in the corebluetooth backend. Instead, a new central manager is created for each scanner object. Since an instance of the `Application()` was created on module import, it could interfere with other code like introspection tools that don't actually want to run `bleak`. This also fixes running `bleak` in threads (hbldh#206).
This removes the global Application() class in the corebluetooth backend. Instead, a new central manager is created for each scanner object. Since an instance of the `Application()` was created on module import, it could interfere with other code like introspection tools that don't actually want to run `bleak`. This also fixes running `bleak` in threads (hbldh#206).
I have tested this issue both with threads and with event loops after merging #227 to |
@dhalbert I have looked at The scanning issue that you are mentioning, could you please open a separate issue for that, because that is something I did not know about. I have been getting |
Trying to do scanning in a new thread raises
BleakError("Bluetooth device is turned off")
. Run the program below with and without--thread
. In the latter case, the error is raised, but the program works fine with everything in the same thread.Using
BleakScanner
rather thandiscover
has the same problem.This program runs fine on Linux with BlueZ, and on Windows 10 with Python 3.7.7 and pythonnet.
This sounds sort of like #93 and #125, but those were BlueZ problems. This stackoverflow Q&A may also be of interest, though I don't know corebluetooth well enough to confirm: https://stackoverflow.com/questions/48958267/how-can-i-use-corebluetooth-for-python-without-giving-up-the-main-thread
The reason I'm using a second thread is that I'm re-implementing an existing non-
async
BLE API using bleak. I was using a fresh thread for the bleakasync
side of things, and ajanus
queue to pass back scanning results.The text was updated successfully, but these errors were encountered: