document idlers and slow them down!
[uccvend-vendserver.git] / sql-edition / servers / VendServer.py
index e896920..12ebe5b 100755 (executable)
@@ -8,7 +8,7 @@ import sys, os, string, re, pwd, signal, math
 import logging, logging.handlers
 from traceback import format_tb
 if USE_DB: import pg
 import logging, logging.handlers
 from traceback import format_tb
 if USE_DB: import pg
-from time import time, sleep
+from time import time, sleep, mktime, localtime
 from popen2 import popen2
 from LATClient import LATClient, LATClientException
 from SerialClient import SerialClient, SerialClientException
 from popen2 import popen2
 from LATClient import LATClient, LATClientException
 from SerialClient import SerialClient, SerialClientException
@@ -42,6 +42,19 @@ PIN_LENGTH = 4
 DOOR = 1
 SWITCH = 2
 KEY = 3
 DOOR = 1
 SWITCH = 2
 KEY = 3
+TICK = 4
+
+
+STATE_IDLE = 1
+STATE_DOOR_OPENING = 2
+STATE_DOOR_CLOSING = 3
+STATE_GETTING_UID = 4
+STATE_GETTING_PIN = 5
+STATE_GET_SELECTION = 6
+STATE_GRANDFATHER_CLOCK = 7
+
+TEXT_SPEED = 0.8
+IDLE_SPEED = 0.02
 
 class DispenseDatabaseException(Exception): pass
 
 
 class DispenseDatabaseException(Exception): pass
 
@@ -76,8 +89,8 @@ class DispenseDatabase:
 
 def scroll_options(username, mk, welcome = False):
        if welcome:
 
 def scroll_options(username, mk, welcome = False):
        if welcome:
-               msg = [(center('WELCOME'), False, 0.8),
-                          (center(username), False, 0.8)]
+               msg = [(center('WELCOME'), False, TEXT_SPEED),
+                          (center(username), False, TEXT_SPEED)]
        else:
                msg = []
        choices = ' '*10+'CHOICES: '
        else:
                msg = []
        choices = ' '*10+'CHOICES: '
@@ -140,19 +153,6 @@ def verify_user_pin(uid, pin):
                logging.info('refused pin for uid %d'%(uid))
                return None
 
                logging.info('refused pin for uid %d'%(uid))
                return None
 
-def door_open_mode(v):
-       logging.warning("Entering open door mode")
-       v.display("-FEED  ME-")
-       while True:
-               e = v.next_event()
-               if e == None: break
-               (event, params) = e
-               if event == DOOR:
-                       if params == 1: # door closed
-                               logging.warning('Leaving open door mode')
-                               v.display("-YUM YUM!-")
-                               sleep(1)
-                               return
 
 def cookie(v):
        seed(time())
 
 def cookie(v):
        seed(time())
@@ -211,12 +211,12 @@ def setup_idlers(v):
                StringIdler(v),
                TrainIdler(v),
                ]
                StringIdler(v),
                TrainIdler(v),
                ]
-    disabled = [
+       disabled = [
                ]
        idler = choose_idler()
 
 def choose_idler():
                ]
        idler = choose_idler()
 
 def choose_idler():
-       global idler
+       global idlers, idler
        iiindex = 0
 
        if idler:
        iiindex = 0
 
        if idler:
@@ -236,64 +236,191 @@ def idle_step():
        global idler
        if idler.finished():
                choose_idler()
        global idler
        if idler.finished():
                choose_idler()
+       sleep(IDLE_SPEED)
        idler.next()
 
 class VendState:
        def __init__(self,v):
        idler.next()
 
 class VendState:
        def __init__(self,v):
+               self.state_table = {}
+               self.state = STATE_IDLE
+               self.counter = 0
+
                self.mk = MessageKeeper(v)
                self.cur_user = ''
                self.cur_pin = ''
                self.mk = MessageKeeper(v)
                self.cur_user = ''
                self.cur_pin = ''
+               self.username = ''
                self.cur_selection = ''
                self.time_to_autologout = None
                self.cur_selection = ''
                self.time_to_autologout = None
