bb38c589cf4bb84b7bbbf9ec62827ba257c3c3b2
[zanchey/dispense2.git] / virtualvend / vvend.py
1 #!/usr/bin/env python
2
3 import sys
4 import socket
5 import string
6
7 try:
8   import pygtk
9   #tell pyGTK, if possible, that we want GTKv2
10   pygtk.require("2.0")
11 except:
12   #Some distributions come with GTK2, but not pyGTK
13   pass
14
15 try:
16   import gtk
17   import gtk.glade
18 except:
19   print "You need to install pyGTK or GTKv2 ",
20   print "or set your PYTHONPATH correctly."
21   print "try: export PYTHONPATH=",
22   print "/usr/local/lib/python2.2/site-packages/"
23   sys.exit(1)
24
25 import pango
26
27 #now we have both gtk and gtk.glade imported
28 #Also, we know we are running GTK v2
29
30 class appgui:
31   def __init__(self):
32     """
33     In this init we are going to display the main
34     serverinfo window
35     """
36     gladefile="vvend.glade"
37     windowname="vvend"
38     self.wTree=gtk.glade.XML (gladefile,windowname)
39     # we only have two callbacks to register, but
40     # you could register any number, or use a
41     # special class that automatically
42     # registers all callbacks. If you wanted to pass
43     # an argument, you would use a tuple like this:
44     # dic = { "on button1_clicked" : 
45     #         (self.button1_clicked, arg1,arg2) , ...
46     
47     dic = { 
48         "on_button1_clicked" : self.keypad_clicked,
49         "on_button2_clicked" : self.keypad_clicked,
50         "on_button3_clicked" : self.keypad_clicked,
51         "on_button4_clicked" : self.keypad_clicked,
52         "on_button5_clicked" : self.keypad_clicked,
53         "on_button6_clicked" : self.keypad_clicked,
54         "on_button7_clicked" : self.keypad_clicked,
55         "on_button8_clicked" : self.keypad_clicked,
56         "on_button9_clicked" : self.keypad_clicked,
57         "on_button10_clicked" : self.keypad_clicked,
58         "on_button11_clicked" : self.keypad_clicked,
59         "on_vvend_destroy_event" : self.quit,
60         "on_vvend_delete_event" : self.quit }
61     self.wTree.signal_autoconnect (dic)
62     display = self.wTree.get_widget("label1")
63     label_font = pango.FontDescription('monospace 28')
64     display.modify_font(label_font)
65     display.set_text("*5N4CK0RZ*")
66
67     # vending machine password set here
68     self.vendpw = "AAAAAAAAAAAAAAAA"
69
70     self.messageid = None
71
72     #s = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
73     #s.setsockopt(socket.SOL_SOCKET,socket.SO_REUSEADDR,1)
74 #
75 #    listenhost=""
76 #    listenport=5150
77 #    s.bind((listenhost, listenport))
78 #    # only one connection
79 #    s.listen(1)
80 #    s.setblocking(1)
81 #    #GDK->gtk.gdk in GTK V 2.0
82 #    id=gtk.input_add(s, gtk.gdk.INPUT_READ, self.handleNewConnection)
83
84     self.server()
85
86
87     return
88
89     def __del__(self):
90         try:
91             self.sock.close()
92             self.sock.shutdown()
93         except:
94             pass
95
96 #####CALLBACKS
97   def keypad_clicked(self,widget):
98     key = widget.get_label()
99     if key == 'RESET':
100         key = '11'
101     else:
102         key = '0'+key
103     self.do_send('2'+key+' keypress\n')
104
105   def handleNewConnection(self,source,condition):
106     #source is a socket in GTK v 1 and a fd in version 2
107     conn, addr = source.accept()
108     sys.stdout.write(conn.recv(1))
109     conn.send("bing\n")
110     return gtk.TRUE
111
112 # from http://www.pythonbrasil.com.br/moin.cgi/MonitorandoSocketsComPygtk
113
114
115   def send(self, data=None, widget=None):
116      text = self.entry.get_text()
117      self.do_send(text)
118      self.entry.set_text('')
119
120      #
121
122   def do_send(self, data):
123
124      # envia ''data'' para todos os clientes conectados
125
126      for addr, (conn, tag) in self.clients.iteritems():
127             conn.send(data)
128
129   def server(self):
130
131      # inicializa o servidor
132      port = 5150
133
134      self.sock = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
135      self.sock.setsockopt(socket.SOL_SOCKET, socket.SO_REUSEADDR, 1)
136      self.sock.bind(('localhost', port))
137      self.sock.listen(0)
138      print "listening on ", port
139
140      # 
141      #
142
143      self.server_tag = gtk.input_add(self.sock, gtk.gdk.INPUT_READ, self.accept)
144
145      # mantemos uma lista dos clientes conectados
146
147      self.clients = {}
148
149   def accept(self, source, condition):
150
151      #
152      # esperando para ser aceito
153
154      conn, addr = source.accept()
155      self.insert("%s:%s conectado\n" % addr)
156
157      # insere o cliente na lista e registra o método self.write como 
158      # callback para quando existirem dados esperando para serem lidos
159
160      self.do_prompt()
161      self.clients[addr] = (conn, gtk.input_add(conn, gtk.gdk.INPUT_READ, self.write))
162
163   def write(self, source, condition):
164
165      # método chamado quando um cliente envia dados 
166
167      data = source.recv(1024)
168      if data.strip() == 'bye' or not len(data):
169
170             # se o cliente enviar um ''bye'', desconecte-o :)
171
172             source.close()
173             for addr, (conn, tag) in self.clients.iteritems():
174                 if source is conn:
175                     gtk.input_remove(tag)
176                     self.insert('%s:%s desconectado\n' % addr)
177                     del self.clients[addr]
178                     
179                     self.server_tag = gtk.input_add(self.sock, gtk.gdk.INPUT_READ, self.accept)
180                     break
181      elif data.strip() == 'quit':
182         self.quit()
183      else:
184             for (addr, port), (conn, tag) in self.clients.iteritems():
185                 if source is conn:
186                     self.insert('%s:%s >>> %s\n'%(addr, port, data.strip()))
187                     self.handle_command(data.strip())
188                     break
189      
190      return gtk.TRUE
191
192   def insert(self, data):
193      statusbar = self.wTree.get_widget("statusbar1")
194      if self.messageid:
195         statusbar.remove(1, self.messageid)
196      self.messageid=statusbar.push(1,data)
197
198   def quit(self, *args):
199      sys.stdout.write("quiting...\n")
200      gtk.input_remove(self.server_tag)
201      for addr, (conn, tag) in self.clients.iteritems():
202             gtk.input_remove(tag)
203             conn.close()
204      self.sock.close()
205
206      gtk.mainquit()
207      sys.stdout.write("quit!\n")
208
209   def do_prompt(self):
210     self.do_send("# ")
211
212   def do_help(self):
213     help = """
214
215 Valid commands are:
216  ABOUT         ROM information
217  B[S][nn]      beep [synchronously] for a duration nn (optional)
218  C[S][nn]      silence [synchronously] for a duration nn (optional)
219  Dxxxxxxxxxx   show a message on the display
220  ECHO {ON|OFF} turn echo on or off
221  GETROM        download the ROM source code using xmodem
222  H[...]        this help screen
223 *JUMPxxxx      jumps to a subroutine at location xxxx
224 *PEEKxxxx      returns the value of the byte at location xxxx
225 *POKExxxxyy    sets the value of location xxxx to yy
226  PING          pongs
227  S[...]        query all internal switch states
228 +Vnn           vend an item
229 +VALL          vend all items
230 *Wxxxxxxxxxxxx set a new password for authenticated vends. xxx=16 chars
231                password will be converted to uppercase
232
233 Very few functions are available when the machine is in standalone 
234 mode (DIP SW 1 is set)
235 + denotes that this item requires authentication if DIP SW 2 is set
236 * denotes that DIP SW 3 must be set to use these
237 Commands starting with # are ignored (comments)
238 """
239     self.do_send(help)
240   
241   def do_about(self):
242     about = """
243
244 The Virtual Vending Machine Company
245
246 Mark Tearle, June 2004
247 """
248     self.do_send(about)
249
250   def do_vend_all(self):
251      for i in range(11,99):
252         self.do_send("101 Vending "+str(i)+"\n")
253         self.do_send("153 Home sensors failing\n")
254      self.do_send("102 Vend all motors complete\n")
255   
256   def do_vend(self,command):
257      fail = None
258      if fail:
259         self.do_send("153 Home sensors failing\n")
260      else:
261         self.insert("Vending "+command)
262         self.do_send("100 Vend successful\n")
263     
264   def do_display(self,string):
265      display = self.wTree.get_widget("label1")
266      display.set_text("%-10.10s" % (string))
267      self.do_send('300 Written\n')
268
269   def do_beep(self,command):
270      sys.stdout.write("\a")
271      self.do_send('500 Beeped\n')
272
273   def do_silence(self,command):
274      pass
275
276   def do_switches(self):
277      self.do_send("600 3F 3F\n")
278
279   def do_pong(self):
280      self.do_send("000 PONG!\n")
281
282   def handle_command(self, command):
283      command = string.upper(command)
284      print command
285      if string.find(command, "HELP",0) == 0:
286         self.do_help()
287      elif string.find(command, "ABOUT",0) == 0:
288         self.do_about()
289      elif string.find(command, "PING",0) == 0:
290         self.do_pong()
291      elif string.find(command, "VALL",0) == 0:
292         self.do_vend_all()
293      elif string.find(command, "V",0) == 0:
294         self.do_vend(command)
295      elif string.find(command, "B",0) == 0:
296         self.do_beep(command)
297      elif string.find(command, "C",0) == 0:
298         self.do_silence(command)
299      elif string.find(command, "S",0) == 0:
300         self.do_switches()
301      elif string.find(command, "D",0) == 0:
302         self.do_display(command[1:])
303      self.do_prompt()
304         
305
306 # we start the app like this...
307 app=appgui()
308 gtk.mainloop()
309
310
311 # notes
312 # http://www.async.com.br/faq/pygtk/index.py?req=show&file=faq20.011.htp

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