Exemple #1
0
class GroundStation(CommandLineHandler):

  def __init__(self, config, ident):
    print "GROUNDSTATION launching as '%s'" % ident
    self.ident = ident
    self.config = config
    self.modules = ModuleHandler(self, 'groundstation')
    self.dying = False
    self.init_death()
    self.command_map = {
      'exit'     : (self.cmd_stop,                      'exit gracefully'),
      'status'   : (self.cmd_status,                    'show status'),
      'module'   : (self.modules.cmd_module,            'manage modules'),
      'config'   : (self.config.cmd_config,             'manage configuration'),
      'reinit'   : (self.cmd_reinit,                    'reconfigures network from config'),
      'trigger'  : (self.cmd_trigger,                   'triggers a message across modules'),
      'psim'     : (self.cmd_piksisim,                  'toggles the piksi simulator on connected piksis'),
      'preset'   : (self.cmd_piksireset,                 'sends a reset message to a connected piksi (optionally specify an IP)'),
      'shutdown' : (self.cmd_shutdown,                  '(IP) shuts down a single or all nodes in network'),
      'restart'  : (self.cmd_restart,                   '(IP) restart a single or all nodes in network (specify an IP to restart a specific node)'),
      'update'   : (self.cmd_update,                    '(IP) does a git pull and restart on a single or all nodes in network'),
      'record'   : (self.cmd_record,                    'start or stop recording data for a session')
    }
    CommandLineHandler.__init__(self, self.command_map)

  def init_death(self):  
    '''Setup Graceful Death'''
    def quit_handler(signum = None, frame = None):
        #print 'Signal handler called with signal', signum
        if self.dying:
            print 'Clean shutdown impossible, forcing an exit'
            sys.exit(0)
        else:
            self.dying = True
            self.stop()

    # Listen for kill signals to cleanly shutdown modules
    fatalsignals = [signal.SIGTERM]
    try:
      fatalsignals.append(signal.SIGHUP, signal.SIGQUIT)
    except Exception:
      pass

    for sig in fatalsignals:
        signal.signal(sig, quit_handler)

  def stop(self, hard=False):
    print ""
    print "Shutting down"
    self.dying = True

    self.modules.unload_all_modules()

    if hard:
      sys.exit(1)

  def cmd_trigger(self, args):
    if len(args) != 1:
      print "we need one and only one argument"
      return
    self.modules.trigger(args[0])

  def cmd_stop(self, args):
    self.stop()

  def cmd_record(self, args):
    if len(args) > 0:
      if 'start' in args:
        return self.modules.trigger('cmd_record_start')
      elif 'stop' in args:
        return self.modules.trigger('cmd_record_stop')
      elif 'next' in args:
        return self.modules.trigger('cmd_record_next')
    print 'USAGE: record (start|stop|next)'

  def cmd_status(self, args):
    self.modules.trigger("cmd_status")

  def cmd_reinit(self, args):
    if len(args):
      if "--force" in args:
        self.modules.unload_all_modules()
    return self.configure_network_from_config()

  def cmd_piksisim(self, args):
    if len(args) > 0:
      if "t" in args:
        self.modules.trigger("enable_piksi_sim")
      else:
        self.modules.trigger("disable_piksi_sim")
    else:
      self.modules.trigger("enable_piksi_sim")
      print "enabling. use 't' for true and 'f' for false to toggle state."

  def cmd_piksireset(self, args):
    if len(args) > 0:
      self.modules.trigger_on("odroidperson_cc", args[0], "reset_piksi")
    else:
      self.modules.trigger("reset_piksi")

  def cmd_shutdown(self, args):
    if len(args) > 0:
      self.modules.trigger_on("odroidperson_cc", args[0], "cmd_shutdown")
    else:
      self.modules.trigger("cmd_shutdown")

  def cmd_restart(self, args):
    if len(args) > 0:
      self.modules.trigger_on("odroidperson_cc", args[0], "cmd_restart")
    else:
      self.modules.trigger("cmd_restart")

  def cmd_update(self, args):
    if len(args) > 0:
      self.modules.trigger_on("odroidperson_cc", args[0], "cmd_update")
    else:
      self.modules.trigger("cmd_update")


  def configure_network_from_config(self):
    '''
    Will attempt to instantiate everything on our end. 
    Won't reinstantiate running threads, 
    won't interact with remote processes
    '''
    self.modules.load_module('systemstate')

    if self.config.get_my("be-the-basestation"):
      print "I AM THE BASE STATION"
      self.modules.load_module('SBPUDPBroadcast')
    else:
      print "I AM NOT THE BASE STATION"
    
    for client in self.config.get_network('odroidperson'):
       self.modules.load_module('odroidperson_cc', instance_name=client)
       self.modules.load_module('odroidperson_sbp', instance_name=client)
       self.modules.load_module('odroidperson_mav', instance_name=client)

    self.modules.load_module('basestation_sbp')

    solo = self.modules.load_module('solo', waitTimeout=15.0)    
    
    # NJ HACK SIGGRAPH 2016: USB broke off...
    solosbp = self.modules.load_module('solo_sbp')
    
    print "CONFIGURATON DONE! Spooky is ready for your commands:"
    
  def set_systemstate(self, module):
    self.systemstate = module

  def unset_systemstate(self):
    self.systemstate = None

  def get_systemstate(self):
    if self.systemstate:
      return self.systemstate
    else:
      return None

  def mainloop(self):

    #Set up our network!
    self.configure_network_from_config()

    # Main command line interface, ensures cleanup on exit 
    while not self.dying:
      # Error handling on the INSIDE so we don't kill app
      try:
        self.handle_terminal_input()
        self.modules.check_modules_integrity()
      except EOFError:
        self.stop(hard=True)
      except KeyboardInterrupt:
        self.stop()
      except Exception:
        #CRUCIAL! This prevents death from exception
        traceback.print_exc()
