9 #tell pyGTK, if possible, that we want GTKv2
12 #Some distributions come with GTK2, but not pyGTK
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/"
29 self.misc_input = 0xff
30 self.switch_input = 0x3f
32 return self.switch_input & 0x20
33 def set_door_open(self, open = True):
35 self.switch_input |= 0x20
37 self.switch_input &= ~0x20
39 #now we have both gtk and gtk.glade imported
40 #Also, we know we are running GTK v2
45 In this init we are going to display the main
48 gladefile="vvend.glade"
50 self.wTree=gtk.glade.XML (gladefile,windowname)
51 # we only have two callbacks to register, but
52 # you could register any number, or use a
53 # special class that automatically
54 # registers all callbacks. If you wanted to pass
55 # an argument, you would use a tuple like this:
56 # dic = { "on button1_clicked" :
57 # (self.button1_clicked, arg1,arg2) , ...
60 "on_button1_clicked" : self.keypad_clicked,
61 "on_button2_clicked" : self.keypad_clicked,
62 "on_button3_clicked" : self.keypad_clicked,
63 "on_button4_clicked" : self.keypad_clicked,
64 "on_button5_clicked" : self.keypad_clicked,
65 "on_button6_clicked" : self.keypad_clicked,
66 "on_button7_clicked" : self.keypad_clicked,
67 "on_button8_clicked" : self.keypad_clicked,
68 "on_button9_clicked" : self.keypad_clicked,
69 "on_button10_clicked" : self.keypad_clicked,
70 "on_button11_clicked" : self.keypad_clicked,
71 "on_button11_clicked" : self.keypad_clicked,
72 "on_door_toggled" : self.door_changed,
73 "on_vvend_destroy_event" : self.quit,
74 "on_vvend_delete_event" : self.quit }
75 self.wTree.signal_autoconnect (dic)
76 display = self.wTree.get_widget("label1")
77 label_font = pango.FontDescription('monospace 28')
78 display.modify_font(label_font)
80 label_style = display.get_style().copy()
81 fg_color = display.get_colormap().alloc_color('lightgreen')
82 label_style.fg[gtk.STATE_NORMAL] = fg_color
83 display.set_style(label_style)
85 w = self.wTree.get_widget("eventbox1")
86 wstyle = w.get_style().copy()
87 bg_color = w.get_colormap().alloc_color('black')
88 wstyle.bg[gtk.STATE_NORMAL] = bg_color
91 display.set_text("*5N4CK0RZ*")
93 # vending machine password set here
94 self.vendpw = "AAAAAAAAAAAAAAAA"
97 self.switches = Switches()
99 #s = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
100 #s.setsockopt(socket.SOL_SOCKET,socket.SO_REUSEADDR,1)
104 # s.bind((listenhost, listenport))
105 # # only one connection
108 # #GDK->gtk.gdk in GTK V 2.0
109 # id=gtk.input_add(s, gtk.gdk.INPUT_READ, self.handleNewConnection)
124 def keypad_clicked(self,widget):
125 key = widget.get_label()
130 self.do_send('2'+key+' keypress\n')
132 def door_changed(self, widget):
133 self.switches.set_door_open(not widget.get_active())
134 if widget.get_active():
135 self.do_send('401 door closed\n')
137 self.do_send('400 door open\n')
139 def handleNewConnection(self,source,condition):
140 #source is a socket in GTK v 1 and a fd in version 2
141 conn, addr = source.accept()
142 sys.stdout.write(conn.recv(1))
146 # from http://www.pythonbrasil.com.br/moin.cgi/MonitorandoSocketsComPygtk
149 def send(self, data=None, widget=None):
150 text = self.entry.get_text()
152 self.entry.set_text('')
156 def do_send(self, data):
158 # envia ''data'' para todos os clientes conectados
160 for addr, (conn, tag) in self.clients.iteritems():
165 # inicializa o servidor
168 self.sock = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
169 self.sock.setsockopt(socket.SOL_SOCKET, socket.SO_REUSEADDR, 1)
170 self.sock.bind(('localhost', port))
172 print "listening on ", port
177 self.server_tag = gtk.input_add(self.sock, gtk.gdk.INPUT_READ, self.accept)
179 # mantemos uma lista dos clientes conectados
183 def accept(self, source, condition):
186 # esperando para ser aceito
188 conn, addr = source.accept()
189 self.insert("%s:%s conectado\n" % addr)
191 # insere o cliente na lista e registra o método self.write como
192 # callback para quando existirem dados esperando para serem lidos
195 self.clients[addr] = (conn, gtk.input_add(conn, gtk.gdk.INPUT_READ, self.write))
197 def write(self, source, condition):
199 # método chamado quando um cliente envia dados
201 data = source.recv(1024)
202 if data.strip() == 'bye' or not len(data):
204 # se o cliente enviar um ''bye'', desconecte-o :)
207 for addr, (conn, tag) in self.clients.iteritems():
209 gtk.input_remove(tag)
210 self.insert('%s:%s desconectado\n' % addr)
211 del self.clients[addr]
213 self.server_tag = gtk.input_add(self.sock, gtk.gdk.INPUT_READ, self.accept)
215 elif data.strip() == 'quit':
218 for (addr, port), (conn, tag) in self.clients.iteritems():
220 self.insert('%s:%s >>> %s\n'%(addr, port, data.strip()))
221 self.handle_command(data.strip())
226 def insert(self, data):
227 statusbar = self.wTree.get_widget("statusbar1")
229 statusbar.remove(1, self.messageid)
230 self.messageid=statusbar.push(1,data)
232 def quit(self, *args):
233 sys.stdout.write("quiting...\n")
234 gtk.input_remove(self.server_tag)
235 for addr, (conn, tag) in self.clients.iteritems():
236 gtk.input_remove(tag)
242 sys.stdout.write("quit!\n")
251 ABOUT ROM information
252 B[S][nn] beep [synchronously] for a duration nn (optional)
253 C[S][nn] silence [synchronously] for a duration nn (optional)
254 Dxxxxxxxxxx show a message on the display
255 ECHO {ON|OFF} turn echo on or off
256 GETROM download the ROM source code using xmodem
257 H[...] this help screen
258 *JUMPxxxx jumps to a subroutine at location xxxx
259 *PEEKxxxx returns the value of the byte at location xxxx
260 *POKExxxxyy sets the value of location xxxx to yy
262 S[...] query all internal switch states
265 *Wxxxxxxxxxxxx set a new password for authenticated vends. xxx=16 chars
266 password will be converted to uppercase
268 Very few functions are available when the machine is in standalone
269 mode (DIP SW 1 is set)
270 + denotes that this item requires authentication if DIP SW 2 is set
271 * denotes that DIP SW 3 must be set to use these
272 Commands starting with # are ignored (comments)
279 The Virtual Vending Machine Company
281 Mark Tearle, June 2004
285 def do_vend_all(self):
286 for i in range(11,99):
287 self.do_send("101 Vending "+str(i)+"\n")
288 self.do_send("153 Home sensors failing\n")
289 self.do_send("102 Vend all motors complete\n")
291 def do_vend(self,command):
294 self.do_send("153 Home sensors failing\n")
296 self.insert("Vending "+command)
297 self.do_send("100 Vend successful\n")
299 def do_display(self,string):
300 display = self.wTree.get_widget("label1")
301 display.set_text("%-10.10s" % (string))
302 self.do_send('300 Written\n')
304 def do_beep(self,command):
305 sys.stdout.write("\a")
306 self.do_send('500 Beeped\n')
308 def do_silence(self,command):
311 def do_switches(self):
312 self.do_send("600 3F 3F\n")
315 self.do_send("000 PONG!\n")
317 def handle_command(self, command):
318 command = string.upper(command)
320 if string.find(command, "HELP",0) == 0:
322 elif string.find(command, "ABOUT",0) == 0:
324 elif string.find(command, "PING",0) == 0:
326 elif string.find(command, "VALL",0) == 0:
328 elif string.find(command, "V",0) == 0:
329 self.do_vend(command)
330 elif string.find(command, "B",0) == 0:
331 self.do_beep(command)
332 elif string.find(command, "C",0) == 0:
333 self.do_silence(command)
334 elif string.find(command, "S",0) == 0:
336 elif string.find(command, "D",0) == 0:
337 self.do_display(command[1:])
341 # we start the app like this...
347 # http://www.async.com.br/faq/pygtk/index.py?req=show&file=faq20.011.htp