File: __init__.py

package info (click to toggle)
python-bumble 0.0.225-1
  • links: PTS, VCS
  • area: main
  • in suites:
  • size: 9,464 kB
  • sloc: python: 75,258; java: 3,782; javascript: 823; xml: 203; sh: 172; makefile: 8
file content (109 lines) | stat: -rw-r--r-- 3,525 bytes parent folder | download | duplicates (2)
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
# Copyright 2022 Google LLC
#
# Licensed under the Apache License, Version 2.0 (the "License");
# you may not use this file except in compliance with the License.
# You may obtain a copy of the License at
#
#     https://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an "AS IS" BASIS,
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
# See the License for the specific language governing permissions and
# limitations under the License.

"""
Bumble Pandora server.
This module implement the Pandora Bluetooth test APIs for the Bumble stack.
"""

__version__ = "0.0.1"

from collections.abc import Callable

import grpc
import grpc.aio
from pandora.host_grpc_aio import add_HostServicer_to_server
from pandora.l2cap_grpc_aio import add_L2CAPServicer_to_server
from pandora.security_grpc_aio import (
    add_SecurityServicer_to_server,
    add_SecurityStorageServicer_to_server,
)

from bumble.pandora.config import Config
from bumble.pandora.device import PandoraDevice
from bumble.pandora.host import HostService
from bumble.pandora.l2cap import L2CAPService
from bumble.pandora.security import SecurityService, SecurityStorageService

# public symbols
__all__ = [
    'register_servicer_hook',
    'serve',
    'Config',
    'PandoraDevice',
]


# Add servicers hooks.
_SERVICERS_HOOKS: list[Callable[[PandoraDevice, Config, grpc.aio.Server], None]] = []


def register_servicer_hook(
    hook: Callable[[PandoraDevice, Config, grpc.aio.Server], None],
) -> None:
    _SERVICERS_HOOKS.append(hook)


async def serve(
    bumble: PandoraDevice,
    config: Config = Config(),
    grpc_server: grpc.aio.Server | None = None,
    port: int = 0,
) -> None:
    # initialize a gRPC server if not provided.
    server = grpc_server if grpc_server is not None else grpc.aio.server()
    port = server.add_insecure_port(f'localhost:{port}')

    try:
        while True:
            # load server config from dict.
            config.load_from_dict(bumble.config.get('server', {}))

            # add Pandora services to the gRPC server.
            add_HostServicer_to_server(
                HostService(server, bumble.device, config), server
            )
            add_SecurityServicer_to_server(
                SecurityService(bumble.device, config), server
            )
            add_SecurityStorageServicer_to_server(
                SecurityStorageService(bumble.device, config), server
            )
            add_L2CAPServicer_to_server(L2CAPService(bumble.device, config), server)

            # call hooks if any.
            for hook in _SERVICERS_HOOKS:
                hook(bumble, config, server)

            # open device.
            await bumble.open()
            try:
                # Pandora require classic devices to be discoverable & connectable.
                if bumble.device.classic_enabled:
                    await bumble.device.set_discoverable(True)
                    await bumble.device.set_connectable(True)

                # start & serve gRPC server.
                await server.start()
                await server.wait_for_termination()
            finally:
                # close device.
                await bumble.close()

            # re-initialize the gRPC server.
            server = grpc.aio.server()
            server.add_insecure_port(f'localhost:{port}')
    finally:
        # stop server.
        await server.stop(None)