Skip to content

Commit

Permalink
Merge pull request hbldh#340 from hbldh/release/0.9.0
Browse files Browse the repository at this point in the history
Release/0.9.0
  • Loading branch information
hbldh authored Oct 20, 2020
2 parents 99f3b73 + f6f4349 commit 4dc6ee4
Show file tree
Hide file tree
Showing 32 changed files with 605 additions and 290 deletions.
12 changes: 6 additions & 6 deletions .gitattributes
Original file line number Diff line number Diff line change
Expand Up @@ -17,7 +17,7 @@
#
# Merging from the command prompt will add diff markers to the files if there
# are conflicts (Merging from VS is not affected by the settings below, in VS
# the diff markers are never inserted). Diff markers may cause the following
# the diff markers are never inserted). Diff markers may cause the following
# file extensions to fail to load in VS. An alternative would be to treat
# these files as binary and thus will always conflict and require user
# intervention with every merge. To do so, just uncomment the entries below
Expand All @@ -40,15 +40,15 @@
#
# image files are treated as binary by default.
###############################################################################
#*.jpg binary
#*.png binary
#*.gif binary
*.jpg binary
*.png binary
*.gif binary

###############################################################################
# diff behavior for common document formats
#
#
# Convert binary document formats to text before diffing them. This feature
# is only available from the command line. Turn it on by uncommenting the
# is only available from the command line. Turn it on by uncommenting the
# entries below.
###############################################################################
#*.doc diff=astextplain
Expand Down
10 changes: 1 addition & 9 deletions .github/workflows/build_and_test.yml
Original file line number Diff line number Diff line change
Expand Up @@ -27,16 +27,8 @@ jobs:
run: python -m pip install --upgrade pip setuptools wheel
- name: Install dependencies
run: pip install -r requirements.txt
- name: Install develoment dependencies
- name: Install development dependencies
run: pip install -r requirements_dev.txt
- name: Check code formatting with black
run: black . --diff
- name: Lint with flake8
run: |
# stop the build if there are Python syntax errors or undefined names
flake8 . --count --select=E9,F63,F7,F82 --show-source --statistics
# exit-zero treats all errors as warnings. Default line length of black is 88
flake8 . --count --exit-zero --max-complexity=10 --max-line-length=88 --statistics
- name: Test with pytest
run: |
pytest tests --junitxml=junit/test-results-${{ matrix.os }}-${{ matrix.python-version }}.xml --cov=com --cov-report=xml --cov-report=html
Expand Down
28 changes: 28 additions & 0 deletions .github/workflows/format_and_lint.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,28 @@
name: Format and Lint

on:
push:
branches: [ master, develop ]
pull_request:
branches: [ master, develop ]

jobs:
format_and_lint:
name: "Format and lint"
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v2
- name: Set up Python
uses: actions/setup-python@v2
- name: Upgrade pip. setuptools and wheel
run: python -m pip install --upgrade pip setuptools wheel
- name: Install development dependencies
run: pip install -r requirements_dev.txt
- name: Check code formatting with black
run: black . --check --diff
- name: Lint with flake8
run: |
# stop the build if there are Python syntax errors or undefined names
flake8 . --count --select=E9,F63,F7,F82 --show-source --statistics
# exit-zero treats all errors as warnings. Default line length of black is 88
flake8 . --count --exit-zero --max-complexity=10 --max-line-length=88 --statistics
48 changes: 47 additions & 1 deletion CHANGELOG.rst
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,51 @@ All notable changes to this project will be documented in this file.
The format is based on `Keep a Changelog <https://keepachangelog.com/en/1.0.0/>`_,
and this project adheres to `Semantic Versioning <https://semver.org/spec/v2.0.0.html>`_.

`0.9.0`_ (2020-10-20)
---------------------

Added
~~~~~

* Timeout for BlueZ backend connect call to avoid potential infinite hanging. Merged #306.
* Added Interfaces API docs again.
* Troubleshooting documentation.
* noqa flags added to ``BleakBridge`` imports.
* Adding a timeout on OSX so that the connect cannot hang forever. Merge #336.

Changed
~~~~~~~

