Skip to content

Commit

Permalink
chore: add docstrings and enable linting
Browse files Browse the repository at this point in the history
Also rename some functions for clarity.

Signed-off-by: Felix Kaechele <felix@kaechele.ca>
  • Loading branch information
kaechele committed Feb 26, 2023
1 parent 4fda679 commit 4d0eedd
Show file tree
Hide file tree
Showing 13 changed files with 158 additions and 51 deletions.
9 changes: 4 additions & 5 deletions pyproject.toml
Original file line number Diff line number Diff line change
Expand Up @@ -114,9 +114,6 @@ load-plugins = [
[tool.pylint."MESSAGES CONTROL"]
disable = [
"format",
"missing-module-docstring", # no docs yet
"missing-class-docstring",
"missing-function-docstring",
"not-context-manager",
"too-few-public-methods",
"too-many-ancestors",
Expand All @@ -142,9 +139,11 @@ expected-line-ending-format = "LF"

[tool.ruff]
target-version = "py310"
exclude = ["docs"]
exclude = ["docs", "setup.py"]

# Let's tone this down once we release the first version
select = ["ALL"]
ignore = ["D","ANN101", "I001", "COM"] # no docs yet
ignore = ["ANN101", "I001", "COM"]
unfixable = ["ERA"]

# Same as Black.
Expand Down
1 change: 1 addition & 0 deletions src/bonaparte/__init__.py
Original file line number Diff line number Diff line change
@@ -1,3 +1,4 @@
"""The Bonaparte Library."""
from __future__ import annotations

__version__ = "0.1.0"
Expand Down
22 changes: 21 additions & 1 deletion src/bonaparte/const.py
Original file line number Diff line number Diff line change
@@ -1,3 +1,5 @@
"""Constants for Napoleon eFIRE devices."""

from __future__ import annotations

from enum import IntEnum
Expand Down Expand Up @@ -30,6 +32,8 @@


class Feature(StrEnum):
"""Enum encapsulating possible device features."""

AUX = "aux"
BLOWER = "blower"
LED_LIGHTS = "led_lights"
Expand All @@ -39,7 +43,7 @@ class Feature(StrEnum):


class EfireCommand(IntEnum):
"""Command names to hex value Enum Class."""
"""Enum encapsulating device commands and their raw hex values."""

SET_IFC_CMD1 = 0x27
SET_IFC_CMD2 = 0x28
Expand Down Expand Up @@ -71,45 +75,61 @@ class EfireCommand(IntEnum):


class ReturnCode(IntEnum):
"""Enum encapsulating command return codes."""

SUCCESS = 0x00
FAILURE = 0x01


class PowerState(IntEnum):
"""Enum encapsulating device power states."""

OFF = 0x00
ON = 0xFF


class AuxControlState(IntEnum):
"""Enum encapsulating return values for remote control use."""

USED = 0x00
NOT_USED = 0xFF


class PasswordAction(IntEnum):
"""Enum encapsulating the values for password actions."""

RESET = 0x3F
SET = 0xF5


class PasswordCommandResult(IntEnum):
"""Enum encapsulating possible return values for password actions."""

SET_SUCCESS = 0x00
SET_FAILED = 0x01
INVALID_PASSWORD = 0x19
LOGIN_SUCCESS = 0x35


class PasswordSetResult(IntEnum):
"""Enum encapsulating return values for authentication requests."""

FAILED = 0x25
SUCCESS = 0x53


class LedState(MultiValueEnum):
"""Enum encapsulating LED controller state."""

_init_ = "short long"

OFF = 0x00, "0x000000"
ON = 0xFF, 0xFFFFFF


class LedMode(MultiValueEnum):
"""Enum encapsulating LED controller modes."""

_init_ = "short long setvalue"

CYCLE = 0x01, 0x010101, 0x20
Expand Down
36 changes: 18 additions & 18 deletions src/bonaparte/device.py
Original file line number Diff line number Diff line change
@@ -1,3 +1,5 @@
"""A generic device class for Napoleon eFIRE devices."""

from __future__ import annotations

import asyncio
Expand Down Expand Up @@ -65,6 +67,8 @@ async def _raise_if_not_connected(


class EfireDevice:
"""A generic eFIRE Device."""

_ble_device: BLEDevice
_client: BleakClientWithServiceCache | None = None
_connect_lock: asyncio.Lock
Expand All @@ -80,6 +84,7 @@ class EfireDevice:
def __init__(
self, ble_device: BLEDevice, advertisement_data: AdvertisementData | None = None
) -> None:
"""Initialize the eFIRE Device."""
self._address = ble_device.address
self._advertisement_data = advertisement_data
self._ble_device = ble_device
Expand All @@ -94,29 +99,30 @@ def __init__(

@property
def name(self) -> str:
"""Device name or, if unavailable, the device address."""
return self._ble_device.name or self._ble_device.address

@property
def address(self) -> str:
"""The device's Bluetooth MAC address."""
return self._address

@property
def rssi(self) -> int | None:
"""Get the rssi of the device."""
"""Get the RSSI of the device."""
if self._advertisement_data:
return self._advertisement_data.rssi
return None

def set_ble_device_and_advertisement_data(
self, ble_device: BLEDevice, advertisement_data: AdvertisementData
) -> None:
"""Set the ble device and advertisement data."""
"""Set the BLE Device and advertisement data."""
self._ble_device = ble_device
self._advertisement_data = advertisement_data

async def _ensure_connected(self) -> None:
"""Connects to the device."""

"""Connect to the device and ensure we stay connected."""
if self._connect_lock.locked():
_LOGGER.debug(
(
Expand Down Expand Up @@ -169,7 +175,7 @@ def _reset_disconnect_timer(self) -> None:
if not self._loop:
self._loop = asyncio.get_running_loop()
self._disconnect_timer = self._loop.call_later(
DISCONNECT_DELAY, self._disconnect
DISCONNECT_DELAY, self._timed_disconnect
)

def _disconnected(self, _client: BleakClientWithServiceCache) -> None:
Expand All @@ -196,12 +202,7 @@ def unregister() -> None:
self._disconnect_callbacks.append(callback)
return unregister

async def disconnect(self) -> None:
"""Disconnect the Fireplace."""
_LOGGER.debug("%s: Stop", self.name)
await self._execute_disconnect()

def _disconnect(self) -> Task[None]:
def _timed_disconnect(self) -> Task[None]:
"""Disconnect from device."""
self._disconnect_timer = None
return asyncio.create_task(self._execute_timed_disconnect())
Expand All @@ -213,10 +214,10 @@ async def _execute_timed_disconnect(self) -> None:
self.name,
DISCONNECT_DELAY,
)
await self._execute_disconnect()
await self.disconnect()

async def _execute_disconnect(self) -> None:
"""Execute disconnection."""
async def disconnect(self) -> None:
"""Disconnect from device."""
async with self._connect_lock:
read_char = self._read_char
client = self._client
Expand Down Expand Up @@ -290,7 +291,6 @@ async def _notification_handler(
@retry_bluetooth_connection_error(DEFAULT_ATTEMPTS)
async def _execute_locked(self, message: bytes | bytearray) -> bytes:
"""Send command to device and read response."""

if not self._write_char:
msg = "Write characteristic missing"
raise CharacteristicMissingError(msg)
Expand All @@ -315,14 +315,14 @@ async def _execute_locked(self, message: bytes | bytearray) -> bytes:
BLEAK_BACKOFF_TIME,
ex,
)
await self._execute_disconnect()
await self.disconnect()
raise
except BleakError as ex:
# Disconnect so we can reset state and try again
_LOGGER.debug(
"%s: RSSI: %s; Disconnecting due to error: %s", self.name, self.rssi, ex
)
await self._execute_disconnect()
await self.disconnect()
raise
return result

Expand All @@ -331,7 +331,6 @@ async def _execute(
message: bytes | bytearray,
) -> bytes:
"""Send command to device and read response."""

await self._ensure_connected()

_LOGGER.debug(
Expand Down Expand Up @@ -375,6 +374,7 @@ async def _execute(
async def execute_command(
self, command: int, parameter: int | bytes | bytearray | None = None
) -> bytes:
"""Execute a command on the device."""
payload = bytearray([command])

if parameter:
Expand Down
19 changes: 8 additions & 11 deletions src/bonaparte/exceptions.py
Original file line number Diff line number Diff line change
@@ -1,33 +1,30 @@
"""Exceptions used in the Bonaparte library."""
from __future__ import annotations


class EfireException(Exception): # noqa: N818
pass
"""Generic eFIRE device exception."""


class AuthError(EfireException):
pass
"""For when authentication fails."""


class CommandFailedException(EfireException):
pass
"""For when a command returns a failure."""


class DisconnectedException(EfireException):
pass
"""For when the device is disconnected and we try to use it."""


class FeatureNotSupported(EfireException):
pass


class ResponseError(EfireException):
pass
"""For when a feature is accessed that the device is not set up for."""


class EfireMessageValueError(ValueError):
pass
"""For when an invalid message is received or generated."""


class CharacteristicMissingError(EfireException):
pass
"""For when a required BLE GATT characteristic is missing."""
Loading

0 comments on commit 4d0eedd

Please # to comment.