Home | History | Annotate | Download | only in pseudomodem
      1 #!/usr/bin/env python
      2 
      3 # Copyright (c) 2013 The Chromium OS Authors. All rights reserved.
      4 # Use of this source code is governed by a BSD-style license that can be
      5 # found in the LICENSE file.
      6 
      7 import cmd
      8 import dbus
      9 import dbus.exceptions
     10 
     11 import pm_constants
     12 
     13 import common
     14 from autotest_lib.client.cros.cellular import mm1_constants
     15 
     16 class PseudoModemClient(cmd.Cmd):
     17     """
     18     Interactive client for PseudoModemManager.
     19 
     20     """
     21     def __init__(self):
     22         cmd.Cmd.__init__(self)
     23         self.prompt = '> '
     24         self._bus = dbus.SystemBus()
     25 
     26 
     27     def _get_proxy(self, path=pm_constants.TESTING_PATH):
     28         return self._bus.get_object(mm1_constants.I_MODEM_MANAGER, path)
     29 
     30 
     31     def _get_ism_proxy(self, state_machine):
     32         return self._get_proxy('/'.join([pm_constants.TESTING_PATH,
     33                                          state_machine]))
     34 
     35 
     36     def Begin(self):
     37         """
     38         Starts the interactive shell.
     39 
     40         """
     41         print '\nWelcome to the PseudoModemManager shell!\n'
     42         self.cmdloop()
     43 
     44 
     45     def can_exit(self):
     46         """Override"""
     47         return True
     48 
     49 
     50     def do_is_alive(self, args):
     51         """
     52         Handles the 'is_alive' command.
     53 
     54         @params args: ignored.
     55 
     56         """
     57         if args:
     58             print '\nCommand "is_alive" expects no arguments.\n'
     59             return
     60         print self._get_proxy().IsAlive(dbus_interface=pm_constants.I_TESTING)
     61 
     62 
     63     def help_is_alive(self):
     64         """ Handles the 'help is_alive' command. """
     65         print '\nChecks that pseudomodem child process is alive.\n'
     66 
     67 
     68     def do_properties(self, args):
     69         """
     70         Handles the 'properties' command.
     71 
     72         @param args: Arguments to the command. Unused.
     73 
     74         """
     75         if args:
     76             print '\nCommand "properties" expects no arguments.\n'
     77             return
     78         try:
     79             props = self._get_proxy().GetAll(
     80                             pm_constants.I_TESTING,
     81                             dbus_interface=mm1_constants.I_PROPERTIES)
     82             print '\nProperties: '
     83             for k, v in props.iteritems():
     84                 print '   ' + k + ': ' + str(v)
     85             print
     86         except dbus.exceptions.DBusException as e:
     87             print ('\nAn error occurred while communicating with '
     88                    'PseudoModemManager: ' + e.get_dbus_name() + ' - ' +
     89                    e.message + '\n')
     90         return False
     91 
     92 
     93     def help_properties(self):
     94         """Handles the 'help properties' command."""
     95         print '\nReturns the properties under the testing interface.\n'
     96 
     97 
     98     def do_sms(self, args):
     99         """
    100         Simulates a received SMS.
    101 
    102         @param args: A string containing the sender and the text message
    103                 content, in which everything before the first ' ' character
    104                 belongs to the sender and everything else belongs to the
    105                 message content. For example "Gandalf You shall not pass!"
    106                 will be parsed into:
    107 
    108                     sender="Gandalf"
    109                     content="You shall not pass!"
    110 
    111                 Pseudomodem doesn't distinguish between phone numbers and
    112                 strings containing non-numeric characters for the sender field
    113                 so args can contain pretty much anything.
    114 
    115         """
    116         arglist = args.split(' ', 1)
    117         if len(arglist) != 2:
    118             print '\nMalformed SMS args: ' + args + '\n'
    119             return
    120         try:
    121             self._get_proxy().ReceiveSms(
    122                     arglist[0], arglist[1],
    123                     dbus_interface=pm_constants.I_TESTING)
    124             print '\nSMS sent!\n'
    125         except dbus.exceptions.DBusException as e:
    126             print ('\nAn error occurred while communicating with '
    127                    'PseudoModemManager: ' + e.get_dbus_name() + ' - ' +
    128                    e.message + '\n')
    129         return False
    130 
    131 
    132     def help_sms(self):
    133         """Handles the 'help sms' command."""
    134         print '\nUsage: sms <sender phone #> <message text>\n'
    135 
    136 
    137     def do_set(self, args):
    138         """
    139         Handles various commands that start with 'set'.
    140 
    141         @param args: Defines the set command to be issued and its
    142                 arguments. Currently supported commands are:
    143 
    144                   set pco <pco-value>
    145 
    146         """
    147         arglist = args.split(' ')
    148         if len(arglist) < 1:
    149             print '\nInvalid command: set ' + args + '\n'
    150             return
    151         if arglist[0] == 'pco':
    152             if len(arglist) == 1:
    153                 arglist.append('')
    154             elif len(arglist) != 2:
    155                 print '\nExpected: pco <pco-value>. Found: ' + args + '\n'
    156                 return
    157             pco_value = arglist[1]
    158             try:
    159                 self._get_proxy().UpdatePcoInfo(
    160                         pco_value, dbus_interface=pm_constants.I_TESTING)
    161                 print '\nPCO value updated!\n'
    162             except dbus.exceptions.DBusException as e:
    163                 print ('\nAn error occurred while communicating with '
    164                        'PseudoModemManager: ' + e.get_dbus_name() + ' - ' +
    165                        e.message + '\n')
    166         else:
    167             print '\nUnknown command: set ' + args + '\n'
    168         return False
    169 
    170 
    171     def help_set(self):
    172         """Handles the 'help set' command."""
    173         print ('\nUsage: set pco <pco-value>\n<pco-value> can be empty to set'
    174                ' the PCO value to an empty string.\n')
    175 
    176 
    177     def _get_state_machine(self, args):
    178         arglist = args.split()
    179         if len(arglist) != 1:
    180             print '\nExpected one argument: Name of state machine\n'
    181             return None
    182         try:
    183             return self._get_ism_proxy(arglist[0])
    184         except dbus.exceptions.DBusException as e:
    185             print '\nNo such interactive state machine.\n'
    186             print 'Error obtained: |%s|\n' % repr(e)
    187             return None
    188 
    189 
    190     def do_is_waiting(self, machine):
    191         """
    192         Determine if a machine is waiting for an advance call.
    193 
    194         @param machine: Case sensitive name of the machine.
    195         @return: True if |machine| is waiting to be advanced by the user.
    196 
    197         """
    198         ism = self._get_state_machine(machine)
    199         if not ism:
    200             return False
    201 
    202         try:
    203             is_waiting = ism.IsWaiting(
    204                     dbus_interface=pm_constants.I_TESTING_ISM)
    205             print ('\nState machine is %swaiting.\n' %
    206                    ('' if is_waiting else 'not '))
    207         except dbus.exceptions.DBusException as e:
    208             print ('\nCould not determine if |%s| is waiting: |%s|\n' %
    209                    (machine, repr(e)))
    210         return False
    211 
    212 
    213     def help_is_waiting(self):
    214         """Handles the 'help is_waiting' command"""
    215         print ('\nUsage: is_waiting <state-machine-name>\n'
    216                'Check whether a state machine is waiting for user action. The '
    217                'waiting machine can be advanced using the |advance| command.\n'
    218                'state-machine-name is the case sensitive name of the machine'
    219                'whose status is to be queried.\n')
    220 
    221 
    222     def do_advance(self, machine):
    223         """
    224         Advance the given state machine.
    225 
    226         @param machine: Case sensitive name of the state machine to advance.
    227         @returns: True if |machine| was successfully advanced, False otherwise.
    228 
    229         """
    230         ism = self._get_state_machine(machine)
    231         if not ism:
    232             return False
    233 
    234         try:
    235             success = ism.Advance(dbus_interface=pm_constants.I_TESTING_ISM)
    236             print ('\nAdvanced!\n' if success else '\nCould not advance.\n')
    237         except dbus.exceptions.DBusException as e:
    238             print '\nError while advancing state machine: |%s|\n' % repr(e)
    239         return False
    240 
    241 
    242     def help_advance(self):
    243         """Handles the 'help advance' command"""
    244         print ('\nUsage: advance <state-machine-name>\n'
    245                'Advance a waiting state machine to the next step.\n'
    246                'state-machine-name is the case sensitive name of the machine'
    247                'to advance.\n')
    248 
    249 
    250     def do_exit(self, args):
    251         """
    252         Handles the 'exit' command.
    253 
    254         @param args: Arguments to the command. Unused.
    255 
    256         """
    257         if args:
    258             print '\nCommand "exit" expects no arguments.\n'
    259             return
    260         resp = raw_input('Are you sure? (yes/no): ')
    261         if resp == 'yes':
    262             print '\nGoodbye!\n'
    263             return True
    264         if resp != 'no':
    265             print '\nDid not understand: ' + resp + '\n'
    266         return False
    267 
    268 
    269     def help_exit(self):
    270         """Handles the 'help exit' command."""
    271         print ('\nExits the interpreter. Shuts down the pseudo modem manager '
    272                'if the interpreter was launched by running pseudomodem.py')
    273 
    274 
    275     do_EOF = do_exit
    276     help_EOF = help_exit
    277 
    278 
    279 def main():
    280     """ main method, run when this module is executed as stand-alone. """
    281     client = PseudoModemClient()
    282     client.Begin()
    283 
    284 
    285 if __name__ == '__main__':
    286     main()
    287