Home | History | Annotate | Download | only in relay_lib
      1 #!/usr/bin/env python
      2 #
      3 #   Copyright 2017 - The Android Open Source Project
      4 #
      5 #   Licensed under the Apache License, Version 2.0 (the "License");
      6 #   you may not use this file except in compliance with the License.
      7 #   You may obtain a copy of the License at
      8 #
      9 #       http://www.apache.org/licenses/LICENSE-2.0
     10 #
     11 #   Unless required by applicable law or agreed to in writing, software
     12 #   distributed under the License is distributed on an "AS IS" BASIS,
     13 #   WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
     14 #   See the License for the specific language governing permissions and
     15 #   limitations under the License.
     16 from acts.controllers.relay_lib.errors import RelayConfigError
     17 from acts.controllers.relay_lib.helpers import validate_key
     18 from acts.controllers.relay_lib.rdl_relay_board import RdlRelayBoard
     19 from acts.controllers.relay_lib.sain_smart_board import SainSmartBoard
     20 from acts.controllers.relay_lib.sain_smart_8_channel_usb_relay_board import SainSmart8ChannelUsbRelayBoard
     21 from acts.controllers.relay_lib.generic_relay_device import GenericRelayDevice
     22 from acts.controllers.relay_lib.fugu_remote import FuguRemote
     23 from acts.controllers.relay_lib.i6s_headset import I6sHeadset
     24 from acts.controllers.relay_lib.logitech_headset import LogitechAudioReceiver
     25 from acts.controllers.relay_lib.sony_xb2_speaker import SonyXB2Speaker
     26 from acts.controllers.relay_lib.sony_xb20_speaker import SonyXB20Speaker
     27 from acts.controllers.relay_lib.ak_xb10_speaker import AkXB10Speaker
     28 from acts.controllers.relay_lib.dongles import SingleButtonDongle
     29 from acts.controllers.relay_lib.dongles import ThreeButtonDongle
     30 
     31 
     32 class RelayRig:
     33     """A group of relay boards and their connected devices.
     34 
     35     This class is also responsible for handling the creation of the relay switch
     36     boards, as well as the devices and relays associated with them.
     37 
     38     The boards dict can contain different types of relay boards. They share a
     39     common interface through inheriting from RelayBoard. This layer can be
     40     ignored by the user.
     41 
     42     The relay devices are stored in a dict of (device_name: device). These
     43     device references should be used by the user when they want to directly
     44     interface with the relay switches. See RelayDevice or GeneralRelayDevice for
     45     implementation.
     46 
     47     """
     48     DUPLICATE_ID_ERR_MSG = 'The {} "{}" is not unique. Duplicated in:\n {}'
     49 
     50     # A dict of lambdas that instantiate relay board upon invocation.
     51     # The key is the class type name, the value is the lambda.
     52     _board_constructors = {
     53         'SainSmartBoard':
     54         lambda x: SainSmartBoard(x),
     55         'RdlRelayBoard':
     56         lambda x: RdlRelayBoard(x),
     57         'SainSmart8ChannelUsbRelayBoard':
     58         lambda x: SainSmart8ChannelUsbRelayBoard(x),
     59     }
     60 
     61     # Similar to the dict above, except for devices.
     62     _device_constructors = {
     63         'GenericRelayDevice': lambda x, rig: GenericRelayDevice(x, rig),
     64         'FuguRemote': lambda x, rig: FuguRemote(x, rig),
     65         'I6sHeadset': lambda x, rig: I6sHeadset(x, rig),
     66         "LogitechAudioReceiver" :lambda x, rig: LogitechAudioReceiver(x, rig),
     67         'SonyXB2Speaker': lambda x, rig: SonyXB2Speaker(x, rig),
     68         'SonyXB20Speaker': lambda x, rig: SonyXB20Speaker(x, rig),
     69         'AkXB10Speaker': lambda x, rig: AkXB10Speaker(x, rig),
     70         'SingleButtonDongle': lambda x, rig: SingleButtonDongle(x, rig),
     71         'ThreeButtonDongle': lambda x, rig: ThreeButtonDongle(x, rig),
     72     }
     73 
     74     def __init__(self, config):
     75         self.relays = dict()
     76         self.boards = dict()
     77         self.devices = dict()
     78 
     79         validate_key('boards', config, list, 'relay config file')
     80 
     81         for elem in config['boards']:
     82             board = self.create_relay_board(elem)
     83             if board.name in self.boards:
     84                 raise RelayConfigError(
     85                     self.DUPLICATE_ID_ERR_MSG.format('name', elem['name'],
     86                                                      elem))
     87             self.boards[board.name] = board
     88 
     89         # Note: 'boards' is a necessary value, 'devices' is not.
     90         if 'devices' in config:
     91             for elem in config['devices']:
     92                 relay_device = self.create_relay_device(elem)
     93                 if relay_device.name in self.devices:
     94                     raise RelayConfigError(
     95                         self.DUPLICATE_ID_ERR_MSG.format(
     96                             'name', elem['name'], elem))
     97                 self.devices[relay_device.name] = relay_device
     98         else:
     99             device_config = dict()
    100             device_config['name'] = 'GenericRelayDevice'
    101             device_config['relays'] = dict()
    102             for relay_id in self.relays:
    103                 device_config['relays'][relay_id] = relay_id
    104             self.devices['device'] = self.create_relay_device(device_config)
    105 
    106     def create_relay_board(self, config):
    107         """Builds a RelayBoard from the given config.
    108 
    109         Args:
    110             config: An object containing 'type', 'name', 'relays', and
    111             (optionally) 'properties'. See the example json file.
    112 
    113         Returns:
    114             A RelayBoard with the given type found in the config.
    115 
    116         Raises:
    117             RelayConfigError if config['type'] doesn't exist or is not a string.
    118 
    119         """
    120         validate_key('type', config, str, '"boards" element')
    121         try:
    122             ret = self._board_constructors[config['type']](config)
    123         except LookupError:
    124             raise RelayConfigError(
    125                 'RelayBoard with type {} not found. Has it been added '
    126                 'to the _board_constructors dict?'.format(config['type']))
    127         for _, relay in ret.relays.items():
    128             self.relays[relay.relay_id] = relay
    129         return ret
    130 
    131     def create_relay_device(self, config):
    132         """Builds a RelayDevice from the given config.
    133 
    134         When given no 'type' key in the config, the function will default to
    135         returning a GenericRelayDevice with the relays found in the 'relays'
    136         array.
    137 
    138         Args:
    139             config: An object containing 'name', 'relays', and (optionally)
    140             type.
    141 
    142         Returns:
    143             A RelayDevice with the given type found in the config. If no type is
    144             found, it will default to GenericRelayDevice.
    145 
    146         Raises:
    147             RelayConfigError if the type given does not match any from the
    148             _device_constructors dictionary.
    149 
    150         """
    151         if 'type' in config:
    152             if config['type'] not in RelayRig._device_constructors:
    153                 raise RelayConfigError(
    154                     'Device with type {} not found. Has it been added '
    155                     'to the _device_constructors dict?'.format(config['type']))
    156             else:
    157                 device = self._device_constructors[config['type']](config,
    158                                                                    self)
    159 
    160         else:
    161             device = GenericRelayDevice(config, self)
    162 
    163         return device
    164