Subversion Repositories HomeAutomation

Rev

Details | Last modification | View Log | SVN | RSS feed

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