hbldh / bleak

A cross platform Bluetooth Low Energy Client for Python using asyncio
MIT License
1.6k stars 280 forks source link

bleak.exc.BleakError: Characteristic was not found! #359

Closed mrdc closed 1 year ago

mrdc commented 3 years ago

Description

I'm trying to connect to a BLE device via bleak- it works fine when I use my script on Windows 10, but the same script fails on Linux:

bleak.exc.BleakError: Characteristic 11111111-1111-1111-1111-111111111111 was not found!

What I Did

My code:

from bleak import BleakClient
import asyncio

address = "xx:xx:xx:xx:xx:xx"
ble_uuid = "11111111-1111-1111-1111-111111111111"

msg = b'ABC'
async def run(address, loop):
        async with BleakClient(address, loop=loop) as client:
            await client.write_gatt_char(ble_uuid, msg, True)

loop = asyncio.get_event_loop()
loop.run_until_complete(run(address, loop))

The difference I see is a different bleak version on Win and on Linux. On Linux pip3 install bleak returns only bleak 0,8.0:

pip3 install bleak
Defaulting to user installation because normal site-packages is not writeable
Looking in indexes: https://pypi.org/simple, https://www.piwheels.org/simple
Requirement already satisfied: bleak in /home/pi/.local/lib/python3.8/site-packages (0.8.0)
Traceback (most recent call last):
  File "script.py", line 13, in <module>
    loop.run_until_complete(run(address, loop))
  File "/usr/local/lib/python3.8/asyncio/base_events.py", line 616, in run_until_complete
    return future.result()
  File "script.py", line 11, in run
    await client.write_gatt_char(ble_uuid, msg, True)
  File "/home/pi/.local/lib/python3.8/site-packages/bleak/backends/bluezdbus/client.py", line 580, in write_gatt_char
    raise BleakError("Characteristic {0} was not found!".format(char_specifier))
bleak.exc.BleakError: Characteristic 11111111-1111-1111-1111-111111111111 was not found!
dhalbert commented 3 years ago

Try pip3 install --upgrade bleak on Linux to move past 0.8.0.

mrdc commented 3 years ago

Try pip3 install --upgrade bleak on Linux to move past 0.8.0.

Thanks!

Unfortunately, the same error with bleak 0.9.1.

hbldh commented 3 years ago

