janickr / kaspersmicrobit

A python package to connect to the Bluetooth LE GATT services of BBC micro:bit devices. Use your micro:bit as a wireless game controller!
https://kaspersmicrobit.readthedocs.io/en/stable/
Mozilla Public License 2.0
16 stars 0 forks source link

[bug] bleak.exc.BleakError: Characteristic (...) was not found! #4

Closed Miniontoby closed 1 year ago

Miniontoby commented 1 year ago

With line: print(microbit.accelerometer.read())

I get error:

Traceback (most recent call last):
  File "C:\Users\Miniontoby\Documents\python\controllers\microbit_bluetooth.py", line 17, in <module>
    print(microbit.accelerometer.read())
  File "C:\Users\Miniontoby\AppData\Local\Programs\Python\Python310\lib\site-packages\kaspersmicrobit\services\accelerometer.py", line 105, in read
    return AccelerometerData.from_bytes(self._device.read(Characteristic.ACCELEROMETER_DATA))
  File "C:\Users\Miniontoby\AppData\Local\Programs\Python\Python310\lib\site-packages\kaspersmicrobit\bluetoothdevice.py", line 78, in read
    result = self.loop.run_async(self.client.read_gatt_char(characteristic.value)).result()
  File "C:\Users\Miniontoby\AppData\Local\Programs\Python\Python310\lib\concurrent\futures\_base.py", line 446, in result
    return self.__get_result()
  File "C:\Users\Miniontoby\AppData\Local\Programs\Python\Python310\lib\concurrent\futures\_base.py", line 391, in __get_result
    raise self._exception
  File "C:\Users\Miniontoby\AppData\Local\Programs\Python\Python310\lib\site-packages\bleak\__init__.py", line 571, in read_gatt_char
    return await self._backend.read_gatt_char(char_specifier, **kwargs)
  File "C:\Users\Miniontoby\AppData\Local\Programs\Python\Python310\lib\site-packages\bleak\backends\winrt\client.py", line 720, in read_gatt_char
    raise BleakError(f"Characteristic {char_specifier} was not found!")
bleak.exc.BleakError: Characteristic E95DCA4B-251D-470A-A062-FA1922DFA9A8 was not found!

Sorry, but I have to get dinner now, so more details will follow up, but for now this is all I have

Update: This is on a Version 1 microbit

UPDATE: It was the hex file missing the accelerometer service, but yeah it now just keeps on giving me the 020 error even with the fix thingy that I use...

janickr commented 1 year ago

Can you try a hex file with only the accelerometer service enabled?

The 020 Error happens when there is not enough memory on the microbit https://support.microbit.org/support/solutions/articles/19000097280-020

Miniontoby commented 1 year ago

Can you try a hex file with only the accelerometer service enabled?

The 020 Error happens when there is not enough memory on the microbit https://support.microbit.org/support/solutions/articles/19000097280-020

Then I get:

Traceback (most recent call last):
  File "C:\Users\Miniontoby\Documents\python\controllers\microbit_bluetooth_tkinter_ball.py", line 70, in <module>
    microbit.accelerometer.notify(accelerometer_data)
  File "C:\Users\Miniontoby\AppData\Local\Programs\Python\Python310\lib\site-packages\kaspersmicrobit\services\accelerometer.py", line 95, in notify
    self._device.notify(Characteristic.ACCELEROMETER_DATA,
  File "C:\Users\Miniontoby\AppData\Local\Programs\Python\Python310\lib\site-packages\kaspersmicrobit\bluetoothdevice.py", line 103, in notify
    self.loop.run_async(self.client.start_notify(characteristic.value, wrap_try_catch(callback))).result()
  File "C:\Users\Miniontoby\AppData\Local\Programs\Python\Python310\lib\concurrent\futures\_base.py", line 446, in result
    return self.__get_result()
  File "C:\Users\Miniontoby\AppData\Local\Programs\Python\Python310\lib\concurrent\futures\_base.py", line 391, in __get_result
    raise self._exception
  File "C:\Users\Miniontoby\AppData\Local\Programs\Python\Python310\lib\site-packages\bleak\__init__.py", line 639, in start_notify
    raise BleakError(f"Characteristic {char_specifier} not found!")
bleak.exc.BleakError: Characteristic E95DCA4B-251D-470A-A062-FA1922DFA9A8 not found!
Miniontoby commented 1 year ago

Hmm now I get 021 error code with some different code...

I think I might just want to not use the acceleration service and just use uart and then send my sensor data over uart

Miniontoby commented 1 year ago

INFO:kaspersmicrobit.bluetoothdevice:Connected
INFO:kaspersmicrobit.bluetoothdevice:Enable notify Characteristic.TX_CHARACTERISTIC
Traceback (most recent call last):
  File "C:\Users\Miniontoby\Documents\python\controllers\microbit_bluetooth_controller.py", line 80, in <module>
    asyncio.run(main())
  File "C:\Users\Miniontoby\AppData\Local\Programs\Python\Python310\lib\asyncio\runners.py", line 44, in run
    return loop.run_until_complete(main)
  File "C:\Users\Miniontoby\AppData\Local\Programs\Python\Python310\lib\asyncio\base_events.py", line 646, in run_until_complete
    return future.result()
  File "C:\Users\Miniontoby\Documents\python\controllers\microbit_bluetooth_controller.py", line 70, in main
    ser_micro.uart.receive_string(handle_received_string)
  File "C:\Users\Miniontoby\AppData\Local\Programs\Python\Python310\lib\site-packages\kaspersmicrobit\services\uart.py", line 41, in receive_string
    self.receive(UartService.to_string(callback))
  File "C:\Users\Miniontoby\AppData\Local\Programs\Python\Python310\lib\site-packages\kaspersmicrobit\services\uart.py", line 30, in receive
    self._device.notify(Characteristic.TX_CHARACTERISTIC, lambda sender, data: callback(data))
  File "C:\Users\Miniontoby\AppData\Local\Programs\Python\Python310\lib\site-packages\kaspersmicrobit\bluetoothdevice.py", line 103, in notify
    self.loop.run_async(self.client.start_notify(characteristic.value, wrap_try_catch(callback))).result()
  File "C:\Users\Miniontoby\AppData\Local\Programs\Python\Python310\lib\concurrent\futures\_base.py", line 446, in result
    return self.__get_result()
  File "C:\Users\Miniontoby\AppData\Local\Programs\Python\Python310\lib\concurrent\futures\_base.py", line 391, in __get_result
    raise self._exception
  File "C:\Users\Miniontoby\AppData\Local\Programs\Python\Python310\lib\site-packages\bleak\__init__.py", line 649, in start_notify
    await self._backend.start_notify(characteristic, wrapped_callback, **kwargs)
  File "C:\Users\Miniontoby\AppData\Local\Programs\Python\Python310\lib\site-packages\bleak\backends\winrt\client.py", line 890, in start_notify
    await winrt_char.write_client_characteristic_configuration_descriptor_async(
OSError: [WinError -2140864511] De gegeven ingang voor kenmerken is niet geldig op deze server

And now it doesn't want to do anything

janickr commented 1 year ago

Then I get:

    raise BleakError(f"Characteristic {char_specifier} not found!")
bleak.exc.BleakError: Characteristic E95DCA4B-251D-470A-A062-FA1922DFA9A8 not found!

When it says "Characteristic E95DCA4B-251D-470A-A062-FA1922DFA9A8 not found" usually means that the accelerometer bluetooth service on your microbit is not activated. Did you upload the hex file to your microbit?

Let's try to isolate the problem:

Hmm now I get 021 error code with some different code...

Error 021 means that your microbit is running out of memory afaik, so I think the makecode program on your microbit uses too much memory

OSError: [WinError -2140864511] De gegeven ingang voor kenmerken is niet geldig op deze server

I don't think I've encountered this before. Did unpairing and re-pairing the microbit with windows solve this?

Miniontoby commented 1 year ago

Look, I don't need the acceleration, if I could just use the UART system. I already have script to do the same for serial, but I don't want to be limited to my two usb ports.

But if I only enable UART system then it doesn't work, so i then enabled acceleration service again and put it on my micro:bit.

I now somewhat have the script not giving error anymore, but it doesn't receive ANY messages! Maybe you have ideas?

janickr commented 1 year ago

The examples in kaspersmicrobit https://github.com/janickr/kaspersmicrobit/tree/main/examples were tested with both the microbit v1 and microbit v2, as far as I know they work. Ofcourse it is always possible that there are bugs in kaspersmicrobit, but if we want to find it we need to isolate it.

So if you think there is something wrong with the accelerometer service then run the accelerometer example with the hex file provided for the accelerometer here https://kaspersmicrobit.readthedocs.io/en/stable/makecode-bluetooth/enable-bluetooth/

Or if you think there is a bug with the uart service then create a hex file with only the ble uart service and on connect write some characters to the uart and see if that works by running the https://github.com/janickr/kaspersmicrobit/blob/main/examples/microbit-uart.py

Miniontoby commented 1 year ago

Hmmm, I firstly tried the microbit-uart.py again and it at least (possibly) sended something, but didn't receive anything.

Then I tried using the hex file in the hex folder for v1 with uart and accel my laptop cannot find the microbit

so i went back to my original code, but now it keeps giving me the OSError: [WinError -2140864509] Het kenmerk kan niet worden geschreven error

janickr commented 1 year ago

The following instructions help you recreate the setup that works for me on windows for my microbit v1.5:

Before doing this you need to un-pair your microbit, remove it from the bluetooth devices, and don't add it again. remove microbit

I created 2 hex files with the setting "No pairing required": microbit-nopairing.zip

This is the source:

Use the uart one to test the uart example below, and the accelerometer hex for the accelerometer example below

There is no pairing step needed, just use the hex file on the microbit, when the "b°" sign appears on the led display, then you can run the python script.

Use these test scripts:

For the uart:

#  This Source Code Form is subject to the terms of the Mozilla Public
#  License, v. 2.0. If a copy of the MPL was not distributed with this
#  file, You can obtain one at https://mozilla.org/MPL/2.0/.
import logging
import time

from kaspersmicrobit import KaspersMicrobit

logging.basicConfig(level=logging.INFO)

MICROBIT_BLUETOOTH_ADDRESS = 'your-microbit-address'

# https://makecode.microbit.org/_EPu73mDqsiFM

def print_received_string(string: str):
    print(f"Received from microbit: '{string}'")

with KaspersMicrobit(MICROBIT_BLUETOOTH_ADDRESS) as microbit:
    # listen for strings sent by the microbit / luister naar tekst die verzonden wordt door de microbit
    microbit.uart.receive_string(print_received_string)

    # send a string to the microbit / verzend tekst naar de microbit
    microbit.uart.send_string("Ping\n")

    time.sleep(25)

For the accellerometer:

#  This Source Code Form is subject to the terms of the Mozilla Public
#  License, v. 2.0. If a copy of the MPL was not distributed with this
#  file, You can obtain one at https://mozilla.org/MPL/2.0/.

import logging
import time

from kaspersmicrobit import KaspersMicrobit
from kaspersmicrobit.services.accelerometer import AccelerometerData

logging.basicConfig(level=logging.INFO)

MICROBIT_BLUETOOTH_ADDRESS =  'your-microbit-address'
# https://makecode.microbit.org/_5drJjCdzpfdf

def accelerometer_data(data: AccelerometerData):
    print(f"Accelerometer data: {data}")

with KaspersMicrobit(MICROBIT_BLUETOOTH_ADDRESS) as microbit:
    # read the current accelerometer data / lees de huidige accelerometer gegevens
    print(f"Current accelerometer reading: {microbit.accelerometer.read()}")

    # check how often accelerometer updates will occur if you listen to them with notify
    # / lees hoe vaak accelerometer updates doorgestuurd worden wanneer je er naar luistert met notify
    print(f"Current period: {microbit.accelerometer.read_period()}")

    # listen for accelerometer data updates / luister naar updates van de accelerometer gegevens
    microbit.accelerometer.notify(accelerometer_data)

    time.sleep(5)

    # change the update interval / pas het update interval aan
    print("Now slow down updates to 160 milliseconds")
    microbit.accelerometer.set_period(160)

    print(f"Accelerometer updates will now occur every {microbit.accelerometer.read_period()} milliseconds")

    time.sleep(5)

Let me know if this works for you

Miniontoby commented 1 year ago

I just removed the device from the bluetooth devices and the default scripts work now, but now I have to test my own script before I am sure it works.

Miniontoby commented 1 year ago

Oke, my script won't work, cause 020 error, will have to try using the services then...

janickr commented 1 year ago

You can find the "No pairing required" setting in makecode: settings

nopairing

Miniontoby commented 1 year ago

I told you it works, but my own script still gives it 020 error,

And now with the services the magneto doesn't want to work with button and accel... also 020 error

Miniontoby commented 1 year ago

You can find the "No pairing required" setting in makecode:

I already had the No Pairing Required enabled

janickr commented 1 year ago

The 020 error means that the makecode script requires too much memory from your microbit. You'll have to slim down your makecode program. If my guess is correct you'll probably can only pick one of accelerometer, magnetometer, or uart.

btw I know you told me it works. I went trough the extra effort of taking screenshots and writing the comment helping you find to the right settings in case you wanted to generate your own hex file.

Miniontoby commented 1 year ago

Look, my code nearly is finished and this issue can nearly be closed, but only when I enable try getting the compass heading I cannot get it to work... What do I have to use for it? Magnetometer or accelero?

janickr commented 1 year ago

The magnetometer: see the examples and the reference on http://kaspersmicrobit.readthedocs.io/

But I think the micro:bit v1 has not enough memory to enable the magnetometer service in combination with the accelerometer or uart.

If you would try it, you can try to trigger the calibration in makecode, before enabling the bluetooth services like this: calibrate

Miniontoby commented 1 year ago

That's not what I asked. I will do it in Dutch so you may understand it better:

"Wat heb ik nodig om de compas richting uit te lezen in het python script."

janickr commented 1 year ago

Beste Miniontoby,

Met mijn begrip van het Engels is niets mis, dank je voor je bezorgdheid 🙂 Misschien is het niet je bedoeling, en misschien komt het omdat Engels niet je moedertaal is, maar je komt in deze hele conversatie nogal grof over.

Het is wel degelijk wat je gevraagd hebt: ".... when I enable try getting the compass heading I cannot get it to work... What do I have to use for it? Magnetometer or accelero?" Dat is letterlijk vertaald: "...wanneer ik de kompas richting probeer uit te lezen krijg ik het niet aan de praat... Wat moet ik hiervoor gebruiken? Magnetometer of accelero?"

Waarop ik antwoordde: "De magnetometer" Met een link naar de documentatie en een screenshot hoe je dit best gebruikt in jouw specifieke geval.
Dat lijkt mij een uitgebreid antwoord op je vraag.

Heb je dat even geprobeerd voor je me antwoordde? Heb je de documentatie doorgenomen? Er is onder meer een voorbeeld met de magnetometer te vinden en de API documentatie is helemaal in het Nederlands.

Ik sluit dit issue nu: het oorspronkelijke issue bleek uiteindelijk geen issue, de connectie met de micro:bit v1 werkt nu, en de magnetometer moet je maar eens proberen. Je mag altijd een nieuw issue maken als je een echte bug ontdekt (die niet te wijten is aan het beperkte geheugen van de micro:bit v1)

Een vriendelijke groet en veel succes met je project!

Misschien nog tot slot wat goede raad (dat had je niet gevraagd, ik weet het 😉 ) Open source projecten zoals deze worden vaak door mensen ontwikkeld die daar niet voor betaald worden, en die zo goed als het kan en voor zover hun vrije tijd het hen toelaat, dit onderhouden en antwoorden op issues. Een vriendelijke toon in een gesprek lijkt me niet zo veel moeite te kosten, en kan je verder brengen dan wanneer het lijkt dat je geen hoge pet op hebt van je gesprekspartner.