+
                self.time_to_idle = None
                self.time_to_idle = None
+
                self.last_timeout_refresh = None
 
                self.last_timeout_refresh = None
 
+       def change_state(self,newstate,newcounter=None):
+               if self.state != newstate:
+                       #print "Changing state from: ", 
+                       #print self.state,
+                       #print " to ", 
+                       #print newstate 
+                       self.state = newstate
+
+               if newcounter is not None and self.counter != newcounter:
+                       #print "Changing counter from: ", 
+                       #print self.counter,
+                       #print " to ", 
+                       #print newcounter 
+                       self.counter = newcounter
 
 
-def handle_door_event(event, params, v, vstatus):
-       if params == 0:
-               door_open_mode(v);
-               vstatus.cur_user = ''
-               vstatus.cur_pin = ''
-               vstatus.mk.set_message(GREETING)
+
+
+def handle_tick_event(event, params, v, vstatus):
+       # don't care right now.
+       pass
 
 def handle_switch_event(event, params, v, vstatus):
        # don't care right now.
        pass
 
 
 def handle_switch_event(event, params, v, vstatus):
        # don't care right now.
        pass
 
-def handle_key_event(event, params, v, vstatus):
+
+def do_nothing(state, event, params, v, vstatus):
+       print "doing nothing (s,e,p)", state, " ", event, " ", params
+       pass
+
+def handle_getting_uid_idle(state, event, params, v, vstatus):
+       # don't care right now.
+       pass
+
+def handle_getting_pin_idle(state, event, params, v, vstatus):
+       # don't care right now.
+       pass
+
+def handle_get_selection_idle(state, event, params, v, vstatus):
+       # don't care right now.
+       ###
+       ### State logging out ..
+       if vstatus.time_to_autologout != None:
+               time_left = vstatus.time_to_autologout - time()
+               if time_left < 6 and (vstatus.last_timeout_refresh is None or vstatus.last_timeout_refresh > time_left):
+                       vstatus.mk.set_message('LOGOUT: '+str(int(time_left)))
+                       vstatus.last_timeout_refresh = int(time_left)
+                       vstatus.cur_selection = ''
+
+       if vstatus.time_to_autologout != None and vstatus.time_to_autologout - time() <= 0:
+               vstatus.time_to_autologout = None
+               vstatus.cur_user = ''
+               vstatus.cur_pin = ''
+               vstatus.cur_selection = ''
+                       
+               idle_in(vstatus,2)
+               vstatus.change_state(STATE_IDLE)
+
+               vstatus.mk.set_message(GREETING)
+
+       ### State fully logged out ... reset variables
+       if vstatus.time_to_autologout and not vstatus.mk.done(): 
+               vstatus.time_to_autologout = None
+       if vstatus.cur_user == '' and vstatus.time_to_autologout: 
+               vstatus.time_to_autologout = None
+       
+       ### State logged in
+       if len(vstatus.cur_pin) == PIN_LENGTH and vstatus.mk.done() and vstatus.time_to_autologout == None:
+               # start autologout
+               vstatus.time_to_autologout = time() + 15
+               vstatus.last_timeout_refresh = None
+
+       ### State logged out ... after normal logout??
+       # perhaps when logged in?
+       if vstatus.time_to_idle is not None and vstatus.cur_user != '': 
+               vstatus.time_to_idle = None
+
+
+       ## FIXME - this may need to be elsewhere.....
+       # need to check
+       vstatus.mk.update_display()
+
+
+
+def handle_get_selection_key(state, event, params, v, vstatus):
        key = params
        key = params
-       # complicated key handling here:
-       if len(vstatus.cur_user) < 5:
+       if len(vstatus.cur_selection) == 0:
                if key == 11:
                if key == 11:
+                       vstatus.cur_pin = ''
                        vstatus.cur_user = ''
                        vstatus.cur_user = ''
-                       vstatus.mk.set_message(GREETING)
+                       vstatus.cur_selection = ''
+                       
+                       idle_in(vstatus,2)
+                       vstatus.change_state(STATE_IDLE)
+
+                       vstatus.mk.set_messages(
+                               [(center('BYE!'), False, 1.5),
+                                (GREETING, False, None)])
                        return
                        return
