Devices that do not include a service UUID in advertising data cannot be detected on macOS 12.0 to 12.2 unless running in app created by py2app
See original GitHub issue- bleak version: 0.14.0
- Python version: all
- Operating System: macOS 12.x
Description
This is basically the same issue as #635. That issue was closed because there is now a workaround available in Bleak v0.14.0 that works in most cases. However, there is one case that doesn’t have an acceptable workaround. If a device does not include a service UUID in the advertising data, then the advertising data from that device cannot be received in Bleak.
Call to action
This is a regression from previous versions of macOS. Please everyone report this issue to Apple using the Feedback Assistant app. If enough people report it, hopefully they will prioritize fixing it.
Workaround
This isn’t great, but it is possible to convert your Python script to an app using py2app to work around the issue. Here is an example setup.py
that can be uses as a starting point:
from setuptools import setup
setup(
app=["my_script.py"],
setup_requires=["py2app"],
options=dict(
py2app=dict(
plist=dict(
NSBluetoothAlwaysUsageDescription="This app uses Bluetooth.",
),
),
),
)
Then run python setup.py py2app
to build the .app.
If your script does not have a graphical user interface, you can run it with:
open -n -W --stdin $TTY --stdout $TTY --stderr $TTY dist/my_script.app
See man open
for more info.
Control C doesn’t work to stop the program, but you can secondary-click on the icon that is created in the dock and force quit if needed.
Issue Analytics
- State:
- Created 2 years ago
- Reactions:1
- Comments:6 (1 by maintainers)
Top GitHub Comments
Good news! It looks like Apple has fixed the issue in macOS 12.3 Beta (21E5196i).
I did a deep dive into the logs in Console.app (enabled debug and info messages and filtered on
bluetoothd
andpython
/my_script
processes) over the weekend and I think I have a pretty good understanding of the issue at this point. Following the advice of @arthurbiancarelli in https://github.com/hbldh/bleak/issues/635#issuecomment-981593036, I was able to successfully get things to work (scanning without specifying service uuids) when running Bleak in an app built withpy2app
. I also found a workaround so that you don’t have to create a graphical user interface (I updated the first comment in this issue with the workaround).My theory is that Apple is bringing macOS closer inline with iOS. So the comments in the CoreBluetooth docs about foreground and background scanning now apply to macOS as well.
In order for your Python script to be considered a foreground app, it has to be a .app with an icon in the dock (doesn’t necessarily have to have a visible window) and the app has to have a valid signature (done automatically by
py2app
).The reason scripts that are run in a terminal window fail is because the Python Framework includes a Python.app. The bluetoothd daemon sees that the process running your script is the Python.app but the foreground app is the Terminal.app, so it considers your Python script as a background app and therefore background scanning rules apply.
The reason Python includes a Python.app is so that it can launch programs that use graphical user interfaces. So you might think if you just open a window (i.e.
import turtle; turtle.showturtle()
), then your app should be the foreground app and all is good. However, this is where the second rule comes in. Bluetoothd sees that your script isn’t part of the Python.app bundle and therefore considers it not properly signed and so you don’t get foreground app treatment.Finally, the
NSBluetoothAlwaysUsageDescription
key ininfo.plist
is unrelated to the foreground/background scanning issue. If your app has already been given permission to use Bluetooth in System Prefereneces, thenNSBluetoothAlwaysUsageDescription
doesn’t have any effect. However, if your app has not been given permission, then havingNSBluetoothAlwaysUsageDescription
in yourinfo.plist
will prevent a crash fromSIGABRT
when your application is run.