From 2b4de8e46eef02e8b572c3f1188063061ead5d0b Mon Sep 17 00:00:00 2001 From: Tim Camise Date: Tue, 15 Aug 2023 20:23:42 +0100 Subject: [PATCH 1/4] Handle more bluetoothctl use cases --- .../open_gopro/ble/adapters/bleak_wrapper.py | 8 +++++--- .../python/sdk_wireless_camera_control/open_gopro/util.py | 2 +- 2 files changed, 6 insertions(+), 4 deletions(-) diff --git a/demos/python/sdk_wireless_camera_control/open_gopro/ble/adapters/bleak_wrapper.py b/demos/python/sdk_wireless_camera_control/open_gopro/ble/adapters/bleak_wrapper.py index f100399d..abbb1fce 100644 --- a/demos/python/sdk_wireless_camera_control/open_gopro/ble/adapters/bleak_wrapper.py +++ b/demos/python/sdk_wireless_camera_control/open_gopro/ble/adapters/bleak_wrapper.py @@ -317,9 +317,11 @@ async def _async_def_pair() -> None: else: # We're not paired so do it now bluetoothctl.sendline(f"pair {handle.address}") - bluetoothctl.expect("Accept pairing") - bluetoothctl.sendline("yes") - bluetoothctl.expect("Pairing successful") + if (match := bluetoothctl.expect(["Accept pairing", "Pairing successful"])) == 0: + bluetoothctl.sendline("yes") + bluetoothctl.expect("Pairing successful") + elif match == 1: # We received pairing successful so nothing else to do + pass elif OS == "Darwin": # No pairing on Mac diff --git a/demos/python/sdk_wireless_camera_control/open_gopro/util.py b/demos/python/sdk_wireless_camera_control/open_gopro/util.py index 5d6c3982..15cfe3e1 100644 --- a/demos/python/sdk_wireless_camera_control/open_gopro/util.py +++ b/demos/python/sdk_wireless_camera_control/open_gopro/util.py @@ -67,7 +67,7 @@ def __init__( "open_gopro.api.http_commands": logging.DEBUG, "open_gopro.api.ble_commands": logging.DEBUG, "open_gopro.communication_client": logging.DEBUG, - "open_gopro.ble.adapters.bleak_wrapper": logging.INFO, + "open_gopro.ble.adapters.bleak_wrapper": logging.INFO, # DEBUG for pexpect communication "open_gopro.ble.client": logging.DEBUG, "open_gopro.wifi.adapters.wireless": logging.DEBUG, "open_gopro.responses": logging.DEBUG, From 1ce9aae1a22f68c39d8b183c39a800f8be488848 Mon Sep 17 00:00:00 2001 From: Tim Camise Date: Tue, 15 Aug 2023 13:00:47 -0700 Subject: [PATCH 2/4] Check for pairing differently on newer bluez versions --- .../open_gopro/ble/adapters/bleak_wrapper.py | 14 ++++++++++++-- 1 file changed, 12 insertions(+), 2 deletions(-) diff --git a/demos/python/sdk_wireless_camera_control/open_gopro/ble/adapters/bleak_wrapper.py b/demos/python/sdk_wireless_camera_control/open_gopro/ble/adapters/bleak_wrapper.py index abbb1fce..5f3a2ef3 100644 --- a/demos/python/sdk_wireless_camera_control/open_gopro/ble/adapters/bleak_wrapper.py +++ b/demos/python/sdk_wireless_camera_control/open_gopro/ble/adapters/bleak_wrapper.py @@ -8,6 +8,7 @@ import logging import platform import threading +from packaging.version import Version from typing import Pattern, Any, Callable, Optional import pexpect @@ -307,9 +308,18 @@ async def _async_def_pair() -> None: if logger.level == logging.DEBUG: bluetoothctl.logfile = sys.stdout.buffer bluetoothctl.expect("Agent registered") + # Get the version + bluetoothctl.sendline("version") + bluetoothctl.expect(r"Version") + bluetoothctl.expect(r"\n") + version = Version(bluetoothctl.before.decode("utf-8").strip()) # First see if we are already paired - bluetoothctl.sendline("paired-devices") - bluetoothctl.expect("paired-devices") + if version >= Version("5.66"): + bluetoothctl.sendline("devices Paired") + bluetoothctl.expect("devices Paired") + else: + bluetoothctl.sendline("paired-devices") + bluetoothctl.expect("paired-devices") bluetoothctl.expect(r"#") for device in bluetoothctl.before.decode("utf-8").splitlines(): if "Device" in device and device.split()[1] == handle.address: From 905309b0dfde4e37ae15cc07e5075a66f7f444ee Mon Sep 17 00:00:00 2001 From: Tim Camise Date: Tue, 15 Aug 2023 21:15:15 +0100 Subject: [PATCH 3/4] Isort imports --- .../open_gopro/ble/adapters/bleak_wrapper.py | 28 +++++++------------ 1 file changed, 10 insertions(+), 18 deletions(-) diff --git a/demos/python/sdk_wireless_camera_control/open_gopro/ble/adapters/bleak_wrapper.py b/demos/python/sdk_wireless_camera_control/open_gopro/ble/adapters/bleak_wrapper.py index 5f3a2ef3..550f591f 100644 --- a/demos/python/sdk_wireless_camera_control/open_gopro/ble/adapters/bleak_wrapper.py +++ b/demos/python/sdk_wireless_camera_control/open_gopro/ble/adapters/bleak_wrapper.py @@ -3,34 +3,25 @@ """Manage a Bluetooth connection using bleak.""" -import sys import asyncio import logging import platform +import sys import threading -from packaging.version import Version -from typing import Pattern, Any, Callable, Optional +from typing import Any, Callable, Optional, Pattern import pexpect -from bleak import BleakScanner, BleakClient -from bleak.backends.device import BLEDevice as BleakDevice +from bleak import BleakClient, BleakScanner from bleak.backends.characteristic import BleakGATTCharacteristic +from bleak.backends.device import BLEDevice as BleakDevice from bleak.backends.scanner import AdvertisementData +from packaging.version import Version -from open_gopro.util import Singleton -from open_gopro.ble import ( - Service, - Characteristic, - Descriptor, - GattDB, - BLEController, - NotiHandlerType, - FailedToFindDevice, - BleUUID, - UUIDs, - CharProps, -) +from open_gopro.ble import (BLEController, BleUUID, Characteristic, CharProps, + Descriptor, FailedToFindDevice, GattDB, + NotiHandlerType, Service, UUIDs) from open_gopro.exceptions import ConnectFailed +from open_gopro.util import Singleton logger = logging.getLogger(__name__) @@ -303,6 +294,7 @@ def pair(self, handle: BleakClient) -> None: async def _async_def_pair() -> None: logger.debug("Attempting to pair...") if (OS := platform.system()) == "Linux": + logger.info("Pairing with bluetoothctl") # Manually control bluetoothctl on Linux bluetoothctl = pexpect.spawn("bluetoothctl") if logger.level == logging.DEBUG: From b77fabdfdf246ddde7bc49e867784eb7b23195b7 Mon Sep 17 00:00:00 2001 From: Tim Camise Date: Tue, 15 Aug 2023 21:22:11 +0100 Subject: [PATCH 4/4] Revert isort, manually sort --- .../open_gopro/ble/adapters/bleak_wrapper.py | 27 ++++++++++++------- 1 file changed, 18 insertions(+), 9 deletions(-) diff --git a/demos/python/sdk_wireless_camera_control/open_gopro/ble/adapters/bleak_wrapper.py b/demos/python/sdk_wireless_camera_control/open_gopro/ble/adapters/bleak_wrapper.py index 550f591f..d51543f2 100644 --- a/demos/python/sdk_wireless_camera_control/open_gopro/ble/adapters/bleak_wrapper.py +++ b/demos/python/sdk_wireless_camera_control/open_gopro/ble/adapters/bleak_wrapper.py @@ -3,25 +3,34 @@ """Manage a Bluetooth connection using bleak.""" +import sys import asyncio import logging import platform -import sys import threading -from typing import Any, Callable, Optional, Pattern +from typing import Pattern, Any, Callable, Optional import pexpect -from bleak import BleakClient, BleakScanner -from bleak.backends.characteristic import BleakGATTCharacteristic +from packaging.version import Version +from bleak import BleakScanner, BleakClient from bleak.backends.device import BLEDevice as BleakDevice +from bleak.backends.characteristic import BleakGATTCharacteristic from bleak.backends.scanner import AdvertisementData -from packaging.version import Version -from open_gopro.ble import (BLEController, BleUUID, Characteristic, CharProps, - Descriptor, FailedToFindDevice, GattDB, - NotiHandlerType, Service, UUIDs) -from open_gopro.exceptions import ConnectFailed from open_gopro.util import Singleton +from open_gopro.ble import ( + Service, + Characteristic, + Descriptor, + GattDB, + BLEController, + NotiHandlerType, + FailedToFindDevice, + BleUUID, + UUIDs, + CharProps, +) +from open_gopro.exceptions import ConnectFailed logger = logging.getLogger(__name__)