File: test_scanner.py

package info (click to toggle)
bleak 2.1.1-1
  • links: PTS, VCS
  • area: main
  • in suites: forky, sid
  • size: 2,076 kB
  • sloc: python: 11,282; makefile: 165; java: 105
file content (144 lines) | stat: -rw-r--r-- 5,142 bytes parent folder | download
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
import asyncio
import contextlib
import sys

import pytest
from bumble import data_types
from bumble.core import UUID
from bumble.device import Device

from bleak import BleakScanner
from bleak.backends.device import BLEDevice
from bleak.backends.scanner import AdvertisementData
from bleak.uuids import normalize_uuid_str
from tests.integration.conftest import configure_and_power_on_bumble_peripheral

DEFAULT_TIMEOUT = 5.0


async def test_discover(bumble_peripheral: Device):
    """Scanner discovery is finding the device."""
    await configure_and_power_on_bumble_peripheral(bumble_peripheral)

    devices = await BleakScanner.discover(return_adv=True)
    filtered_devices = list(
        filter(
            lambda device: device[1].local_name == bumble_peripheral.name,
            devices.values(),
        )
    )

    assert len(filtered_devices) == 1
    assert filtered_devices[0][1].local_name == bumble_peripheral.name
    if sys.platform != "darwin":
        # accessing the address is not possible on macOS
        assert filtered_devices[0][0].address == str(bumble_peripheral.static_address)


@pytest.mark.parametrize("service_uuid_available", [True, False])
async def test_discover_filter_by_service_uuid(
    bumble_peripheral: Device,
    service_uuid_available: bool,
):
    """Scanner discovery is filtering service uuids correctly."""
    await configure_and_power_on_bumble_peripheral(
        bumble_peripheral,
        additional_adv_data=(
            [data_types.IncompleteListOf16BitServiceUUIDs([UUID(0x180F)])]
            if service_uuid_available
            else []
        ),
    )

    found_adv_data_future: asyncio.Future[AdvertisementData] = asyncio.Future()

    def detection_callback(device: BLEDevice, adv_data: AdvertisementData):
        if device.name == bumble_peripheral.name:
            found_adv_data_future.set_result(adv_data)

    async with BleakScanner(
        detection_callback,
        service_uuids=[normalize_uuid_str("180f")],
    ):
        found_adv_data = None
        with contextlib.suppress(asyncio.TimeoutError):
            found_adv_data = await asyncio.wait_for(
                found_adv_data_future, timeout=DEFAULT_TIMEOUT
            )

    if service_uuid_available:
        assert found_adv_data is not None
    else:
        assert found_adv_data is None


async def test_adv_data_simple(bumble_peripheral: Device):
    """Simple advertising data is parsed correct."""
    await configure_and_power_on_bumble_peripheral(bumble_peripheral)

    found_adv_data_future: asyncio.Future[AdvertisementData] = asyncio.Future()

    def detection_callback(device: BLEDevice, adv_data: AdvertisementData):
        if device.name == bumble_peripheral.name:
            found_adv_data_future.set_result(adv_data)

    async with BleakScanner(detection_callback):
        found_adv_data = await asyncio.wait_for(
            found_adv_data_future, timeout=DEFAULT_TIMEOUT
        )

    assert found_adv_data is not None
    assert found_adv_data.local_name == bumble_peripheral.name
    assert found_adv_data.manufacturer_data == {}
    assert found_adv_data.service_data == {}
    assert found_adv_data.service_uuids == []
    assert found_adv_data.tx_power is None
    assert found_adv_data.platform_data

    # Verify that this value is an integer and not some other
    # type from a ffi binding framework.
    assert isinstance(found_adv_data.rssi, int)

    # The rssi can vary. So we only check for a plausible range.
    assert -127 <= found_adv_data.rssi < 0


async def test_adv_data_complex(bumble_peripheral: Device):
    """Complex advertising data is parsed correct."""
    await configure_and_power_on_bumble_peripheral(
        bumble_peripheral,
        [
            data_types.ManufacturerSpecificData(0x1234, b"MFG"),
            data_types.IncompleteListOf16BitServiceUUIDs([UUID(0x180F)]),
            data_types.TxPowerLevel(123),
            data_types.ServiceData16BitUUID(UUID(0x180F), b"SER"),
        ],
    )

    found_adv_data_future: asyncio.Future[AdvertisementData] = asyncio.Future()

    def detection_callback(device: BLEDevice, adv_data: AdvertisementData):
        if device.name == bumble_peripheral.name:
            found_adv_data_future.set_result(adv_data)

    async with BleakScanner(detection_callback):
        found_adv_data = await asyncio.wait_for(
            found_adv_data_future, timeout=DEFAULT_TIMEOUT
        )

    assert found_adv_data is not None
    assert found_adv_data.local_name == bumble_peripheral.name
    assert found_adv_data.manufacturer_data == {0x1234: b"MFG"}
    assert found_adv_data.service_data == {
        "0000180f-0000-1000-8000-00805f9b34fb": b"SER"
    }
    assert found_adv_data.service_uuids == ["0000180f-0000-1000-8000-00805f9b34fb"]
    assert found_adv_data.tx_power == 123
    assert found_adv_data.platform_data

    # Verify that this value is an integer and not some other
    # type from a ffi binding framework.
    assert isinstance(found_adv_data.rssi, int)

    # The rssi can vary. So we only check for a plausible range.
    assert -127 <= found_adv_data.rssi < 0