Project

General

Profile

Statistics
| Revision:

root / trunk / common / common.py @ 282

History | View | Annotate | Download (5.37 KB)

1
"""
2
  This file is part of Tooltron.
3
 
4
  Tooltron is free software: you can redistribute it and/or modify
5
  it under the terms of the Lesser GNU General Public License as published by
6
  the Free Software Foundation, either version 3 of the License, or
7
  (at your option) any later version.
8
 
9
  Tooltron is distributed in the hope that it will be useful,
10
  but WITHOUT ANY WARRANTY; without even the implied warranty of
11
  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
12
  Lesser GNU General Public License for more details.
13
  You should have received a copy of the Lesser GNU General Public License
14
  along with Tooltron.  If not, see <http://www.gnu.org/licenses/>.
15

16
  Copyright 2009 Bradford Neuman <bneuman@andrew.cmu.edu>
17

18
"""
19

    
20
####
21
# This file contains common code for both manualTron and the real tooltron server
22

    
23
import serial
24
import sys
25
import time
26

    
27
keypadTimeout = 31 #in seconds
28

    
29
TT_ACK     = 'a'
30
TT_NACK    = 'n'
31
TT_TIMEOUT = 't'
32
TT_KC        = 'x' # A transaction containing a key and a card number
33
TT_GRANT     = 'q' # Tool access granted
34
TT_DENY      = 'f' # Tool access denied
35
TT_PING    = 'g'
36
TT_BOOT    = 'b'
37
TT_PROGRAM_MODE = 'p'
38
TT_RESET = 'r'
39
TT_PING = 'g'
40
TT_BAD = 0
41
TT_PROGM = 'p'
42
TT_PROGD = 'd'
43

    
44
TT_MAX_RETRY = 3
45

    
46
MAX_PAYLOAD_LEN = 32
47

    
48
BAUD_RATE = 9600
49

    
50
# cardbox id
51
CARDBOX_ID = 2
52

    
53
#fails until a warning is sent
54
MAX_TOOL_FAILS = 5
55

    
56
bus = None
57

    
58
class BusException(Exception):
59
    def __str__(self):
60
        return "Bus Not Init'd"
61

    
62
class TimeoutException(Exception):
63
    def __init__(self, val):
64
        Exception.__init__(self)
65
        self.str = val
66

    
67
    def __str__(self):
68
        return "TimeoutException: " + self.str
69

    
70
def printMsg(msg):
71
    if len(msg) < 5:
72
        print "ERROR: trying to print message thats too small!"
73
        return
74
    if msg[0] == '^':
75
        print '^',
76
    else:
77
        print str(ord(msg[0]))
78

    
79
    for c in msg[1:]:
80
        print str(ord(c)),
81

    
82
    print
83

    
84

    
85
#tn is an actual tool number
86
# ^ <src> <dest> <cmd> <plen> <payload> <crc>
87
def sendMessage(tn, cmd, msg):
88
    global bus
89
    if bus == None:
90
        raise BusException
91
    if len(msg) > MAX_PAYLOAD_LEN:
92
        print "ERROR: message too long! max size is " + str(MAX_PAYLOAD_LEN)
93
    else:
94
        body = chr(1) + chr(tn) + cmd + chr(len(msg)) + msg
95
        crc = 0
96
        for c in body:
97
            crc = crc ^ ord(c)
98
        msg = '^' + body + chr(crc)
99
        print "sending packet to tool",tn
100
        printMsg(msg)
101
        bus.write(msg)
102

    
103
def sendTool(t):
104
    tn = t
105
    print "sending power to tool ID",tn
106
    sendMessage(tn, TT_GRANT, "")
107

    
108
def sendGrant():
109
    print "seding grant to cardbox (",CARDBOX_ID," )"
110
    sendMessage(CARDBOX_ID, TT_GRANT, "")
111

    
112
def sendDeny():
113
    print "seding deny to cardbox (",CARDBOX_ID," )"
114
    sendMessage(CARDBOX_ID, TT_DENY, "")
115

    
116
def sendAck(toolNum):
117
   print "seding ACK to",toolNum
118
   sendMessage(toolNum, TT_ACK, "")
119

    
120
def sendNack(toolNum):
121
   print "seding NACK to",toolNum
122
   sendMessage(toolNum, TT_NACK, "")
123

    
124
# This function eats the rest of the packet where data is what we have so far
125
def flushPacket(data):
126
    global bus
127
    if bus == None:
128
        raise BusException
129

    
130
    while len(data) < 6:
131
        c = bus.read(1)
132
        #print "("+str(ord(c))+")"
133
        data += c
134

    
135
    plen = data[4]
136
    if plen > 0:
137
        bus.read(ord(plen))
138

    
139

    
140
#reads until a timeout
141
def readInf():
142
    c = ' '
143
    while c != '':
144
        c = bus.read(1)
145
        if c != '':
146
            print "<" + str(ord(c)) + ">"
147

    
148
# Returns [src, dest, cmd, data]
149
def readMessage():
150
    global bus
151
    if bus == None:
152
        raise BusException
153

    
154
    start = bus.read(1)
155
    if start == '^':
156
        src = bus.read(1)
157
        if src == chr(1): #reflection
158
            print "(reflection)"
159
            flushPacket('^' + src)
160
            return readMessage()
161

    
162
        dest = bus.read(1)
163
        cmd = bus.read(1)
164
        plen = bus.read(1)
165
        data = bus.read(ord(plen))
166
        x = bus.read(1)
167

    
168
        print "got packet"
169
        printMsg('^' + src + dest + cmd + plen + data + x)
170

    
171
        crc = ord(src) ^ ord(dest) ^ ord(cmd) ^ ord(plen)
172
        for d in data:
173
            crc ^= ord(d)
174

    
175
        if crc == ord(x):
176
            return [src, dest, cmd, data]
177
        else:
178
            print "xor fail. got", str(ord(x)), "should have been got",crc
179
            return None
180
    else:
181
        if start == '':
182
            print "ERROR: timeout on start delim"
183
        else:
184
            print "ERROR: did not get start delimiter: "+str(ord(start))
185
        return None
186

    
187
#returns [key, carnum] pair
188
def readTransaction():
189
    m = readMessage()
190
    if m != None:
191
        [src, dest, cmd, data] = m
192
        if src == CARDBOX_ID and cmd == TT_KC and len(data) >= 2:
193
            return data[0], data[1:end]
194
        else:
195
            print "ERROR: wrong size data from transaction"
196
            logMessage("ERROR: got bad packet from cardbox")
197
            sendNack(CARDBOX_IDX)
198
            return None
199

    
200

    
201
#returns [src, dest, command] or [] on error
202
# because of reflection, this will quietly ignore packets send by the server
203
def readTool():
204
    m = readMessage()
205
    if m == None:
206
        return None
207
    [src, dest, cmd, data] = m
208
    return [src, dest, cmd]
209

    
210
def checkAck(t):
211
    tn = t
212
    m = readTool()
213
    if m==None:
214
        print "timeout"
215
        return False
216
    [src,dest,cmd] = m
217
    return cmd == TT_ACK
218

    
219

    
220
def initBus(filename):
221
    global bus
222

    
223
    bus = serial.Serial(filename, BAUD_RATE, timeout = 2)
224
    bus.flushInput()
225
    print bus
226

    
227
    return True