TEXT_SPEED = 0.8
IDLE_SPEED = 0.05
-_pin_uid = 0
-_pin_uname = 'root'
-_pin_pin = '----'
-
-_last_card_id = -1
-
-idlers = []
-idler = None
config_options = {
'DBServer': ('Database', 'Server'),
if newcounter is not None and self.counter != newcounter:
self.counter = newcounter
-"""
-Show information to the user as to what can be dispensed.
-"""
-def scroll_options(username, mk, welcome = False):
- # If the user has just logged in, show them their balance
- if welcome:
- # Balance checking
- acct, unused = Popen(['dispense', 'acct', username], close_fds=True, stdout=PIPE).communicate()
+class VendServer():
+
+ v = None
+ vstatus = None
+ state = None
+ event = None
+ idlers = []
+ idler = None
+
+ _pin_uid = 0
+ _pin_uname = 'root'
+ _pin_pin = '----'
+ _last_card_id = -1
+
+ """
+ Show information to the user as to what can be dispensed.
+ """
+ def scroll_options(self, username, mk, welcome = False):
+ # If the user has just logged in, show them their balance
+ if welcome:
+ # Balance checking
+ acct, unused = Popen(['dispense', 'acct', username], close_fds=True, stdout=PIPE).communicate()
+ # this is fucking appalling
+ balance = acct[acct.find("$")+1:acct.find("(")].strip()
+
+ msg = [(self.center('WELCOME'), False, TEXT_SPEED),
+ (self.center(username), False, TEXT_SPEED),
+ (self.center(balance), False, TEXT_SPEED),]
+ else:
+ msg = []
+ choices = ' '*10+'CHOICES: '
+
+ # Show what is in the coke machine
+ cokes = []
+ for i in range(0, 7):
+ args = ('dispense', 'iteminfo', 'coke:%i' % i)
+ info, unused = Popen(args, close_fds=True, stdout=PIPE).communicate()
+ m = re.match("\s*[a-z]+:\d+\s+(\d+)\.(\d\d)\s+([^\n]+)", info)
+ cents = int(m.group(1))*100 + int(m.group(2))
+ cokes.append('%i %i %s' % (i, cents, m.group(3)));
+
+ for c in cokes:
+ c = c.strip()
+ (slot_num, price, slot_name) = c.split(' ', 2)
+ if slot_name == 'dead': continue
+ choices += '%s-(%sc)-%s8 '%(slot_name, price, slot_num)
+
+ # Show the final few options
+ choices += '55-DOOR '
+ choices += 'OR ANOTHER SNACK. '
+ choices += '99 TO READ AGAIN. '
+ choices += 'CHOICE? '
+ msg.append((choices, False, None))
+ # Send it to the display
+ mk.set_messages(msg)
+
+
+ """
+ Verify the users pin
+ """
+ def _check_pin(self, uid, pin):
+ print "_check_pin('",uid,"',---)"
+ if uid != self._pin_uid:
+ try:
+ info = pwd.getpwuid(uid)
+ except KeyError:
+ logging.info('getting pin for uid %d: user not in password file'%uid)
+ return None
+ if info.pw_dir == None: return False
+ pinfile = os.path.join(info.pw_dir, '.pin')
+ try:
+ s = os.stat(pinfile)
+ except OSError:
+ logging.info('getting pin for uid %d: .pin not found in home directory'%uid)
+ return None
+ if s.st_mode & 077:
+ logging.info('getting pin for uid %d: .pin has wrong permissions. Fixing.'%uid)
+ os.chmod(pinfile, 0600)
+ try:
+ f = file(pinfile)
+ except IOError:
+ logging.info('getting pin for uid %d: I cannot read pin file'%uid)
+ return None
+ pinstr = f.readline()
+ f.close()
+ if not re.search('^'+'[0-9]'*PIN_LENGTH+'$', pinstr):
+ logging.info('getting pin for uid %d: %s not a good pin'%(uid,repr(pinstr)))
+ return None
+ self._pin_uid = uid
+ self._pin_pin = pinstr
+ self._pin_uname = info.pw_name
+ else:
+ pinstr = self._pin_pin
+ if pin == int(pinstr):
+ logging.info("Pin correct for %d",uid)
+ else:
+ logging.info("Pin incorrect for %d",uid)
+ return pin == int(pinstr)
+
+ """
+ Check if the users account has been disabled
+ """
+ def acct_is_disabled(self, name=None):
+ if name == None:
+ name = self._pin_uname
+ acct, unused = Popen(['dispense', 'acct', self._pin_uname], close_fds=True, stdout=PIPE).communicate()
# this is fucking appalling
- balance = acct[acct.find("$")+1:acct.find("(")].strip()
-
- msg = [(center('WELCOME'), False, TEXT_SPEED),
- (center(username), False, TEXT_SPEED),
- (center(balance), False, TEXT_SPEED),]
- else:
- msg = []
- choices = ' '*10+'CHOICES: '
-
- # Show what is in the coke machine
- cokes = []
- for i in range(0, 7):
- args = ('dispense', 'iteminfo', 'coke:%i' % i)
- info, unused = Popen(args, close_fds=True, stdout=PIPE).communicate()
- m = re.match("\s*[a-z]+:\d+\s+(\d+)\.(\d\d)\s+([^\n]+)", info)
- cents = int(m.group(1))*100 + int(m.group(2))
- cokes.append('%i %i %s' % (i, cents, m.group(3)));
-
- for c in cokes:
- c = c.strip()
- (slot_num, price, slot_name) = c.split(' ', 2)
- if slot_name == 'dead': continue
- choices += '%s-(%sc)-%s8 '%(slot_name, price, slot_num)
-
- # Show the final few options
- choices += '55-DOOR '
- choices += 'OR ANOTHER SNACK. '
- choices += '99 TO READ AGAIN. '
- choices += 'CHOICE? '
- msg.append((choices, False, None))
- # Send it to the display
- mk.set_messages(msg)
-
-
-"""
-Verify the users pin
-"""
-def _check_pin(uid, pin):
- global _pin_uid
- global _pin_uname
- global _pin_pin
- print "_check_pin('",uid,"',---)"
- if uid != _pin_uid:
- try:
+ flags = acct[acct.find("(")+1:acct.find(")")].strip()
+ if 'disabled' in flags:
+ return True
+ if 'internal' in flags:
+ return True
+ return False
+
+ """
+ Check that the user has a valid pin set
+ """
+ def has_good_pin(self, uid):
+ return self._check_pin(uid, None) != None
+
+ """
+ Verify the users pin.
+ """
+ def verify_user_pin(self, uid, pin, skip_pin_check=False):
+ if skip_pin_check or self._check_pin(uid, pin) == True:
info = pwd.getpwuid(uid)
- except KeyError:
- logging.info('getting pin for uid %d: user not in password file'%uid)
- return None
- if info.pw_dir == None: return False
- pinfile = os.path.join(info.pw_dir, '.pin')
- try:
- s = os.stat(pinfile)
- except OSError:
- logging.info('getting pin for uid %d: .pin not found in home directory'%uid)
- return None
- if s.st_mode & 077:
- logging.info('getting pin for uid %d: .pin has wrong permissions. Fixing.'%uid)
- os.chmod(pinfile, 0600)
- try:
- f = file(pinfile)
- except IOError:
- logging.info('getting pin for uid %d: I cannot read pin file'%uid)
- return None
- pinstr = f.readline()
- f.close()
- if not re.search('^'+'[0-9]'*PIN_LENGTH+'$', pinstr):
- logging.info('getting pin for uid %d: %s not a good pin'%(uid,repr(pinstr)))
- return None
- _pin_uid = uid
- _pin_pin = pinstr
- _pin_uname = info.pw_name
- else:
- pinstr = _pin_pin
- if pin == int(pinstr):
- logging.info("Pin correct for %d",uid)
- else:
- logging.info("Pin incorrect for %d",uid)
- return pin == int(pinstr)
-
-"""
-Check if the users account has been disabled
-"""
-def acct_is_disabled(name=None):
- global _pin_uname
- if name == None:
- name = _pin_uname
- acct, unused = Popen(['dispense', 'acct', _pin_uname], close_fds=True, stdout=PIPE).communicate()
- # this is fucking appalling
- flags = acct[acct.find("(")+1:acct.find(")")].strip()
- if 'disabled' in flags:
- return True
- if 'internal' in flags:
- return True
- return False
-
-"""
-Check that the user has a valid pin set
-"""
-def has_good_pin(uid):
- return _check_pin(uid, None) != None
-
-"""
-Verify the users pin.
-"""
-def verify_user_pin(uid, pin, skip_pin_check=False):
- if skip_pin_check or _check_pin(uid, pin) == True:
- info = pwd.getpwuid(uid)
- if skip_pin_check:
- if acct_is_disabled(info.pw_name):
- logging.info('refused mifare for disabled acct uid %d (%s)'%(uid,info.pw_name))
- return '-disabled-'
- logging.info('accepted mifare for uid %d (%s)'%(uid,info.pw_name))
+ if skip_pin_check:
+ if self.acct_is_disabled(info.pw_name):
+ logging.info('refused mifare for disabled acct uid %d (%s)'%(uid,info.pw_name))
+ return '-disabled-'
+ logging.info('accepted mifare for uid %d (%s)'%(uid,info.pw_name))
+ else:
+ logging.info('accepted pin for uid %d (%s)'%(uid,info.pw_name))
+ return info.pw_name
else:
- logging.info('accepted pin for uid %d (%s)'%(uid,info.pw_name))
- return info.pw_name
- else:
- logging.info('refused pin for uid %d'%(uid))
- return None
+ logging.info('refused pin for uid %d'%(uid))
+ return None
-"""
-In here just for fun.
-"""
-def cookie(v):
- seed(time())
- messages = [' WASSUP! ', 'PINK FISH ', ' SECRETS ', ' ESKIMO ', ' FORTUNES ', 'MORE MONEY']
- choice = int(random()*len(messages))
- msg = messages[choice]
- left = range(len(msg))
- for i in range(len(msg)):
- if msg[i] == ' ': left.remove(i)
- reveal = 1
- while left:
- s = ''
- for i in range(0, len(msg)):
- if i in left:
- if reveal == 0:
- left.remove(i)
- s += msg[i]
+ """
+ In here just for fun.
+ """
+ def cookie(self):
+ seed(time())
+ messages = [' WASSUP! ', 'PINK FISH ', ' SECRETS ', ' ESKIMO ', ' FORTUNES ', 'MORE MONEY']
+ choice = int(random()*len(messages))
+ msg = messages[choice]
+ left = range(len(msg))
+ for i in range(len(msg)):
+ if msg[i] == ' ': left.remove(i)
+ reveal = 1
+ while left:
+ s = ''
+ for i in range(0, len(msg)):
+ if i in left:
+ if reveal == 0:
+ left.remove(i)
+ s += msg[i]
+ else:
+ s += chr(int(random()*26)+ord('A'))
+ reveal += 1
+ reveal %= 17
else:
- s += chr(int(random()*26)+ord('A'))
- reveal += 1
- reveal %= 17
- else:
- s += msg[i]
- v.display(s)
-
-"""
-Format text so it will appear centered on the screen.
-"""
-def center(str):
- LEN = 10
- return ' '*((LEN-len(str))/2)+str
-
-"""
-Configure the things that will appear on screen whil the machine is idling.
-"""
-def setup_idlers(v):
- global idlers, idler
- idlers = [
- #
- GrayIdler(v),
- GrayIdler(v,one="*",zero="-"),
- GrayIdler(v,one="/",zero="\\"),
- GrayIdler(v,one="X",zero="O"),
- GrayIdler(v,one="*",zero="-",reorder=1),
- GrayIdler(v,one="/",zero="\\",reorder=1),
- GrayIdler(v,one="X",zero="O",reorder=1),
- #
- ClockIdler(v),
- ClockIdler(v),
- ClockIdler(v),
- #
- StringIdler(v), # Hello Cruel World
- StringIdler(v, text="Kill 'em all", repeat=False),
- StringIdler(v, text=CREDITS),
- StringIdler(v, text=str(math.pi) + " "),
- StringIdler(v, text=str(math.e) + " "),
- StringIdler(v, text=" I want some pizza - please call Broadway Pizza on +61 8 9389 8500 - and order as Quinn - I am getting really hungry", repeat=False),
- # "Hello World" in brainfuck
- StringIdler(v, text=">+++++++++[<++++++++>-]<.>+++++++[<++++>-]<+.+++++++..+++.[-]>++++++++[<++++>-] <.>+++++++++++[<++++++++>-]<-.--------.+++.------.--------.[-]>++++++++[<++++>- ]<+.[-]++++++++++."),
- #
- TrainIdler(v),
- #
- FileIdler(v, '/usr/share/common-licenses/GPL-2',affinity=2),
- #
- PipeIdler(v, "/usr/bin/getent", "passwd"),
- FortuneIdler(v,affinity=20),
- ]
- disabled = [
- ]
-
-"""
-Go back to the default idler.
-"""
-def reset_idler(v, vstatus, t = None):
- global idlers, idler
- idler = GreetingIdler(v, t)
- vstatus.time_of_next_idlestep = time()+idler.next()
- vstatus.time_of_next_idler = None
- vstatus.time_to_autologout = None
- vstatus.change_state(STATE_IDLE, 1)
-
-"""
-Change to a random idler.
-"""
-def choose_idler():
- global idlers, idler
-
- # Implementation of the King Of the Hill algorithm from;
- # http://eli.thegreenplace.net/2010/01/22/weighted-random-generation-in-python/
-
- #def weighted_choice_king(weights):
- # total = 0
- # winner = 0
- # for i, w in enumerate(weights):
- # total += w
- # if random.random() * total < w:
- # winner = i
- # return winner
- #
-
- total = 0
- winner = None
-
- for choice in idlers:
- weight = choice.affinity()
- total += weight
- if random() * total < weight:
- winner = choice
-
- idler = winner
-
- if idler:
- idler.reset()
-"""
-Run every step while the machine is idling.
-"""
-def idle_step(vstatus):
- global idler
- if idler.finished():
- choose_idler()
- vstatus.time_of_next_idler = time() + 30
- nextidle = idler.next()
- if nextidle is None:
- nextidle = IDLE_SPEED
- vstatus.time_of_next_idlestep = time()+nextidle
-
-"""
-These next two events trigger no response in the code.
-"""
-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
-
-"""
-Don't do anything for this event.
-"""
-def do_nothing(state, event, params, v, vstatus):
- print "doing nothing (s,e,p)", state, " ", event, " ", params
- pass
+ s += msg[i]
+ self.v.display(s)
+
+ """
+ Format text so it will appear centered on the screen.
+ """
+ def center(self, str):
+ LEN = 10
+ return ' '*((LEN-len(str))/2)+str
+
+ """
+ Configure the things that will appear on screen whil the machine is idling.
+ """
+ def setup_idlers(self):
+ self.idlers = [
+ #
+ GrayIdler(self.v),
+ GrayIdler(self.v,one="*",zero="-"),
+ GrayIdler(self.v,one="/",zero="\\"),
+ GrayIdler(self.v,one="X",zero="O"),
+ GrayIdler(self.v,one="*",zero="-",reorder=1),
+ GrayIdler(self.v,one="/",zero="\\",reorder=1),
+ GrayIdler(self.v,one="X",zero="O",reorder=1),
+ #
+ ClockIdler(self.v),
+ ClockIdler(self.v),
+ ClockIdler(self.v),
+ #
+ StringIdler(self.v), # Hello Cruel World
+ StringIdler(self.v, text="Kill 'em all", repeat=False),
+ StringIdler(self.v, text=CREDITS),
+ StringIdler(self.v, text=str(math.pi) + " "),
+ StringIdler(self.v, text=str(math.e) + " "),
+ StringIdler(self.v, text=" I want some pizza - please call Broadway Pizza on +61 8 9389 8500 - and order as Quinn - I am getting really hungry", repeat=False),
+ # "Hello World" in brainfuck
+ StringIdler(self.v, text=">+++++++++[<++++++++>-]<.>+++++++[<++++>-]<+.+++++++..+++.[-]>++++++++[<++++>-] <.>+++++++++++[<++++++++>-]<-.--------.+++.------.--------.[-]>++++++++[<++++>- ]<+.[-]++++++++++."),
+ #
+ TrainIdler(self.v),
+ #
+ FileIdler(self.v, '/usr/share/common-licenses/GPL-2',affinity=2),
+ #
+ PipeIdler(self.v, "/usr/bin/getent", "passwd"),
+ FortuneIdler(self.v,affinity=20),
+ ]
+ disabled = [
+ ]
+
+ """
+ Go back to the default idler.
+ """
+ def reset_idler(self, t = None):
+ self.idler = GreetingIdler(self.v, t)
+ self.vstatus.time_of_next_idlestep = time()+self.idler.next()
+ self.vstatus.time_of_next_idler = None
+ self.vstatus.time_to_autologout = None
+ self.vstatus.change_state(STATE_IDLE, 1)
+
+ """
+ Change to a random idler.
+ """
+ def choose_idler(self):
+
+ # Implementation of the King Of the Hill algorithm from;
+ # http://eli.thegreenplace.net/2010/01/22/weighted-random-generation-in-python/
+
+ #def weighted_choice_king(weights):
+ # total = 0
+ # winner = 0
+ # for i, w in enumerate(weights):
+ # total += w
+ # if random.random() * total < w:
+ # winner = i
+ # return winner
+ #
+
+ total = 0
+ winner = None
+
+ for choice in self.idlers:
+ weight = choice.affinity()
+ total += weight
+ if random() * total < weight:
+ winner = choice
+
+ self.idler = winner
+
+ if self.idler:
+ self.idler.reset()
+ """
+ Run every step while the machine is idling.
+ """
+ def idle_step(self):
+ if self.idler.finished():
+ self.choose_idler()
+ self.vstatus.time_of_next_idler = time() + 30
+ nextidle = self.idler.next()
+ if nextidle is None:
+ nextidle = IDLE_SPEED
+ self.vstatus.time_of_next_idlestep = time()+nextidle
+
+ """
+ These next two events trigger no response in the code.
+ """
+ def handle_tick_event(self, event, params):
+ # don't care right now.
+ pass
-"""
-These next few entrie tell us to do nothing while we are idling
-"""
-def handle_getting_uid_idle(state, event, params, v, vstatus):
- # don't care right now.
- pass
+ def handle_switch_event(self, event, params):
+ # don't care right now.
+ pass
-def handle_getting_pin_idle(state, event, params, v, vstatus):
- # don't care right now.
- pass
+ """
+ Don't do anything for this event.
+ """
+ def do_nothing(self, event, params):
+ print "doing nothing (s,e,p)", state, " ", event, " ", params
+ pass
-"""
-While logged in and waiting for user input, slowly get closer to logging out.
-"""
-def handle_get_selection_idle(state, event, params, v, vstatus):
- global _last_card_id
- # 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 = ''
- _last_card_id = -1
- reset_idler(v, vstatus)
-
- ### 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
+ """
+ These next few entrie tell us to do nothing while we are idling
+ """
+ def handle_getting_uid_idle(self, event, params):
+ # don't care right now.
+ pass
- ## FIXME - this may need to be elsewhere.....
- # need to check
- vstatus.mk.update_display()
+ def handle_getting_pin_idle(self, event, params):
+ # don't care right now.
+ pass
-"""
-Triggered on user input while logged in.
-"""
-def handle_get_selection_key(state, event, params, v, vstatus):
- global _last_card_id
- key = params
- if len(vstatus.cur_selection) == 0:
- if key == 11:
- vstatus.cur_pin = ''
- vstatus.cur_user = ''
- vstatus.cur_selection = ''
- _last_card_id = -1
- vstatus.mk.set_messages([(center('BYE!'), False, 1.5)])
- reset_idler(v, vstatus, 2)
- 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(vstatus.username, vstatus.mk)
+ """
+ While logged in and waiting for user input, slowly get closer to logging out.
+ """
+ def handle_get_selection_idle(self, event, params):
+ # don't care right now.
+ ###
+ ### State logging out ..
+ if self.vstatus.time_to_autologout != None:
+ time_left = self.vstatus.time_to_autologout - time()
+ if time_left < 6 and (self.vstatus.last_timeout_refresh is None or self.vstatus.last_timeout_refresh > time_left):
+ self.vstatus.mk.set_message('LOGOUT: '+str(int(time_left)))
+ self.vstatus.last_timeout_refresh = int(time_left)
+ self.vstatus.cur_selection = ''
+
+ if self.vstatus.time_to_autologout != None and self.vstatus.time_to_autologout - time() <= 0:
+ self.vstatus.time_to_autologout = None
+ self.vstatus.cur_user = ''
+ self.vstatus.cur_pin = ''
+ self.vstatus.cur_selection = ''
+ self._last_card_id = -1
+ self.reset_idler()
+
+ ### State fully logged out ... reset variables
+ if self.vstatus.time_to_autologout and not self.vstatus.mk.done():
+ self.vstatus.time_to_autologout = None
+ if self.vstatus.cur_user == '' and self.vstatus.time_to_autologout:
+ self.vstatus.time_to_autologout = None
+
+ ### State logged in
+ if len(self.vstatus.cur_pin) == PIN_LENGTH and self.vstatus.mk.done() and self.vstatus.time_to_autologout == None:
+ # start autologout
+ self.vstatus.time_to_autologout = time() + 15
+ self.vstatus.last_timeout_refresh = None
+
+ ## FIXME - this may need to be elsewhere.....
+ # need to check
+ self.vstatus.mk.update_display()
+
+ """
+ Triggered on user input while logged in.
+ """
+ def handle_get_selection_key(self, event, params):
+ key = params
+ if len(self.vstatus.cur_selection) == 0:
+ if key == 11:
+ self.vstatus.cur_pin = ''
+ self.vstatus.cur_user = ''
+ self.vstatus.cur_selection = ''
+ _last_card_id = -1
+ self.vstatus.mk.set_messages([(self.center('BYE!'), False, 1.5)])
+ self.reset_idler(2)
+ return
+ self.vstatus.cur_selection += chr(key + ord('0'))
+ self.vstatus.mk.set_message('SELECT: '+self.vstatus.cur_selection)
+ self.vstatus.time_to_autologout = None
+ elif len(self.vstatus.cur_selection) == 1:
+ if key == 11:
+ self.vstatus.cur_selection = ''
+ self.vstatus.time_to_autologout = None
+ self.scroll_options(self.vstatus.username, self.vstatus.mk)
+ return
+ else:
+ self.vstatus.cur_selection += chr(key + ord('0'))
+ if self.vstatus.cur_user:
+ self.make_selection()
+ self.vstatus.cur_selection = ''
+ self.vstatus.time_to_autologout = time() + 8
+ self.vstatus.last_timeout_refresh = None
+ else:
+ # Price check mode.
+ self.price_check()
+ self.vstatus.cur_selection = ''
+ self.vstatus.time_to_autologout = None
+ self.vstatus.last_timeout_refresh = None
+
+ """
+ Triggered when the user has entered the id of something they would like to purchase.
+ """
+ def make_selection(self):
+ # should use sudo here
+ if self.vstatus.cur_selection == '55':
+ self.vstatus.mk.set_message('OPENSESAME')
+ logging.info('dispensing a door for %s'%self.vstatus.username)
+ if geteuid() == 0:
+ ret = os.system('dispense -u "%s" door'%self.vstatus.username)
+ else:
+ ret = os.system('dispense door')
+ if ret == 0:
+ logging.info('door opened')
+ self.vstatus.mk.set_message(self.center('DOOR OPEN'))
+ else:
+ logging.warning('user %s tried to dispense a bad door'%self.vstatus.username)
+ self.vstatus.mk.set_message(self.center('BAD DOOR'))
+ sleep(1)
+ elif self.vstatus.cur_selection == '81':
+ self.cookie()
+ elif self.vstatus.cur_selection == '99':
+ self.scroll_options(self.vstatus.username, self.vstatus.mk)
+ self.vstatus.cur_selection = ''
return
- else:
- vstatus.cur_selection += chr(key + ord('0'))
- if vstatus.cur_user:
- make_selection(v,vstatus)
- vstatus.cur_selection = ''
- vstatus.time_to_autologout = time() + 8
- vstatus.last_timeout_refresh = None
+ elif self.vstatus.cur_selection[1] == '8':
+ self.v.display('GOT DRINK?')
+ if ((os.system('dispense -u "%s" coke:%s'%(self.vstatus.username, self.vstatus.cur_selection[0])) >> 8) != 0):
+ self.v.display('SEEMS NOT')
else:
- # Price check mode.
- price_check(v,vstatus)
- vstatus.cur_selection = ''
- vstatus.time_to_autologout = None
- vstatus.last_timeout_refresh = None
-
-"""
-Triggered when the user has entered the id of something they would like to purchase.
-"""
-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('dispense -u "%s" door'%vstatus.username)
- else:
- ret = os.system('dispense door')
- if ret == 0:
- logging.info('door opened')
- vstatus.mk.set_message(center('DOOR OPEN'))
+ self.v.display('GOT DRINK!')
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 == '81':
- 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 DRINK?')
- if ((os.system('dispense -u "%s" coke:%s'%(vstatus.username, vstatus.cur_selection[0])) >> 8) != 0):
- v.display('SEEMS NOT')
- else:
- v.display('GOT DRINK!')
- else:
- # first see if it's a named slot
- try:
- price, shortname, name = get_snack( vstatus.cur_selection )
- except:
- price, shortname, name = get_snack( '--' )
- dollarprice = "$%.2f" % ( price / 100.0 )
- v.display(vstatus.cur_selection+' - %s'%dollarprice)
- exitcode = os.system('dispense -u "%s" snack:%s'%(vstatus.username, vstatus.cur_selection)) >> 8
- if (exitcode == 0):
- # magic dispense syslog service
- syslog.syslog(syslog.LOG_INFO | syslog.LOG_LOCAL4, "vended %s (slot %s) for %s" % (name, vstatus.cur_selection, vstatus.username))
- (worked, code, string) = v.vend(vstatus.cur_selection)
- if worked:
- v.display('THANK YOU')
+ # first see if it's a named slot
+ try:
+ price, shortname, name = get_snack( self.vstatus.cur_selection )
+ except:
+ price, shortname, name = get_snack( '--' )
+ dollarprice = "$%.2f" % ( price / 100.0 )
+ self.v.display(self.vstatus.cur_selection+' - %s'%dollarprice)
+ exitcode = os.system('dispense -u "%s" snack:%s'%(self.vstatus.username, self.vstatus.cur_selection)) >> 8
+ if (exitcode == 0):
+ # magic dispense syslog service
+ syslog.syslog(syslog.LOG_INFO | syslog.LOG_LOCAL4, "vended %s (slot %s) for %s" % (name, self.vstatus.cur_selection, self.vstatus.username))
+ (worked, code, string) = self.v.vend(self.vstatus.cur_selection)
+ if worked:
+ self.v.display('THANK YOU')
+ else:
+ print "Vend Failed:", code, string
+ self.v.display('VEND FAIL')
+ elif (exitcode == 5): # RV_BALANCE
+ self.v.display('NO MONEY?')
+ elif (exitcode == 4): # RV_ARGUMENTS (zero give causes arguments)
+ self.v.display('EMPTY SLOT')
+ elif (exitcode == 1): # RV_BADITEM (Dead slot)
+ self.v.display('EMPTY SLOT')
else:
- print "Vend Failed:", code, string
- v.display('VEND FAIL')
- elif (exitcode == 5): # RV_BALANCE
- v.display('NO MONEY?')
- elif (exitcode == 4): # RV_ARGUMENTS (zero give causes arguments)
- v.display('EMPTY SLOT')
- elif (exitcode == 1): # RV_BADITEM (Dead slot)
- v.display('EMPTY SLOT')
- else:
- syslog.syslog(syslog.LOG_INFO | syslog.LOG_LOCAL4, "failed vending %s (slot %s) for %s (code %d)" % (name, vstatus.cur_selection, vstatus.username, exitcode))
- v.display('UNK ERROR')
- sleep(1)
-
-"""
-Find the price of an item.
-"""
-def price_check(v, vstatus):
- if vstatus.cur_selection[1] == '8':
- args = ('dispense', 'iteminfo', 'coke:' + vstatus.cur_selection[0])
- info, unused = Popen(args, close_fds=True, stdout=PIPE).communicate()
- dollarprice = re.match("\s*[a-z]+:\d+\s+(\d+\.\d\d)\s+([^\n]+)", info).group(1)
- else:
- # first see if it's a named slot
- try:
- price, shortname, name = get_snack( vstatus.cur_selection )
- except:
- price, shortname, name = get_snack( '--' )
- dollarprice = "$%.2f" % ( price / 100.0 )
- v.display(vstatus.cur_selection+' - %s'%dollarprice)
-
-"""
-Triggered when the user presses a button while entering their pin.
-"""
-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 = ''
- reset_idler(v, vstatus)
+ syslog.syslog(syslog.LOG_INFO | syslog.LOG_LOCAL4, "failed vending %s (slot %s) for %s (code %d)" % (name, self.vstatus.cur_selection, self.vstatus.username, exitcode))
+ self.v.display('UNK ERROR')
+ sleep(1)
+ """
+ Find the price of an item.
+ """
+ def price_check():
+ if self.vstatus.cur_selection[1] == '8':
+ args = ('dispense', 'iteminfo', 'coke:' + self.vstatus.cur_selection[0])
+ info, unused = Popen(args, close_fds=True, stdout=PIPE).communicate()
+ dollarprice = re.match("\s*[a-z]+:\d+\s+(\d+\.\d\d)\s+([^\n]+)", info).group(1)
+ else:
+ # first see if it's a named slot
+ try:
+ price, shortname, name = get_snack( self.vstatus.cur_selection )
+ except:
+ price, shortname, name = get_snack( '--' )
+ dollarprice = "$%.2f" % ( price / 100.0 )
+ self.v.display(self.vstatus.cur_selection+' - %s'%dollarprice)
+
+ """
+ Triggered when the user presses a button while entering their pin.
+ """
+ def handle_getting_pin_key(self, event, params):
+ key = params
+ if len(self.vstatus.cur_pin) < PIN_LENGTH:
+ if key == 11:
+ if self.vstatus.cur_pin == '':
+ self.vstatus.cur_user = ''
+ slef.reset_idler()
+
+ return
+ self.vstatus.cur_pin = ''
+ self.vstatus.mk.set_message('PIN: ')
return
- vstatus.cur_pin = ''
- vstatus.mk.set_message('PIN: ')
+ self.vstatus.cur_pin += chr(key + ord('0'))
+ self.vstatus.mk.set_message('PIN: '+'X'*len(self.vstatus.cur_pin))
+ if len(self.vstatus.cur_pin) == PIN_LENGTH:
+ self.vstatus.username = self.verify_user_pin(int(self.vstatus.cur_user), int(self.vstatus.cur_pin))
+ if self.vstatus.username:
+ self.v.beep(0, False)
+ self.vstatus.cur_selection = ''
+ self.vstatus.change_state(STATE_GET_SELECTION)
+ self.scroll_options(self.vstatus.username, self.vstatus.mk, True)
+ return
+ else:
+ self.v.beep(40, False)
+ self.vstatus.mk.set_messages(
+ [(self.center('BAD PIN'), False, 1.0),
+ (self.center('SORRY'), False, 0.5)])
+ self.vstatus.cur_user = ''
+ self.vstatus.cur_pin = ''
+
+ self.reset_idler(2)
+
+ return
+
+ """
+ Triggered when the user presses a button while entering their user id.
+ """
+ def handle_getting_uid_key(self, event, params):
+ key = params
+ # complicated key handling here:
+
+ if len(self.vstatus.cur_user) == 0 and key == 9:
+ self.vstatus.cur_selection = ''
+ self.vstatus.time_to_autologout = None
+ self.vstatus.mk.set_message('PRICECHECK')
+ sleep(0.5)
+ self.scroll_options('', vstatus.mk)
+ self.vstatus.change_state(STATE_GET_SELECTION)
return
- 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.username = verify_user_pin(int(vstatus.cur_user), int(vstatus.cur_pin))
- if vstatus.username:
- v.beep(0, False)
- vstatus.cur_selection = ''
- vstatus.change_state(STATE_GET_SELECTION)
- scroll_options(vstatus.username, vstatus.mk, True)
+
+ if len(self.vstatus.cur_user) <8:
+ if key == 11:
+ self.vstatus.cur_user = ''
+
+ self.reset_idler()
return
+ self.vstatus.cur_user += chr(key + ord('0'))
+ #logging.info('dob: '+vstatus.cur_user)
+ if len(self.vstatus.cur_user) > 5:
+ self.vstatus.mk.set_message('>'+self.vstatus.cur_user)
else:
- v.beep(40, False)
- vstatus.mk.set_messages(
- [(center('BAD PIN'), False, 1.0),
- (center('SORRY'), False, 0.5)])
- vstatus.cur_user = ''
- vstatus.cur_pin = ''
-
- reset_idler(v, vstatus, 2)
+ self.vstatus.mk.set_message('UID: '+self.vstatus.cur_user)
+
+ if len(self.vstatus.cur_user) == 5:
+ uid = int(self.vstatus.cur_user)
- return
+ if uid == 0:
+ logging.info('user '+self.vstatus.cur_user+' has a bad PIN')
+ pfalken="""
+ CARRIER DETECTED
-"""
-Triggered when the user presses a button while entering their user id.
-"""
-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) == 0 and key == 9:
- vstatus.cur_selection = ''
- vstatus.time_to_autologout = None
- vstatus.mk.set_message('PRICECHECK')
- sleep(0.5)
- scroll_options('', vstatus.mk)
- vstatus.change_state(STATE_GET_SELECTION)
- return
-
- if len(vstatus.cur_user) <8:
- if key == 11:
- vstatus.cur_user = ''
+ CONNECT 128000
- reset_idler(v, vstatus)
- return
- vstatus.cur_user += chr(key + ord('0'))
- #logging.info('dob: '+vstatus.cur_user)
- if len(vstatus.cur_user) > 5:
- vstatus.mk.set_message('>'+vstatus.cur_user)
- else:
- vstatus.mk.set_message('UID: '+vstatus.cur_user)
-
- if len(vstatus.cur_user) == 5:
- uid = int(vstatus.cur_user)
+ Welcome to Picklevision Sytems, Sunnyvale, CA
- if uid == 0:
- logging.info('user '+vstatus.cur_user+' has a bad PIN')
- pfalken="""
-CARRIER DETECTED
+ Greetings Professor Falken.
-CONNECT 128000
-Welcome to Picklevision Sytems, Sunnyvale, CA
-Greetings Professor Falken.
+ Shall we play a game?
+ Please choose from the following menu:
-Shall we play a game?
+ 1. Tic-Tac-Toe
+ 2. Chess
+ 3. Checkers
+ 4. Backgammon
+ 5. Poker
+ 6. Toxic and Biochemical Warfare
+ 7. Global Thermonuclear War
+ 7 [ENTER]
-Please choose from the following menu:
+ Wouldn't you prefer a nice game of chess?
-1. Tic-Tac-Toe
-2. Chess
-3. Checkers
-4. Backgammon
-5. Poker
-6. Toxic and Biochemical Warfare
-7. Global Thermonuclear War
+ """.replace('\n',' ')
+ self.vstatus.mk.set_messages([(pfalken, False, 10)])
+ self.vstatus.cur_user = ''
+ self.vstatus.cur_pin = ''
+
+ self.reset_idler(10)
-7 [ENTER]
+ return
-Wouldn't you prefer a nice game of chess?
+ if not self.has_good_pin(uid):
+ logging.info('user '+self.vstatus.cur_user+' has a bad PIN')
+ self.vstatus.mk.set_messages(
+ [(' '*10+'INVALID PIN SETUP'+' '*11, False, 3)])
+ self.vstatus.cur_user = ''
+ self.vstatus.cur_pin = ''
+
+ self.reset_idler(3)
-""".replace('\n',' ')
- vstatus.mk.set_messages([(pfalken, False, 10)])
- vstatus.cur_user = ''
- vstatus.cur_pin = ''
+ return
- reset_idler(v, vstatus, 10)
+ if self.acct_is_disabled():
+ logging.info('user '+self.vstatus.cur_user+' is disabled')
+ self.vstatus.mk.set_messages(
+ [(' '*11+'ACCOUNT DISABLED'+' '*11, False, 3)])
+ self.vstatus.cur_user = ''
+ self.vstatus.cur_pin = ''
+
+ self.reset_idler(3)
+ return
- return
- if not has_good_pin(uid):
- logging.info('user '+vstatus.cur_user+' has a bad PIN')
- vstatus.mk.set_messages(
- [(' '*10+'INVALID PIN SETUP'+' '*11, False, 3)])
- vstatus.cur_user = ''
- vstatus.cur_pin = ''
-
- reset_idler(v, vstatus, 3)
+ self.vstatus.cur_pin = ''
+ self.vstatus.mk.set_message('PIN: ')
+ logging.info('need pin for user %s'%self.vstatus.cur_user)
+ self.vstatus.change_state(STATE_GETTING_PIN)
+ return
+ """
+ Triggered when a key is pressed and the machine is idling.
+ """
+ def handle_idle_key(self, event, params):
+ key = params
+ if key == 11:
+ self.vstatus.cur_user = ''
+ self.reset_idler()
return
- if acct_is_disabled():
- logging.info('user '+vstatus.cur_user+' is disabled')
- vstatus.mk.set_messages(
- [(' '*11+'ACCOUNT DISABLED'+' '*11, False, 3)])
- vstatus.cur_user = ''
- vstatus.cur_pin = ''
-
- reset_idler(v, vstatus, 3)
- return
-
-
- 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
-
-"""
-Triggered when a key is pressed and the machine is idling.
-"""
-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 = ''
- reset_idler(v, vstatus)
- return
-
- vstatus.change_state(STATE_GETTING_UID)
- run_handler(event, key, v, vstatus)
-
-"""
-What to do when there is nothing to do.
-"""
-def handle_idle_tick(state, event, params, v, vstatus):
- ### State idling
- if vstatus.mk.done():
- idle_step(vstatus)
-
- if vstatus.time_of_next_idler and time() > vstatus.time_of_next_idler:
- vstatus.time_of_next_idler = time() + 30
- choose_idler()
-
- ###
-
- vstatus.mk.update_display()
-
- vstatus.change_state(STATE_GRANDFATHER_CLOCK)
- run_handler(event, params, v, vstatus)
- sleep(0.05)
-
-"""
-Manages the beeps for the grandfather clock
-"""
-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)
+ self.vstatus.change_state(STATE_GETTING_UID)
+ self.run_handler(event, params)
+
+ """
+ What to do when there is nothing to do.
+ """
+ def handle_idle_tick(self, event, params):
+ ### State idling
+ if self.vstatus.mk.done():
+ self.idle_step()
+
+ if self.vstatus.time_of_next_idler and time() > self.vstatus.time_of_next_idler:
+ self.vstatus.time_of_next_idler = time() + 30
+ self.choose_idler()
+
+ ###
-def handle_grandfather_tick(state, event, params, v, vstatus):
- go_idle = 1
+ self.vstatus.mk.update_display()
- msg = []
- ### we live in interesting times
- now = localtime()
+ self.vstatus.change_state(STATE_GRANDFATHER_CLOCK)
+ self.run_handler(event, params)
+ sleep(0.05)
- 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]])
+ """
+ Manages the beeps for the grandfather clock
+ """
+ def beep_on(self, when, before=0):
+ start = int(when - before)
+ end = int(when)
+ now = int(time())
- 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]])
+ if now >= start and now <= end:
+ return 1
+ return 0
+ def handle_idle_grandfather_tick(self, event, params):
+ ### check for interesting times
+ now = localtime()
- #print "when it fashionable to wear a onion on your hip"
+ 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]])
- 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)
+ 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 self.beep_on(onthehour,15) \
+ or self.beep_on(halfhour,0) \
+ or self.beep_on(quarterhour,0) \
+ or self.beep_on(threequarterhour,0) \
+ or self.beep_on(fivetothehour,0):
+ self.vstatus.change_state(STATE_GRANDFATHER_CLOCK,2)
+ self.run_handler(event, params)
+ else:
+ self.vstatus.change_state(STATE_IDLE)
- t = int(time())
- if (t % 2) == 0:
- msg.append(("DING!", False, None))
- else:
- 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:
+ def handle_grandfather_tick(self, event, params):
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)
-
-"""
-What to do when the door is open.
-"""
-def handle_door_idle(state, event, params, v, vstatus):
- def twiddle(clock,v,wise = 2):
- if (clock % 4 == 0):
- v.display("-FEED ME-")
- elif (clock % 4 == 1+wise):
- v.display("\\FEED ME/")
- elif (clock % 4 == 2):
- v.display("-FEED ME-")
- elif (clock % 4 == 3-wise):
- v.display("/FEED ME\\")
-
- # don't care right now.
- now = int(time())
-
- if ((now % 60 % 2) == 0):
- twiddle(now, v)
- else:
- twiddle(now, v, wise=0)
+ msg = []
+ ### we live in interesting times
+ now = localtime()
-"""
-What to do when the door is opened or closed.
-"""
-def handle_door_event(state, event, params, v, vstatus):
- if params == 0: #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 == 1: #door closed
- vstatus.change_state(STATE_DOOR_CLOSING)
- reset_idler(v, vstatus, 3)
-
- logging.warning('Leaving open door mode')
- v.display("-YUM YUM!-")
+ 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]])
-"""
-Triggered when a user swipes their caed, and the machine is logged out.
-"""
-def handle_mifare_event(state, event, params, v, vstatus):
- global _last_card_id
- card_id = params
- # Translate card_id into uid.
- if card_id == None or card_id == _last_card_id:
- return
-
- _last_card_id = card_id
-
- try:
- vstatus.cur_user = get_uid(card_id)
- logging.info('Mapped card id to uid %s'%vstatus.cur_user)
- vstatus.username = get_uname(vstatus.cur_user)
- if acct_is_disabled(vstatus.username):
- vstatus.username = '-disabled-'
- except ValueError:
- vstatus.username = None
- if vstatus.username == '-disabled-':
- v.beep(40, False)
- vstatus.mk.set_messages(
- [(center('ACCT DISABLED'), False, 1.0),
- (center('SORRY'), False, 0.5)])
- vstatus.cur_user = ''
- vstatus.cur_pin = ''
- vstatus.username = None
-
- reset_idler(v, vstatus, 2)
- return
- elif vstatus.username:
- v.beep(0, False)
- vstatus.cur_selection = ''
- vstatus.change_state(STATE_GET_SELECTION)
- scroll_options(vstatus.username, vstatus.mk, True)
- return
- else:
- v.beep(40, False)
- vstatus.mk.set_messages(
- [(center('BAD CARD'), False, 1.0),
- (center('SORRY'), False, 0.5)])
- vstatus.cur_user = ''
- vstatus.cur_pin = ''
- _last_card_id = -1
-
- reset_idler(v, vstatus, 2)
- return
+ 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]])
-"""
-Triggered when a user swipes their card and the machine is logged in.
-"""
-def handle_mifare_add_user_event(state, event, params, v, vstatus):
- global _last_card_id
- card_id = params
- # Translate card_id into uid.
- if card_id == None or card_id == _last_card_id:
- return
+ #print "when it fashionable to wear a onion on your hip"
- _last_card_id = card_id
-
- try:
- if get_uid(card_id) != None:
- vstatus.mk.set_messages(
- [(center('ALREADY'), False, 0.5),
- (center('ENROLLED'), False, 0.5)])
+ if self.beep_on(onthehour,15):
+ go_idle = 0
+ next_hour=((hourfromnow[3] + 11) % 12) + 1
+ if onthehour - time() < next_hour and onthehour - time() > 0:
+ self.v.beep(0, False)
- # scroll_options(vstatus.username, vstatus.mk)
+ t = int(time())
+ if (t % 2) == 0:
+ msg.append(("DING!", False, None))
+ else:
+ msg.append((" DING!", False, None))
+ elif int(onthehour - time()) == 0:
+ self.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 self.beep_on(halfhour,0):
+ go_idle = 0
+ self.v.beep(0, False)
+ msg.append((" HALFHOUR ", False, 50))
+ elif self.beep_on(quarterhour,0):
+ go_idle = 0
+ self.v.beep(0, False)
+ msg.append((" QTR HOUR ", False, 50))
+ elif self.beep_on(threequarterhour,0):
+ go_idle = 0
+ self.v.beep(0, False)
+ msg.append((" 3 QTR HR ", False, 50))
+ elif self.beep_on(fivetothehour,0):
+ go_idle = 0
+ self.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):
+ self.vstatus.mk.set_messages(msg)
+ sleep(1)
+
+ self.vstatus.mk.update_display()
+ ## if no longer case, return to idle
+
+ ## change idler to be clock
+ if go_idle and self.vstatus.mk.done():
+ self.vstatus.change_state(STATE_IDLE,1)
+
+ """
+ What to do when the door is open.
+ """
+ def handle_door_idle(self, event, params):
+ def twiddle(clock,v,wise = 2):
+ if (clock % 4 == 0):
+ v.display("-FEED ME-")
+ elif (clock % 4 == 1+wise):
+ v.display("\\FEED ME/")
+ elif (clock % 4 == 2):
+ v.display("-FEED ME-")
+ elif (clock % 4 == 3-wise):
+ v.display("/FEED ME\\")
+
+ # don't care right now.
+ now = int(time())
+
+ if ((now % 60 % 2) == 0):
+ twiddle(now, self.v)
+ else:
+ twiddle(now, self.v, wise=0)
+
+ """
+ What to do when the door is opened or closed.
+ """
+ def handle_door_event(self, event, params):
+ if params == 0: #door open
+ self.vstatus.change_state(STATE_DOOR_OPENING)
+ logging.warning("Entering open door mode")
+ self.v.display("-FEED ME-")
+ #door_open_mode(v);
+ self.vstatus.cur_user = ''
+ self.vstatus.cur_pin = ''
+ elif params == 1: #door closed
+ self.vstatus.change_state(STATE_DOOR_CLOSING)
+ self.reset_idler(3)
+
+ logging.warning('Leaving open door mode')
+ self.v.display("-YUM YUM!-")
+
+ """
+ Triggered when a user swipes their caed, and the machine is logged out.
+ """
+ def handle_mifare_event(self, event, params):
+ card_id = params
+ # Translate card_id into uid.
+ if card_id == None or card_id == self._last_card_id:
return
- except ValueError:
- pass
- logging.info('Enrolling card %s to uid %s (%s)'%(card_id, vstatus.cur_user, vstatus.username))
- set_card_id(vstatus.cur_user, card_id)
- vstatus.mk.set_messages(
- [(center('CARD'), False, 0.5),
- (center('ENROLLED'), False, 0.5)])
-
- # scroll_options(vstatus.username, vstatus.mk)
-
-def return_to_idle(state,event,params,v,vstatus):
- reset_idler(v, vstatus)
-
-"""
-Maps what to do when the state changes.
-"""
-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_IDLE,MIFARE,1)] = handle_mifare_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_OPENING,MIFARE,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_DOOR_CLOSING,MIFARE,1)] = do_nothing
-
- vstatus.state_table[(STATE_GETTING_UID,TICK,1)] = handle_getting_uid_idle
- vstatus.state_table[(STATE_GETTING_UID,DOOR,1)] = handle_door_event
- vstatus.state_table[(STATE_GETTING_UID,KEY,1)] = handle_getting_uid_key
- vstatus.state_table[(STATE_GETTING_UID,MIFARE,1)] = handle_mifare_event
-
- vstatus.state_table[(STATE_GETTING_PIN,TICK,1)] = handle_getting_pin_idle
- vstatus.state_table[(STATE_GETTING_PIN,DOOR,1)] = handle_door_event
- vstatus.state_table[(STATE_GETTING_PIN,KEY,1)] = handle_getting_pin_key
- vstatus.state_table[(STATE_GETTING_PIN,MIFARE,1)] = handle_mifare_event
-
- vstatus.state_table[(STATE_GET_SELECTION,TICK,1)] = handle_get_selection_idle
- vstatus.state_table[(STATE_GET_SELECTION,DOOR,1)] = handle_door_event
- vstatus.state_table[(STATE_GET_SELECTION,KEY,1)] = handle_get_selection_key
- vstatus.state_table[(STATE_GET_SELECTION,MIFARE,1)] = handle_mifare_add_user_event
-
- 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)] = handle_door_event
- vstatus.state_table[(STATE_GRANDFATHER_CLOCK,DOOR,2)] = handle_door_event
- vstatus.state_table[(STATE_GRANDFATHER_CLOCK,KEY,1)] = do_nothing
- vstatus.state_table[(STATE_GRANDFATHER_CLOCK,KEY,2)] = do_nothing
- vstatus.state_table[(STATE_GRANDFATHER_CLOCK,MIFARE,1)] = handle_mifare_event
-
-"""
-Get what to do on a state change.
-"""
-def get_state_table_handler(vstatus, state, event, counter):
- return vstatus.state_table[(state,event,counter)]
-
-def time_to_next_update(vstatus):
- idle_update = vstatus.time_of_next_idlestep - time()
- if not vstatus.mk.done() and vstatus.mk.next_update is not None:
- mk_update = vstatus.mk.next_update - time()
- if mk_update < idle_update:
- idle_update = mk_update
- return idle_update
-
-def run_forever(rfh, wfh, options, cf):
- v = VendingMachine(rfh, wfh, USE_MIFARE)
- vstatus = VendState(v)
- create_state_table(vstatus)
-
- logging.debug('PING is ' + str(v.ping()))
-
- if USE_DB: db = DispenseDatabase(v, cf.DBServer, cf.DBName, cf.DBUser, cf.DBPassword)
-
- setup_idlers(v)
- reset_idler(v, vstatus)
+ self._last_card_id = card_id
+
+ try:
+ self.vstatus.cur_user = get_uid(card_id)
+ logging.info('Mapped card id to uid %s'%vstatus.cur_user)
+ self.vstatus.username = get_uname(vstatus.cur_user)
+ if self.acct_is_disabled(self.vstatus.username):
+ self.vstatus.username = '-disabled-'
+ except ValueError:
+ self.vstatus.username = None
+ if self.vstatus.username == '-disabled-':
+ self.v.beep(40, False)
+ self.vstatus.mk.set_messages(
+ [(self.center('ACCT DISABLED'), False, 1.0),
+ (self.center('SORRY'), False, 0.5)])
+ self.vstatus.cur_user = ''
+ self.vstatus.cur_pin = ''
+ self.vstatus.username = None
+
+ self.reset_idler(2)
+ return
+ elif self.vstatus.username:
+ self.v.beep(0, False)
+ self.vstatus.cur_selection = ''
+ self.vstatus.change_state(STATE_GET_SELECTION)
+ self.scroll_options(self.vstatus.username, self.vstatus.mk, True)
+ return
+ else:
+ self.v.beep(40, False)
+ self.vstatus.mk.set_messages(
+ [(self.center('BAD CARD'), False, 1.0),
+ (self.center('SORRY'), False, 0.5)])
+ self.vstatus.cur_user = ''
+ self.vstatus.cur_pin = ''
+ self._last_card_id = -1
+
+ self.reset_idler(2)
+ return
- while True:
- if USE_DB:
- try:
- db.handle_events()
- except DispenseDatabaseException, e:
- logging.error('Database error: '+str(e))
+ """
+ Triggered when a user swipes their card and the machine is logged in.
+ """
+ def handle_mifare_add_user_event(self, evnt, params):
+ card_id = params
- timeout = time_to_next_update(vstatus)
- e = v.next_event(timeout)
- (event, params) = e
+ # Translate card_id into uid.
+ if card_id == None or card_id == self._last_card_id:
+ return
- run_handler(event, params, v, vstatus)
+ self._last_card_id = card_id
+
+ try:
+ if get_uid(card_id) != None:
+ self.vstatus.mk.set_messages(
+ [(self.center('ALREADY'), False, 0.5),
+ (self.center('ENROLLED'), False, 0.5)])
-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)
+ # scroll_options(vstatus.username, vstatus.mk)
+ return
+ except ValueError:
+ pass
+
+ logging.info('Enrolling card %s to uid %s (%s)'%(card_id, vstatus.cur_user, vstatus.username))
+ self.set_card_id(self.vstatus.cur_user, card_id)
+ self.vstatus.mk.set_messages(
+ [(self.center('CARD'), False, 0.5),
+ (self.center('ENROLLED'), False, 0.5)])
+
+ # scroll_options(vstatus.username, vstatus.mk)
+
+ def return_to_idle(self, event, params):
+ self.reset_idler()
+
+ """
+ Maps what to do when the state changes.
+ """
+ def create_state_table(self):
+ self.vstatus.state_table[(STATE_IDLE,TICK,1)] = self.handle_idle_tick
+ self.vstatus.state_table[(STATE_IDLE,KEY,1)] = self.handle_idle_key
+ self.vstatus.state_table[(STATE_IDLE,DOOR,1)] = self.handle_door_event
+ self.vstatus.state_table[(STATE_IDLE,MIFARE,1)] = self.handle_mifare_event
+
+ self.vstatus.state_table[(STATE_DOOR_OPENING,TICK,1)] = self.handle_door_idle
+ self.vstatus.state_table[(STATE_DOOR_OPENING,DOOR,1)] = self.handle_door_event
+ self.vstatus.state_table[(STATE_DOOR_OPENING,KEY,1)] = self.do_nothing
+ self.vstatus.state_table[(STATE_DOOR_OPENING,MIFARE,1)] = self.do_nothing
+
+ self.vstatus.state_table[(STATE_DOOR_CLOSING,TICK,1)] = self.return_to_idle
+ self.vstatus.state_table[(STATE_DOOR_CLOSING,DOOR,1)] = self.handle_door_event
+ self.vstatus.state_table[(STATE_DOOR_CLOSING,KEY,1)] = self.do_nothing
+ self.vstatus.state_table[(STATE_DOOR_CLOSING,MIFARE,1)] = self.do_nothing
+
+ self.vstatus.state_table[(STATE_GETTING_UID,TICK,1)] = self.handle_getting_uid_idle
+ self.vstatus.state_table[(STATE_GETTING_UID,DOOR,1)] = self.handle_door_event
+ self.vstatus.state_table[(STATE_GETTING_UID,KEY,1)] = self.handle_getting_uid_key
+ self.vstatus.state_table[(STATE_GETTING_UID,MIFARE,1)] = self.handle_mifare_event
+
+ self.vstatus.state_table[(STATE_GETTING_PIN,TICK,1)] = self.handle_getting_pin_idle
+ self.vstatus.state_table[(STATE_GETTING_PIN,DOOR,1)] = self.handle_door_event
+ self.vstatus.state_table[(STATE_GETTING_PIN,KEY,1)] = self.handle_getting_pin_key
+ self.vstatus.state_table[(STATE_GETTING_PIN,MIFARE,1)] = self.handle_mifare_event
+
+ self.vstatus.state_table[(STATE_GET_SELECTION,TICK,1)] = self.handle_get_selection_idle
+ self.vstatus.state_table[(STATE_GET_SELECTION,DOOR,1)] = self.handle_door_event
+ self.vstatus.state_table[(STATE_GET_SELECTION,KEY,1)] = self.handle_get_selection_key
+ self.vstatus.state_table[(STATE_GET_SELECTION,MIFARE,1)] = self.handle_mifare_add_user_event
+
+ self.vstatus.state_table[(STATE_GRANDFATHER_CLOCK,TICK,1)] = self.handle_idle_grandfather_tick
+ self.vstatus.state_table[(STATE_GRANDFATHER_CLOCK,TICK,2)] = self.handle_grandfather_tick
+ self.vstatus.state_table[(STATE_GRANDFATHER_CLOCK,DOOR,1)] = self.handle_door_event
+ self.vstatus.state_table[(STATE_GRANDFATHER_CLOCK,DOOR,2)] = self.handle_door_event
+ self.vstatus.state_table[(STATE_GRANDFATHER_CLOCK,KEY,1)] = self.do_nothing
+ self.vstatus.state_table[(STATE_GRANDFATHER_CLOCK,KEY,2)] = self.do_nothing
+ self.vstatus.state_table[(STATE_GRANDFATHER_CLOCK,MIFARE,1)] = self.handle_mifare_event
+
+ """
+ Get what to do on a state change.
+ """
+ def get_state_table_handler(self, state, event, counter):
+ return self.vstatus.state_table[(state,event,counter)]
+
+ def time_to_next_update(self):
+ idle_update = self.vstatus.time_of_next_idlestep - time()
+ if not self.vstatus.mk.done() and self.vstatus.mk.next_update is not None:
+ mk_update = self.vstatus.mk.next_update - time()
+ if mk_update < idle_update:
+ idle_update = mk_update
+ return idle_update
+
+ def run_forever(self, rfh, wfh, options, cf):
+ self.v = VendingMachine(rfh, wfh, USE_MIFARE)
+ self.vstatus = VendState(self.v)
+ self.create_state_table()
+
+ logging.debug('PING is ' + str(self.v.ping()))
+
+ if USE_DB: db = DispenseDatabase(v, cf.DBServer, cf.DBName, cf.DBUser, cf.DBPassword)
+
+ self.setup_idlers()
+ self.reset_idler()
+
+ while True:
+ if USE_DB:
+ try:
+ db.handle_events()
+ except DispenseDatabaseException, e:
+ logging.error('Database error: '+str(e))
+
+ timeout = self.time_to_next_update()
+ (event, params) = self.v.next_event(timeout)
+ self.run_handler(event, params)
+
+ def run_handler(self, event, params):
+ handler = self.get_state_table_handler(self.vstatus.state,event,self.vstatus.counter)
+ if handler:
+ handler(event, params)
"""
Connect to the machine.
logging.info('Connecting to vending machine using LAT')
latclient = LATClient(service = cf.ServiceName, password = cf.ServicePassword, server_name = cf.ServerName, connect_password = cf.ConnectPassword, priv_password = cf.PrivPassword)
rfh, wfh = latclient.get_fh()
- elif options.use_serial:
- # Open vending machine via serial.
- logging.info('Connecting to vending machine using serial')
- serialclient = SerialClient(port = '/dev/ttyS1', baud = 9600)
- rfh,wfh = serialclient.get_fh()
+ #elif options.use_serial:
+ # # Open vending machine via serial.
+ # logging.info('Connecting to vending machine using serial')
+ # serialclient = SerialClient(port = '/dev/ttyS1', baud = 9600)
+ # rfh,wfh = serialclient.get_fh()
else:
#(rfh, wfh) = popen2('../../virtualvend/vvend.py')
logging.info('Connecting to virtual vending machine on %s:%d'%(options.host,options.port))
from optparse import OptionParser
op = OptionParser(usage="%prog [OPTION]...")
- op.add_option('-f', '--config-file', default='/etc/dispense2/servers.conf', metavar='FILE', dest='config_file', help='use the specified config file instead of /etc/dispense/servers.conf')
- op.add_option('--serial', action='store_true', default=True, dest='use_serial', help='use the serial port')
+ op.add_option('-f', '--config-file', default='./servers.conf', metavar='FILE', dest='config_file', help='use the specified config file instead of /etc/dispense/servers.conf')
+ op.add_option('--serial', action='store_true', default=False, dest='use_serial', help='use the serial port')
op.add_option('--lat', action='store_true', default=False, dest='use_lat', help='use LAT')
op.add_option('--virtualvend', action='store_false', default=True, dest='use_serial', help='use the virtual vending server instead of LAT')
op.add_option('-n', '--hostname', dest='host', default='localhost', help='the hostname to connect to for virtual vending machine mode (default: localhost)')
# run_forever(rfh, wfh, options, config_opts)
try:
- run_forever(rfh, wfh, options, config_opts)
+ vserver = VendServer()
+ vserver.run_forever(rfh, wfh, options, config_opts)
except VendingException:
logging.error("Connection died, trying again...")
logging.info("Trying again in 5 seconds.")