Exemple #2
0
class GroundStation(CommandLineHandler):
    def __init__(self, config, ident):
        print "GROUNDSTATION launching as '%s'" % ident
        self.ident = ident
        self.config = config
        self.modules = ModuleHandler(self, 'groundstation')
        self.dying = False
        self.init_death()
        self.command_map = {
            'exit': (self.cmd_stop, 'exit gracefully'),
            'status': (self.cmd_status, 'show status'),
            'module': (self.modules.cmd_module, 'manage modules'),
            'config': (self.config.cmd_config, 'manage configuration'),
            'reinit': (self.cmd_reinit, 'reconfigures network from config'),
            'trigger': (self.cmd_trigger, 'triggers a message across modules'),
            'psim': (self.cmd_piksisim,
                     'toggles the piksi simulator on connected piksis'),
            'preset':
            (self.cmd_piksireset,
             'sends a reset message to a connected piksi (optionally specify an IP)'
             ),
            'shutdown': (self.cmd_shutdown,
                         '(IP) shuts down a single or all nodes in network'),
            'restart':
            (self.cmd_restart,
             '(IP) restart a single or all nodes in network (specify an IP to restart a specific node)'
             ),
            'update':
            (self.cmd_update,
             '(IP) does a git pull and restart on a single or all nodes in network'
             ),
            'record':
            (self.cmd_record, 'start or stop recording data for a session')
        }
        CommandLineHandler.__init__(self, self.command_map)

    def init_death(self):
        '''Setup Graceful Death'''
        def quit_handler(signum=None, frame=None):
            #print 'Signal handler called with signal', signum
            if self.dying:
                print 'Clean shutdown impossible, forcing an exit'
                sys.exit(0)
            else:
                self.dying = True
                self.stop()

        # Listen for kill signals to cleanly shutdown modules
        fatalsignals = [signal.SIGTERM]
        try:
            fatalsignals.append(signal.SIGHUP, signal.SIGQUIT)
        except Exception:
            pass

        for sig in fatalsignals:
            signal.signal(sig, quit_handler)

    def stop(self, hard=False):
        print ""
        print "Shutting down"
        self.dying = True

        self.modules.unload_all_modules()

        if hard:
            sys.exit(1)

    def cmd_trigger(self, args):
        if len(args) != 1:
            print "we need one and only one argument"
            return
        self.modules.trigger(args[0])

    def cmd_stop(self, args):
        self.stop()

    def cmd_record(self, args):
        if len(args) > 0:
            if 'start' in args:
                return self.modules.trigger('cmd_record_start')
            elif 'stop' in args:
                return self.modules.trigger('cmd_record_stop')
            elif 'next' in args:
                return self.modules.trigger('cmd_record_next')
        print 'USAGE: record (start|stop|next)'

    def cmd_status(self, args):
        self.modules.trigger("cmd_status")

    def cmd_reinit(self, args):
        if len(args):
            if "--force" in args:
                self.modules.unload_all_modules()
        return self.configure_network_from_config()

    def cmd_piksisim(self, args):
        if len(args) > 0:
            if "t" in args:
                self.modules.trigger("enable_piksi_sim")
            else:
                self.modules.trigger("disable_piksi_sim")
        else:
            self.modules.trigger("enable_piksi_sim")
            print "enabling. use 't' for true and 'f' for false to toggle state."

    def cmd_piksireset(self, args):
        if len(args) > 0:
            self.modules.trigger_on("odroidperson_cc", args[0], "reset_piksi")
        else:
            self.modules.trigger("reset_piksi")

    def cmd_shutdown(self, args):
        if len(args) > 0:
            self.modules.trigger_on("odroidperson_cc", args[0], "cmd_shutdown")
        else:
            self.modules.trigger("cmd_shutdown")

    def cmd_restart(self, args):
        if len(args) > 0:
            self.modules.trigger_on("odroidperson_cc", args[0], "cmd_restart")
        else:
            self.modules.trigger("cmd_restart")

    def cmd_update(self, args):
        if len(args) > 0:
            self.modules.trigger_on("odroidperson_cc", args[0], "cmd_update")
        else:
            self.modules.trigger("cmd_update")

    def configure_network_from_config(self):
        '''
    Will attempt to instantiate everything on our end. 
    Won't reinstantiate running threads, 
    won't interact with remote processes
    '''
        self.modules.load_module('systemstate')

        if self.config.get_my("be-the-basestation"):
            print "I AM THE BASE STATION"
            self.modules.load_module('SBPUDPBroadcast')
        else:
            print "I AM NOT THE BASE STATION"

        for client in self.config.get_network('odroidperson'):
            self.modules.load_module('odroidperson_cc', instance_name=client)
            self.modules.load_module('odroidperson_sbp', instance_name=client)
            self.modules.load_module('odroidperson_mav', instance_name=client)

        solo = self.modules.load_module('solo', waitTimeout=15.0)

        # NJ HACK SIGGRAPH 2016: USB broke off...
        solosbp = self.modules.load_module('solo_sbp')

        print "CONFIGURATON DONE! Spooky is ready for your commands:"

    def set_systemstate(self, module):
        self.systemstate = module

    def unset_systemstate(self):
        self.systemstate = None

    def get_systemstate(self):
        if self.systemstate:
            return self.systemstate
        else:
            return None

    def mainloop(self):

        #Set up our network!
        self.configure_network_from_config()

        # Main command line interface, ensures cleanup on exit
        while not self.dying:
            # Error handling on the INSIDE so we don't kill app
            try:
                self.handle_terminal_input()
                self.modules.check_modules_integrity()
            except EOFError:
                self.stop(hard=True)
            except KeyboardInterrupt:
                self.stop()
            except Exception:
                #CRUCIAL! This prevents death from exception
                traceback.print_exc()