| # Copyright 2019 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 |
| # |
| # http://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. |
| """Controller class for a Bluetooth Device. |
| |
| This controller will instantiate derived classes from BtDevice and the |
| module/class specified via strings in configs dictionary. |
| |
| The idea is to allow vendors to run blueberry tests with their controller class |
| through this controller module, eliminating the need to edit the test classes |
| themselves. |
| """ |
| |
| from __future__ import absolute_import |
| from __future__ import division |
| from __future__ import print_function |
| |
| import importlib |
| import logging |
| import yaml |
| |
| MOBLY_CONTROLLER_CONFIG_NAME = "DerivedBtDevice" |
| MOBLY_CONTROLLER_CONFIG_MODULE_KEY = "ModuleName" |
| MOBLY_CONTROLLER_CONFIG_CLASS_KEY = "ClassName" |
| MOBLY_CONTROLLER_CONFIG_PARAMS_KEY = "Params" |
| |
| |
| def create(configs): |
| """Creates DerivedBtDevice controller objects. |
| |
| For each config dict in configs: |
| Import desired controller class from config, compose DerivedBtDevice class |
| from that class and BtDevice, instantiate with params from config. |
| |
| Args: |
| configs (list): A list of dicts, each representing a configuration for a |
| Bluetooth device. Each dict should be of the format: |
| {"ModuleName": <name of module in blueberry.controllers>, |
| "ClassName": <name of class to derive controller from>, |
| "Params": <kwargs in dict form to instantiate class with>} |
| |
| Returns: |
| A list with DerivedBtDevice objects. |
| """ |
| return [_create_bt_device_class(config) for config in configs] |
| |
| |
| def _create_bt_device_class(config): |
| """Created new device class from associated device controller from config.""" |
| module = importlib.import_module( |
| "blueberry.controllers.%s" % |
| config[MOBLY_CONTROLLER_CONFIG_MODULE_KEY]) |
| logging.info("Creating DerivedBtDevice from %r", config) |
| cls = getattr(module, config[MOBLY_CONTROLLER_CONFIG_CLASS_KEY]) |
| params = yaml.safe_load("%s" % |
| config.get(MOBLY_CONTROLLER_CONFIG_PARAMS_KEY, {})) |
| new_class = type(MOBLY_CONTROLLER_CONFIG_NAME, (cls, BtDevice), params) |
| new_class_inst = new_class(**params) |
| return new_class_inst |
| |
| |
| def destroy(derived_bt_devices): |
| """Cleans up DerivedBtDevice objects.""" |
| for device in derived_bt_devices: |
| # Execute cleanup if the controller class has the method "clean_up". |
| if hasattr(device, "clean_up"): |
| device.clean_up() |
| del derived_bt_devices |
| |
| |
| class BtDevice(object): |
| """Base class for all Bluetooth Devices. |
| |
| Provides additional necessary functionality for use within blueberry. |
| """ |
| |
| def __init__(self): |
| """Initializes a derived bt base class.""" |
| self._user_params = {} |
| |
| def setup(self): |
| """For devices that need extra setup.""" |
| |
| def set_user_params(self, params): |
| """Intended for passing mobly user_params into a derived device class. |
| |
| Args: |
| params: Mobly user params. |
| """ |
| self._user_params = params |
| |
| def get_user_params(self): |
| """Return saved user_params. |
| |
| Returns: |
| user_params. |
| """ |
| return self._user_params |
| |
| def factory_reset_bluetooth(self) -> None: |
| """Factory resets Bluetooth on an BT Device.""" |
| raise NotImplementedError |
| |
| def activate_pairing_mode(self) -> None: |
| """Activates pairing mode on an AndroidDevice.""" |
| raise NotImplementedError |