* ``BleakCharacteristic.description()`` on .NET now returns the same value as
other platforms.
* Changed all adding and removal of .NET event handler from ``+=``/``-=`` syntax to
calling ``add_`` and ``remove_`` methods instead. This allows for proper
removal of event handlers in .NET backend.
* All code dependence on the ``BleakBridge`` is now removed. It is only imported to
allow for access to UWP namespaces.
* Removing internal method ``_start_notify`` in the .NET backend.
* ``GattSession`` object now manages lifetime of .NET ``BleakClient`` connection.
* ``BleakClient`` in .NET backend will reuse previous device information when
reconnecting so that it doesn't have to scan/discover again.


Fixed
~~~~~

* UUID property bug fixed in BlueZ backend. Merged #307.
* Fix for broken RTD documentation.
* Fix UUID string arguments should not be case sensitive.
* Fix ``BleakGATTService.get_characteristic()`` method overridden with ``NotImplementedError``
in BlueZ backend.
* Fix ``AttributeError`` when trying to connect using CoreBluetooth backend. Merged #323.
* Fix disconnect callback called multiple times in .NET backend. Fixes #312.
* Fix ``BleakClient.disconnect()`` method failing when called multiple times in
.NET backend. Fixes #313.
* Fix ``BleakClient.disconnect()`` method failing when called multiple times in
Core Bluetooth backend. Merge #333.
* Catch RemoteError in ``is_connected`` in BlueZ backend. Fixes #310,
* Prevent overwriting address in constructor of ``BleakClient`` in BlueZ backend. Merge #311.
* Fix nordic uart UUID. Merge #339.

`0.8.0`_ (2020-09-22)
---------------------
Expand Down Expand Up @@ -302,7 +347,8 @@ Fixed
* Bleak created.


.. _Unreleased: https://github.com/hbldh/bleak/compare/v0.8.0...develop
.. _Unreleased: https://github.com/hbldh/bleak/compare/v0.9.0...develop
.. _0.9.0: https://github.com/hbldh/bleak/compare/v0.9.0...v0.8.0
.. _0.8.0: https://github.com/hbldh/bleak/compare/v0.8.0...v0.7.1
.. _0.7.1: https://github.com/hbldh/bleak/compare/v0.7.1...v0.7.0
.. _0.7.0: https://github.com/hbldh/bleak/compare/v0.7.0...v0.6.4
Expand Down
2 changes: 1 addition & 1 deletion bleak/__version__.py
Original file line number Diff line number Diff line change
@@ -1,3 +1,3 @@
# -*- coding: utf-8 -*-

__version__ = "0.8.0"
__version__ = "0.9.0"
6 changes: 0 additions & 6 deletions bleak/backends/bluezdbus/characteristic.py
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,6 @@

from bleak.backends.characteristic import BleakGATTCharacteristic
from bleak.backends.descriptor import BleakGATTDescriptor
from bleak.uuids import uuidstr_to_str


