Heerkog / MicroPythonBLEHID

Human Interface Device (HID) over Bluetooth Low Energy (BLE) GATT library for MicroPython.
GNU General Public License v3.0
222 stars 28 forks source link

Can't Reconnect paired device after power cycling device #2

Closed Fedack closed 2 months ago

Fedack commented 3 years ago

When I attempt to reconnect a keyboard that's already been paired with Windows 10, I get this: Started advertising Central connected: 0 Central disconnected

Connecting for the first time seems to be fine, but as soon as I do a reset, it doesn't work.

Heerkog commented 3 years ago

This is odd. You're mentioning a reset. Is this a full power cycle on the keyboard? If so, the Bluetooth might require pairing again.

Note that this package does not (yet?) support Bluetooth bonding.

Fedack commented 3 years ago

What's happening is that it pairs fine the first time, then any time I do a d.start() it requires forgetting it in Windows Bluetooth then adding it again.

I see, well that's unfortunate. Is there any intention to support it because aside of that, everything works superbly and was easy to implement. That is literally the only thing that'd prevent usage. For a peripheral being unable to pair once again is a requirement at this point. That said, it seems to be ATTEMPTING to. Windows tries to pair again but it seems the device rejects the pairing, then it tries again and again, it goes in a pairing loop.

On Fri, Sep 17, 2021 at 3:53 AM Heerko Groefsema @.***> wrote:

This is odd. You're mentioning a reset. Is this a full power cycle on the keyboard? If so, the Bluetooth might require pairing again.

Note that this package does not (yet?) support Bluetooth bonding.

— You are receiving this because you authored the thread. Reply to this email directly, view it on GitHub https://github.com/Heerkog/MicroPythonBLEHID/issues/2#issuecomment-921586473, or unsubscribe https://github.com/notifications/unsubscribe-auth/AH7Y3L6IQ55J3X75H3JQPJLUCLXWHANCNFSM5EGMW6CQ . Triage notifications on the go with GitHub Mobile for iOS https://apps.apple.com/app/apple-store/id1477376905?ct=notification-email&mt=8&pt=524675 or Android https://play.google.com/store/apps/details?id=com.github.android&referrer=utm_campaign%3Dnotification-email%26utm_medium%3Demail%26utm_source%3Dgithub.

Heerkog commented 3 years ago

I'm assuming you are using my keyboard example and that you're calling d.stop() before calling d.start() for the second time.

The way this simple keyboard example works is that in the init, it calls self.keyboard.start(), where keyboard is the device from the package. When you call d.stop(), it calls self.keyboard.stop(), which stops all Bluetooth services. When you then call d.start(), it never calls self.keyboard.start() again. If you want this start/stop behavior, I suggest implementing a d.restart() method that first calls self.keyboard.start() and then calls the d.start() loop.

I hope this solves the issue!

Fedack commented 3 years ago

The issue I am experiencing is where I reset the device (by pressing the button or unplugging) then it tries to start again but doesn't succeed in reconnecting to Windows.

Heerkog commented 3 years ago

Ok, thanks. I think this is an issue where (somehow) Windows doesn't recognize the device as the same one that was paired earlier. I'm unsure why this is happening. It could be the lack of bonding, but I'm unsure. It could also be another Bluetooth issue. I would need to look into this, but can't promise quick results. As a temporary solution, you could consider starting/stopping the device and putting the device in some deep sleep mode instead of fully power cycling.

Fedack commented 3 years ago

Thank you for your answers, I'll try to fiddle with it. Hopefully you figure it out.

Heerkog commented 3 years ago

I have been able to replicate your issue. The issue appears when the bluetooth device is restarted either through a hardware reset or by the software calling stop(), creating a new device, and calling start() for the newly created device.

The issue is indeed a pairing/bonding issue. as confirmed through this MicroPython issue.

I have pushed a new version of the package, for which bonding and secure pairing can be enabled, that should work. I say should, because the ESP32 implementation of MicroPython does NOT support this behavior (as confirmed in the linked issue). I own only ESP32 devices and, therefore, can't test properly. Calling methods related to bonding, or secure pairing, on an ESP32 will result in errors. In case your hardware is not an ESP32 device, you may try the code from my latest push and call set_bonding(True) and set_le_secure(True) before calling start() from the package. Please do let me know about the results! In case your device is also an ESP32 device, it seems we will both have to wait until the behavior is supported in a future MicroPython build (if ever).

Fedack commented 3 years ago

Well, that's unfortunate since my device is an esp32. Thank you for your hard work. I'll keep it in mind for the future when I select hardware for ble. Do you reckon esp8266 have the same issue?

