diff --git a/examples/device_scanner.py b/examples/device_scanner.py index 8ab61da..78d35bb 100644 --- a/examples/device_scanner.py +++ b/examples/device_scanner.py @@ -1,5 +1,8 @@ +from __future__ import annotations + import asyncio import logging +import sys from findmy import KeyPair from findmy.scanner import ( @@ -10,11 +13,6 @@ from findmy.scanner import ( logging.basicConfig(level=logging.INFO) -# Set if you want to check whether a specific key (or accessory!) is in the scan results. -# Make sure to enter its private key! -# Leave empty (= None) to not check. -CHECK_KEY = KeyPair.from_b64("") - def _print_nearby(device: NearbyOfflineFindingDevice) -> None: print(f"NEARBY Device - {device.mac_address}") @@ -37,7 +35,7 @@ def _print_separated(device: SeparatedOfflineFindingDevice) -> None: print() -async def scan() -> None: +async def scan(check_key: KeyPair | None = None) -> None: scanner = await OfflineFindingScanner.create() print("Scanning for FindMy-devices...") @@ -55,14 +53,18 @@ async def scan() -> None: print() continue - if CHECK_KEY and device.is_from(CHECK_KEY): + if check_key and device.is_from(check_key): scan_device = device if scan_device: print("Key or accessory was found in scan results! :D") - elif CHECK_KEY: + elif check_key: print("Selected key or accessory was not found in scan results... :c") if __name__ == "__main__": - asyncio.run(scan()) + key = None + if len(sys.argv) >= 2: + key = KeyPair.from_b64(sys.argv[1]) + + asyncio.run(scan(key)) diff --git a/findmy/scanner/scanner.py b/findmy/scanner/scanner.py index b7e4aa0..af10f12 100644 --- a/findmy/scanner/scanner.py +++ b/findmy/scanner/scanner.py @@ -30,13 +30,6 @@ class OfflineFindingDevice(ABC): OF_HEADER_SIZE = 2 OF_TYPE = 0x12 - @classmethod - @property - @abstractmethod - def payload_len(cls) -> int: - """Length of OfflineFinding data payload in bytes.""" - raise NotImplementedError - def __init__( self, mac_bytes: bytes, @@ -105,7 +98,11 @@ class OfflineFindingDevice(ABC): return None device_type = next( - (dev for dev in cls.__subclasses__() if dev.payload_len == ble_payload[1]), + ( + dev + for dev in _DEVICE_TYPES + if getattr(dev, "OF_PAYLOAD_LEN", None) == ble_payload[1] + ), None, ) if device_type is None: @@ -134,12 +131,7 @@ class OfflineFindingDevice(ABC): class NearbyOfflineFindingDevice(OfflineFindingDevice): """Offline-Finding device in nearby state.""" - @classmethod - @property - @override - def payload_len(cls) -> int: - """Length of OfflineFinding data payload in bytes.""" - return 0x02 # 2 + OF_PAYLOAD_LEN = 0x02 # 2 def __init__( self, @@ -180,7 +172,7 @@ class NearbyOfflineFindingDevice(OfflineFindingDevice): additional_data: dict[Any, Any] | None = None, ) -> NearbyOfflineFindingDevice | None: """Get a NearbyOfflineFindingDevice object from an OF message payload.""" - if len(payload) != cls.payload_len: + if len(payload) != cls.OF_PAYLOAD_LEN: logger.error( "Invalid OF data length: %s instead of %s", len(payload), @@ -208,12 +200,7 @@ class NearbyOfflineFindingDevice(OfflineFindingDevice): class SeparatedOfflineFindingDevice(OfflineFindingDevice, HasPublicKey): """Offline-Finding device in separated state.""" - @classmethod - @property - @override - def payload_len(cls) -> int: - """Length of OfflineFinding data in bytes.""" - return 0x19 # 25 + OF_PAYLOAD_LEN = 0x19 # 25 def __init__( # noqa: PLR0913 self, @@ -267,7 +254,7 @@ class SeparatedOfflineFindingDevice(OfflineFindingDevice, HasPublicKey): additional_data: dict[Any, Any] | None = None, ) -> SeparatedOfflineFindingDevice | None: """Get a SeparatedOfflineFindingDevice object from an OF message payload.""" - if len(payload) != cls.payload_len: + if len(payload) != cls.OF_PAYLOAD_LEN: logger.error( "Invalid OF data length: %s instead of %s", len(payload), @@ -306,6 +293,12 @@ class SeparatedOfflineFindingDevice(OfflineFindingDevice, HasPublicKey): ) +_DEVICE_TYPES = { + NearbyOfflineFindingDevice, + SeparatedOfflineFindingDevice, +} + + class OfflineFindingScanner: """BLE scanner that searches for `OfflineFindingDevice`s."""