Subversion Repositories HomeAutomation

Rev

Rev 742 | Rev 747 | Go to most recent revision | Blame | Compare with Previous | Last modification | View Log | SVN | RSS feed

  1. #!/bin/env python
  2.  
  3. import os
  4. import sys
  5. import logging as log
  6. import getopt
  7. import atexit
  8. import time
  9.  
  10. from CanPktHandlerBase import CanPktHandlerBase
  11. from CanPktHandler1 import CanPktHandler1
  12.  
  13. from NodeIfBase import NodeIfBase
  14. from NodeIfCanStim import NodeIfCanStim
  15. from NodeIfSerial import NodeIfSerial
  16. from NodeIfTCP import NodeIfTCP
  17.  
  18. from DaemonConfig import DaemonConfig
  19.  
  20. daemonApp = None
  21.  
  22. class CanDaemon():
  23.    
  24.     cfg = None
  25.     nodeIf = None
  26.     ifNotifier = None
  27.     terminated = False
  28.    
  29.     command_list = []
  30.     command_map = {}
  31.     CMDLIST_NAME = 0
  32.     CMDLIST_HANDLER = 1
  33.     CMDLIST_PARAMINFO = 2
  34.     CMDLIST_HELP = 3
  35.  
  36.     logHelp = 'usage:\t log [options]\n\n' \
  37.               '\t options:\n' \
  38.               '\t level <num>, where: 0 < num < 3\n'
  39.     stateHelp = 'usage: state [name/add/rem]'
  40.     filterHelp = 'usage: filter [name/add/rem]'
  41.     addifHelp = 'usage: addif [name] [options]'
  42.     addbridgeHelp = 'usage: addbridge [interface names]'
  43.     tcpdHelp = 'usage: tcpd [start/stop/configure] [options]'
  44.     tlsdHelp = 'usage: tlsd [start/stop/configure] [options]'
  45.     canctldHelp = 'usage: canctld [start/stop/configure] [options]'
  46.     simHelp = 'usage: sim [record/play/add/rem/save/load] [options]'
  47.     help_command_map = {}
  48.    
  49.     logOptions = {}
  50.     ifOptions = {}
  51.     bridgeOptions = {}
  52.     tcpdOptions = {}
  53.     tlsdOptions = {}
  54.     canctldOptions = {}
  55.     simOptions = {}
  56.  
  57.     logValidOptions = {'level' : ['range', 0, 3]}
  58.     ifValidOptions = {'type' : ['alt', 'serial','udp']}
  59.    
  60.     ifSerialOptions = {'' : []}
  61.     ifCanStimOptions = {'' : []}
  62.     ifTelnetOptions = {'' : []}
  63.     ifTcpTlsOptions = {'' : []}
  64.     ifUDPOptions = {'' : []}
  65.    
  66.     bridgeValidOptions = {'' : ['']}
  67.     tcpdValidOptions = {'' : []}
  68.     tlsdValidOptions = {'' : []}
  69.     canctldValidOptions = {'' : []}
  70.     simValidOptions = {'' : []}
  71.  
  72.     def __init__ (self):
  73.        
  74.         self.command_list = [['help', self.helpCmd, '', 'display help'],
  75.                        ['log', self.logCmd, '<options>', 'log control: \"help log\"'],
  76.                        ['exec', self.execCmd, '<filename>', 'run command listing\n'],
  77.                        ['filter', self.filterCmd, '<cmd>', 'filter commands: \"help filter\"'],
  78.                        ['state', self.stateCmd, '<cmd>', 'state commands: \"help state\"\n'],
  79.                        ['addif', self.ifAddCmd, '<options>', 'add interface: \"help addif\"'],
  80.                        ['remif', self.ifRemCmd, '<name>', 'remove interface'],
  81.                        ['ifup', self.ifUpCmd, '<name>', 'bring up interface'],
  82.                        ['ifdown', self.ifDownCmd, '<name>', 'bring down interface\n'],
  83.                        ['addbrigde', self.addBridgeCmd, '<options>', 'add bridge: \"help addbridge\"'],
  84.                        ['rembridge', self.remBridgeCmd, '<id>', 'remove bridge\n'],
  85.                        ['tcpd', self.tcpdCmd, '<cmd>', 'tcpd server control: \"help tcpd\"'],
  86.                        ['tlsd', self.tlsdCmd, '<cmd>', 'tlsd server control: \"help tlsd\"'],
  87.                        ['canctld', self.canCtldCmd, '<cmd>', 'canctld server control: \"help canctld\"\n'],
  88.                        ['status', self.statusCmd, '', 'show daemon status'],
  89.                        ['stats', self.statsCmd, '', 'show statistics\n'],
  90.                        ['nodelist', self.nodesCmd, '', 'list can nodes'],
  91.                        ['filterlist', self.filterlistCmd, '', 'list active filters\n'],
  92.                        ['sim', self.simCmd, '<cmd>', 'simulator commands: \"help sim\"']]
  93.        
  94.         index = 0
  95.         for cmd in self.command_list:
  96.             self.command_map[cmd[0]] = index
  97.             index += 1
  98.  
  99.         self.help_command_map = {'log' : self.logHelp,
  100.                                 'filter' : self.filterHelp,
  101.                                 'state' : self.stateHelp,
  102.                                 'addif' : self.addifHelp,
  103.                                 'addbridge' : self.addbridgeHelp,
  104.                                 'tcpd' : self.tcpdHelp,
  105.                                 'tlsd' : self.tlsdHelp,
  106.                                 'canctld' : self.canctldHelp,
  107.                                 'sim' : self.simHelp}
  108.  
  109.         self.cfg = DaemonConfig()
  110.    
  111.     class IfNotifier():
  112.         """ Used by if threads to send messages to the main program thread """
  113.        
  114.         parent = None
  115.         UNDEFINED = 0
  116.         TERMINATE = 1
  117.        
  118.         def __init__(self, parent):
  119.             self.parent = parent
  120.    
  121.         def notify(self, msg):
  122.             if msg == self.TERMINATE:
  123.                 print 'Main terminate notify'
  124.             else:
  125.                 print 'UNDEFINED NOTIFY'
  126.        
  127.    
  128.     def __rightAdjust(self, refstr, str):
  129.         spcstr = ''
  130.         endpos = 25-len(refstr)
  131.         for i in range(1,endpos):
  132.             if i == endpos-5:
  133.                 spcstr += ':'
  134.             else:
  135.                 spcstr += ' '
  136.         return (spcstr+str)
  137.    
  138.     def helpCmd(self, *args):
  139.         try:
  140.             args = args[0]
  141.         except:
  142.             args = []
  143.         if len(args) < 1:
  144.             quitStr = 'quit, exit'
  145.             print quitStr, self.__rightAdjust(quitStr, 'shutdown pyCanDaemon')
  146.             for cmd in self.command_list:
  147.                 cmdstr = cmd[self.CMDLIST_NAME] + ' ' + cmd[self.CMDLIST_PARAMINFO]
  148.                 print cmdstr, \
  149.                       self.__rightAdjust(cmdstr, cmd[self.CMDLIST_HELP])
  150.         elif len(args) < 2:
  151.             subCmd = args[0]
  152.             if self.help_command_map.has_key(subCmd):
  153.                 print self.help_command_map[subCmd]
  154.             else:
  155.                 print 'no help for ' + subCmd
  156.         else:
  157.             print 'usage: help [topic]'
  158.  
  159.     def filterCmd(self, *args):
  160.         try:
  161.             args = args[0]
  162.         except:
  163.             args = []
  164.         log.debug('filterCmd ' + str(args))
  165.         if len(args) < 2:
  166.             print 'Invalid arguments\n' + self.filterHelp
  167.             return
  168.         cmd = args[0]
  169.         filterName = args[1]
  170.         # FIXME: verify
  171.         if cmd == 'add':
  172.             print 'Importing filter: ' + filterName
  173.             self.cfg.filterCfg.importFilter(filterName)
  174.         elif cmd == 'rem' or cmd == 'remove':
  175.             print 'Deleting filter: ' + filterName
  176.             # FIXME: actually delete
  177.             raise 'Not implemented'
  178.    
  179.     def stateCmd(self, *args):
  180.         try:
  181.             args = args[0]
  182.         except:
  183.             args = []
  184.         log.debug('stateCmd ' + str(args))
  185.         if len(args) < 2:
  186.             print 'Invalid arguments\n' + self.stateHelp
  187.             return
  188.         cmd = args[0]
  189.         spaceName = args[1]
  190.         # FIXME: verify
  191.         if cmd == 'add':
  192.             print 'Importing state space: ' + spaceName
  193.             self.cfg.stateSpaceCfg.importSpace(spaceName)
  194.         elif cmd == 'rem' or cmd == 'remove':
  195.             print 'Deleting state space: ' + spaceName
  196.             # FIXME: actually delete statespace
  197.             raise 'Not implemented'
  198.    
  199.     def ifAddCmd(self, *args):
  200.         raise 'not implemented'
  201.    
  202.     def ifRemCmd(self, *args):
  203.         raise 'not implemented'
  204.  
  205.     def ifUpCmd(self, *args):
  206.         raise 'not implemented'
  207.  
  208.     def ifDownCmd(self, *args):
  209.         raise 'not implemented'
  210.    
  211.     def addBridgeCmd(self, *args):
  212.         raise 'not implemented'
  213.  
  214.     def remBridgeCmd(self, *args):
  215.         raise 'not implemented'
  216.    
  217.     def tcpdCmd(self, *args):
  218.         raise 'not implemented'
  219.    
  220.     def tlsdCmd(self, *args):
  221.         raise 'not implemented'
  222.    
  223.     def canCtldCmd(self, *args):
  224.         raise 'not implemented'
  225.    
  226.     def statusCmd(self, *args):
  227.         raise 'not implemented'
  228.    
  229.     def statsCmd(self, *args):
  230.         raise 'not implemented'
  231.    
  232.     def nodesCmd(self, *args):
  233.         raise 'not implemented'
  234.    
  235.     def filterlistCmd(self, *args):
  236.         raise 'not implemented'
  237.    
  238.     def simCmd(self, *args):
  239.         raise 'not implemented'
  240.    
  241.     def logCmd(self, *args):
  242.         raise 'not implemented'
  243.  
  244.     def execCmd(self, *args):
  245.         raise 'not implemented'
  246.    
  247.     def parseCommand(self, cmdstr):
  248.         incmd = cmdstr.strip()
  249.         cmd = incmd.split(' ')
  250.         if len(cmd[0]) < 2:
  251.             return
  252.         cmd[0] = cmd[0].lower()
  253.         if cmd[0] == 'quit' or cmd[0] == 'exit':
  254.             self.terminated = True
  255.         elif self.command_map.has_key(cmd[0]):
  256.             self.command_list[self.command_map[cmd[0]]][self.CMDLIST_HANDLER](cmd[1:])
  257.         else:
  258.             print 'unknown command: ' + cmd[0]
  259.    
  260.     def exitHelper(self):
  261.         if self.nodeIf is not None and self.nodeIf.running():
  262.             self.nodeIf.stop()
  263.            
  264.     def exceptHelper(self, type, value, tb):
  265.         import traceback
  266.         traceback.print_exception(type, value, tb)
  267.         print '\nException in main program, shutting down threads'
  268.         self.terminated = True
  269.         self.exitHelper()
  270.  #       sys.exit(-1)
  271.  
  272.     def run(self):
  273.         try:
  274.             myPath = os.path.dirname(__file__)
  275.             os.chdir(myPath)
  276.         except:
  277.             return
  278.        
  279.         print 'INIT: Start logging'
  280.         log.basicConfig(level=log.DEBUG)
  281.        
  282.         """command parameters only dictate verbosity and use of config file"""
  283.         print 'INIT: Get config options from command line / config file'
  284.         try:
  285.             opts, args = getopt.getopt(sys.argv[1:], "ho:v", ["help", "output="])
  286.         except getopt.GetoptError:
  287.             print 'Invalid usage'
  288.             usage()
  289.             sys.exit(2)
  290.      #   output = None
  291.      #   verbose = False
  292.         for o, a in opts:
  293.             if o == "-v":
  294.                 pass
  295.      #           verbose = True
  296.             if o in ("-h", "--help"):
  297.                 usage()
  298.                 sys.exit()
  299.             if o in ("-o", "--output"):
  300.                 pass
  301.     #            output = a
  302.  
  303.         """load config defaults, or last config if exists"""
  304.         """run startup.cfg"""
  305.        
  306. #        print 'INIT: Loading filters and spaces'
  307. #       self.cfg.filterCfg.importFilter('DefaultFilter')
  308. #       self.cfg.stateSpaceCfg.importSpace('DefaultStateSpace')
  309. #        self.cfg.stateSpaceCfg.loadSpaces()
  310. #        self.cfg.filterCfg.loadFilters()
  311. #        self.cfg.setupFilterBindings()
  312. #        self.cfg.setupFilterChain()
  313.  
  314. #        print 'INIT: Starting selected can interface'
  315. #        ''' nodeif thread launch '''
  316.         self.ifNotifier = self.IfNotifier(self)
  317.         pktHandler = CanPktHandler1(self.cfg)
  318. #        
  319. #        ifConfig = NodeIfCanStim.DEFAULT_CONFIG
  320. #        self.nodeIf = NodeIfCanStim(ifConfig, pktHandler, self.ifNotifier)
  321. # #       ifConfig = NodeIfSerial.DEFAULT_CONFIG
  322.         ifConfig = NodeIfTCP.DEFAULT_CONFIG
  323. #    
  324.         atexit.register(self.exitHelper)
  325.         sys.excepthook = self.exceptHelper
  326.         self.nodeIf = NodeIfTCP(pktHandler, self.ifNotifier ,None)
  327. #       self.nodeIf = NodeIfSerial(pktHandler, ifConfig)
  328. #        
  329.         if not self.nodeIf.start():
  330.             print 'FATAL: Failed to initialize node interface.'
  331.             print 'This may indicate that the interface is unavailable, ' \
  332.                   'or that you do not have permission to access it.'
  333.             sys.exit(-1)
  334.  
  335.         print 'Initialize/gather info on connected can nodes and load associated state'
  336.         print 'Start selected TCP and UDP server(s)'
  337.         # server threads launch
  338.        
  339.         print 'CanDaemon v1 ready'
  340.         print 'Enter command or type \"help\" for a list of commands'
  341.         while not self.terminated:
  342.             input = raw_input('> ')
  343.             self.parseCommand(input)
  344.  
  345.         print 'Shutdown'
  346. #        if self.nodeIf.running():
  347. #            print 'Stopping If thread'
  348. #            self.nodeIf.stop()
  349.  
  350. #        self.cfg.stateSpaceCfg.saveSpaces()
  351. #        self.cfg.filterCfg.saveFilters()
  352.        
  353.         print 'Waiting 0.1..'
  354.         time.sleep(0.1) # wait for threads
  355.         print 'Terminating'
  356.         sys.exit(0) # will except if there are threads remaining
  357.  
  358. #---------------------------------------------------------------------------
  359.  
  360. def main():
  361.     daemonApp = CanDaemon()
  362. #    install_thread_excepthook()
  363.     daemonApp.run()
  364.  
  365. #---------------------------------------------------------------------------
  366.  
  367. if __name__ == '__main__':
  368.     __name__ = 'Main'
  369.     main()
  370.