-               vstatus.cur_user += chr(key + ord('0'))
-               vstatus.mk.set_message('UID: '+vstatus.cur_user)
-               if len(vstatus.cur_user) == 5:
-                       uid = int(vstatus.cur_user)
-                       if not has_good_pin(uid):
-                               logging.info('user '+vstatus.cur_user+' has a bad PIN')
-                               #mk.set_messages(
-                                       #[(center('INVALID'), False, 0.7),
-                                        #(center('PIN'), False, 0.7),
-                                        #(center('SETUP'), False, 1.0),
-                                        #(GREETING, False, None)])
-                               vstatus.mk.set_messages(
-                                       [(' '*10+'INVALID PIN SETUP'+' '*10, False, 3),
-                                        (GREETING, False, None)])
-                               vstatus.cur_user = ''
-                               vstatus.cur_pin = ''
-                               return
-                       vstatus.cur_pin = ''
-                       vstatus.mk.set_message('PIN: ')
-                       logging.info('need pin for user %s'%vstatus.cur_user)
+               vstatus.cur_selection += chr(key + ord('0'))
+               vstatus.mk.set_message('SELECT: '+vstatus.cur_selection)
+               vstatus.time_to_autologout = None
+       elif len(vstatus.cur_selection) == 1:
+               if key == 11:
+                       vstatus.cur_selection = ''
+                       vstatus.time_to_autologout = None
+                       scroll_options(vstatus.username, vstatus.mk)
                        return
                        return
-       elif len(vstatus.cur_pin) < PIN_LENGTH:
+               else:
+                       vstatus.cur_selection += chr(key + ord('0'))
+                       make_selection(v,vstatus)
+                       vstatus.cur_selection = ''
+                       vstatus.time_to_autologout = time() + 8
+                       vstatus.last_timeout_refresh = None
+
+def make_selection(v, vstatus):
+       # should use sudo here
+       if vstatus.cur_selection == '55':
+               vstatus.mk.set_message('OPENSESAME')
+               logging.info('dispensing a door for %s'%vstatus.username)
+               if geteuid() == 0:
+                       ret = os.system('su - "%s" -c "dispense door"'%vstatus.username)
+               else:
+                       ret = os.system('dispense door')
+               if ret == 0:
+                       logging.info('door opened')
+                       vstatus.mk.set_message(center('DOOR OPEN'))
+               else:
+                       logging.warning('user %s tried to dispense a bad door'%vstatus.username)
+                       vstatus.mk.set_message(center('BAD DOOR'))
+               sleep(1)
+       elif vstatus.cur_selection == '91':
+               cookie(v)
+       elif vstatus.cur_selection == '99':
+               scroll_options(vstatus.username, vstatus.mk)
+               vstatus.cur_selection = ''
+               return
+       elif vstatus.cur_selection[1] == '8':
+               v.display('GOT COKE?')
+               if ((os.system('su - "%s" -c "dispense %s"'%(vstatus.username, vstatus.cur_selection[0])) >> 8) != 0):
+                       v.display('SEEMS NOT')
+               else:
+                       v.display('GOT COKE!')
+       else:
+               v.display(vstatus.cur_selection+' - $1.00')
+               if ((os.system('su - "%s" -c "dispense snack"'%(vstatus.username)) >> 8) == 0):
+                       v.vend(vstatus.cur_selection)
+                       v.display('THANK YOU')
+               else:
+                       v.display('NO MONEY?')
+       sleep(1)
+
+
+def handle_getting_pin_key(state, event, params, v, vstatus):
+       #print "handle_getting_pin_key (s,e,p)", state, " ", event, " ", params
+       key = params
+       if len(vstatus.cur_pin) < PIN_LENGTH:
                if key == 11:
                        if vstatus.cur_pin == '':
                                vstatus.cur_user = ''
                                vstatus.mk.set_message(GREETING)
                if key == 11:
                        if vstatus.cur_pin == '':
                                vstatus.cur_user = ''
                                vstatus.mk.set_message(GREETING)