@mrdc Could you please run the service_explorer.py example script (https://github.com/hbldh/bleak/blob/develop/examples/service_explorer.py) for your peripheral and post the results here?

mrdc commented 3 years ago

@hbldh Here you go:

$ python3 service_explorer.py
Executing <Task pending name='Task-1' coro=<run() running at service_explorer.py:25> wait_for=<Future pending cb=[Deferred.asFuture.<locals>.checkCancel() at /home/pi/.local/lib/python3.8/site-packages/twisted/internet/defer.py:786, <TaskWakeupMethWrapper object at 0x7584d838>()] created at /usr/local/lib/python3.8/asyncio/base_events.py:422> cb=[_run_until_complete_cb() at /usr/local/lib/python3.8/asyncio/base_events.py:184] created at /usr/local/lib/python3.8/asyncio/base_events.py:595> took 0.136 seconds
Connected: True
pi@raspberrypi:~

It outputs nothing, but Connected: True Maybe it's related to https://github.com/hbldh/bleak/issues/332? I'm also using RPi3b+

hbldh commented 3 years ago

It might. Regardless, the script should print something more at least? Or throw an error? Otherwise BlueZ just didn't detect any services on your peripheral.

BlueZ does its own handling of services, e.g. the Battery Service is not available in BlueZ as it is in Windows. Maybe it disregards services with non-standard uuids? Have you written the peripheral code yourself?

mrdc commented 3 years ago

the script should print something more at least? Or throw an error?

Unfortunately, no output: it just says Connected: True and then script exits. The same script works fine on Windows 10. BTW I've updated BT firmware and still the same issue.

Have you written the peripheral code yourself?

Yes, it's homemade :) Had no issues with BLE part - it connects from macOS, Win10, iOS, but not from RPi3b+ Still it's strange - ble should be able to connect to any characteristic UUID I provide.

hbldh commented 3 years ago

Do you have any non-RPi Linux system to try connecting from?

mrdc commented 3 years ago

I can try to install Ubuntu, I hope it will work with CSR 4.0 dongle.

mrdc commented 3 years ago

@hbldh

Do you have any non-RPi Linux system to try connecting from?

ubuntu-20.04.1-desktop-amd64@LiveMode and CSR 4.0 dongle.

Here you go:

root@ubuntu:~# python3 service_explorer.py
Connected: True
[Service] cc1ad9ab-9be8-400b-bde1-4af132b3a1b0: Unknown
        [Characteristic] 22222222-2222-2222-2222-222222222222: (Handle: 43) (read,notify) | Name: Unknown, Value: b'#2'
        [Characteristic] 11111111-1111-1111-1111-111111111111: (Handle: 41) (read,write) | Name: Unknown, Value: b'#1'
[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 my initial script:

root@ubuntu:~# python3 ble2.py
Traceback (most recent call last):
  File "ble2.py", line 14, in <module>
    loop.run_until_complete(run(address, loop))
  File "/usr/lib/python3.8/asyncio/base_events.py", line 616, in run_until_complete
    return future.result()
  File "ble2.py", line 11, in run
    await client.write_gatt_char(ble_uuid, msg, True)
  File "/usr/local/lib/python3.8/dist-packages/bleak/backends/bluezdbus/client.py", line 614, in write_gatt_char
    await self._bus.callRemote(
txdbus.error.MarshallingError: List, Tuple, Bytearray, or Dictionary required for DBus array.  Received: b'ABC'

So, looks like it's RPi related issue.

hbldh commented 3 years ago

Have you tried the suggestions in #332? Otherwise, do that in this case!

mrdc commented 3 years ago

Have you tried the suggestions in #332? Otherwise, do that in this case!

Yes, I’ve updated the firmware. BTW I've updated BT firmware and still the same issue.

dhalbert commented 3 years ago

Which version of the firmware did you update to?

mrdc commented 3 years ago

Which version of the firmware did you update to?

BCM4345C0_003.001.025.0171.0339.hcd (https://drive.google.com/file/d/1DVOtBjrsoR2NhwEBVn3ei0sv-xTIBCxR/view?usp=sharing)

According to the firmware change log (https://github.com/RPi-Distro/bluez-firmware/blob/master/debian/changelog), it fixes the connection issue, in my case RPi3 connects to BLE device.

aayushsingla commented 3 years ago

Any updates with this one? Facing similar issue.

dlech commented 3 years ago

We're getting ready to do a release (probably tomorrow) that includes some troubleshooting tips on making sure the problem isn't cached device info. Also, there are major changes to the BlueZ backend, so if anything else, it should at least provide better debugging info.

hbldh commented 3 years ago

@aayushsingla The new version 0.11.0 has new been released to PyPI. Install that as see if that improves your situation.

mrdc commented 3 years ago

@hbldh Hello, I've checked with the latest bleak (0.11.0) - the same issue :(

dlech commented 3 years ago

Did you try removing the device using bluetoothctl ?

mrdc commented 3 years ago

Did you try removing the device using bluetoothctl ?

In case I've paired my device? Or you mean something else?

dlech commented 3 years ago

Even if it is not paired, BlueZ still caches information about the device. Removing the device will clear all of the cached info so that you can start fresh.

mrdc commented 3 years ago

Removing the device will clear all of the cached info so that you can start fresh.

I've tried it: bluetoothctl -> remove DEVICE_MAC - the same result.

dlech commented 3 years ago

Does it still raise a BleakError with v0.11.0? What is the new stack trace?

mrdc commented 3 years ago

Does it still raise a BleakError with v0.11.0? What is the new stack trace?

Hi, yes, it's the same error: bleak.exc.BleakError: Characteristic XXXXXXXXXXXXXXXXX was not found!

Carlitox7 commented 3 years ago

Same problem 😢

hbldh commented 3 years ago

If you are using a Raspberry Pi, then try to follow the advice here: https://github.com/hbldh/bleak/issues/332#issuecomment-803623516

If the characteristic you want to use isn't printed when running service_explorer.py example script, then BlueZ registered it, or at least did not give Bleak an opportunity to find it...

mrdc commented 3 years ago

If the characteristic you want to use isn't printed when running service_explorer.py example script, then BlueZ registered it, or at least did not give Bleak an opportunity to find it...

Yes, in my case there are no characteristics found when I use service_explorer.py

If you are using a Raspberry Pi, then try to follow the advice here: #332 (comment)

Thanks, I'll test it and provide feedback.

mrdc commented 3 years ago

bluez-firmware is already the newest version (1.2-4+rpt8)

The same issue :(

hbldh commented 3 years ago

@mrdc I honestly have no idea what might be causing this, Does it happen on other RPis, if you happen to have more to try the code on?

mrdc commented 3 years ago

@mrdc I honestly have no idea what might be causing this, Does it happen on other RPis, if you happen to have more to try the code on?

Actually, it's not a big deal - I don't depend on it. I'll buy RPi4 late for tests - will update the issue.

dlech commented 2 years ago

I recently found a bug in BlueZ where the cache was not entirely cleared when the device is removed. Here is the workaround:

bluetoothctl -- remove XX:XX:XX:XX:XX:XX
# prior to BlueZ 5.62 you also need to manually delete the GATT cache
sudo rm "/var/lib/bluetooth/YY:YY:YY:YY:YY:YY/cache/XX:XX:XX:XX:XX:XX"

...where XX:XX:XX:XX:XX:XX is the Bluetooth address of your device and YY:YY:YY:YY:YY:YY is the Bluetooth address of the Bluetooth adapter on your computer.

Does this resolve the issue?

Divya-nemuri commented 1 year ago

im getting the same issue bleak.exc.BleakError: Characteristic UUID was not found! while trying to connect to a ble device from a linux PC, i tried all the above things. i tried with both uuid's which i got from client.get_services()

dlech commented 1 year ago

i tried with both uuid's which i got from client.get_services()

This sounds like you are trying to use service UUIDs when you should be using characteristic UUIDs.

Divya-nemuri commented 1 year ago

i tried with both uuid's which i got from client.get_services()

This sounds like you are trying to use service UUIDs when you should be using characteristic UUIDs.

i tried with this code and the same uuids im getting in metadata as well
devices = await BleakScanner.discover() for d in devices: print(d) print(d.metadata["uuids"]) is there any other way to get the characteristic uuid other than these two methods.

dlech commented 1 year ago

Those are not characteristic UUIDs, those are service UUIDs. You can use the service_explorer.py example to view the full tree of services, characteristics and descriptors.

Divya-nemuri commented 1 year ago

Those are not characteristic UUIDs, those are service UUIDs. You can use the service_explorer.py example to view the full tree of services, characteristics and descriptors.

i tried this i got the uuids but not for reading, i tried with the uuids which i got but for that the read is not permitted, what does it mean, i cant read the data from it?

dlech commented 1 year ago

Some characteristics require authorization/authentication in order to read, which means the device needs to be paired first. Some characteristics may not support reading. These properties should be reported by the service explorer.

bubez81 commented 1 year ago

hello maybe I'm in the right place, something strange happen when I try to use service_explorer.py on a raspberry and on a Mac these are the results: raspberry:

INFO:__main__:Connected: True
INFO:__main__:[Service] 00001801-0000-1000-8000-00805f9b34fb (Handle: 10): Generic Attribute Profile
INFO:__main__:  [Characteristic] 00002a05-0000-1000-8000-00805f9b34fb (Handle: 11): Service Changed (indicate), Value: None
INFO:__main__:      [Descriptor] 00002902-0000-1000-8000-00805f9b34fb (Handle: 13): Client Characteristic Configuration) | Value: b'\x02\x00'
INFO:__main__:[Service] 00035b03-58e6-07dd-021a-08123a000300 (Handle: 14): Unknown
INFO:__main__:  [Characteristic] 00035b03-58e6-07dd-021a-08123a000301 (Handle: 15): Unknown (read,write,indicate), Value: b'\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00'
INFO:__main__:      [Descriptor] 00002902-0000-1000-8000-00805f9b34fb (Handle: 17): Client Characteristic Configuration) | Value: b'\x02\x00'
INFO:__main__:  [Characteristic] 00035b03-58e6-07dd-021a-08123a0003ff (Handle: 18): Unknown (read,write), Value: b'\x00'

macOS:

INFO:__main__:Connected: True
INFO:__main__:[Service] 00035b03-58e6-07dd-021a-08123a000300 (Handle: 14): Unknown
INFO:__main__:  [Characteristic] 00035b03-58e6-07dd-021a-08123a000301 (Handle: 15): Unknown (read,write,indicate), Value: b'\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00'
INFO:__main__:      [Descriptor] 00002902-0000-1000-8000-00805f9b34fb (Handle: 17): Client Characteristic Configuration) | Value: b'\x00\x00'
INFO:__main__:  [Characteristic] 00035b03-58e6-07dd-021a-08123a0003ff (Handle: 18): Unknown (read,write), Value: b'\x00'

it seems that not all services are recognized by the mac

dlech commented 1 year ago

The "Generic Attribute Profile" is used internally by the Bluetooth stack so may not be exposed on all OSes.

bubez81 commented 1 year ago

mmm and 11 and 13?

dlech commented 1 year ago

Those are children of the service, so if the service is not available, then the characteristics of that service (and their descriptors) will not be available either.

bubez81 commented 1 year ago

Ah ok thank you!

Divya-nemuri commented 1 year ago

Some characteristics require authorization/authentication in order to read, which means the device needs to be paired first. Some characteristics may not support reading. These properties should be reported by the service explorer.

i tried the following code to pair and get the uuids

ADDRESS = (
    "EE:3B:19:4B:E3:E6"
)
async def main(address):
    async with BleakClient(address) as client:
        logger.info(f"Connected: {client.is_connected}")
        paired = await client.pair(protection_level=2)
        print(f"Paired: {paired}")

        for service in client.services:
            logger.info(f"[Service] {service}")
            for char in service.characteristics:
                if "read" in char.properties:
                    print("trueee")
                    try:
                        print("read")
                        value = bytes(await client.read_gatt_char(char.uuid))
                        logger.info(
                            f"\t[Characteristic] {char} ({','.join(char.properties)}), Valueread: {value}"
                        )
                    except Exception as e:
                        logger.error(
                            f"\t[Characteristic] {char} ({','.join(char.properties)}), Value: {e}"
                        )

                else:
                    value = None
                    logger.info(
                        f"\t[Characteristic] {char} ({','.join(char.properties)}), Value: {value}"
                    )

                for descriptor in char.descriptors:
                    try:
                        value = bytes(
                            await client.read_gatt_descriptor(descriptor.handle)
                        )
                        logger.info(f"\t\t[Descriptor] {descriptor}) | Value: {value}")
                    except Exception as e:
                        logger.error(f"\t\t[Descriptor] {descriptor}) | Value: {e}")

if __name__ == "__main__":
    logging.basicConfig(level=logging.INFO)
    asyncio.run(main(ADDRESS))

got the following response:

INFO:__main__:Connected: True
Paired: True
INFO:__main__:[Service] 569a1101-b87f-490c-92cb-11ba5ea5167c (Handle: 11): Unknown
INFO:__main__:  [Characteristic] 569a2001-b87f-490c-92cb-11ba5ea5167c (Handle: 15): Unknown (write-without-response,write), Value: None
INFO:__main__:  [Characteristic] 569a2000-b87f-490c-92cb-11ba5ea5167c (Handle: 12): Unknown (notify), Value: None
INFO:__main__:      [Descriptor] 00002902-0000-1000-8000-00805f9b34fb (Handle: 14): Client Characteristic Configuration) | Value: b'\x00\x00'
INFO:__main__:[Service] 00001801-0000-1000-8000-00805f9b34fb (Handle: 10): Generic Attribute Profile

did i do the pairing correctly, if yes then i dint get read uuid.. how can i get it

dlech commented 1 year ago

There are no readable characteristics, but you could enable notifications on the characteristic with UUID 569a2000-b87f-490c-92cb-11ba5ea5167c to receive information from the remote device.

celiafb commented 1 year ago

Hi everyone, I'm having a somewhat similar issue but in my case, using service_explorer.py does show the readable characteristics:

INFO:__main__:Connected: True
INFO:__main__:[Service] a3e0539e-3cf8-867e-2b7b-1ee451ec384b (Handle: 12): Unknown
INFO:__main__:  [Characteristic] 6e400003-b5a3-f393-e0a9-e50e24dcca9e (Handle: 13): Nordic UART TX (write-without-response,write), Value: None
INFO:__main__:  [Characteristic] 6e400002-b5a3-f393-e0a9-e50e24dcca9e (Handle: 15): Nordic UART RX (read,notify), Value: b'CH0: 2958 mV CH1: 29'
INFO:__main__:      [Descriptor] 00002902-0000-1000-8000-00805f9b34fb (Handle: 17): Client Characteristic Configuration) | Value: b''

This is how I'm setting up my service/characteristics on the peripheral side:

// create service
BLEService ADCService = BLEService("A3E0539E-3CF8-867E-2B7B-1EE451EC384B");

// create characteristics
BLECharCharacteristic readCharacteristic = BLECharCharacteristic("6E400003-B5A3-F393-E0A9-E50E24DCCA9E", BLEWriteWithoutResponse | BLEWrite);
BLECharacteristic writeCharacteristic = BLECharacteristic("6E400002-B5A3-F393-E0A9-E50E24DCCA9E", BLERead | BLENotify | BLEBroadcast,51);

and on the central side:

device = "A3E0539E-3CF8-867E-2B7B-1EE451EC384B"
write_characteristic = "6e400003-b5a3-f393-e0a9-e50e24dcca9e"
read_characteristic = "6e400002-b5a3-f393-e0a9-e50e24dcca9e"

... and trying to read centrally using:

await client.start_notify(read_characteristic, handle_rx)

My custom script allows my central device (Mac) to originally establish a connection with the peripheral (nRF52DK), but it gets disconnected in about 2 seconds, after the await line above fails to run successfully. Using the example uart_service.py also yields a momentary connection and disconnection within a couple seconds.

Any clues to fix this? I've been trying to figure it out to no avail for the past couple of weeks...

Thanks in advance!

dlech commented 1 year ago
INFO:__main__:        [Descriptor] 00002902-0000-1000-8000-00805f9b34fb (Handle: 17): Client Characteristic Configuration) | Value: b''

The value should be two bytes, so there appears to be a problem with the remote device itself.

celiafb commented 1 year ago

Thanks for your reply. Why should the value be two bytes? Especially since I'm not writing to the remote device...

dlech commented 1 year ago

b'\x00\x00' if notifications are disabled or b'\x01\x00' if notifications are enabled.

celiafb commented 1 year ago

So the descriptor is also something I need to set up for the peripheral in my Arduino code? How do I set it to be b'\x01\x00'? Thanks again.

dlech commented 1 year ago

So the descriptor is also something I need to set up for the peripheral in my Arduino code?

Yes.

How do I set it to be b'\x01\x00'?

This happens behind the scenes already when you call:

await client.start_notify(read_characteristic, handle_rx)
celiafb commented 1 year ago

I think I'm not understanding something critical. The function:

await client.start_notify(read_characteristic, handle_rx)

Gets called in my Python script, which is used to talk to the remote device, but does not get flashed. I don't have the descriptor set up in my Arduino code (which I'm flashing onto the remote device) so far. Could you please point me to how to find the line of code that I need to add on the Arduino end?

Thanks again!