Added command commands, some doc, and made changes to movies/idles.
[blynken.git] / server / server.py
blob4181058d41f9448f80e31e514d16e4918ee7f3dd
1 #!/usr/bin/env python
2 from __future__ import with_statement
3 from blinken_handler import BlinkenHandler
4 from control_handler import ControlHandler
5 from my_threading import Thread, schedule, ThreadingMixIn, Lock, sleep
6 from SocketServer import TCPServer
7 from socket import error
9 __all__ = ['BlinkenServer']
11 def dummy_projector():
12 while True:
13 sleep(0.1)
14 yield []
16 class Server(ThreadingMixIn, TCPServer):
17 allow_reuse_address = True
19 class BlinkenServer(Server):
20 blinken_port = 10000
21 control_port = 10001
22 _force_next = False
23 _is_idling = True
24 _queue = []
25 idles = ['dummy']
26 movies = {'dummy': dummy_projector()}
28 def __init__(self):
29 self._blinken = Server(('', self.blinken_port), BlinkenHandler)
30 self._blinken.connections = {}
31 self._blinken.lock = Lock()
33 Server.__init__(self, ('', self.control_port), ControlHandler)
35 Thread(self._serve_nodes)()
36 Thread(self._blinken.serve_forever)()
37 Thread(self.serve_forever)()
39 def set_projector(self, projector):
40 self._force_next = True
41 self._queue.insert(0, projector)
43 def enqueue_projector(self, projector):
44 self._queue.append(projector)
46 def _projectors(self):
47 import random
48 while True:
49 if not self._queue:
50 self._is_idling = True
51 yield self.movies[random.choice(self.idles)]
52 else:
53 self._is_idling = False
54 yield self._queue.pop(0)
56 def _serve_nodes(self):
57 val = { True: 'on', False: 'off' }
58 for projector in self._projectors():
59 for frame in projector:
60 to_clean = []
61 with self._blinken.lock:
62 for pixel, sock in self._blinken.connections.iteritems():
63 try:
64 sock.send(val[pixel in frame] + "\r\n")
65 except error:
66 to_clean.append(pixel)
68 for i in to_clean:
69 del self._blinken.connections[i]
71 if self._force_next or self._queue and self._is_idling:
72 self._force_next = False
73 break
75 schedule()
78 if __name__ == '__main__':
79 from sys import argv
80 from optparse import OptionParser
81 import cPickle as pickle
83 opts = OptionParser()
85 opts.add_option('-f', '--file', dest="filename")
87 server = BlinkenServer()
88 try:
89 import stackless
90 stackless.run()
91 except ImportError:
92 pass