1# Copyright 2021-2022 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 sys
20import os
21import logging
22from bumble.colors import color
23from bumble.device import Device, Peer
24from bumble.hci import Address
25from bumble.profiles.device_information_service import DeviceInformationServiceProxy
26from bumble.transport import open_transport
27
28
29# -----------------------------------------------------------------------------
30async def main() -> None:
31    if len(sys.argv) != 3:
32        print(
33            'Usage: device_information_client.py <transport-spec> <bluetooth-address>'
34        )
35        print('example: device_information_client.py usb:0 E1:CA:72:48:C4:E8')
36        return
37
38    print('<<< connecting to HCI...')
39    async with await open_transport(sys.argv[1]) as hci_transport:
40        print('<<< connected')
41
42        # Create and start a device
43        device = Device.with_hci(
44            'Bumble',
45            Address('F0:F1:F2:F3:F4:F5'),
46            hci_transport.source,
47            hci_transport.sink,
48        )
49        await device.power_on()
50
51        # Connect to the peer
52        target_address = sys.argv[2]
53        print(f'=== Connecting to {target_address}...')
54        connection = await device.connect(target_address)
55        print(f'=== Connected to {connection}')
56
57        # Discover the Device Information service
58        peer = Peer(connection)
59        print('=== Discovering Device Information Service')
60        device_information_service = await peer.discover_service_and_create_proxy(
61            DeviceInformationServiceProxy
62        )
63
64        # Check that the service was found
65        if device_information_service is None:
66            print('!!! Service not found')
67            return
68
69        # Read and print the fields
70        if device_information_service.manufacturer_name is not None:
71            print(
72                color('Manufacturer Name:       ', 'green'),
73                await device_information_service.manufacturer_name.read_value(),
74            )
75        if device_information_service.model_number is not None:
76            print(
77                color('Model Number:            ', 'green'),
78                await device_information_service.model_number.read_value(),
79            )
80        if device_information_service.serial_number is not None:
81            print(
82                color('Serial Number:           ', 'green'),
83                await device_information_service.serial_number.read_value(),
84            )
85        if device_information_service.hardware_revision is not None:
86            print(
87                color('Hardware Revision:       ', 'green'),
88                await device_information_service.hardware_revision.read_value(),
89            )
90        if device_information_service.firmware_revision is not None:
91            print(
92                color('Firmware Revision:       ', 'green'),
93                await device_information_service.firmware_revision.read_value(),
94            )
95        if device_information_service.software_revision is not None:
96            print(
97                color('Software Revision:       ', 'green'),
98                await device_information_service.software_revision.read_value(),
99            )
100        if device_information_service.system_id is not None:
101            print(
102                color('System ID:               ', 'green'),
103                await device_information_service.system_id.read_value(),
104            )
105        if (
106            device_information_service.ieee_regulatory_certification_data_list
107            is not None
108        ):
109            print(
110                color('Regulatory Certification:', 'green'),
111                (
112                    # pylint: disable-next=line-too-long
113                    await device_information_service.ieee_regulatory_certification_data_list.read_value()
114                ).hex(),
115            )
116
117
118# -----------------------------------------------------------------------------
119logging.basicConfig(level=os.environ.get('BUMBLE_LOGLEVEL', 'DEBUG').upper())
120asyncio.run(main())
121