1# Copyright 2021-2024 Google LLC
2#
3# Licensed under the Apache License, Version 2.0 (the "License");
4# you may not use this file except in compliance with the License.
5# You may obtain a copy of the License at
6#
7#      https://www.apache.org/licenses/LICENSE-2.0
8#
9# Unless required by applicable law or agreed to in writing, software
10# distributed under the License is distributed on an "AS IS" BASIS,
11# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12# See the License for the specific language governing permissions and
13# limitations under the License.
14
15# -----------------------------------------------------------------------------
16# Imports
17# -----------------------------------------------------------------------------
18import asyncio
19import logging
20import sys
21import os
22from bumble.device import AdvertisingParameters, AdvertisingEventProperties, Device
23from bumble.hci import Address
24from bumble.core import AdvertisingData
25from bumble.transport import open_transport_or_link
26
27
28# -----------------------------------------------------------------------------
29async def main() -> None:
30    if len(sys.argv) < 3:
31        print('Usage: run_extended_advertiser_2.py <config-file> <transport-spec>')
32        print('example: run_extended_advertiser_2.py device1.json usb:0')
33        return
34
35    print('<<< connecting to HCI...')
36    async with await open_transport_or_link(sys.argv[2]) as hci_transport:
37        print('<<< connected')
38
39        device = Device.from_config_file_with_hci(
40            sys.argv[1], hci_transport.source, hci_transport.sink
41        )
42        await device.power_on()
43
44        if not device.supports_le_extended_advertising:
45            print("Device does not support extended advertising")
46            return
47
48        print("Max advertising sets:", device.host.number_of_supported_advertising_sets)
49        print(
50            "Max advertising data length:", device.host.maximum_advertising_data_length
51        )
52
53        if device.host.number_of_supported_advertising_sets >= 1:
54            advertising_data1 = AdvertisingData(
55                [(AdvertisingData.COMPLETE_LOCAL_NAME, "Bumble 1".encode("utf-8"))]
56            )
57
58            set1 = await device.create_advertising_set(
59                advertising_data=bytes(advertising_data1),
60            )
61            print("Selected TX power 1:", set1.selected_tx_power)
62
63            advertising_data2 = AdvertisingData(
64                [(AdvertisingData.COMPLETE_LOCAL_NAME, "Bumble 2".encode("utf-8"))]
65            )
66
67        if device.host.number_of_supported_advertising_sets >= 2:
68            set2 = await device.create_advertising_set(
69                random_address=Address("F0:F0:F0:F0:F0:F1"),
70                advertising_parameters=AdvertisingParameters(),
71                advertising_data=bytes(advertising_data2),
72                auto_start=False,
73                auto_restart=True,
74            )
75            print("Selected TX power 2:", set2.selected_tx_power)
76            await set2.start()
77
78        if device.host.number_of_supported_advertising_sets >= 3:
79            scan_response_data3 = AdvertisingData(
80                [(AdvertisingData.COMPLETE_LOCAL_NAME, "Bumble 3".encode("utf-8"))]
81            )
82
83            set3 = await device.create_advertising_set(
84                random_address=Address("F0:F0:F0:F0:F0:F2"),
85                advertising_parameters=AdvertisingParameters(
86                    advertising_event_properties=AdvertisingEventProperties(
87                        is_connectable=False, is_scannable=True
88                    )
89                ),
90                scan_response_data=bytes(scan_response_data3),
91            )
92            print("Selected TX power 3:", set2.selected_tx_power)
93
94        await hci_transport.source.terminated
95
96
97# -----------------------------------------------------------------------------
98logging.basicConfig(level=os.environ.get('BUMBLE_LOGLEVEL', 'DEBUG').upper())
99asyncio.run(main())
100