_GattCharacteristicsFlagsEnum = {
Expand Down Expand Up @@ -54,11 +53,6 @@ def uuid(self) -> str:
"""The uuid of this characteristic"""
return self.obj.get("UUID")

@property
def description(self) -> str:
"""Description for this characteristic"""
return uuidstr_to_str(self._uuid)

@property
def properties(self) -> List:
"""Properties of this characteristic
Expand Down
7 changes: 5 additions & 2 deletions bleak/backends/bluezdbus/client.py
Original file line number Diff line number Diff line change
Expand Up @@ -50,7 +50,6 @@ class BleakClientBlueZDBus(BaseBleakClient):
def __init__(self, address_or_ble_device: Union[BLEDevice, str], **kwargs):
super(BleakClientBlueZDBus, self).__init__(address_or_ble_device, **kwargs)
self.device = kwargs.get("device") if kwargs.get("device") else "hci0"
self.address = address_or_ble_device

# Backend specific, TXDBus objects and data
if isinstance(address_or_ble_device, BLEDevice):
Expand Down Expand Up @@ -86,8 +85,8 @@ async def connect(self, **kwargs) -> bool:
"""
# A Discover must have been run before connecting to any devices.
# Find the desired device before trying to connect.
timeout = kwargs.get("timeout", self._timeout)
if self._device_path is None:
timeout = kwargs.get("timeout", self._timeout)
device = await BleakScannerBlueZDBus.find_device_by_address(
self.address, timeout=timeout, device=self.device
)
Expand Down Expand Up @@ -129,6 +128,7 @@ def _services_resolved_callback(message):
"Connect",
interface=defs.DEVICE_INTERFACE,
destination=defs.BLUEZ_SERVICE,
timeout=timeout,
).asFuture(loop)
except RemoteError as e:
await self._cleanup_all()
Expand Down Expand Up @@ -350,6 +350,9 @@ async def is_connected(self) -> bool:
except ConnectionDone:
# Twisted error stating that "Connection was closed cleanly."
pass
except RemoteError as e:
if e.errName != "org.freedesktop.DBus.Error.UnknownObject":
raise
except Exception as e:
# Do not want to silence unknown errors. Send this upwards.
raise
Expand Down
6 changes: 0 additions & 6 deletions bleak/backends/bluezdbus/descriptor.py
Original file line number Diff line number Diff line change
@@ -1,5 +1,4 @@
from bleak.backends.descriptor import BleakGATTDescriptor
from bleak.uuids import uuidstr_to_str


class BleakGATTDescriptorBlueZDBus(BleakGATTDescriptor):
Expand Down Expand Up @@ -42,8 +41,3 @@ def handle(self) -> int:
def path(self) -> str:
"""The DBus path. Mostly needed by `bleak`, not by end user"""
return self.__path

@property
def description(self) -> str:
"""Description for this descriptor"""
return uuidstr_to_str(self.uuid)
6 changes: 0 additions & 6 deletions bleak/backends/bluezdbus/service.py
Original file line number Diff line number Diff line change
Expand Up @@ -23,12 +23,6 @@ def characteristics(self) -> List[BleakGATTCharacteristicBlueZDBus]:
"""List of characteristics for this service"""
return self.__characteristics

def get_characteristic(
self, _uuid: Union[str, UUID]
) -> Union[BleakGATTCharacteristicBlueZDBus, None]:
"""Get a characteristic by UUID"""
raise NotImplementedError()

