From: Bernard Blackham Date: Fri, 25 Jun 2004 16:40:56 +0000 (+0000) Subject: Start of asynchronous support - reading database & vending machine simultaneously X-Git-Tag: IMPORT-FROM-UCCCVS~152 X-Git-Url: https://git.ucc.asn.au/?a=commitdiff_plain;h=5b7731894d56c10c4deae2e23686742d790a8a27;p=uccvend-vendserver.git Start of asynchronous support - reading database & vending machine simultaneously --- diff --git a/sql-edition/servers/VendServer.py b/sql-edition/servers/VendServer.py index 3f806bc..c3f04bc 100755 --- a/sql-edition/servers/VendServer.py +++ b/sql-edition/servers/VendServer.py @@ -1,18 +1,54 @@ #!/usr/bin/python import sys, os, string, socket, time, re -from popen2 import popen2 -from pyPgSQL import PgSQL +import pg from LATClient import LATClient from VendingMachine import VendingMachine +class DispenseDatabase: + def __init__(self, vending_machine): + self.vending_machine = vending_machine + self.db = pg.DB(dbname = 'dispense', host = 'dispense.ucc.gu.uwa.edu.au', user = 'vendserver', passwd = 'revresdnev') + self.db.query('LISTEN vend_requests') + + def process_requests(self): + print 'processing' + query = 'SELECT request_id, request_slot FROM vend_requests WHERE request_handled = false' + try: + outstanding = self.db.query(query).getresult() + except (pg.error,), db_err: + sys.stderr.write('Failed to query database: %s\n'%(db_err.strip())) + return + for (id, slot) in outstanding: + (worked, code, string) = self.vending_machine.vend(slot) + print (worked, code, string) + if worked: + query = 'SELECT vend_success(%s)'%id + self.db.query(query).getresult() + else: + query = 'SELECT vend_failed(%s)'%id + self.db.query(query).getresult() + + def handle_events(self): + notifier = self.db.getnotify() + while notifier is not None: + self.process_requests() + notify = self.db.getnotify() + if __name__ == '__main__': # Open vending machine via LAT latclient = LATClient(service = 'VEND', password = 'dmscptd') (rfh, wfh) = latclient.get_fh() v = VendingMachine(rfh, wfh) print 'PING is', v.ping() - print 'BEEP is', v.beep() - print 'VEND 11 is', v.vend('11') - print 'SILENCE is', v.silence() - print 'DISPLAY is', v.display('GOOD NIGHT') + #print 'BEEP is', v.beep() + #print 'VEND 11 is', v.vend('11') + #print 'SILENCE is', v.silence() + #print 'DISPLAY is', v.display('WELCOME') + print 'S is', v.get_switches() + + db = DispenseDatabase(v) + db.process_requests() + while True: + v.wait_for_events(1) + db.handle_events() diff --git a/sql-edition/servers/VendingMachine.py b/sql-edition/servers/VendingMachine.py index 3046360..2574c6d 100644 --- a/sql-edition/servers/VendingMachine.py +++ b/sql-edition/servers/VendingMachine.py @@ -1,13 +1,19 @@ -import re +import re, pg from CRC import do_crc -from binascii import unhexlify +from select import select asynchronous_responses = [ '400', '401', # door open/closed '610', # switches changed + '200', '201', '202', '203', '204', '205', '206', + '207', '208', '209', '211', # key presses ] +DOOR = 1 +SWITCH = 2 +KEY = 3 class VendingMachine: def __init__(self, rfh, wfh): + self.events = [] self.secret = 'AAAAAAAAAAAAAAAA' self.rfh = rfh self.wfh = wfh @@ -21,6 +27,7 @@ class VendingMachine: code = '' while code != '000': (code, _) = self.get_response() + self.get_switches() def await_prompt(self): self.wfh.flush() @@ -39,7 +46,7 @@ class VendingMachine: self.challenge = None return if re.search('^[0-9a-fA-F]{4}$', prefix): - self.challenge = unhexlify(prefix) + self.challenge = int(prefix, 16) return def get_response(self): @@ -58,8 +65,29 @@ class VendingMachine: self.await_prompt() return (code, text) + def get_switches(self): + self.wfh.write('S\n') + (code, text) = self.get_response() + if code != '600': + return (False, code, text) + self.interpret_switches(text) + return (True, code, text) + + def interpret_switches(self, text): + self.switches = (int(text[0:2], 16) << 8) | int(text[3:5], 16) + def handle_event(self, code, text): - pass + if code == '400': + self.events.append((DOOR, 0)) + elif code == '401': + self.events.append((DOOR, 1)) + elif code == '610': + self.events_append((SWITCH, None)) + self.interpret_switches(text) + elif code[0] == '2': + self.events.append((KEY, int(code[1:3]))) + else: + sys.stderr.write('WARNING: Unhandled event! (%s %s)\n'%(code,text)) def authed_message(self, message): if self.challenge == None: @@ -79,7 +107,7 @@ class VendingMachine: return (False, 'Invalid item requested (%s)'%item) self.wfh.write(self.authed_message(('V%s\n'%item)+'\n')) (code, string) = self.get_response() - return (code, string) + return (code == '100', code, string) def beep(self, duration = None, synchronous = True): msg = 'B' @@ -111,3 +139,18 @@ class VendingMachine: (code, string) = self.get_response() return (code == '300', code, string) + def next_event(self): + if len(self.events) > 0: + ret = self.events[0] + del self.events[0] + return ret + return None + + def wait_for_events(self, timeout = None): + (r, _, _) = select([self.rfh], [], [], timeout) + if not r: return False + event_added = False + while True: + r.get_response() + (r, _, _) = select([self.rfh], [], [], 0) + if not r: return event_added