+                       
+                               idle_in(vstatus,5)
+                               vstatus.change_state(STATE_IDLE)
+
                                return
                        vstatus.cur_pin = ''
                        vstatus.mk.set_message('PIN: ')
                                return
                        vstatus.cur_pin = ''
                        vstatus.mk.set_message('PIN: ')
@@ -301,11 +428,12 @@ def handle_key_event(event, params, v, vstatus):
                vstatus.cur_pin += chr(key + ord('0'))
                vstatus.mk.set_message('PIN: '+'X'*len(vstatus.cur_pin))
                if len(vstatus.cur_pin) == PIN_LENGTH:
                vstatus.cur_pin += chr(key + ord('0'))
                vstatus.mk.set_message('PIN: '+'X'*len(vstatus.cur_pin))
                if len(vstatus.cur_pin) == PIN_LENGTH:
-                       username = verify_user_pin(int(vstatus.cur_user), int(vstatus.cur_pin))
-                       if username:
+                       vstatus.username = verify_user_pin(int(vstatus.cur_user), int(vstatus.cur_pin))
+                       if vstatus.username:
                                v.beep(0, False)
                                vstatus.cur_selection = ''
                                v.beep(0, False)
                                vstatus.cur_selection = ''
-                               scroll_options(username, vstatus.mk, True)
+                               vstatus.change_state(STATE_GET_SELECTION)
+                               scroll_options(vstatus.username, vstatus.mk, True)
                                return
                        else:
                                v.beep(40, False)
                                return
                        else:
                                v.beep(40, False)
@@ -315,71 +443,268 @@ def handle_key_event(event, params, v, vstatus):
                                         (GREETING, False, None)])
                                vstatus.cur_user = ''
                                vstatus.cur_pin = ''
                                         (GREETING, False, None)])
                                vstatus.cur_user = ''
                                vstatus.cur_pin = ''
+                       
+                               idle_in(vstatus,5)
+                               vstatus.change_state(STATE_IDLE)
+
                                return
                                return
-       elif len(vstatus.cur_selection) == 0:
+
+
+def handle_getting_uid_key(state, event, params, v, vstatus):
+       #print "handle_getting_uid_key (s,e,p)", state, " ", event, " ", params
+       key = params
+       # complicated key handling here:
+       if len(vstatus.cur_user) < 5:
                if key == 11:
                if key == 11:
-                       vstatus.cur_pin = ''
                        vstatus.cur_user = ''
                        vstatus.cur_user = ''
-                       vstatus.cur_selection = ''
+                       vstatus.mk.set_message(GREETING)
+
+                       idle_in(vstatus,5)
+                       vstatus.change_state(STATE_IDLE)
+                       return
+
+               vstatus.cur_user += chr(key + ord('0'))
+               vstatus.mk.set_message('UID: '+vstatus.cur_user)
+
+       if len(vstatus.cur_user) == 5:
+               uid = int(vstatus.cur_user)
+               if not has_good_pin(uid):
+                       logging.info('user '+vstatus.cur_user+' has a bad PIN')
                        vstatus.mk.set_messages(
                        vstatus.mk.set_messages(
-                               [(center('BYE!'), False, 1.5),
+                               [(' '*10+'INVALID PIN SETUP'+' '*10, False, 3),
                                 (GREETING, False, None)])
                                 (GREETING, False, None)])
+                       vstatus.cur_user = ''
+                       vstatus.cur_pin = ''
+                       
+                       idle_in(vstatus,5)
+                       vstatus.change_state(STATE_IDLE)
+
                        return
                        return
