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
16
 
17
from DaemonConfig import DaemonConfig
18
 
19
daemonApp = None
20
 
21
class CanDaemon():
22
 
740 olof 23
    cfg = None
736 olof 24
    nodeIf = None
738 olof 25
    ifNotifier = None
26
    terminated = False
741 olof 27
 
739 olof 28
    command_list = []
740 olof 29
    command_map = {}
741 olof 30
    CMDLIST_NAME = 0
31
    CMDLIST_HANDLER = 1
32
    CMDLIST_PARAMINFO = 2
33
    CMDLIST_HELP = 3
34
 
35
    logHelp = 'usage:\t log [options]\n\n' \
36
              '\t options:\n' \
37
              '\t level <num>, where: 0 < num < 3\n'
38
    stateHelp = 'usage: state [name/add/rem]'
39
    filterHelp = 'usage: filter [name/add/rem]'
40
    addifHelp = 'usage: addif [name] [options]'
41
    addbridgeHelp = 'usage: addbridge [interface names]'
42
    tcpdHelp = 'usage: tcpd [start/stop/configure] [options]'
43
    tlsdHelp = 'usage: tlsd [start/stop/configure] [options]'
44
    canctldHelp = 'usage: canctld [start/stop/configure] [options]'
45
    simHelp = 'usage: sim [record/play/add/rem/save/load] [options]'
740 olof 46
    help_command_map = {}
741 olof 47
 
48
    logOptions = {}
49
    ifOptions = {}
50
    bridgeOptions = {}
51
    tcpdOptions = {}
52
    tlsdOptions = {}
53
    canctldOptions = {}
54
    simOptions = {}
739 olof 55
 
741 olof 56
    logValidOptions = {'level' : ['range', 0, 3]}
57
    ifValidOptions = {'type' : ['alt', 'serial','udp']}
58
 
59
    ifSerialOptions = {'' : []}
60
    ifCanStimOptions = {'' : []}
61
    ifTelnetOptions = {'' : []}
62
    ifTcpTlsOptions = {'' : []}
63
    ifUDPOptions = {'' : []}
64
 
65
    bridgeValidOptions = {'' : ['']}
66
    tcpdValidOptions = {'' : []}
67
    tlsdValidOptions = {'' : []}
68
    canctldValidOptions = {'' : []}
69
    simValidOptions = {'' : []}
70
 
739 olof 71
    def __init__ (self):
740 olof 72
 
