90 lines
2.9 KiB
Python
90 lines
2.9 KiB
Python
|
"""A generic gRPC mock device controller.
|
||
|
|
||
|
Example MH testbed config for Hostside:
|
||
|
- name: GrpcBtSyncStub-1
|
||
|
devices:
|
||
|
- type: MiscTestbedSubDevice
|
||
|
dimensions:
|
||
|
mobly_type: DerivedBtDevice
|
||
|
properties:
|
||
|
ModuleName: grpc_bt_sync_mock
|
||
|
ClassName: GrpcBtSyncMock
|
||
|
Params:
|
||
|
config:
|
||
|
mac_address: FE:ED:BE:EF:CA:FE
|
||
|
dimensions:
|
||
|
device: GrpcBtSyncStub
|
||
|
"""
|
||
|
|
||
|
import subprocess
|
||
|
from typing import Any, Dict, Optional, Tuple
|
||
|
|
||
|
from absl import flags
|
||
|
from absl import logging
|
||
|
import grpc
|
||
|
|
||
|
# Internal import
|
||
|
from blueberry.grpc.proto import blueberry_device_controller_pb2
|
||
|
from blueberry.grpc.proto import blueberry_device_controller_pb2_grpc
|
||
|
|
||
|
|
||
|
FLAGS = flags.FLAGS
|
||
|
flags.DEFINE_string('server', 'dns:///[::1]:10000', 'server address')
|
||
|
|
||
|
|
||
|
class GrpcBtSyncMock(object):
|
||
|
"""Generic GRPC device controller."""
|
||
|
|
||
|
def __init__(self, config: Dict[str, str]) -> None:
|
||
|
"""Initialize GRPC object."""
|
||
|
super(GrpcBtSyncMock, self).__init__()
|
||
|
self.config = config
|
||
|
self.mac_address = config['mac_address']
|
||
|
|
||
|
def __del__(self) -> None:
|
||
|
# pytype: disable=attribute-error
|
||
|
self.server_proc.terminate()
|
||
|
del self.channel_creds
|
||
|
del self.channel
|
||
|
del self.stub
|
||
|
|
||
|
def setup(self) -> None:
|
||
|
"""Setup the gRPC server that the sync mock will respond to."""
|
||
|
# pytype: disable=attribute-error
|
||
|
server_path = self.get_user_params()['mh_files']['grpc_server'][0]
|
||
|
logging.info('Start gRPC server: %s', server_path)
|
||
|
self.server_proc = subprocess.Popen([server_path],
|
||
|
stdin=subprocess.PIPE,
|
||
|
stdout=subprocess.PIPE,
|
||
|
stderr=subprocess.PIPE,
|
||
|
universal_newlines=True,
|
||
|
bufsize=0)
|
||
|
|
||
|
self.channel_creds = loas2.loas2_channel_credentials()
|
||
|
self.channel = grpc.secure_channel(FLAGS.server, self.channel_creds)
|
||
|
grpc.channel_ready_future(self.channel).result()
|
||
|
self.stub = blueberry_device_controller_pb2_grpc.BlueberryDeviceControllerStub(
|
||
|
self.channel)
|
||
|
|
||
|
def init_setup(self) -> None:
|
||
|
logging.info('init setup TO BE IMPLEMENTED')
|
||
|
|
||
|
def set_target(self, bt_device: Any) -> None:
|
||
|
self._target_device = bt_device
|
||
|
|
||
|
def pair_and_connect_bluetooth(
|
||
|
self, target_mac_address: str) -> Optional[Tuple[float, float]]:
|
||
|
"""Pair and connect to a peripheral Bluetooth device."""
|
||
|
request = blueberry_device_controller_pb2.TargetMacAddress(
|
||
|
mac_address=target_mac_address)
|
||
|
try:
|
||
|
# pytype: disable=attribute-error
|
||
|
response = self.stub.PairAndConnectBluetooth(request)
|
||
|
logging.info('pair and connect bluetooth response: %s', response)
|
||
|
if response.error:
|
||
|
print('error handler TO BE IMPLEMENTED')
|
||
|
else:
|
||
|
return response.pairing_time_sec, response.connection_time_sec
|
||
|
except grpc.RpcError as rpc_error:
|
||
|
print(rpc_error)
|