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