def add_characteristic(self, characteristic: BleakGATTCharacteristicBlueZDBus):
"""Add a :py:class:`~BleakGATTCharacteristicBlueZDBus` to the service.
Expand Down
4 changes: 2 additions & 2 deletions bleak/backends/characteristic.py
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,7 @@
from typing import List, Union, Any

from bleak.backends.descriptor import BleakGATTDescriptor
from bleak.uuids import uuidstr_to_str


class GattCharacteristicsFlags(enum.Enum):
Expand Down Expand Up @@ -54,10 +55,9 @@ def uuid(self) -> str:
raise NotImplementedError()

@property
@abc.abstractmethod
def description(self) -> str:
"""Description for this characteristic"""
raise NotImplementedError()
return uuidstr_to_str(self.uuid)

@property
@abc.abstractmethod
Expand Down
49 changes: 37 additions & 12 deletions bleak/backends/corebluetooth/CentralManagerDelegate.py
Original file line number Diff line number Diff line change
Expand Up @@ -36,9 +36,7 @@
from bleak.backends.corebluetooth.PeripheralDelegate import PeripheralDelegate
from bleak.backends.corebluetooth.device import BLEDeviceCoreBluetooth


logger = logging.getLogger(__name__)

CBCentralManagerDelegate = objc.protocolNamed("CBCentralManagerDelegate")

try:
Expand Down Expand Up @@ -77,6 +75,7 @@ def init(self):

self.callbacks = {}
self.disconnected_callback = None
self._connection_state_changed = asyncio.Event()

self.central_manager = CBCentralManager.alloc().initWithDelegate_queue_(
self, dispatch_queue_create(b"bleak.corebluetooth", DISPATCH_QUEUE_SERIAL)
Expand Down Expand Up @@ -142,18 +141,29 @@ async def scanForPeripherals_(self, scan_options) -> List[CBPeripheral]:
await asyncio.sleep(float(scan_options.get("timeout", 0.0)))
return await self.stop_scan()

async def connect_(self, peripheral: CBPeripheral) -> bool:
async def connect_(self, peripheral: CBPeripheral, timeout=10.0) -> bool:
self._connection_state = CMDConnectionState.PENDING
self._connection_state_changed.clear()
self.central_manager.connectPeripheral_options_(peripheral, None)

while self._connection_state == CMDConnectionState.PENDING:
await asyncio.sleep(0)
try:
await asyncio.wait_for(
self._connection_state_changed.wait(), timeout=timeout
)
except asyncio.TimeoutError:
logger.debug(f"Connection timed out after {timeout} seconds.")
self.central_manager.cancelPeripheralConnection_(peripheral)
raise

self.connected_peripheral = peripheral

return self._connection_state == CMDConnectionState.CONNECTED

async def disconnect(self) -> bool:
# Is a peripheral even connected?
if self.connected_peripheral is None:
return True

self._connection_state = CMDConnectionState.PENDING
self.central_manager.cancelPeripheralConnection_(self.connected_peripheral)

Expand Down Expand Up @@ -187,7 +197,8 @@ def did_update_state(self, centralManager):
def centralManagerDidUpdateState_(self, centralManager):
logger.debug("centralManagerDidUpdateState_")
self.event_loop.call_soon_threadsafe(
self.did_update_state, centralManager,
self.did_update_state,
centralManager,
)

@objc.python_method
Expand Down Expand Up @@ -234,8 +245,8 @@ def did_discover_peripheral(
callback(peripheral, advertisementData, RSSI)

logger.debug(
"Discovered device {}: {} @ RSSI: {} (kCBAdvData {})".format(
uuid_string, device.name, RSSI, advertisementData.keys()
"Discovered device {}: {} @ RSSI: {} (kCBAdvData {}) and Central: {}".format(
uuid_string, device.name, RSSI, advertisementData.keys(), central
)
)

Expand All @@ -248,7 +259,11 @@ def centralManager_didDiscoverPeripheral_advertisementData_RSSI_(
):
logger.debug("centralManager_didDiscoverPeripheral_advertisementData_RSSI_")
self.event_loop.call_soon_threadsafe(
self.did_discover_peripheral, central, peripheral, advertisementData, RSSI,
self.did_discover_peripheral,
central,
peripheral,
advertisementData,
RSSI,
)

@objc.python_method
Expand All @@ -264,11 +279,14 @@ def did_connect_peripheral(self, central, peripheral):
)
self.connected_peripheral_delegate = peripheralDelegate
self._connection_state = CMDConnectionState.CONNECTED
self._connection_state_changed.set()

def centralManager_didConnectPeripheral_(self, central, peripheral):
logger.debug("centralManager_didConnectPeripheral_")
self.event_loop.call_soon_threadsafe(
self.did_connect_peripheral, central, peripheral,
self.did_connect_peripheral,
central,
peripheral,
)

@objc.python_method
Expand All @@ -281,13 +299,17 @@ def did_fail_to_connect_peripheral(
)
)
self._connection_state = CMDConnectionState.DISCONNECTED
self._connection_state_changed.set()

def centralManager_didFailToConnectPeripheral_error_(
self, centralManager: CBCentralManager, peripheral: CBPeripheral, error: NSError
):
logger.debug("centralManager_didFailToConnectPeripheral_error_")
self.event_loop.call_soon_threadsafe(
self.did_fail_to_connect_peripheral, centralManager, peripheral, error,
self.did_fail_to_connect_peripheral,
centralManager,
peripheral,
error,
)

@objc.python_method
Expand All @@ -307,7 +329,10 @@ def centralManager_didDisconnectPeripheral_error_(
):
logger.debug("centralManager_didDisconnectPeripheral_error_")
self.event_loop.call_soon_threadsafe(
self.did_disconnect_peripheral, central, peripheral, error,
self.did_disconnect_peripheral,
central,
peripheral,
error,
)


Expand Down
Loading

0 comments on commit 4dc6ee4

Please sign in to comment.