Closed lbussy closed 2 years ago
Bleak does not require using sudo
. Do you get the same results if you run without sudo
?
Thank you for the reply.
Running scanner.py as a regular user gives me:
$ ./scanner.py
Traceback (most recent call last):
File "./scanner.py", line 12, in <module>
loop.run_until_complete(run())
File "/usr/lib/python3.7/asyncio/base_events.py", line 584, in run_until_complete
return future.result()
File "./scanner.py", line 7, in run
devices = await BleakScanner.discover()
File "/usr/local/lib/python3.7/dist-packages/bleak/backends/scanner.py", line 83, in discover
async with cls(**kwargs) as scanner:
File "/usr/local/lib/python3.7/dist-packages/bleak/backends/scanner.py", line 63, in __aenter__
await self.start()
File "/usr/local/lib/python3.7/dist-packages/bleak/backends/bluezdbus/scanner.py", line 123, in start
).asFuture(loop)
txdbus.error.RemoteError: org.freedesktop.DBus.Error.AccessDenied: Rejected send message, 2 matched rules; type="method_call", sender=":1.14" (uid=1000 pid=494 comm="python3 ./scanner.py ") interface="org.freedesktop.DBus.ObjectManager" member="GetManagedObjects" error name="(unset)" requested_reply="0" destination="org.bluez" (uid=0 pid=359 comm="/usr/lib/bluetooth/bluetoothd ")
With sudo:
$ sudo ./scanner.py
56:1D:FF:FE:90:74: 56-1D-FF-FE-90-74
2F:EC:10:83:7A:C3: 2F-EC-10-83-7A-C3
4C:B1:78:F5:61:62: 4C-B1-78-F5-61-62
FC:8F:90:A6:1B:EC: FC-8F-90-A6-1B-EC
49:6F:02:31:8A:7F: 49-6F-02-31-8A-7F
6B:A0:AF:3E:0D:87: 6B-A0-AF-3E-0D-87
04:C6:51:E4:E1:EA: 04-C6-51-E4-E1-EA
74:9C:3F:D2:0D:A9: 74-9C-3F-D2-0D-A9
28:2C:02:B4:D0:0E: R+_24_282C02B4D00E
50:65:83:6D:B2:5C: 50:65:83:6D:B2:5C <--- This is the target this time
74:E7:7D:A6:BF:A6: 74-E7-7D-A6-BF-A6
75:4F:36:19:0C:70: 75-4F-36-19-0C-70
B8:BC:5B:61:AC:1A: B8-BC-5B-61-AC-1A
F4:BC:DA:32:96:39: D7881F01D551
FC:5E:BC:EF:17:64: FC-5E-BC-EF-17-64
Running service_explorer without sudo:
$ ./service_explorer.py
Executing <Task pending coro=<run() running at ./service_explorer.py:27> wait_for=<Future pending cb=[Deferred.asFuture.<locals>.checkCancel() at /usr/local/lib/python3.7/dist-packages/twisted/internet/defer.py:786, <TaskWakeupMethWrapper object at 0xb5a3ee70>()] created at /usr/lib/python3.7/asyncio/base_events.py:396> cb=[_run_until_complete_cb() at /usr/lib/python3.7/asyncio/base_events.py:158] created at /usr/lib/python3.7/asyncio/base_events.py:563> took 0.441 seconds
Traceback (most recent call last):
File "./service_explorer.py", line 64, in <module>
loop.run_until_complete(run(address, True))
File "/usr/lib/python3.7/asyncio/base_events.py", line 584, in run_until_complete
return future.result()
File "./service_explorer.py", line 27, in run
async with BleakClient(address) as client:
File "/usr/local/lib/python3.7/dist-packages/bleak/backends/client.py", line 59, in __aenter__
await self.connect()
File "/usr/local/lib/python3.7/dist-packages/bleak/backends/bluezdbus/client.py", line 95, in connect
self.address, timeout=timeout, adapter=self._adapter
File "/usr/local/lib/python3.7/dist-packages/bleak/backends/scanner.py", line 167, in find_device_by_address
timeout=timeout, detection_callback=stop_if_detected, **kwargs
File "/usr/local/lib/python3.7/dist-packages/bleak/backends/scanner.py", line 63, in __aenter__
await self.start()
File "/usr/local/lib/python3.7/dist-packages/bleak/backends/bluezdbus/scanner.py", line 123, in start
).asFuture(loop)
txdbus.error.RemoteError: org.freedesktop.DBus.Error.AccessDenied: Rejected send message, 2 matched rules; type="method_call", sender=":1.16" (uid=1000 pid=511 comm="python3 ./service_explorer.py ") interface="org.freedesktop.DBus.ObjectManager" member="GetManagedObjects" error name="(unset)" requested_reply="0" destination="org.bluez" (uid=0 pid=359 comm="/usr/lib/bluetooth/bluetoothd ")
With sudo:
sudo ./service_explorer.py
Executing <Task pending coro=<run() running at ./service_explorer.py:27> wait_for=<Future pending cb=[Deferred.asFuture.<locals>.checkCancel() at /usr/local/lib/python3.7/dist-packages/twisted/internet/defer.py:786, <TaskWakeupMethWrapper object at 0xb5b06cf0>()] created at /usr/lib/python3.7/asyncio/base_events.py:396> cb=[_run_until_complete_cb() at /usr/lib/python3.7/asyncio/base_events.py:158] created at /usr/lib/python3.7/asyncio/base_events.py:563> took 0.317 seconds
Executing <Handle callWithLogger(<twisted.inte...at 0xb5b7eeb0>, <bound method...t 0xb5b7eab0>>, <twisted.inte...at 0xb5b7eeb0>, True) at /usr/local/lib/python3.7/dist-packages/twisted/python/log.py:90 created at /usr/lib/python3.7/asyncio/selector_events.py:249> took 0.116 seconds
(and then it just repeats)
I did add the user to dialout
, logout, and login, no changes in the results.
I think the user needs to be added to the bluetooth
group rather than dialout
. See #9.
I did not see anything in #9 about that, however, did find #228, #356, and #358 which echoed your suggestion. I added my user to bluetooth
and restarted bluetoothd and as you probably already suspect, I am able to run scanner.py
as my regular user.
Running service_explorer.py
as the regular user gives me a different error now at least:
Executing <Task pending coro=<run() running at ./service_explorer.py:27> wait_for=<Future pending cb=[Deferred.asFuture.<locals>.checkCancel() at /usr/local/lib/python3.7/dist-packages/twisted/internet/defer.py:786, <TaskWakeupMethWrapper object at 0xb5af0e90>()] created at /usr/lib/python3.7/asyncio/base_events.py:396> cb=[_run_until_complete_cb() at /usr/lib/python3.7/asyncio/base_events.py:158] created at /usr/lib/python3.7/asyncio/base_events.py:563> took 0.280 seconds
Traceback (most recent call last):
File "./service_explorer.py", line 64, in <module>
loop.run_until_complete(run(address, True))
File "/usr/lib/python3.7/asyncio/base_events.py", line 584, in run_until_complete
return future.result()
File "./service_explorer.py", line 27, in run
async with BleakClient(address) as client:
File "/usr/local/lib/python3.7/dist-packages/bleak/backends/client.py", line 59, in __aenter__
await self.connect()
File "/usr/local/lib/python3.7/dist-packages/bleak/backends/bluezdbus/client.py", line 161, in connect
await self.get_services()
File "/usr/local/lib/python3.7/dist-packages/bleak/backends/bluezdbus/client.py", line 390, in get_services
raise BleakError("Services discovery error")
bleak.exc.BleakError: Services discovery error
The await self.get_services()
part has me curious. Is the MAC in the example supposed to be changed to the target device?
if __name__ == "__main__":
address = ("50:65:83:6D:B2:5C")
loop = asyncio.get_event_loop()
loop.set_debug(True)
loop.run_until_complete(run(address, True))
No idea where I got #9
from but whatever I was looking at was similar to the issues you found anyway.
Yes, you need to change the sample to match the address of the device you want as it looks like you have done.
That error looks like it is a timeout trying to resolve services:
You could try a branch I am working on instead of v0.10.0:
pip install --force-reinstall https://github.com/hbldh/bleak/archive/dbus-next-2.zip#egg=bleak
Not sure if it will make a difference or not but it changes the code where the error is happening.
Okay, so some progress. I spun up a quick ESP32 to serve a BLEacon. service_discovery.py
yielded the following:
$ ./service_explorer.py
Executing <Task pending coro=<run() running at ./service_explorer.py:27> wait_for=<Future pending cb=[<TaskWakeupMethWrapper object at 0xb5a97bb0>()] created at /usr/lib/python3.7/asyncio/base_events.py:396> cb=[_run_until_complete_cb() at /usr/lib/python3.7/asyncio/base_events.py:158] created at /usr/lib/python3.7/asyncio/base_events.py:563> took 0.170 seconds
Executing <Handle MessageBus._message_reader() created at /usr/lib/python3.7/asyncio/selector_events.py:249> took 0.139 seconds
Executing <Handle MessageBus._message_reader() created at /usr/lib/python3.7/asyncio/selector_events.py:249> took 0.118 seconds
Executing <Handle MessageBus._message_reader() created at /usr/lib/python3.7/asyncio/selector_events.py:249> took 0.139 seconds
Connected: True
[Service] 00001801-0000-1000-8000-00805f9b34fb: Generic Attribute Profile
[Characteristic] 00002a05-0000-1000-8000-00805f9b34fb: (Handle: 2) (indicate) | Name: Service Changed, Value: None
[Descriptor] 00002902-0000-1000-8000-00805f9b34fb: (Handle: 4) | Value: b'\x02\x00'
Task was destroyed but it is pending!
source_traceback: Object created at (most recent call last):
File "./service_explorer.py", line 64, in <module>
loop.run_until_complete(run(address, True))
File "/usr/lib/python3.7/asyncio/base_events.py", line 571, in run_until_complete
self.run_forever()
File "/usr/lib/python3.7/asyncio/base_events.py", line 539, in run_forever
self._run_once()
File "/usr/lib/python3.7/asyncio/base_events.py", line 1767, in _run_once
handle._run()
File "/usr/lib/python3.7/asyncio/events.py", line 88, in _run
self._context.run(self._callback, *self._args)
File "./service_explorer.py", line 27, in run
async with BleakClient(address) as client:
File "/usr/local/lib/python3.7/dist-packages/bleak/backends/client.py", line 59, in __aenter__
await self.connect()
File "/usr/local/lib/python3.7/dist-packages/bleak/backends/bluezdbus/client.py", line 261, in connect
asyncio.create_task(self._disconnect_monitor())
File "/usr/lib/python3.7/asyncio/tasks.py", line 325, in create_task
return loop.create_task(coro)
task: <Task pending coro=<BleakClientBlueZDBus._disconnect_monitor() running at /usr/local/lib/python3.7/dist-packages/bleak/backends/bluezdbus/client.py:282> wait_for=<Future pending cb=[<TaskWakeupMethWrapper object at 0xb5949eb0>()] created at /usr/lib/python3.7/asyncio/base_events.py:396> created at /usr/lib/python3.7/asyncio/tasks.py:325>
Connecting to my intended device failed however:
$ ./service_explorer.py
Executing <Task pending coro=<run() running at ./service_explorer.py:27> wait_for=<Future pending cb=[<TaskWakeupMethWrapper object at 0xb5acdc30>()] created at /usr/lib/python3.7/asyncio/base_events.py:396> cb=[_run_until_complete_cb() at /usr/lib/python3.7/asyncio/base_events.py:158] created at /usr/lib/python3.7/asyncio/base_events.py:563> took 0.164 seconds
ERROR:root:A message handler raised an exception: 'Address'.
Traceback (most recent call last):
File "/usr/local/lib/python3.7/dist-packages/dbus_next/message_bus.py", line 656, in _process_message
result = handler(msg)
File "/usr/local/lib/python3.7/dist-packages/bleak/backends/bluezdbus/scanner.py", line 294, in _parse_msg
props["Address"], props["Alias"], props, props.get("RSSI", 0)
KeyError: 'Address'
WARNING:asyncio:Executing <Handle MessageBus._message_reader() created at /usr/lib/python3.7/asyncio/selector_events.py:249> took 0.286 seconds
ERROR:root:A message handler raised an exception: 'Address'.
Traceback (most recent call last):
File "/usr/local/lib/python3.7/dist-packages/dbus_next/message_bus.py", line 656, in _process_message
result = handler(msg)
File "/usr/local/lib/python3.7/dist-packages/bleak/backends/bluezdbus/scanner.py", line 294, in _parse_msg
props["Address"], props["Alias"], props, props.get("RSSI", 0)
KeyError: 'Address'
{Same error message x 10}
WARNING:asyncio:Executing <Handle MessageBus._message_reader() created at /usr/lib/python3.7/asyncio/selector_events.py:249> took 0.168 seconds
ERROR:root:A message handler raised an exception: 'Address'.
Traceback (most recent call last):
File "/usr/local/lib/python3.7/dist-packages/dbus_next/message_bus.py", line 656, in _process_message
result = handler(msg)
File "/usr/local/lib/python3.7/dist-packages/bleak/backends/bluezdbus/scanner.py", line 294, in _parse_msg
props["Address"], props["Alias"], props, props.get("RSSI", 0)
KeyError: 'Address'
{Same error message x 10}
WARNING:asyncio:Executing <Handle MessageBus._message_reader() created at /usr/lib/python3.7/asyncio/selector_events.py:249> took 0.123 seconds
ERROR:root:A message handler raised an exception: 'Address'.
Traceback (most recent call last):
File "/usr/local/lib/python3.7/dist-packages/dbus_next/message_bus.py", line 656, in _process_message
result = handler(msg)
File "/usr/local/lib/python3.7/dist-packages/bleak/backends/bluezdbus/scanner.py", line 294, in _parse_msg
props["Address"], props["Alias"], props, props.get("RSSI", 0)
KeyError: 'Address'
WARNING:asyncio:Executing <Handle MessageBus._message_reader() created at /usr/lib/python3.7/asyncio/selector_events.py:249> took 0.250 seconds
ERROR:root:A message handler raised an exception: 'Address'.
Traceback (most recent call last):
File "/usr/local/lib/python3.7/dist-packages/dbus_next/message_bus.py", line 656, in _process_message
result = handler(msg)
File "/usr/local/lib/python3.7/dist-packages/bleak/backends/bluezdbus/scanner.py", line 294, in _parse_msg
props["Address"], props["Alias"], props, props.get("RSSI", 0)
KeyError: 'Address'
{Same error message x 4}
WARNING:asyncio:Executing <Handle MessageBus._message_reader() created at /usr/lib/python3.7/asyncio/selector_events.py:249> took 0.102 seconds
ERROR:root:A message handler raised an exception: 'Address'.
Traceback (most recent call last):
File "/usr/local/lib/python3.7/dist-packages/dbus_next/message_bus.py", line 656, in _process_message
result = handler(msg)
File "/usr/local/lib/python3.7/dist-packages/bleak/backends/bluezdbus/scanner.py", line 294, in _parse_msg
props["Address"], props["Alias"], props, props.get("RSSI", 0)
KeyError: 'Address'
WARNING:asyncio:Executing <Handle MessageBus._message_reader() created at /usr/lib/python3.7/asyncio/selector_events.py:249> took 0.155 seconds
Traceback (most recent call last):
File "./service_explorer.py", line 64, in <module>
loop.run_until_complete(run(address, True))
File "/usr/lib/python3.7/asyncio/base_events.py", line 584, in run_until_complete
return future.result()
File "./service_explorer.py", line 27, in run
async with BleakClient(address) as client:
File "/usr/local/lib/python3.7/dist-packages/bleak/backends/client.py", line 59, in __aenter__
await self.connect()
File "/usr/local/lib/python3.7/dist-packages/bleak/backends/bluezdbus/client.py", line 119, in connect
"Device with address {0} was not found.".format(self.address)
bleak.exc.BleakError: Device with address 50:65:83:6d:b2:5c was not found.
In the "I'm not sure if this is interesting or not" category: I mentioned I have a Pi Zero and a Pi 4. The tests above were on the Zero (and of course painfully slow). I tried on the Pi 4 as well. This is with 0.10.0:
$ ./service_discovery.py
Traceback (most recent call last):
File "/usr/local/lib/python3.7/dist-packages/bleak/backends/bluezdbus/client.py", line 139, in connect
).asFuture(loop)
txdbus.error.RemoteError: org.freedesktop.DBus.Error.UnknownObject: Method "Connect" with signature "" on interface "org.bluez.Device1" doesn't exist
During handling of the above exception, another exception occurred:
Traceback (most recent call last):
File "./service_discovery.py", line 64, in <module>
loop.run_until_complete(run(address, True))
File "/usr/lib/python3.7/asyncio/base_events.py", line 584, in run_until_complete
return future.result()
File "./service_discovery.py", line 27, in run
async with BleakClient(address) as client:
File "/usr/local/lib/python3.7/dist-packages/bleak/backends/client.py", line 59, in __aenter__
await self.connect()
File "/usr/local/lib/python3.7/dist-packages/bleak/backends/bluezdbus/client.py", line 146, in connect
self.address
bleak.exc.BleakError: Device with address 50:65:83:6D:B2:5C could not be found. Try increasing `timeout` value or moving the device closer.
So I then installed the other branch you recommended and got this:
$ ./service_discovery.py Traceback (most recent call last):
File "./service_discovery.py", line 64, in <module>
loop.run_until_complete(run(address, True))
File "/usr/lib/python3.7/asyncio/base_events.py", line 584, in run_until_complete
return future.result()
File "./service_discovery.py", line 27, in run
async with BleakClient(address) as client:
File "/usr/local/lib/python3.7/dist-packages/bleak/backends/client.py", line 59, in __aenter__
await self.connect()
File "/usr/local/lib/python3.7/dist-packages/bleak/backends/bluezdbus/client.py", line 119, in connect
"Device with address {0} was not found.".format(self.address)
bleak.exc.BleakError: Device with address 50:65:83:6D:B2:5C was not found.
I am not sure if the difference is interesting or not.
What I do see however is that I am failing to connect to the device I can see with a different scanning tool. When I go back to my ESP32 "BLEacon" I get this:
$ ./service_discovery.py
Connected: True
[Service] 00001801-0000-1000-8000-00805f9b34fb: Generic Attribute Profile
[Characteristic] 00002a05-0000-1000-8000-00805f9b34fb: (Handle: 2) (indicate) | Name: Service Changed, Value: None
[Descriptor] 00002902-0000-1000-8000-00805f9b34fb: (Handle: 4) | Value: b'\x02\x00'
(and then a stack trace probably related to threading)
So, it looks like (and please tell me if you think I am off-track) I have a "me" issue to fix. It also looks like I was more successful with your newer branch, but I'm not sure what differences you expected to see.
I'll continue to dig and report what I am able to figure out. Thank you very much for your help so far. It's challenging keeping up with us knuckle-draggers I am sure.
We really appreciate people like you that don't give up and take the time to dig into issues like this too. Dealing with such a wide variety of hardware devices is always going to be challenging. :smile:
I have not looked closely at your traces, but I recall that bluez treats the battery service specially and intercepts it, rather than just passing it through as a regular service. I do not know the exact details but here is an example of what a websearch would turn up: https://stackoverflow.com/questions/49078659/check-battery-level-of-connected-bluetooth-device-on-linux
Dealing with such a wide variety of hardware devices is always going to be challenging.
I can't even imagine. I have a couple of ESP-based projects and it's amazing to me how you get differences even between the knockoffs of the same device.
I recall that bluez treats the battery service specially and intercepts it, rather than just passing it through as a regular service.
Now that's interesting. I did find an example of an implementation for headsets that uses AT commands via RFCOMM. I was able to confirm that this is not a viable approach for my device. The discussion did lead me to trying bluetoothctl
and within that, the gatt
commands which seem to be available therein. My "dummy" ESP32 device does allow me to list attributes:
[bluetooth]# list-attributes
Missing device address argument
[bluetooth]# list-attributes 24:6F:28:2E:7F:9E
Primary Service
/org/bluez/hci0/dev_24_6F_28_2E_7F_9E/service0001
00001801-0000-1000-8000-00805f9b34fb
Generic Attribute Profile
Characteristic
/org/bluez/hci0/dev_24_6F_28_2E_7F_9E/service0001/char0002
00002a05-0000-1000-8000-00805f9b34fb
Service Changed
Descriptor
/org/bluez/hci0/dev_24_6F_28_2E_7F_9E/service0001/char0002/desc0004
00002902-0000-1000-8000-00805f9b34fb
Client Characteristic Configuration
... sadly my intended target device does not. The only other tool I have right now is nRF Connect (on my iPhone) and with that, I can connect to my device and see the battery level. Therefore I know it works somehow. Finding the "how" is my challenge.
I also found getsenic/gatt-python
which made it very easy to get services from my dummy device:
$ gattctl --connect 24:6f:28:2e:7f:9e
Connecting...
Terminate with Ctrl+C
[24:6f:28:2e:7f:9e] Discovered, alias = BLE Battery
[24:6f:28:2e:7f:9e] Connected
[24:6f:28:2e:7f:9e] Discovered, alias = BLE Battery
[24:6f:28:2e:7f:9e] Resolved services
[24:6f:28:2e:7f:9e] Service [0000180f-0000-1000-8000-00805f9b34fb]
[24:6f:28:2e:7f:9e] Characteristic [00002a19-0000-1000-8000-00805f9b34fb]
[24:6f:28:2e:7f:9e] Service [00001801-0000-1000-8000-00805f9b34fb]
[24:6f:28:2e:7f:9e] Characteristic [00002a05-0000-1000-8000-00805f9b34fb]
Alas, still no joy on my intended target. I am unable to make a connection, which jives with what I have been able to do with this library. But again, the nRF tool does connect, adding to the mystery:
Can you imagine how fast development would be if things worked the first try? I mean, forget virus vaccines, that would be a game changer.
We have some related issues, like #393 open, so closing this as a duplicate.
bluetoothctl -v
) in case of Linux: 5.50Description
My end goal is to get the battery level via python in a Raspberry Pi from a device with known battery level capabilities (verified with nRF Connect on iOS.) This is what I am trying to replace (
gattool
being deprecated):gatttool -b 50-C2-A8-3D-80-7C --char-read -a 0x3b
What I Did
I did see issue #332 and as a result, I tested with both a Raspberry Pi Zero W Rev 1.1 as well as a Raspberry Pi 4 Model B Rev 1.1.
I started with the Bluetooth discovery example listed in the README:
From this I did see my device:
Then I tried the
service_explorer_py
example and replaced the address in main with the address of the device to which I want to connect:I receive the following:
I get a new "
Executing
message every so often. It's not what I expected to see, and I certainly don't see any mention of services from which I may be able to figure out how to drill down and get the battery level.I would be exceedingly grateful for any assistance in getting this seemingly simple piece of information out of my device.