On Wed., Sep. 22, 2021, 6:08 a.m. Heerko Groefsema, < @.***> wrote:

I have been able to replicate your issue. The issue appears when the bluetooth device is restarted either through a hardware reset or by the software calling stop(), creating a new device, and calling start() for the newly created device.

The issue is indeed a pairing/bonding issue. as confirmed through this https://github.com/micropython/micropython/issues/5767 MicroPython issue.

I have pushed a new version of the package, for which bonding and secure pairing can be enabled, that should work. I say should, because the ESP32 implementation of MicroPython does NOT support this behavior (as confirmed in the linked issue). I own only ESP32 devices and, therefore, can't test properly. Calling methods related to bonding, or secure pairing, on an ESP32 will result in errors. In case your hardware is not an ESP32 device, you may try the code from my latest push and call set_bonding(True) and set_le_secure(True) before calling start() from the package. Please do let me know about the results! In case your device is also an ESP32 device, it seems we will both have to wait until the behavior is supported in a future MicroPython build (if ever).

— You are receiving this because you authored the thread. Reply to this email directly, view it on GitHub https://github.com/Heerkog/MicroPythonBLEHID/issues/2#issuecomment-924782981, or unsubscribe https://github.com/notifications/unsubscribe-auth/AH7Y3LY37NDQDG2MLVFWV6LUDGTJTANCNFSM5EGMW6CQ . Triage notifications on the go with GitHub Mobile for iOS https://apps.apple.com/app/apple-store/id1477376905?ct=notification-email&mt=8&pt=524675 or Android https://play.google.com/store/apps/details?id=com.github.android&referrer=utm_campaign%3Dnotification-email%26utm_medium%3Demail%26utm_source%3Dgithub.

Heerkog commented 3 years ago

The MicroPython Bluetooth documentation notes the following under the Pairing and bonding section:

This is currently only supported when using the NimBLE stack on STM32 and Unix (not ESP32).

This is all I know.

Fedack commented 3 years ago

Alright, thank you. Good thing this was a personal project and nothing more. Ultimately it's just an annoyance but can be worked around. I'm still surprised something as bad was left in. Esp32 is super popular and mostly because of its Bluetooth. Oh, wait esp8266 doesn't even have Bluetooth so that answers that question.

On Wed., Sep. 22, 2021, 6:25 a.m. Heerko Groefsema, < @.***> wrote:

The MicroPython Bluetooth implementation notes the following under the Bonding section https://docs.micropython.org/en/latest/library/bluetooth.html#pairing-and-bonding :

This is currently only supported when using the NimBLE stack on STM32 and Unix (not ESP32).

This is all I know.

— You are receiving this because you authored the thread. Reply to this email directly, view it on GitHub https://github.com/Heerkog/MicroPythonBLEHID/issues/2#issuecomment-924796761, or unsubscribe https://github.com/notifications/unsubscribe-auth/AH7Y3LYR7MHBOHKNJG4NYJTUDGVKHANCNFSM5EGMW6CQ . Triage notifications on the go with GitHub Mobile for iOS https://apps.apple.com/app/apple-store/id1477376905?ct=notification-email&mt=8&pt=524675 or Android https://play.google.com/store/apps/details?id=com.github.android&referrer=utm_campaign%3Dnotification-email%26utm_medium%3Demail%26utm_source%3Dgithub.

jd3096-mpy commented 2 years ago

Now esp32 micropython supported Pairing and bonding section,I have tested,it worked. But esp32 is still can't auto reconnect paired device after power cycling device. How to make it work?

Heerkog commented 2 years ago

Now esp32 micropython supported Pairing and bonding section,I have tested,it worked.

Do you have a source for this information? The documentation still says it's not supported for ESP32.

But esp32 is still can't auto reconnect paired device after power cycling device. How to make it work?

Call mouse.set_bonding(True) before mouse.start().

jd3096-mpy commented 2 years ago

Now esp32 micropython supported Pairing and bonding section,I have tested,it worked.

Do you have a source for this information? The documentation still says it's not supported for ESP32.

But esp32 is still can't auto reconnect paired device after power cycling device. How to make it work?

Call mouse.set_bonding(True) before mouse.start().

Thanks here is link https://github.com/micropython/micropython/issues/7008

Heerkog commented 2 years ago

Nice! Four days ago.

Can you try calling _ble.gap_pair(self.conn_handle) on line 243 and let us know if that works?

jd3096-mpy commented 2 years ago

_ble.gap_pair(self.conn_handle)

