1import asyncio 2import click 3import logging 4import json 5 6from bumble.pandora import PandoraDevice, Config, serve 7from typing import Dict, Any 8 9BUMBLE_SERVER_GRPC_PORT = 7999 10ROOTCANAL_PORT_CUTTLEFISH = 7300 11 12 13@click.command() 14@click.option('--grpc-port', help='gRPC port to serve', default=BUMBLE_SERVER_GRPC_PORT) 15@click.option( 16 '--rootcanal-port', help='Rootcanal TCP port', default=ROOTCANAL_PORT_CUTTLEFISH 17) 18@click.option( 19 '--transport', 20 help='HCI transport', 21 default=f'tcp-client:127.0.0.1:<rootcanal-port>', 22) 23@click.option( 24 '--config', 25 help='Bumble json configuration file', 26) 27def main(grpc_port: int, rootcanal_port: int, transport: str, config: str) -> None: 28 if '<rootcanal-port>' in transport: 29 transport = transport.replace('<rootcanal-port>', str(rootcanal_port)) 30 31 bumble_config = retrieve_config(config) 32 bumble_config.setdefault('transport', transport) 33 device = PandoraDevice(bumble_config) 34 35 server_config = Config() 36 server_config.load_from_dict(bumble_config.get('server', {})) 37 38 logging.basicConfig(level=logging.DEBUG) 39 asyncio.run(serve(device, config=server_config, port=grpc_port)) 40 41 42def retrieve_config(config: str) -> Dict[str, Any]: 43 if not config: 44 return {} 45 46 with open(config, 'r') as f: 47 return json.load(f) 48 49 50if __name__ == '__main__': 51 main() # pylint: disable=no-value-for-parameter 52