-               vstatus.cur_selection += chr(key + ord('0'))
-               vstatus.mk.set_message('SELECT: '+vstatus.cur_selection)
-               vstatus.time_to_autologout = None
-       elif len(vstatus.cur_selection) == 1:
-               if key == 11:
-                       vstatus.cur_selection = ''
-                       vstatus.time_to_autologout = None
-                       scroll_options(username, vstatus.mk)
-                       return
-               else:
-                       vstatus.cur_selection += chr(key + ord('0'))
-                       #make_selection(cur_selection)
-                       # XXX this should move somewhere else:
-                       if vstatus.cur_selection == '55':
-                               vstatus.mk.set_message('OPENSESAME')
-                               logging.info('dispensing a door for %s'%username)
-                               if geteuid() == 0:
-                                       ret = os.system('su - "%s" -c "dispense door"'%username)
-                               else:
-                                       ret = os.system('dispense door')
-                               if ret == 0:
-                                       logging.info('door opened')
-                                       vstatus.mk.set_message(center('DOOR OPEN'))
-                               else:
-                                       logging.warning('user %s tried to dispense a bad door'%username)
-                                       vstatus.mk.set_message(center('BAD DOOR'))
-                               sleep(1)
-                       elif vstatus.cur_selection == '91':
-                               cookie(v)
-                       elif vstatus.cur_selection == '99':
-                               scroll_options(username, vstatus.mk)
-                               vstatus.cur_selection = ''
-                               return
-                       elif vstatus.cur_selection[1] == '8':
-                               v.display('GOT COKE?')
-                               if ((os.system('su - "%s" -c "dispense %s"'%(username, vstatus.cur_selection[0])) >> 8) != 0):
-                                       v.display('SEEMS NOT')
-                               else:
-                                       v.display('GOT COKE!')
+
+
+               vstatus.cur_pin = ''
+               vstatus.mk.set_message('PIN: ')
+               logging.info('need pin for user %s'%vstatus.cur_user)
+               vstatus.change_state(STATE_GETTING_PIN)
+               return
+
+
+def handle_idle_key(state, event, params, v, vstatus):
+       #print "handle_idle_key (s,e,p)", state, " ", event, " ", params
+
+       key = params
+
+       if key == 11:
+               vstatus.cur_user = ''
+               vstatus.mk.set_message(GREETING)
+               idle_in(vstatus,5)
+               choose_idler()
+               return
+       
+       vstatus.change_state(STATE_GETTING_UID)
+       run_handler(event, key, v, vstatus)
+
+
+def handle_idle_tick(state, event, params, v, vstatus):
+       ### State logged out ... initiate idler in 5  (first start?)
+       if vstatus.time_to_idle == None and vstatus.cur_user == '':
+               vstatus.time_to_idle = time() + 5
+               choose_idler()
+
+       ### State idling
+
+       if vstatus.time_to_idle is not None and time() > vstatus.time_to_idle: 
+               idle_step()
+
+       if vstatus.time_to_idle is not None and time() > vstatus.time_to_idle + 30:
+               vstatus.time_to_idle = time()
+               choose_idler()
+       
+       ###
+
+       vstatus.mk.update_display()
+
+       vstatus.change_state(STATE_GRANDFATHER_CLOCK)
+       run_handler(event, params, v, vstatus)
+       sleep(0.05)
+
+def beep_on(when, before=0):
+       start = int(when - before)
+       end = int(when)
+       now = int(time())
+
+       if now >= start and now <= end:
+               return 1
+       return 0
+
+def handle_idle_grandfather_tick(state, event, params, v, vstatus):
+       ### check for interesting times
+       now = localtime()
+
+       quarterhour = mktime([now[0],now[1],now[2],now[3],15,0,now[6],now[7],now[8]])
+       halfhour = mktime([now[0],now[1],now[2],now[3],30,0,now[6],now[7],now[8]])
+       threequarterhour = mktime([now[0],now[1],now[2],now[3],45,0,now[6],now[7],now[8]])
+       fivetothehour = mktime([now[0],now[1],now[2],now[3],55,0,now[6],now[7],now[8]])
+
+       hourfromnow = localtime(time() + 3600)
+       
+       #onthehour = mktime([now[0],now[1],now[2],now[3],03,0,now[6],now[7],now[8]])
+       onthehour = mktime([hourfromnow[0],hourfromnow[1],hourfromnow[2],hourfromnow[3], \
+               0,0,hourfromnow[6],hourfromnow[7],hourfromnow[8]])
+
+       ## check for X seconds to the hour
+       ## if case, update counter to 2
+       if beep_on(onthehour,15) \
+               or beep_on(halfhour,0) \
+               or beep_on(quarterhour,0) \
+               or beep_on(threequarterhour,0) \
+               or beep_on(fivetothehour,0):
+               vstatus.change_state(STATE_GRANDFATHER_CLOCK,2)
+               run_handler(event, params, v, vstatus)
+       else:
+               vstatus.change_state(STATE_IDLE)
+
+def handle_grandfather_tick(state, event, params, v, vstatus):
+       go_idle = 1
+
+       msg = []
+       ### we live in interesting times
+       now = localtime()
+
+       quarterhour = mktime([now[0],now[1],now[2],now[3],15,0,now[6],now[7],now[8]])
+       halfhour = mktime([now[0],now[1],now[2],now[3],30,0,now[6],now[7],now[8]])
+       threequarterhour = mktime([now[0],now[1],now[2],now[3],45,0,now[6],now[7],now[8]])
+       fivetothehour = mktime([now[0],now[1],now[2],now[3],55,0,now[6],now[7],now[8]])
+
+       hourfromnow = localtime(time() + 3600)
+       
+#      onthehour = mktime([now[0],now[1],now[2],now[3],03,0,now[6],now[7],now[8]])
+       onthehour = mktime([hourfromnow[0],hourfromnow[1],hourfromnow[2],hourfromnow[3], \
+               0,0,hourfromnow[6],hourfromnow[7],hourfromnow[8]])
+
+
+       #print "when it fashionable to wear a onion on your hip"
+
+       if beep_on(onthehour,15):
+               go_idle = 0
+               next_hour=((hourfromnow[3] + 11) % 12) + 1
+               if onthehour - time() < next_hour and onthehour - time() > 0:
+                       v.beep(0, False)
+
+                       t = int(time())
+                       if (t % 2) == 0:
+                               msg.append(("DING!", False, None))
                        else:
                        else:
-                               v.display(vstatus.cur_selection+' - $1.00')
-                               if ((os.system('su - "%s" -c "dispense snack"'%(username)) >> 8) == 0):
-                                       v.vend(vstatus.cur_selection)
-                                       v.display('THANK YOU')
-                               else:
-                                       v.display('NO MONEY?')
-                       sleep(1)
-                       vstatus.cur_selection = ''
-                       vstatus.time_to_autologout = time() + 8
-                       vstatus.last_timeout_refresh = None
+                               msg.append(("     DING!", False, None))
+               elif int(onthehour - time()) == 0:
+                       v.beep(255, False)
+                       msg.append(("   BONG!", False, None))
+                       msg.append(("     IT'S "+ str(next_hour) + "O'CLOCK AND ALL IS WELL .....", False, TEXT_SPEED*4))
+       elif beep_on(halfhour,0):
+               go_idle = 0
+               v.beep(0, False)
+               msg.append((" HALFHOUR ", False, 50))
+       elif beep_on(quarterhour,0):
+               go_idle = 0
+               v.beep(0, False)
+               msg.append((" QTR HOUR ", False, 50))
+       elif beep_on(threequarterhour,0):
+               go_idle = 0
+               v.beep(0, False)
+               msg.append((" 3 QTR HR ", False, 50))
+       elif beep_on(fivetothehour,0):
+               go_idle = 0
+               v.beep(0, False)
+               msg.append(("Quick run to your lectures!  Hurry! Hurry!", False, TEXT_SPEED*4))
+       else:
+               go_idle = 1
+       
+       ## check for X seconds to the hour
+
+       if len(msg):
+               vstatus.mk.set_messages(msg)
+               sleep(1)
+
+       vstatus.mk.update_display()
+       ## if no longer case, return to idle
+
+       ## change idler to be clock
+       if go_idle and vstatus.mk.done():
+               vstatus.change_state(STATE_IDLE,1)
+
+def handle_door_idle(state, event, params, v, vstatus):
+       # don't care right now.
+       pass
+
+def handle_door_event(state, event, params, v, vstatus):
+       vstatus.time_to_idle = None
+
+       if params == 1:  #door open
+               vstatus.change_state(STATE_DOOR_OPENING)
+               logging.warning("Entering open door mode")
+               v.display("-FEED  ME-")
+               #door_open_mode(v);
+               vstatus.cur_user = ''
+               vstatus.cur_pin = ''
+       elif params == 0:  #door closed
+               vstatus.change_state(STATE_DOOR_CLOSING)
+               idle_in(vstatus, 5)
 
 
+               logging.warning('Leaving open door mode')
+               v.display("-YUM YUM!-")
+
+def idle_in(vstatus,seconds):
+       vstatus.time_to_idle = time() + seconds
+
+def return_to_idle(state,event,params,v,vstatus):
+       if vstatus.time_to_idle is not None and time() > vstatus.time_to_idle: 
+               vstatus.mk.set_message(GREETING)
+               vstatus.change_state(STATE_IDLE)
+               return
+       if not vstatus.time_to_idle:
+               vstatus.mk.set_message(GREETING)
+               vstatus.change_state(STATE_IDLE)
+               return
+
+def create_state_table(vstatus):
+       vstatus.state_table[(STATE_IDLE,TICK,1)] = handle_idle_tick
+       vstatus.state_table[(STATE_IDLE,KEY,1)] = handle_idle_key
+       vstatus.state_table[(STATE_IDLE,DOOR,1)] = handle_door_event
+
+       vstatus.state_table[(STATE_DOOR_OPENING,TICK,1)] = handle_door_idle
+       vstatus.state_table[(STATE_DOOR_OPENING,DOOR,1)] = handle_door_event
+       vstatus.state_table[(STATE_DOOR_OPENING,KEY,1)] = do_nothing
+
+       vstatus.state_table[(STATE_DOOR_CLOSING,TICK,1)] = return_to_idle
+       vstatus.state_table[(STATE_DOOR_CLOSING,DOOR,1)] = handle_door_event
+       vstatus.state_table[(STATE_DOOR_CLOSING,KEY,1)] = do_nothing
+
+       vstatus.state_table[(STATE_GETTING_UID,TICK,1)] = handle_getting_uid_idle
+       vstatus.state_table[(STATE_GETTING_UID,DOOR,1)] = do_nothing
+       vstatus.state_table[(STATE_GETTING_UID,KEY,1)] = handle_getting_uid_key
+
+       vstatus.state_table[(STATE_GETTING_PIN,TICK,1)] = handle_getting_pin_idle
+       vstatus.state_table[(STATE_GETTING_PIN,DOOR,1)] = do_nothing
+       vstatus.state_table[(STATE_GETTING_PIN,KEY,1)] = handle_getting_pin_key
+
+       vstatus.state_table[(STATE_GET_SELECTION,TICK,1)] = handle_get_selection_idle
+       vstatus.state_table[(STATE_GET_SELECTION,DOOR,1)] = do_nothing
+       vstatus.state_table[(STATE_GET_SELECTION,KEY,1)] = handle_get_selection_key
+
+       vstatus.state_table[(STATE_GRANDFATHER_CLOCK,TICK,1)] = handle_idle_grandfather_tick
+       vstatus.state_table[(STATE_GRANDFATHER_CLOCK,TICK,2)] = handle_grandfather_tick
+       vstatus.state_table[(STATE_GRANDFATHER_CLOCK,DOOR,1)] = do_nothing
+       vstatus.state_table[(STATE_GRANDFATHER_CLOCK,DOOR,2)] = do_nothing
+       vstatus.state_table[(STATE_GRANDFATHER_CLOCK,KEY,1)] = do_nothing
+       vstatus.state_table[(STATE_GRANDFATHER_CLOCK,KEY,2)] = do_nothing
+
+def get_state_table_handler(vstatus, state, event, counter):
+       return vstatus.state_table[(state,event,counter)]
 
 def run_forever(rfh, wfh, options, cf):
        v = VendingMachine(rfh, wfh)
        vstatus = VendState(v)
 
 def run_forever(rfh, wfh, options, cf):
        v = VendingMachine(rfh, wfh)
        vstatus = VendState(v)
