Project

General

Profile

Revision 283

massive updates for new cardbox transaction system

View differences:

trunk/swipe/manualtron.py
29 29
common.initBus(sys.argv[1])
30 30

  
31 31
def key():
32
    if not common.sendKeyRequest():
33
        print "could not send request!!"
32
    x = readTransaction()
33

  
34
    if x == None:
35
        print "Didn't get valid transaction"
34 36
        return False
35 37

  
36
    ret = common.readKey()
37
    common.sendAck(2)
38
    [key,card] = x
38 39

  
39
    print ret
40
    print "key:",key
41
    print "cardnum:",card
42
    return True
40 43

  
44

  
41 45
def ping(t):
42 46
    common.sendMessage(t, common.TT_PING, "")
43 47
    print common.checkAck(t)
trunk/swipe/tooltron.py
2 2

  
3 3
"""
4 4
  This file is part of Tooltron.
5
 
5

  
6 6
  Tooltron is free software: you can redistribute it and/or modify
7 7
  it under the terms of the Lesser GNU General Public License as published by
8 8
  the Free Software Foundation, either version 3 of the License, or
9 9
  (at your option) any later version.
10
 
10

  
11 11
  Tooltron is distributed in the hope that it will be useful,
12 12
  but WITHOUT ANY WARRANTY; without even the implied warranty of
13 13
  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
......
37 37
################################################################################
38 38

  
39 39

  
40
import re
41 40
import sys
42 41
import MySQLdb
43 42
import getpass
......
77 76
   '0':13
78 77
}
79 78

  
80
#################################################
81
#this code spawns a thread which always puts the last card id in the
82
#lastid variable.
83
#################################################
84
import threading
85
import time
86
import select
87
import os
88

  
89
lastid = None
90
idready = False
91
threadDone = False
92
threadDoneExcp = None
93

  
94
cv = threading.Condition()
95

  
96
class ctrlDException (Exception):
97
   def __init__(self,str):
98
      Exception.__init__(self)
99
      self.str = str
100

  
101
   def __str__(self):
102
      return "Ctrl-D pressed: " + self.str
103

  
104
class idThread ( threading.Thread ):
105

  
106
   def __init__ (self):
107
      threading.Thread.__init__(self)
108
      self.wpipe = None
109

  
110
   def stop (self):
111
      self.stop_thread = True
112
      if self.wpipe != None:
113
         # write to this pipe so that the select will drop out
114
         self.wpipe.write('!')
115

  
116
   def run (self):
117
       global lastid
118
       global idready
119
       global threadDone
120
       global threadDoneExcp
121
       self.stop_thread = False
122

  
123
       [r,w] = os.pipe()
124
       self.rpipe = os.fdopen(r,'r')
125
       self.wpipe = os.fdopen(w,'w')
126

  
127
       try:
128
          while not self.stop_thread:
129
             # hang until we either get keyboard input or are told to stop
130
             [active,a,b] = select.select([sys.stdin,self.rpipe],[],[])
131

  
132
             if not self.stop_thread:
133
                l = raw_input()
134

  
135
                cv.acquire()
136
                try:
137
                   id = re.search('%([0-9]*)=.*', l)
138
                   if id != None:
139
                      lastid = id
140
                      print "!!! setting idready"
141
                      idready = True
142
                      cv.notify()
143
                   else:
144
                      ifready = False
145
                finally:
146
                   cv.release()
147
          print "thread stopped"
148

  
149
       except EOFError:
150
           cv.acquire()
151
           idready = True
152
           lastid=None
153
           threadDoneExcp=ctrlDException("thread exiting cleanly")
154
           cv.notify()
155
           cv.release()
156
       except Exception, e:
157
          threadDoneExcp = e #TODO: provide a line number or something?
158
       finally:
159
          print "id thread getting ready to exit..."
160
          threadDone = True
161
          cv.acquire()
162
          idready = False
163
          cv.notify()
164
          cv.release()
165
          print "id thread exiting"
166
          
167
#end thread
168
###############################################
169

  
170 79
try:
171 80
   flog = open("/var/log/tooltron", "a")
172 81
except IOError as e:
......
203 112
for t in toolFails:
204 113
   toolFails[t] = 0
205 114

  
206
def get_last_id():
207
    global idready
208
    global lastid
209
    global threadDoneExcp
210 115

  
211
    got = None
116
################################################################################
117
# Main:
212 118

  
213
    print ">>> locking for last_id"
214

  
215
    cv.acquire()
216
    while not idready:
217
       if threadDoneExcp != None:
218
          print "thread has been exited"
219
          raise threadDoneExcp
220

  
221
       print ">>> wait"
222
       try:
223
          cv.wait()
224
       # if the user hits ctrl-c, cleanly exit
225
       except KeyboardInterrupt:
226
          print "cv.wait() got a keyboard interupt!"
227
          cv.release()
228
          return None
229

  
230
    print ">>> idready set"
231

  
232
    got = lastid
233
    idready = False
234
    cv.release()
235
    print ">>> done"
236

  
237
    return got
238

  
239
def clear_id():
240
    global idready
241
    global lastid
242

  
243
    print "=== locking to clear idready flag"
244
    cv.acquire()
245
    idready = False
246
    lastid = None
247
    cv.release()
248
    print "=== done"
249

  
250
    return
251

  
252 119
if len(sys.argv) < 2:
253 120
   print "usage: tooltron.py /path/to/bus/device"
254 121
   exit(-1)
......
259 126

  
260 127
   pw = getpass.getpass("mysql password: ")
261 128

  
262
   #start the id scan thread AFTER the getpass prompt
263
   idt = idThread()
264
   idt.start()
265
   
266
   # If there are any uncaught exceptions in the rest of the code, we need to kill the id thread
267
   # so the program as a whole will exit
268
   try:
269
      cursor = None
270
      qry = "SELECT tools_6 FROM civicrm_value_roboclub_info_2 WHERE card_number_1 = "
129
   cursor = None
130
   qry1 = "SELECT tools_6 FROM civicrm_value_roboclub_info_2 WHERE card_number_1 = "
271 131

  
272
      def sendTool(t):
273
         tn = keypad2toolID(t)
274
         common.sendTool(tn)
132
   # wapper to translate tool number
133
   def sendTool(t):
134
      tn = keypad2toolID(t)
135
      common.sendTool(tn)
275 136

  
276
      # This function eats the rest of the packet where data is what we have so far
277
      def flushPacket(data):
278
         while len(data) < 6:
279
            data += bus.read(1)
137
   # This function eats the rest of the packet where data is what we have so far
138
   # TODO: do I still need this?
139
   def flushPacket(data):
140
      while len(data) < 6:
141
         data += bus.read(1)
280 142

  
281
         plen = data[4]
282
         if plen > 0:
283
            bus.read(ord(plen))
143
      plen = data[4]
144
      if plen > 0:
145
         bus.read(ord(plen))
284 146

  
285
      while True:
286
         id = get_last_id()
147
   while True:
287 148

  
288
         if id != None:
289
            print "\--------------------\n",strftime("%Y.%m.%d %H:%M:%S \n"),"id# ", id.group(1)
149
      x = common.readTransaction()
290 150

  
151
      print "\n"
291 152

  
292
            # Send a key request
293
            common.sendMessage(2, common.TT_GET_KEY, "")
294
            
295
            # listen for an ACK or a key response
296
            msg = common.readMessage()
297
            if msg == None:
298
               print "ERROR: Timeout waiting for response from key request!"
299
               continue
153
      if x == None:
154
         print "ERROR: bad transaction"
155
         logMessage("ERROR: got bad packet from cardbox")
156
         continue
300 157

  
301
            # resp hols the key response, so set it to None since we don't have one yet
302
            resp = None
158
      [key, cardnum] = x
303 159

  
304
            [src,dest,cmd,data] = msg
305
            src = ord(src)
306
            dest = ord(dest)
307
            # print "tooltron.py has message:"
308
            # print "src:", src
309
            # print "dest:", dest
310
            # print "cmd:", cmd
311
            # print "data: {",data,"}"
160
      print "\--------------------\n",strftime("%Y.%m.%d %H:%M:%S \n")
161
      print "cardnum:", cardnum
162
      print "key:", key
312 163

  
313
            #TODO: no magic number '2' for cardbox or '1' for server
314
            if src == 2 and dest == 1:
315
               if cmd == common.TT_ACK:
316
                  print "got ACK from cardbox"
317
               elif cmd == common.TT_SEND_KEY:
318
                  print "got key response instead of ACK from cardbox"
319
                  print "using key: ", data
320
                  resp = data[0]
321
               else:
322
                  print "ERROR: got some other packet type: ", cmd, " (data = {", data, "})"
323
                  continue
324
            else:
325
               print "ERROR: got confusing packet. Excpecting something from cardbox (2) but got:"
326
               common.printMsg(msg)
327
               continue
164
      # Start doing the MySQL queries, hope this isn't too slow
328 165

  
329
            # start the timer so we can timeout if we are still waiting for a key response
330
            startTime = time.time()
166
      print "running queries..."
331 167

  
332
            # while we are (or might be) waiting for a key response, do the MySQL stuff
333
            if cursor != None:
334
               cursor.close()
168
      if cursor != None:
169
         cursor.close()
335 170

  
336
            db = MySQLdb.connect(host="roboclub8.frc.ri.cmu.edu", user="tooltron", passwd=pw, db="civicrm")
337
            print "connected to mysql server"
338
            cursor = db.cursor()
339
            print "got db cursor"
171
      #TODO: handle timeouts / slow connections!
172
      db = MySQLdb.connect(host="roboclub8.frc.ri.cmu.edu", user="tooltron", passwd=pw, db="civicrm")
173
      print "connected to mysql server"
174
      cursor = db.cursor()
175
      print "got db cursor"
340 176

  
341
            cursor.execute(qry + id.group(1))
177
      print "qry1 (ACL)..."
178
      cursor.execute(qry1 + cardnum)
342 179

  
343
            result = cursor.fetchall()
180
      result = cursor.fetchall()
344 181

  
345
            acl = []
182
      acl = []
346 183

  
347
            for r in result:
348
               tls = r[0].split("\x01")
349
               for t in tls:
350
                  if t != '':
351
                     try:
352
                        acl.extend (tools[t])
353
                     except KeyError:
354
                        #this doesn't really matter
355
                        pass
184
      for r in result:
185
         tls = r[0].split("\x01")
186
         for t in tls:
187
            if t != '':
188
               try:
189
                  acl.extend (tools[t])
190
               except KeyError:
191
                  #this doesn't really matter
192
                  pass
356 193

  
357
            print "user has access to:", acl
194
      print "user has access to:", acl
358 195

  
359
            user = ""
196
      user = ""
360 197

  
361
            #query for name
362
            qry2 = "SELECT civicrm_contact.display_name \
363
                    FROM civicrm_value_roboclub_info_2 \
364
                    INNER JOIN (civicrm_contact) \
365
                    ON civicrm_value_roboclub_info_2.entity_id = civicrm_contact.id \
366
                    WHERE civicrm_value_roboclub_info_2.card_number_1 = " + id.group(1) + ";"
198
      print "qry2 (name/email)..."
199
      #query for name
200
      qry2 = "SELECT civicrm_contact.display_name \
201
              FROM civicrm_value_roboclub_info_2 \
202
              INNER JOIN (civicrm_contact) \
203
              ON civicrm_value_roboclub_info_2.entity_id = civicrm_contact.id \
204
              WHERE civicrm_value_roboclub_info_2.card_number_1 = " + cardnum + ";"
367 205

  
368
            cursor.execute(qry2)
369
            result = cursor.fetchall()
206
      cursor.execute(qry2)
207
      result = cursor.fetchall()
370 208

  
371
            if len(result) > 0:
372
               user += result[0][0]
209
      if len(result) > 0:
210
         user += result[0][0]
373 211

  
374
            qry2 = "SELECT civicrm_email.email \
375
                    FROM civicrm_value_roboclub_info_2 \
376
                    INNER JOIN (civicrm_email) \
377
                    ON civicrm_email.contact_id = civicrm_value_roboclub_info_2.entity_id \
378
                    WHERE civicrm_value_roboclub_info_2.card_number_1 = " + id.group(1) + ";"
212
      qry2 = "SELECT civicrm_email.email \
213
              FROM civicrm_value_roboclub_info_2 \
214
              INNER JOIN (civicrm_email) \
215
              ON civicrm_email.contact_id = civicrm_value_roboclub_info_2.entity_id \
216
              WHERE civicrm_value_roboclub_info_2.card_number_1 = " + cardnum + ";"
379 217

  
380
            cursor.execute(qry2)
381
            result = cursor.fetchall()
218
      cursor.execute(qry2)
219
      result = cursor.fetchall()
382 220

  
383
            if len(result) > 0:
384
               user += " ("+result[0][0]+")"
221
      if len(result) > 0:
222
         user += " ("+result[0][0]+")"
385 223

  
386
            if user == "":
387
               user = str(id.group(1))
224
      if user == "":
225
         user = cardnum
388 226

  
389
            print user
227
      print "[[[",user,"]]]"
390 228

  
229
      print "qry3 (payment)..."
230
      # check if member has paid recently 
231
      # first, figure out what semester it is
232
      today = date.today()
391 233

  
392
            # check if member has paid recently 
234
      # semester start dates
235
      aug20 = datetime.date(today.year, 8, 20) # Fall semester
236
      may21 = datetime.date(today.year, 5, 21) # summer
237
      jan1  = datetime.date(today.year, 1,  1) # Spring semester
238
      # if they don't fall after those two, its fall
393 239

  
394
            # first, figure out what semester it is
395
            today = date.today()
240
      if today > aug20:
241
         print "its fall semester!"
242
         #its fall, so they must have paid after may21 (either full year of half) to be paid
243
         qry3 = "SELECT civicrm_value_roboclub_info_2.date_paid_10 >= STR_TO_DATE('" + may21.strftime('%m/%d/%Y') + "', '%m/%d/%Y') ,  \
244
                 DATE_FORMAT(civicrm_value_roboclub_info_2.date_paid_10, '%M %d %Y') \
245
                 FROM civicrm_value_roboclub_info_2 \
246
                 WHERE civicrm_value_roboclub_info_2.card_number_1 = " + cardnum + ";"
396 247

  
397
            # semester start dates
398
            aug20 = datetime.date(today.year, 8, 20) # Fall semester
399
            may21 = datetime.date(today.year, 5, 21) # summer
400
            jan1  = datetime.date(today.year, 1,  1) # Spring semester
401
            # if they don't fall after those two, its fall
248
      elif today > may21:
249
         print "its summer!"
250
         #its summer, so they need to have paid either full year since aug20 or one semester since jan 1
251
         qry3 = "SELECT (civicrm_value_roboclub_info_2.date_paid_10 >= STR_TO_DATE('" + aug20.strftime('%m/%d/%Y') + "', '%m/%d/%Y') AND \
252
                         civicrm_value_roboclub_info_2.amount_paid_11 = 25) OR \
253
                        (civicrm_value_roboclub_info_2.date_paid_10 >= STR_TO_DATE('" + jan1.strftime('%m/%d/%Y') + "', '%m/%d/%Y') AND \
254
                         civicrm_value_roboclub_info_2.amount_paid_11 = 15) , \
255
                 DATE_FORMAT(civicrm_value_roboclub_info_2.date_paid_10, '%M %d %Y') \
256
                 FROM civicrm_value_roboclub_info_2 \
257
                 WHERE civicrm_value_roboclub_info_2.card_number_1 = " + cardnum + ";"
258
      else:
259
         print "its spring!"
260
         #its spring, so they must have either paid full after aug20 or one semester since jan 1 (this is the same as summer)
261
         qry3 = "SELECT (civicrm_value_roboclub_info_2.date_paid_10 >= STR_TO_DATE('" + aug20.strftime('%m/%d/%Y') + "', '%m/%d/%Y') AND \
262
                         civicrm_value_roboclub_info_2.amount_paid_11 = 25) OR \
263
                        (civicrm_value_roboclub_info_2.date_paid_10 >= STR_TO_DATE('" + jan1.strftime('%m/%d/%Y') + "', '%m/%d/%Y') AND \
264
                         civicrm_value_roboclub_info_2.amount_paid_11 = 15) , \
265
                 DATE_FORMAT(civicrm_value_roboclub_info_2.date_paid_10, '%M %d %Y') \
266
                 FROM civicrm_value_roboclub_info_2 \
267
                 WHERE civicrm_value_roboclub_info_2.card_number_1 = " + cardnum + ";"
402 268

  
403
            if today > aug20:
404
               print "its fall semester!"
405
               #its fall, so they must have paid after may21 (either full year of half) to be paid
406
               qry3 = "SELECT civicrm_value_roboclub_info_2.date_paid_10 >= STR_TO_DATE('" + may21.strftime('%m/%d/%Y') + "', '%m/%d/%Y') ,  \
407
                       DATE_FORMAT(civicrm_value_roboclub_info_2.date_paid_10, '%M %d %Y') \
408
                       FROM civicrm_value_roboclub_info_2 \
409
                       WHERE civicrm_value_roboclub_info_2.card_number_1 = " + id.group(1) + ";"
410
               
411
            elif today > may21:
412
               print "its summer!"
413
               #its summer, so they need to have paid either full year since aug20 or one semester since jan 1
414
               qry3 = "SELECT (civicrm_value_roboclub_info_2.date_paid_10 >= STR_TO_DATE('" + aug20.strftime('%m/%d/%Y') + "', '%m/%d/%Y') AND \
415
                               civicrm_value_roboclub_info_2.amount_paid_11 = 25) OR \
416
                              (civicrm_value_roboclub_info_2.date_paid_10 >= STR_TO_DATE('" + jan1.strftime('%m/%d/%Y') + "', '%m/%d/%Y') AND \
417
                               civicrm_value_roboclub_info_2.amount_paid_11 = 15) , \
418
                       DATE_FORMAT(civicrm_value_roboclub_info_2.date_paid_10, '%M %d %Y') \
419
                       FROM civicrm_value_roboclub_info_2 \
420
                       WHERE civicrm_value_roboclub_info_2.card_number_1 = " + id.group(1) + ";"
421 269

  
270
      cursor.execute(qry3)
271
      result = cursor.fetchall()
422 272

  
423
               cursor.execute(qry3)
424
               result = cursor.fetchall()
425
               print result
426
            else:
427
               print "its spring!"
428
               #its spring, so they must have either paid full after aug20 or one semester since jan 1 (this is the same as summer)
429
               qry3 = "SELECT (civicrm_value_roboclub_info_2.date_paid_10 >= STR_TO_DATE('" + aug20.strftime('%m/%d/%Y') + "', '%m/%d/%Y') AND \
430
                               civicrm_value_roboclub_info_2.amount_paid_11 = 25) OR \
431
                              (civicrm_value_roboclub_info_2.date_paid_10 >= STR_TO_DATE('" + jan1.strftime('%m/%d/%Y') + "', '%m/%d/%Y') AND \
432
                               civicrm_value_roboclub_info_2.amount_paid_11 = 15) , \
433
                       DATE_FORMAT(civicrm_value_roboclub_info_2.date_paid_10, '%M %d %Y') \
434
                       FROM civicrm_value_roboclub_info_2 \
435
                       WHERE civicrm_value_roboclub_info_2.card_number_1 = 810797813"
436
#" + id.group(1) + ";"
273
      if len(result) == 0 or result[0][0] == 0 or result[0][0] == "NULL":
274
         print "DENIED: user has not paid recently enough!"
275
         if len(result[0]) >= 2:
276
            print "date_paid: ",result[0][1]
277
            logMessage(user + " has not paid since " + result[0][1] + ", revoking access!")
278
         else:
279
            logMessage(user + " has not paid, revoking access!")
280
            #acl = [] #TODO: uncomment!
437 281

  
438 282

  
439
            cursor.execute(qry3)
440
            result = cursor.fetchall()
283
      toolName = reverseTool(key)
284
      toolNameLong = toolName + " (k="+str(key)+"("+str(ord(key))+"), t="+str(keypad2toolID(key))+")"
285
      print "request:",key,"(",ord(key),") ",toolNameLong
441 286

  
442
            if len(result) == 0 or result[0][0] == 0 or result[0][0] == "NULL":
443
               print "DENIED: user has not paid recently enough!"
444
               if len(result[0]) >= 2:
445
                  print "date_paid: ",result[0][1]
446
                  logMessage(user + " has not paid since " + result[0][1] + ", revoking access!")
447
               else:
448
                  logMessage(user + " has not paid, revoking access!")
449
               acl = []
287
      if acl.count(key) > 0:
288
         common.sendGrant()
289
         #time.sleep(0.5) #TODO: do I still need this?
290
         sendTool(key)
291
         print "ACCESS GRANTED"
292
         logMessage(user+" ACCESSED tool "+toolNameLong)
293
         if common.checkAck(key):
294
            print "ACK"
295
            toolFails[toolName] = 0
296
         else:
297
            print "NO ACK!!!!"
298
            logMessage("tool "+toolNameLong+" did not ACK")
299
            toolFails[toolName] += 1
300
            if toolFails[toolName] > common.MAX_TOOL_FAILS:
301
               #TODO: send email
302
               logMessage("WARNING: tool "+toolNameLong+
303
                          " has failed to ACK "+
304
                          str(common.MAX_TOOL_FAILS)+" times in a row.")
450 305

  
451

  
452
            # while we don't have a valid response
453
            # Note that this might already be set above when we were heoping for an ACK
454
            while resp==None:
455
               try:
456
                  resp = common.readKey()
457
               except common.TimeoutException:
458
                  print "got TIMEOUT from keypad, breaking out of loop"
459
                  break
460

  
461
               if idready == True:
462
                  #if someone swipes while waiting for keypad, ignore it
463
                  print "got swipe during transaction, ignoring"
464
               if time.time() - startTime > keypadTimeout:
465
                  print "KEYPAD TIMEOUT!"
466
                  logMessage("keypad timed out")
467
                  common.sendMessage(2,common.TT_TIMEOUT,'')
468
                  break
469

  
470
            #if we have a valid response
471
            #sometimes the FTDI chip seems to give a zero as a string when power is reset
472
            if resp != None and ord(resp) != 0 and resp != common.TT_TIMEOUT:
473

  
474
               toolName = reverseTool(resp)
475
               toolNameLong = toolName + " (k="+str(resp)+"("+str(ord(resp))+"), t="+str(keypad2toolID(resp))+")"
476
               print "request:",resp,"(",ord(resp),") ",toolNameLong
477

  
478
               if acl.count(resp) > 0:
479
                  common.sendAck(2)
480
                  time.sleep(0.5)
481
                  sendTool(resp)
482
                  print "ACCESS GRANTED"
483
                  logMessage(user+" ACCESSED tool "+toolNameLong)
484
                  if common.checkAck(resp):
485
                     print "ACK"
486
                     toolFails[toolName] = 0
487
                  else:
488
                     print "NO ACK!!!!"
489
                     logMessage("tool "+toolNameLong+" did not ACK")
490
                     toolFails[toolName] += 1
491
                     if toolFails[toolName] > common.MAX_TOOL_FAILS:
492
                        #TODO: send email
493
                        logMessage("WARNING: tool "+toolNameLong+
494
                                   " has failed to ACK "+
495
                                   str(common.MAX_TOOL_FAILS)+" times in a row.")
496

  
497
               else:
498
                  common.sendNack(2)
499
                  print "ACCESS DENIED!!"
500
                  logMessage(user + " DENIED on tool "+toolNameLong)
501

  
502
               clear_id()
503

  
504
            elif resp == common.TT_TIMEOUT:
505
               print "TIMEOUT sent from keypad"
506
               continue
507
            else:
508
               break
509
   except ctrlDException:
510
      print "got a ctrl-D, exiting cleanly"
511
      logMessage("NOTICE: tooltron going down because of ctrl-D press")
512
      
513
   finally:
514
      if not threadDone:
515
         print "stopping id reader thread..."
516
         idt.stop()
306
      else:
307
         common.sendDeny()
308
         print "ACCESS DENIED!!"
309
         logMessage(user + " DENIED on tool "+toolNameLong)
trunk/common/common.py
23 23
import serial
24 24
import sys
25 25
import time
26
import re
26 27

  
27 28
keypadTimeout = 31 #in seconds
28 29

  
......
76 77
    else:
77 78
        print str(ord(msg[0]))
78 79

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

  
83
    for c in msg[4:]:
80 84
        print str(ord(c)),
81 85

  
82 86
    print
......
100 104
        printMsg(msg)
101 105
        bus.write(msg)
102 106

  
107
    #time.sleep(0.05) #TODO: do I still need this?
108

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

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

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

  
116 122
def sendAck(toolNum):
......
179 185
            return None
180 186
    else:
181 187
        if start == '':
182
            print "ERROR: timeout on start delim"
188
            #print "ERROR: timeout on start delim"
189
            pass #TODO: do I need this printout for other (non-transaction reading) cases???
183 190
        else:
184 191
            print "ERROR: did not get start delimiter: "+str(ord(start))
185 192
        return None
186 193

  
187
#returns [key, carnum] pair
194
# This function keeps trying to read the message until it gets something
195
def readMessageBlocking():
196
    print "blocking on read"
197
    m = None
198
    while m == None:
199
        m = readMessage();
200

  
201
    return m
202

  
203
#returns [key, cardnum] pair
188 204
def readTransaction():
189
    m = readMessage()
205
    m = readMessageBlocking()
190 206
    if m != None:
207
        print "got a message:"
191 208
        [src, dest, cmd, data] = m
209
        src = ord(src)
210
        dest = ord(dest)
211
        print "src:", src, " (should be:",CARDBOX_ID,")"
212
        print "dest:", dest
213
        print "cmd:", cmd, " (should be:",TT_KC,")"
214
        print "len(data)", len(data)
215
        print "data:", data
192 216
        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
217
            print "looks like a transaction"
218
            card = re.search('%([0-9]*)=.*', data[1:])
219
            if card != None:
220
                print "got a card number!"
221
                sendAck(CARDBOX_ID)
222
                return [data[0], card.group(1)] #return the key and parsed out cardnum
199 223

  
224
    # send nack if things didn't look right
225
    sendNack(CARDBOX_ID)
226
    return None
200 227

  
228

  
201 229
#returns [src, dest, command] or [] on error
202 230
# because of reflection, this will quietly ignore packets send by the server
203 231
def readTool():

Also available in: Unified diff