Subversion Repositories HomeAutomation

Rev

Rev 739 | Only display areas with differences | Regard whitespace | Details | Blame | Last modification | View Log | SVN | RSS feed

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