+       create_state_table(vstatus)
 
        logging.debug('PING is ' + str(v.ping()))
 
 
        logging.debug('PING is ' + str(v.ping()))
 
@@ -387,9 +712,12 @@ def run_forever(rfh, wfh, options, cf):
 
        vstatus.mk.set_message(GREETING)
        setup_idlers(v)
 
        vstatus.mk.set_message(GREETING)
        setup_idlers(v)
+       choose_idler()
+       vstatus.mk.set_message("Booted")
 
 
 
 
-       # This main loop is hideous and the work of the devil - mtearle
+       # This main loop was hideous and the work of the devil.
+       # This has now been fixed (mostly) - mtearle
        #
        #
        # notes for later surgery
        #
        #
        # notes for later surgery
@@ -397,7 +725,9 @@ def run_forever(rfh, wfh, options, cf):
        #        V
        #   d[      ] = (method)
        #
        #        V
        #   d[      ] = (method)
        #
-       #  return state
+       # ( return state - not currently implemented )
+
+       vstatus.change_state(STATE_IDLE,1)
 
        while True:
                if USE_DB:
 
        while True:
                if USE_DB:
@@ -406,53 +736,19 @@ def run_forever(rfh, wfh, options, cf):
                        except DispenseDatabaseException, e:
                                logging.error('Database error: '+str(e))
 
                        except DispenseDatabaseException, e:
                                logging.error('Database error: '+str(e))
 