741 olof 73
        self.command_list = [['help', self.helpCmd, '', 'display help'],
74
                       ['log', self.logCmd, '<options>', 'log control: \"help log\"'],
75
                       ['exec', self.execCmd, '<filename>', 'run command listing\n'],
76
                       ['filter', self.filterCmd, '<cmd>', 'filter commands: \"help filter\"'],
77
                       ['state', self.stateCmd, '<cmd>', 'state commands: \"help state\"\n'],
78
                       ['addif', self.ifAddCmd, '<options>', 'add interface: \"help addif\"'],
79
                       ['remif', self.ifRemCmd, '<name>', 'remove interface'],
80
                       ['ifup', self.ifUpCmd, '<name>', 'bring up interface'],
81
                       ['ifdown', self.ifDownCmd, '<name>', 'bring down interface\n'],
82
                       ['addbrigde', self.addBridgeCmd, '<options>', 'add bridge: \"help addbridge\"'],
83
                       ['rembridge', self.remBridgeCmd, '<id>', 'remove bridge\n'],
84
                       ['tcpd', self.tcpdCmd, '<cmd>', 'tcpd server control: \"help tcpd\"'],
85
                       ['tlsd', self.tlsdCmd, '<cmd>', 'tlsd server control: \"help tlsd\"'],
86
                       ['canctld', self.canCtldCmd, '<cmd>', 'canctld server control: \"help canctld\"\n'],
87
                       ['status', self.statusCmd, '', 'show daemon status'],
88
                       ['stats', self.statsCmd, '', 'show statistics\n'],
89
                       ['nodelist', self.nodesCmd, '', 'list can nodes'],
90
                       ['filterlist', self.filterlistCmd, '', 'list active filters\n'],
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 filterlistCmd(self, *args):
741 olof 235
        raise 'not implemented'
739 olof 236
 
237
    def simCmd(self, *args):
741 olof 238
        raise 'not implemented'
739 olof 239
 
240
    def logCmd(self, *args):
741 olof 241
        raise 'not implemented'
740 olof 242
 
739 olof 243
    def execCmd(self, *args):
741 olof 244
        raise 'not implemented'
739 olof 245
 
741 olof 246
    def parseCommand(self, cmdstr):
247
        incmd = cmdstr.strip()
248
        cmd = incmd.split(' ')
249
        if len(cmd[0]) < 2:
250
            return
251
        cmd[0] = cmd[0].lower()
252
        if cmd[0] == 'quit' or cmd[0] == 'exit':
253
            self.terminated = True
254
        elif self.command_map.has_key(cmd[0]):
255
            self.command_list[self.command_map[cmd[0]]][self.CMDLIST_HANDLER](cmd[1:])
256
        else:
257
            print 'unknown command: ' + cmd[0]
258
 
736 olof 259
    def exitHelper(self):
737 olof 260
        if self.nodeIf is not None and self.nodeIf.running():
736 olof 261
            self.nodeIf.stop()
739 olof 262
 
263
    def exceptHelper(self, type, value, tb):
264
        import traceback
265
        traceback.print_exception(type, value, tb)
266
        print '\nException in main program, shutting down threads'
267
        self.terminated = True
268
        self.exitHelper()
269
 #       sys.exit(-1)
270
 
736 olof 271
    def run(self):
272
        try:
741 olof 273
            myPath = os.path.dirname(__file__)
274
            os.chdir(myPath)
736 olof 275
        except:
276
            return
277
 
737 olof 278
        print 'INIT: Start logging'
736 olof 279
        log.basicConfig(level=log.DEBUG)
280
 
741 olof 281
        """command parameters only dictate verbosity and use of config file"""
737 olof 282
        print 'INIT: Get config options from command line / config file'
736 olof 283
        try:
284
            opts, args = getopt.getopt(sys.argv[1:], "ho:v", ["help", "output="])
285
        except getopt.GetoptError:
286
            print 'Invalid usage'
287
            usage()
288
            sys.exit(2)
289
     #   output = None
290
     #   verbose = False
291
        for o, a in opts:
292
            if o == "-v":
293
                pass
294
     #           verbose = True
295
            if o in ("-h", "--help"):
296
                usage()
297
                sys.exit()
298
            if o in ("-o", "--output"):
299
                pass
300
    #            output = a
740 olof 301
 
741 olof 302
        """load config defaults, or last config if exists"""
303
        """run startup.cfg"""
304
 
305
#        print 'INIT: Loading filters and spaces'
740 olof 306
#       self.cfg.filterCfg.importFilter('DefaultFilter')
307
#       self.cfg.stateSpaceCfg.importSpace('DefaultStateSpace')
741 olof 308
#        self.cfg.stateSpaceCfg.loadSpaces()
309
#        self.cfg.filterCfg.loadFilters()
310
#        self.cfg.setupFilterBindings()
311
#        self.cfg.setupFilterChain()
740 olof 312
 
741 olof 313
#        print 'INIT: Starting selected can interface'
314
#        ''' nodeif thread launch '''
315
#        self.ifNotifier = self.IfNotifier()
316
#        pktHandler = CanPktHandler1(self.cfg)
317
#        
318
#        ifConfig = NodeIfCanStim.DEFAULT_CONFIG
319
#        self.nodeIf = NodeIfCanStim(ifConfig, pktHandler, self.ifNotifier)
320
# #       ifConfig = NodeIfSerial.DEFAULT_CONFIG
321
#    
322
#        atexit.register(self.exitHelper)
323
#        sys.excepthook = self.exceptHelper
738 olof 324
 #       self.nodeIf = NodeIfSerial(pktHandler, ifConfig)
741 olof 325
#        
326
#        if not self.nodeIf.start():
327
#            print 'FATAL: Failed to initialize node interface.'
328
#            print 'This may indicate that the interface is unavailable, ' \
329
#                  'or that you do not have permission to access it.'
330
#            sys.exit(-1)
736 olof 331
 
332
        print 'Initialize/gather info on connected can nodes and load associated state'
333
        print 'Start selected TCP and UDP server(s)'
334
        # server threads launch
335
 
336
        print 'CanDaemon v1 ready'
337
        print 'Enter command or type \"help\" for a list of commands'
738 olof 338
        while not self.terminated:
741 olof 339
            input = raw_input('> ')
340
            self.parseCommand(input)
739 olof 341
 
736 olof 342
        print 'Shutdown'
741 olof 343
#        if self.nodeIf.running():
344
#            print 'Stopping If thread'
345
#            self.nodeIf.stop()
738 olof 346
 
741 olof 347
#        self.cfg.stateSpaceCfg.saveSpaces()
348
#        self.cfg.filterCfg.saveFilters()
738 olof 349
 
739 olof 350
        print 'Waiting 0.1..'
738 olof 351
        time.sleep(0.1) # wait for threads
739 olof 352
        print 'Terminating'
738 olof 353
        sys.exit(0) # will except if there are threads remaining
736 olof 354
 
355
#---------------------------------------------------------------------------
356
 
357
def main():
358
    daemonApp = CanDaemon()
737 olof 359
#    install_thread_excepthook()
736 olof 360
    daemonApp.run()
361
 
362
#---------------------------------------------------------------------------
363
 
364
if __name__ == '__main__':
365
    __name__ = 'Main'
366
    main()