OpenGoPro icon indicating copy to clipboard operation
OpenGoPro copied to clipboard

BLE Reconnection Fails After GoPro Battery Removal or Extended Idle Time (Requires Manual Re-pairing)

Open areiner222 opened this issue 1 year ago • 4 comments

Component What is the bug in?

  • Demos (python sdk, etc) - Using WirelessGoPro / python sdk

Describe the bug I can successfully pair my gopro via ble and then connect with the WirelessGoPro (connecting and disconnecting successfully). However, if the battery is removed / changes or the camera sits idle for long enough after powering off then I cannot reconnect via ble without manually repairing.

Repro

gp0 = WirelessGoPro(
    target=target0,
    enable_wifi=False,
    maintain_state=False,
)
await gp0.open()

Error:
Connection failed during establishment..
[org.bluez.Error.Failed] Operation already in progress
Failed to connect: ConnectFailed('BLE connection failed to establish after 1 retries with timeout 1'). Retrying #1
Failed to connect: ConnectFailed('BLE connection failed to establish after 1 retries with timeout 1'). Retrying #2
Connection failed during establishment..
[org.bluez.Error.Failed] Operation already in progress
Error while opening: BLE connection failed to establish after 5 retries with timeout 15
Failed to connect: ConnectFailed('BLE connection failed to establish after 1 retries with timeout 1'). Retrying #3
Failed to connect: ConnectFailed('BLE connection failed to establish after 1 retries with timeout 1'). Retrying #4
---------------------------------------------------------------------------
BleakDBusError                            Traceback (most recent call last)
File [~/miniforge3/envs/zed_dev2/lib/python3.10/site-packages/bleak/__init__.py:615](http://localhost:9091/home/areiner/miniforge3/envs//lib/python3.10/site-packages/bleak/__init__.py#line=614), in BleakClient.connect(self, **kwargs)
    606 """Connect to the specified GATT server.
    607 
    608 Args:
   (...)
    613 
    614 """
--> 615 return await self._backend.connect(**kwargs)

File [~/miniforge3/envs/zed_dev2/lib/python3.10/site-packages/bleak/backends/bluezdbus/client.py:254](http://localhost:9091/home/areiner/miniforge3/envs/zed_dev2/lib/python3.10/site-packages/bleak/backends/bluezdbus/client.py#line=253), in BleakClientBlueZDBus.connect(self, dangerous_use_bleak_cache, **kwargs)
    249             raise BleakDeviceNotFoundError(
    250                 self.address,
    251                 f"Device with address {self.address} was not found. It may have been removed from BlueZ when scanning stopped.",
    252             )
--> 254     assert_reply(reply)
    256 self._is_connected = True

File [~/miniforge3/envs/zed_dev2/lib/python3.10/site-packages/bleak/backends/bluezdbus/utils.py:20](http://localhost:9091/home/areiner/miniforge3/envs/zed_dev2/lib/python3.10/site-packages/bleak/backends/bluezdbus/utils.py#line=19), in assert_reply(reply)
     19 if reply.message_type == MessageType.ERROR:
---> 20     raise BleakDBusError(reply.error_name, reply.body)
     21 assert reply.message_type == MessageType.METHOD_RETURN

BleakDBusError: [org.bluez.Error.Failed] Operation already in progress

The above exception was the direct cause of the following exception:

ConnectFailed                             Traceback (most recent call last)
File [~/miniforge3/envs/zed_dev2/lib/python3.10/site-packages/open_gopro/ble/client.py:110](http://localhost:9091/home/areiner/miniforge3/envs/zed_dev2/lib/python3.10/site-packages/open_gopro/ble/client.py#line=109), in BleClient.open(self, timeout, retries)
    109 try:
--> 110     self._handle = await self._controller.connect(self._disconnected_cb, self._device, timeout=timeout)
    111     break

File [~/miniforge3/envs/zed_dev2/lib/python3.10/site-packages/open_gopro/ble/adapters/bleak_wrapper.py:249](http://localhost:9091/home/areiner/miniforge3/envs/zed_dev2/lib/python3.10/site-packages/open_gopro/ble/adapters/bleak_wrapper.py#line=248), in BleakWrapperController.connect(self, disconnect_cb, device, timeout)
    248     logger.warning(exception)
--> 249     raise ConnectFailed("BLE", 1, 1) from exception
    250 return client

ConnectFailed: BLE connection failed to establish after 1 retries with timeout 1

The above exception was the direct cause of the following exception:

ConnectFailed                             Traceback (most recent call last)
File [~/miniforge3/envs/zed_dev2/lib/python3.10/site-packages/open_gopro/gopro_wireless.py:294](http://localhost:9091/home/areiner/miniforge3/envs/zed_dev2/lib/python3.10/site-packages/open_gopro/gopro_wireless.py#line=293), in WirelessGoPro.open(self, timeout, retries)
    293 try:
--> 294     await self._open_ble(timeout, retries)
    296     # Set current dst-aware time. Don't assert on success since some old cameras don't support this command.

File [~/miniforge3/envs/zed_dev2/lib/python3.10/site-packages/open_gopro/gopro_wireless.py:583](http://localhost:9091/home/areiner/miniforge3/envs/zed_dev2/lib/python3.10/site-packages/open_gopro/gopro_wireless.py#line=582), in WirelessGoPro._open_ble(self, timeout, retries)
    582 # Establish connection, pair, etc.
--> 583 await self._ble.open(timeout, retries)
    584 # Start state maintenance

File [~/miniforge3/envs/zed_dev2/lib/python3.10/site-packages/open_gopro/ble/client.py:115](http://localhost:9091/home/areiner/miniforge3/envs/zed_dev2/lib/python3.10/site-packages/open_gopro/ble/client.py#line=114), in BleClient.open(self, timeout, retries)
    114         if retry == retries - 1:
--> 115             raise ConnectFailed("BLE", timeout, retries) from e
    117 assert self._handle is not None

ConnectFailed: BLE connection failed to establish after 5 retries with timeout 15

During handling of the above exception, another exception occurred:

GoProNotOpened                            Traceback (most recent call last)
Cell In[13], line 1
----> 1 r = await gp0.open()

File [~/miniforge3/envs/zed_dev2/lib/python3.10/site-packages/open_gopro/gopro_wireless.py:318](http://localhost:9091/home/areiner/miniforge3/envs/zed_dev2/lib/python3.10/site-packages/open_gopro/gopro_wireless.py#line=317), in WirelessGoPro.open(self, timeout, retries)
    316 except Exception as e:
    317     logger.error(f"Error while opening: {e}")
--> 318     await self.close()
    319     raise e

File [~/miniforge3/envs/zed_dev2/lib/python3.10/site-packages/open_gopro/gopro_wireless.py:329](http://localhost:9091/home/areiner/miniforge3/envs/zed_dev2/lib/python3.10/site-packages/open_gopro/gopro_wireless.py#line=328), in WirelessGoPro.close(self)
    321 async def close(self) -> None:
    322     """Safely stop the GoPro instance.
    323 
    324     This will disconnect BLE and WiFI if applicable.
   (...)
    327     prevent reconnection issues because the OS has never disconnected from the previous session.
    328     """
--> 329     await self._close_wifi()
    330     await self._close_ble()
    331     self._open = False

File [~/miniforge3/envs/zed_dev2/lib/python3.10/site-packages/open_gopro/gopro_wireless.py:805](http://localhost:9091/home/areiner/miniforge3/envs/zed_dev2/lib/python3.10/site-packages/open_gopro/gopro_wireless.py#line=804), in WirelessGoPro._close_wifi(self)
    803 async def _close_wifi(self) -> None:
    804     """Terminate the Wifi connection."""
--> 805     assert (await self.ble_command.enable_wifi_ap(enable=False)).ok
    806     if hasattr(self, "_wifi"):  # Corner case where instantiation fails before superclass is initialized
    807         self._wifi.close()

File [~/miniforge3/envs/zed_dev2/lib/python3.10/site-packages/open_gopro/api/builders.py:275](http://localhost:9091/home/areiner/miniforge3/envs/zed_dev2/lib/python3.10/site-packages/open_gopro/api/builders.py#line=274), in ble_write_command.<locals>.wrapper(wrapped, instance, _, kwargs)
    273 @wrapt.decorator
    274 async def wrapper(wrapped: Callable, instance: BleMessages, _: Any, kwargs: Any) -> GoProResp:
--> 275     return await instance._communicator._send_ble_message(message, rules, **(await wrapped(**kwargs) or kwargs))

File [~/miniforge3/envs/zed_dev2/lib/python3.10/site-packages/open_gopro/gopro_base.py:89](http://localhost:9091/home/areiner/miniforge3/envs/zed_dev2/lib/python3.10/site-packages/open_gopro/gopro_base.py#line=88), in ensure_opened.<locals>.wrapper(wrapped, instance, args, kwargs)
     86 @wrapt.decorator
     87 def wrapper(wrapped: Callable, instance: GoProBase, args: Any, kwargs: Any) -> Callable:
     88     if GoProMessageInterface.BLE in interface and not instance.is_ble_connected:
---> 89         raise GpException.GoProNotOpened("BLE not connected")
     90     if GoProMessageInterface.HTTP in interface and not instance.is_http_connected:
     91         raise GpException.GoProNotOpened("HTTP interface not connected")

GoProNotOpened: GoPro is not correctly open: BLE not connected

Screenshots If applicable, add screenshots to help explain your problem.

Hardware

  • Camera: Hero13 Black etc.
  • PC, Ubuntu 22.04

Additional Info

Here are some additional logs via btmon:

> HCI Event: Encryption Change (0x08) plen 4                                                                                                                                                                                   #453 [hci1] 39.779169
        Status: PIN or Key Missing (0x06)
        Handle: 16
        Encryption: Disabled (0x00)
< HCI Command: Disconnect (0x01|0x0006) plen 3                                                                                                                                                                                 #454 [hci1] 39.779438
        Handle: 16
        Reason: Authentication Failure (0x05)
> HCI Event: Command Status (0x0f) plen 4                                                                                                                                                                                      #455 [hci1] 39.781072
      Disconnect (0x01|0x0006) ncmd 2
        Status: Success (0x00)
> HCI Event: Disconnect Complete (0x05) plen 4                                                                                                                                                                                 #456 [hci1] 39.823092
        Status: Success (0x00)
        Handle: 16
        Reason: Connection Terminated By Local Host (0x16)
@ MGMT Event: Device Disconnected (0x000c) plen 8                                                                                                                                                                          {0x0001} [hci1] 39.823134
        LE Address: D6:DE:15:46:94:6E (Static)
        Reason: Connection terminated due to authentication failure (0x04)
@ MGMT Event: Connect Failed (0x000d) plen 8                                                                                                                                                                               {0x0001} [hci1] 39.843463
        LE Address: D6:DE:15:46:94:6E (Static)
        Status: Disconnected (0x0e)

areiner222 avatar Dec 17 '24 22:12 areiner222

Hey @areiner222 did you ever find a way to resolve this? I am having very similar issues.

MRL-00 avatar Mar 14 '25 02:03 MRL-00

@MRL-00 I never determined a very reliable way to reconnect... I have successfully connected via BLE + COHN up to 6 cameras but I can't get it to work consistently

@tcamise-gpsw is there a way to connect to the WirelessGoPro directly via https over COHN without connecting via BLE first?

areiner222 avatar Mar 20 '25 23:03 areiner222

This sounds similar to a discussion I was having in the bleak repo. I'm still trying to characterize this but at least on Windows there are situations you can get into where the OS automatically reconnects and you can thus no longer connect from bleak. Also, there is no way to "access" the existing connection.

@areiner222 about your above question about establishing without BLE...unfortunately no. The Python SDK was designed before COHN existed and not in a scalable enough way to handle any type / order of connections. I've since released the Kotlin SDK which does allow such scalable connecting and plan on refactoring the Python SDK to a similar design. But this is a fairly major effort and I'm not sure when I will get to it.

tcamise-gpsw avatar Mar 25 '25 20:03 tcamise-gpsw

FYI the Python SDK has been updated to allow directory connecting COHN without BLE.

@MRL-00 I never determined a very reliable way to reconnect... I have successfully connected via BLE + COHN up to 6 cameras but I can't get it to work consistently

@tcamise-gpsw is there a way to connect to the WirelessGoPro directly via https over COHN without connecting via BLE first?

tcamise-gpsw avatar Jun 26 '25 17:06 tcamise-gpsw

@tcamise-gpsw did you ever manage to find the cause of GoPros not reconnecting if they turn off or batteries are removed from them?

We still see this happening randomly with certain devices. If we connect to 4 devices on one day, then overnight the devices power off, if we try to connect to the same 4 devices the next day, 2 of them may reconnect but 2 of them appear to fail. They have to be manually put back into pairing mode before they will reconnect.

I don't think this is a Bleak issue as we are not using the Python SDK.

MRL-00 avatar Oct 07 '25 23:10 MRL-00

I recently had the same problem. I have a device with an NRF52840 chip that connects to a GoPro13. The device pairs successfully and then connects successfully for a few days. But at some point, it stops connecting. The connection doesn't work until I pair it again. I looked for the problem in my NRF52840 code and asked a question on the Nordic support forum (https://devzone.nordicsemi.com/f/nordic-q-a/124754/ble-connection-to-paired-device-failed-after-some-time). I have wireshark logs of the pairing, successful connection, and unsuccessful connection.

If the problem is with the GoPro, is there on GoPro Lab firmware version? What about other GoPro versions? In my case, the problem is only with my NRF52 device; other devices (remote control, laptop, phone) continue to connect successfully.

Sergey1560 avatar Oct 08 '25 18:10 Sergey1560

This falls under the same bucket as the pinned issue: #487

Basically there needs to be large investigation into how the Python SDK (and bleak) handle nongraceful reconnections.

I'll close this and follow ups can be done in #487

tcamise-gpsw avatar Nov 07 '25 17:11 tcamise-gpsw