I test it with android phone, I add code on line 243,it works everytime esp32 restart, the phone remind me to pair but the normal status is pair at the first time ,auto connected later I try to Call set_bonding(True) before start() but it doesn't work still disconnected instantly

Server created
get secret:  10 0 b'irk'
BLE on
Registering services
Writing service characteristics
Writing device information service characteristics
Writing battery service characteristics
Writing hid service characteristics
Advertiser created:  Mouse  with services:  [UUID(0x1812)]
Server started
Started advertising
Central connected:  1
Central disconnected:  1

when pair first time ,here are the print codes:

Server created
get secret:  10 0 b'irk'
BLE on
Registering services
Writing service characteristics
Writing device information service characteristics
Writing battery service characteristics
Writing hid service characteristics
Advertiser created:  Mouse  with services:  [UUID(0x1812)]
Server started
Started advertising
Central connected:  1
encryption update 1 1 0 1 16
Connection update
Connection update
Unhandled IRQ event:  4
Unhandled IRQ event:  4
Unhandled IRQ event:  4
Unhandled IRQ event:  4
Unhandled IRQ event:  4
Unhandled IRQ event:  4
Unhandled IRQ event:  4

Unhandled IRQ event: 4 means _IRQ_GATTS_READ_REQUEST = const(4) not reply?

Heerkog commented 2 years ago

I'm going to assume that the _IRQ_GATTS_READ_REQUEST returns an event stating _GATTS_ERROR_INSUFFICIENT_ENCRYPTION, _GATTS_ERROR_INSUFFICIENT_AUTHENTICATION or something similar.

After calling set_bonding(True), can you call set_le_secure(True)?

You can set i/o capabilities by calling set_io_capability(capability) if you want. The standard value for this is _IO_CAPABILITY_NO_INPUT_OUTPUT with passkey 1234.

Heerkog commented 2 years ago

@jd3096-mpy did this work?

jd3096-mpy commented 2 years ago

@jd3096-mpy did this work?

passkey works but it still can't connected auto after reboot

Heerkog commented 2 months ago

@Fedack @jd3096-mpy

I have just pushed a version which allows bonding, solving this issue. Note that it requires MicroPython 1.20+ (tested with 1.23).

jd3096-mpy commented 2 months ago

@Fedack @jd3096-mpy

I have just pushed a version which allows bonding, solving this issue. Note that it requires MicroPython 1.20+ (tested with 1.23).

Thanks a lot. I test with MicroPython 1.23, it works.

wenwen19115 commented 1 month ago

This issue occurs again on MicroPython version 1.24, and the Bluetooth that has been paired before cannot be connected after restarting. Steps: Restart ESP32 and run the keyboard_example.py to print the following data: Server created get secret: 2 0 None get secret: 10 0 b'irk' set secret: (10, b'irk') b'\xb0\xd4\xa5|7R\xfd\xef\xa8\x0f\xf3\x9b\xafN\xc3\x08' BLE on Registering services Writing service characteristics h_mod = 16 h_ser = 18 h_fwr = 20 h_hwr = 22 h_swr = 24 h_man = 26 h_pnp = 28 h_bat = 31 Writing device information service characteristics Writing battery service characteristics Writing hid service characteristics Advertiser created: Keyboard with services: [UUID(0x1812)] Server started Started advertising Central connected: 0 get secret: 1 0 b'\x00\x16\xa7\xebR\xd2\xd4' Central disconnected: 0 Started advertising Central connected: 0 get secret: 1 0 b'\x00\x16\xa7\xebR\xd2\xd4' Central disconnected: 0 Started advertising Central connected: 0 get secret: 1 0 b'\x00\x16\xa7\xebR\xd2\xd4' Central disconnected: 0 Started advertising Central connected: 0 get secret: 1 0 b'\x00\x16\xa7\xebR\xd2\xd4' Central disconnected: 0

Heerkog commented 1 month ago

I've pushed a new version that hopefully fixes the issue.

wenwen19115 commented 1 month ago

image Hello, there is a grammatical error here, a comma is missing. Also, after I added it, I didn't get an error, but I still can't connect to the paired device. Line 938 (h_info, hhid, , self.hrep, , h_d1, self.hrepout, h_d2, h_proto) = handles[2]

Heerkog commented 1 month ago

Can you try with this earlier version?

wenwen19115 commented 1 month ago

image I tried the version you gave and still have the same problem. I wonder if this has something to do with my micropython version, which is 1.24 image

Heerkog commented 1 month ago

Could be. I can confirm it works perfectly with version 1.23. Could you try that?

wenwen19115 commented 1 month ago

I'll give it a try,thank you!