/[anoncvs]/projects/dispense2/sql-edition/servers/VendingMachine.py


UCC Code Repository

Diff of /projects/dispense2/sql-edition/servers/VendingMachine.py

Parent Directory Parent Directory | Revision Log Revision Log | View Patch Patch

revision 1.6 by dagobah, Sun Jun 27 11:11:00 2004 UTC revision 1.24 by tpg, Sat Jan 12 14:43:49 2013 UTC
# Line 1  Line 1 
1  # vim:ts=4  # vim:ts=4
2  import re, pg  import re
3  from CRC import do_crc  from CRC import do_crc
4  from select import select  from select import select
5    import socket, logging
6    from time import time, sleep
7    from MIFAREClient import MIFAREClient
8    
9  asynchronous_responses = [      '400', '401', # door open/closed  asynchronous_responses = [      '400', '401', # door open/closed
10                                  '610',        # switches changed                                  '610',        # switches changed
# Line 11  asynchronous_responses = [     '400', '401', Line 14  asynchronous_responses = [     '400', '401',
14  DOOR = 1  DOOR = 1
15  SWITCH = 2  SWITCH = 2
16  KEY = 3  KEY = 3
17    TICK = 4
18    MIFARE = 5
19    
20    class VendingException(Exception): pass
21    
22  class VendingMachine:  class VendingMachine:
23          def __init__(self, rfh, wfh):          def __init__(self, rfh, wfh, use_mifare):
24                  self.events = []                  self.events = []
25                  self.secret = 'AAAAAAAAAAAAAAAA'                  # Secret
26                    self.secret = 'SN4CKZ0RZZZZZZZZ'
27                  self.rfh = rfh                  self.rfh = rfh
28                  self.wfh = wfh                  self.wfh = wfh
29                  self.challenge = None                  self.challenge = None
# Line 27  class VendingMachine: Line 35  class VendingMachine:
35                  self.wfh.write('PING\n')                  self.wfh.write('PING\n')
36                  code = ''                  code = ''
37                  while code != '000':                  while code != '000':
38                          (code, _) = self.get_response()                          code = self.get_response()[0]
39                  self.get_switches()                  self.get_switches()
40                    if use_mifare:
41                            self.mifare = MIFAREClient()
42                            self.mifare_timeout = 0
43                    else:
44                            self.mifare = None
45    
46          def await_prompt(self):          def await_prompt(self):
47                  self.wfh.flush()                  self.wfh.flush()
48                  state = 1                  state = 1
49                    timeout = 0.5
50                  prefix = ''                  prefix = ''
51                  s = ''                  s = ''
52                    # mtearle - vending machine was dying wait for a response from
53                    # the hardware, suspect it was missing characters
54                    #
55                    # fixed by migration to pyserial - but future good place to start
56                  while True:                  while True:
57                          s = self.rfh.read(1)                          try:
58                          if s == '': raise Exception('nothing read!')                                  s = self.rfh.read(1)
59                            except socket.error:
60                                    raise VendingException('failed to read input from vending machine')
61                            if s == '': raise VendingException('nothing read!')
62                            if (s != '#' and s != '%') and state == 1: prefix += s
63                          if s == '\n' or s == '\r':                          if s == '\n' or s == '\r':
64                                  state = 1                                  state = 1
65                                  prefix = ''                                  prefix = ''
# Line 56  class VendingMachine: Line 78  class VendingMachine:
78                          s = ''                          s = ''
79                          while s == '':                          while s == '':
80                                  s = self.rfh.readline()                                  s = self.rfh.readline()
81                                  if s == '': return None                                  if s == '':
82                                            raise VendingException('Input socket has closed!')
83                                  s = s.strip('\r\n')                                  s = s.strip('\r\n')
84                          code = s[0:3]                          code = s[0:3]
85                          text = s[4:]                          text = s[4:]
# Line 80  class VendingMachine: Line 103  class VendingMachine:
103    
104          def handle_event(self, code, text):          def handle_event(self, code, text):
105                  if code == '400':                  if code == '400':
                         self.events.append((DOOR, 0))  
                 elif code == '401':  
106                          self.events.append((DOOR, 1))                          self.events.append((DOOR, 1))
107                    elif code == '401':
108                            self.events.append((DOOR, 0))
109                  elif code == '610':                  elif code == '610':
110                          self.events.append((SWITCH, None))                          # NOP this. Nothing handles this yet.
111                            #self.events.append((SWITCH, None))
112                          self.interpret_switches(text)                          self.interpret_switches(text)
113                  elif code[0] == '2':                  elif code[0] == '2':
114                          self.events.append((KEY, int(code[1:3])))                          self.events.append((KEY, int(code[1:3])))
115                  else:                  else:
116                          sys.stderr.write('WARNING: Unhandled event! (%s %s)\n'%(code,text))                          logging.warning('Unhandled event! (%s %s)\n'%(code,text))
117    
118          def authed_message(self, message):          def authed_message(self, message):
119                    print 'self.challenge = %04x' % self.challenge
120                  if self.challenge == None:                  if self.challenge == None:
121                          return message                          return message
122                  crc = do_crc('%c%c'%(self.challenge >> 8, self.challenge & 0xff))                  crc = do_crc('%c%c'%(self.challenge >> 8, self.challenge & 0xff))
123                  crc = do_crc(self.secret, crc)                  crc = do_crc(self.secret, crc)
124                  crc = do_crc(message, crc)                  crc = do_crc(message, crc)
125                    print 'output = "%s|%04x"' % (message, crc)
126                  return message+'|'+('%04x'%crc)                  return message+'|'+('%04x'%crc)
127    
128          def ping(self):          def ping(self):
# Line 107  class VendingMachine: Line 133  class VendingMachine:
133          def vend(self, item):          def vend(self, item):
134                  if not re.search('^[0-9][0-9]$', item):                  if not re.search('^[0-9][0-9]$', item):
135                          return (False, 'Invalid item requested (%s)'%item)                          return (False, 'Invalid item requested (%s)'%item)
136                  self.wfh.write(self.authed_message(('V%s\n'%item)+'\n'))                  self.wfh.write(self.authed_message(('V%s'%item))+'\n')
137                  (code, string) = self.get_response()                  (code, string) = self.get_response()
138                  return (code == '100', code, string)                  return (code == '100', code, string)
139    
# Line 136  class VendingMachine: Line 162  class VendingMachine:
162          def display(self, string):          def display(self, string):
163                  if len(string) > 10:                  if len(string) > 10:
164                          string = string[0:10]                          string = string[0:10]
165                    string = re.sub('(.)\.', lambda match: '.'+match.group(1), string)
166                  self.wfh.write('D'+string+'\n')                  self.wfh.write('D'+string+'\n')
167                  (code, string) = self.get_response()                  (code, string) = self.get_response()
168                  return (code == '300', code, string)                  return (code == '300', code, string)
# Line 143  class VendingMachine: Line 170  class VendingMachine:
170          def next_event(self, timeout = None):          def next_event(self, timeout = None):
171                  # we don't want to buffer in the serial port, so we get all the events                  # we don't want to buffer in the serial port, so we get all the events
172                  # we can ASAP.                  # we can ASAP.
173                  if len(self.events) > 0: timeout = 0  
174                  while True:                  # Never have no timeout...
175                          (r, _, _) = select([self.rfh], [], [], timeout)                  if timeout == None: timeout = 60*60*24*365
176    
177                    # Make sure we go through the loop at least once.
178                    if timeout < 0: timeout = 0
179    
180                    while timeout >= 0:
181                            this_timeout = min(timeout, 0.2)
182                            timeout -= this_timeout
183    
184                            (r, _, _) = select([self.rfh], [], [], this_timeout)
185                          if r:                          if r:
186                                  self.get_response(async = True)                                  self.get_response(async = True)
187                                  timeout = 0                                  timeout = 0
188                          else:  
189                            if self.mifare:
190                                    now = time()
191                                    if now > self.mifare_timeout:
192                                            self.mifare_timeout = now + 0.5
193                                            mifare_uid = self.mifare.get_card_id()
194                                            if mifare_uid != None:
195                                                    logging.info('Got MIFARE card id %s'%(repr(mifare_uid)))
196                                                    self.events.append((MIFARE, mifare_uid))
197                                                    timeout = 0
198                            if timeout == 0:
199                                  break                                  break
200                  if len(self.events) == 0: return None  
201                    if len(self.events) == 0: return (TICK, time())
202                  ret = self.events[0]                  ret = self.events[0]
203                  del self.events[0]                  del self.events[0]
204                  return ret                  return ret

Legend:
Removed from v.1.6  
changed lines
  Added in v.1.24

Managed by UCC Webmasters ViewVC Help
Powered by ViewVC 1.1.26