447dcf76846403c8d82da72627b7e21e01a4e99d
[zanchey/dispense2.git] / sql-edition / servers / VendServer.py
1 #!/usr/bin/python
2 # vim:ts=4
3
4 import sys, os, string, time, re, pwd
5 import pg
6 from LATClient import LATClient
7 from VendingMachine import VendingMachine
8
9 GREETING = 'UCC SNACKS'
10 PIN_LENGTH = 4
11
12 DOOR = 1
13 SWITCH = 2
14 KEY = 3
15
16 class DispenseDatabase:
17         def __init__(self, vending_machine):
18                 self.vending_machine = vending_machine
19                 self.db = pg.DB(dbname = 'dispense', host = 'dispense.ucc.gu.uwa.edu.au', user = 'vendserver', passwd = 'revresdnev')
20                 self.db.query('LISTEN vend_requests')
21
22         def process_requests(self):
23                 print 'processing'
24                 query = 'SELECT request_id, request_slot FROM vend_requests WHERE request_handled = false'
25                 try:
26                         outstanding = self.db.query(query).getresult()
27                 except (pg.error,), db_err:
28                         sys.stderr.write('Failed to query database: %s\n'%(db_err.strip()))
29                         return
30                 for (id, slot) in outstanding:
31                         (worked, code, string) = self.vending_machine.vend(slot)
32                         print (worked, code, string)
33                         if worked:
34                                 query = 'SELECT vend_success(%s)'%id
35                                 self.db.query(query).getresult()
36                         else:
37                                 query = 'SELECT vend_failed(%s)'%id
38                                 self.db.query(query).getresult()
39
40         def handle_events(self):
41                 notifier = self.db.getnotify()
42                 while notifier is not None:
43                         self.process_requests()
44                         notify = self.db.getnotify()
45
46 def get_pin(uid):
47         try:
48                 info = pwd.getpwuid(uid)
49         except KeyError:
50                 return None
51         if info.pw_dir == None: return False
52         pinfile = os.path.join(info.pw_dir, '.pin')
53         try:
54                 s = os.stat(pinfile)
55         except OSError:
56                 return None
57         if s.st_mode & 077:
58                 return None
59         try:
60                 f = file(pinfile)
61         except IOError:
62                 return None
63         pinstr = f.readline()
64         f.close()
65         if not re.search('^'+'[0-9]'*PIN_LENGTH+'$', pinstr):
66                 return None
67         return int(pinstr)
68
69 def has_good_pin(uid):
70         return get_pin(uid) != None
71
72 def verify_user_pin(uid, pin):
73         if get_pin(uid) == pin:
74                 info = pwd.getpwuid(uid)
75                 return info.pw_name
76         else:
77                 return None
78
79 def door_open_mode(vending_machine):
80         print "Entering open door mode"
81         v.display("DOOR  OPEN")
82         while True:
83                 e = v.next_event()
84                 if e == None: break
85                 (event, params) = e
86                 if event == DOOR:
87                         if params == 1: # door closed
88                                 v.display("BYE BYE!")
89                                 time.sleep(1)
90                                 return
91
92 if __name__ == '__main__':
93         # Open vending machine via LAT
94         latclient = LATClient(service = 'VEND', password = 'dmscptd')
95         (rfh, wfh) = latclient.get_fh()
96         v = VendingMachine(rfh, wfh)
97         print 'PING is', v.ping()
98         #print 'BEEP is', v.beep()
99         #print 'VEND 11 is', v.vend('11')
100         #print 'SILENCE is', v.silence()
101         #print 'DISPLAY is', v.display('WELCOME')
102         print 'S is', v.get_switches()
103
104         db = DispenseDatabase(v)
105         db.process_requests()
106         cur_user = ''
107         cur_pin = ''
108         cur_selection = ''
109
110         scrolling_message = [GREETING]
111         scrolling_wraps = False
112         need_repaint = True
113         timeout = None
114         last_tick = time.time()
115
116         while True:
117                 if time.time() > last_tick+1:
118                         if timeout != None and timeout > 0: timeout -= 1
119                         if len(scrolling_message) > 0:
120                                 need_repaint = True
121                 if need_repaint and len(scrolling_message) > 0:
122                         v.display(scrolling_message[0])
123                         if scrolling_wraps:
124                                 scrolling_message.append(scrolling_message[0])
125                         del scrolling_message[0]
126                         need_repaint = False
127                 if timeout == 0:
128                         timeout = None
129                         cur_user = ''
130                         cur_pin = ''
131                         cur_selection = ''
132                         scrolling_message = [GREETING]
133                         scrolling_wraps = False
134                         need_repaint = True
135                         continue
136
137                 while True:
138                         e = v.next_event(1)
139                         if e == None: break
140                         (event, params) = e
141                         print e
142                         if event == DOOR:
143                                 if params == 0:
144                                         door_open_mode(v);
145                                         cur_user = ''
146                                         cur_pin = ''
147                                         scrolling_message = [GREETING]
148                                         scrolling_wraps = False
149                                         need_repaint = True
150                         elif event == SWITCH:
151                                 # don't care right now.
152                                 pass
153                         elif event == KEY:
154                                 key = params
155                                 # complicated key handling here:
156                                 if len(cur_user) < 5:
157                                         if key == 11:
158                                                 cur_user = ''
159                                                 scrolling_message = [GREETING]
160                                                 scrolling_wraps = False
161                                                 need_repaint = True
162                                                 continue
163                                         cur_user += chr(key + ord('0'))
164                                         scrolling_message = []
165                                         v.display('UID: '+cur_user)
166                                         if len(cur_user) == 5:
167                                                 uid = int(cur_user)
168                                                 if not has_good_pin(uid):
169                                                         scrolling_message = [' INVALID  ', '   PIN', '  `SETUP', GREETING]
170                                                         scrolling_wraps = False
171                                                         need_repaint = True
172                                                         cur_user = ''
173                                                         cur_pin = ''
174                                                         continue
175                                                 cur_pin = ''
176                                                 v.display('PIN: ')
177                                                 scrolling_message = []
178                                                 continue
179                                 elif len(cur_pin) < PIN_LENGTH:
180                                         if key == 11:
181                                                 if cur_pin == '':
182                                                         cur_user = ''
183                                                         scrolling_message = [GREETING]
184                                                         scrolling_wraps = False
185                                                         need_repaint = True
186                                                         continue
187                                                 cur_pin = ''
188                                                 v.display('PIN: ')
189                                                 scrolling_message = []
190                                                 continue
191                                         cur_pin += chr(key + ord('0'))
192                                         v.display('PIN: '+'X'*len(cur_pin))
193                                         scrolling_message = []
194                                         if len(cur_pin) == PIN_LENGTH:
195                                                 username = verify_user_pin(int(cur_user), int(cur_pin))
196                                                 if username:
197                                                         v.beep(0, False)
198                                                         cur_selection = ''
199
200                                                         scrolling_message = [' WELCOME  ', username]
201                                                         scrolling_message.append('OR A SNACK')
202                                                         scrolling_wraps = True
203                                                         need_repaint = True
204                                                         continue
205                                                 else:
206                                                         v.beep(40, False)
207                                                         scrolling_message = [' BAD PIN  ', '  SORRY   ', GREETING]
208                                                         scrolling_wraps = False
209                                                         need_repaint = True
210
211                                                         cur_user = ''
212                                                         cur_pin = ''
213                                                         continue
214                                 elif len(cur_selection) == 0:
215                                         if key == 11:
216                                                 cur_pin = ''
217                                                 cur_user = ''
218                                                 cur_selection = ''
219                                                 v.display('BYE!')
220                                                 time.sleep(0.5)
221                                                 scrolling_message = [GREETING]
222                                                 scrolling_wraps = False
223                                                 need_repaint = True
224                                                 continue
225                                         cur_selection += chr(key + ord('0'))
226                                         scrolling_message = []
227                                         v.display('SELECT: '+cur_selection)
228                                 elif len(cur_selection) == 1:
229                                         if key == 11:
230                                                 cur_selection = ''
231                                                 scrolling_message = []
232                                                 v.display('SELECT: ')
233                                                 continue
234                                         else:
235                                                 cur_selection += chr(key + ord('0'))
236                                                 #make_selection(cur_selection)
237                                                 # XXX this should move somewhere else:
238                                                 if cur_selection == '55':
239                                                         v.display('GOT DOOR?')
240                                                         os.system('su - "%s" -c "dispense door"'%username)
241                                                 elif cur_selection[1] == '8':
242                                                         v.display('GOT COKE?')
243                                                         os.system('su - "%s" -c "dispense %s"'%(username, cur_selection[0]))
244                                                 else:
245                                                         v.display('HERES A '+cur_selection)
246                                                         v.vend(cur_selection)
247                                                 time.sleep(0.5)
248                                                 v.display('THANK YOU')
249                                                 time.sleep(0.5)
250                                                 cur_selection = ''
251                                                 scrolling_message = [
252                                                         'LOGOUT: 5',
253                                                         'LOGOUT: 4',
254                                                         'LOGOUT: 3',
255                                                         'LOGOUT: 2',
256                                                         'LOGOUT: 1',
257                                                         'BYE BYE!']
258                                                 timeout = 7
259                                                 scrolling_wraps = True
260                                                 need_repaint = True
261
262                 db.handle_events()

UCC git Repository :: git.ucc.asn.au