Project

General

Profile

Statistics
| Revision:

root / trunk / swipe / dustmite.py @ 131

History | View | Annotate | Download (5.31 KB)

1
#!/usr/bin/python
2

    
3
################################################################################
4
## dustmite.py is the main tooltron server
5
# It connects to the civicrm database of mysql and sends commands to
6
# the cardbox and tools.  It must be connected over usb to the card
7
# reader, and the two arguments specify the devices to use for the
8
# serial communication to the card and tool boxes.
9
#
10
# This script requires the modules seen below, which may not be
11
# present by default
12
#
13
# Because of a problem with card scans buffering in stdio, there is a
14
# seperate thread which stores the last swiped id. To cleanly exit the
15
# program type C-d
16
#
17
# email bradneuman@gmail.com if you have any questions
18
################################################################################
19

    
20

    
21
import re
22
import sys
23
import serial
24
import MySQLdb
25
import getpass
26

    
27

    
28
#tools for messages are these + 1 but in decimal, not ascii
29
#the values are lists of numbers which get appended to the acl
30
tools = {
31
   'Bandsaw':['2','8'],
32
   'DrillPress':['1','9'],
33
   'Mill':['4'],
34
   'Lathe':['5'],
35
   'ChopMiterSaw':['3']
36
}
37

    
38

    
39

    
40
TT_GET_KEY = 'k'
41
TT_ACK     = 'a'
42
TT_NACK    = 'n'
43
TT_TO      = 'f'
44
TT_TIMEOUT = 't'
45

    
46
BAUD_RATE = 9600
47

    
48
#################################################
49
#this code spawns a thread which always puts the last card id in the
50
#lastid variable.
51
#################################################
52
import threading
53
import time
54

    
55
lastid = None
56
idready = False
57

    
58
cv = threading.Condition()
59

    
60
class idThread ( threading.Thread ):
61

    
62
   def run ( self ):
63
       global lastid
64
       global idready
65

    
66
       try:
67
           while True:
68
               l = raw_input()
69
               cv.acquire()
70
               id = re.search('%([0-9]*)=.*', l)
71
               if id != None:
72
                   lastid = id
73
                   print "!!! setting idready"
74
                   idready = True
75
                   cv.notify()
76
               cv.release()
77

    
78
       except EOFError:
79
           cv.acquire()
80
           idready = True
81
           lastid=None
82
           cv.notify()
83
           cv.release()
84
#end thread
85
###############################################
86

    
87
def get_last_id():
88
    global idready
89
    global lastid
90

    
91
    got = None
92

    
93
    print ">>> locking for last_id"
94

    
95
    cv.acquire()
96
    while not idready:
97
        print ">>> wait"
98
        cv.wait()
99

    
100
    print ">>> idready set"
101

    
102
    got = lastid
103
    idready = False
104
    cv.release()
105
    print ">>> done"
106

    
107
    return got
108

    
109
def clear_id():
110
    global idready
111
    global lastid
112

    
113
    print "=== locking to clear idready flag"
114
    cv.acquire()
115
    idready = False
116
    lastid = None
117
    cv.release()
118
    print "=== done"
119

    
120
    return
121

    
122

    
123

    
124
if len(sys.argv) < 3:
125
    print "usage: dustmite.py /path/to/keypad/device /path/to/tool/bus/device"
126

    
127
else:
128

    
129

    
130
    pw = getpass.getpass("mysql password: ")
131
    db = MySQLdb.connect(host="roboclub8.frc.ri.cmu.edu", user="tooltron", passwd=pw, db="civicrm")
132
    print "connected, now accepting input"
133

    
134
    #start the id scan thread AFTER the getpass prompt
135
    idThread().start()
136

    
137

    
138
    cursor = db.cursor()
139

    
140
    qry = "SELECT tools_6 FROM civicrm_value_roboclub_info_2 WHERE card_number_1 = "
141

    
142
    keypad = serial.Serial(sys.argv[1], BAUD_RATE, timeout = 30) 
143
    keypad.flushInput()
144
    print keypad
145

    
146
    bus = serial.Serial(sys.argv[2], BAUD_RATE, timeout = 15)
147
    bus.flushInput()
148
    print bus
149

    
150
    # ^ <src> <dest> <data>
151
    def sendTool(t):
152
        tn = int(t) + 1 
153
        msg = '^' + chr(1) + chr(tn) + 'O' + chr(1 ^ tn ^ ord('O'))
154

    
155
        bus.write(msg)
156
        return
157

    
158
    #returns [src, data] or [] on error
159
    def readTool():
160
        ret = [0,0,0]
161

    
162
        if bus.read(1) == '^':
163
            ret[0] = bus.read(1)
164
            ret[1] = bus.read(1)
165
            ret[2] = bus.read(1)
166
            x = bus.read(1)
167

    
168
            print "got packet",ret
169

    
170
            if chr(ord(ret[0]) ^ ord(ret[1]) ^ ord(ret[2])) == x:
171
                return ret
172
            else:
173
                print "xor fail. got", x, "should have been got",(ord(ret[0]) ^ ord(ret[1]) ^ ord(ret[2]))
174

    
175
        return []
176

    
177
    def checkAck(t):
178
        tn = int(t) + 1 
179
        m = readTool()
180

    
181
        if m== []:
182
            return False
183

    
184

    
185
        return m[0] == chr(tn) and m[1] == chr(1) and m[2] == 'A'
186

    
187

    
188
    while True:
189

    
190
        id = get_last_id()
191
        
192
        if id != None:
193
            print "\n-----------\nid# ", id.group(1)
194

    
195

    
196
            print "sending key request"
197
            keypad.write(TT_GET_KEY)
198

    
199
            cursor.execute(qry + id.group(1))
200

    
201
            result = cursor.fetchall()
202

    
203
            acl = []
204

    
205
            for r in result:
206
                tls = r[0].split("\x01")
207
                for t in tls:
208
                    if t != '':
209
                        try:
210
                            acl.extendy (tools[t])
211
                        except KeyError:
212
                            #this doesn't really matter
213
                            pass
214

    
215
            print "user has access to:", acl
216

    
217
            resp = keypad.read(1)
218

    
219
            print "request:",resp
220

    
221

    
222
            if acl.count(resp) > 0:
223
                keypad.write(TT_ACK)
224
                sendTool(resp)
225
                print "ACCESS GRANTED"
226
                if checkAck(resp):
227
                    print "ACK"
228
                else:
229
                    print "NO ACK!!!!"
230

    
231
            else:
232
                keypad.write(TT_NACK)
233
                print "ACCESS DENIED!!"
234

    
235
        else:
236
            break
237

    
238
        clear_id()