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