-               if vstatus.time_to_autologout != None:
-                       time_left = vstatus.time_to_autologout - time()
-                       if time_left < 6 and (vstatus.last_timeout_refresh is None or vstatus.last_timeout_refresh > time_left):
-                               vstatus.mk.set_message('LOGOUT: '+str(int(time_left)))
-                               vstatus.last_timeout_refresh = int(time_left)
-                               vstatus.cur_selection = ''
 
 
-               if vstatus.time_to_autologout != None and vstatus.time_to_autologout - time() <= 0:
-                       vstatus.time_to_autologout = None
-                       vstatus.cur_user = ''
-                       vstatus.cur_pin = ''
-                       vstatus.cur_selection = ''
-                       vstatus.mk.set_message(GREETING)
+               e = v.next_event(0)
+               (event, params) = e
 
 
-               if vstatus.time_to_autologout and not vstatus.mk.done(): vstatus.time_to_autologout = None
-               if vstatus.cur_user == '' and vstatus.time_to_autologout: vstatus.time_to_autologout = None
-               if len(vstatus.cur_pin) == PIN_LENGTH and vstatus.mk.done() and vstatus.time_to_autologout == None:
-                       # start autologout
-                       vstatus.time_to_autologout = time() + 15
-                       vstatus.last_timeout_refresh = None
+               run_handler(event, params, v, vstatus)
 
 
-               if vstatus.time_to_idle == None and vstatus.cur_user == '':
-                       vstatus.time_to_idle = time() + 5
-                       choose_idler()
-               if vstatus.time_to_idle is not None and vstatus.cur_user != '': vstatus.time_to_idle = None
-               if vstatus.time_to_idle is not None and time() > vstatus.time_to_idle: idle_step()
-               if vstatus.time_to_idle is not None and time() > vstatus.time_to_idle + 300:
-                       vstatus.time_to_idle = time()
-                       choose_idler()
+#              logging.debug('Got event: ' + repr(e))
 
 
-               vstatus.mk.update_display()
 
 
-               e = v.next_event(0)
-               if e == None:
-                       e = v.next_event(0.05)
-                       if e == None:
-                               continue
-               vstatus.time_to_idle = None
-               (event, params) = e
-               logging.debug('Got event: ' + repr(e))
-
-               if event == DOOR:
-                       handle_door_event(event, params, v, vstatus)
-               elif event == SWITCH:
-                       handle_switch_event(event, params, v, vstatus)
-               elif event == KEY:
-                       handle_key_event(event, params, v, vstatus)
+def run_handler(event, params, v, vstatus):
+       handler = get_state_table_handler(vstatus,vstatus.state,event,vstatus.counter)
+       if handler:
+               handler(vstatus.state, event, params, v, vstatus)
 
 def connect_to_vend(options, cf):
 
 
 def connect_to_vend(options, cf):
 

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