Package joy ::
Module scratch
|
|
1 import struct
2 import socket
3 import time
4 import sys
5 import select
6 import re
7 from warnings import warn
10 - def __init__(self, host="127.0.0.1", port=42001):
11 self.addr = (host,port)
12 self.iterLimit = 32
13 self.sock = None
14
16 return self.sock is not None
17
19 if self.sock != None:
20 raise ValueError("Socket is already open")
21 self.sock = socket.socket(socket.AF_INET,socket.SOCK_STREAM)
22 self.sock.connect(self.addr)
23
25 if self.sock is not None:
26 self.sock.close()
27 self.sock = None
28
30 hdr = self.sock.recv(4)
31 if len(hdr) != 4:
32 raise IOError("Failed to read header from socket")
33 H = struct.unpack(">L",hdr)[0]
34 N = 0
35 msg = []
36 while N<H:
37 msg.append( self.sock.recv(H-N) )
38 N += len(msg[-1])
39 return "".join(msg)
40
41 - def send( self, msg ):
42 hdr = struct.pack(">L",len(msg))
43 self.sock.send( hdr+msg )
44
46 if self.sock:
47 r,_,_ = select.select( [self.sock],[],[],timeout )
48 if r:
49 return self.recv()
50 return None
51
53 for k in xrange(self.iterLimit):
54 msg = self.recv_async()
55 if msg is None:
56 break
57 yield msg
58
60 - def __init__(self, host="127.0.0.1", port=42001 ):
62
63 REX_STR = re.compile('\s*(?:"(([^"]|"")*)")\s*')
64 REX_VAL = re.compile('\s*((?:-?\d*(.\d+)?)|(?:\w[-A-Za-z0-9_]*))\s*')
65 REX_CMD = re.compile('\s*((?:sensor-update)|(?:broadcast))\s*')
66 @classmethod
68 tok = []
69
70 m = cls.REX_CMD.match(msg)
71 if not m: return tok
72 tok.append( m.group(1) )
73 msg = msg[len(m.group(0)):]
74
75 while msg:
76 m = cls.REX_STR.match(msg)
77 if m:
78 tok.append( m.group(1).replace('""','"') )
79 msg = msg[len(m.group(0)):]
80 continue
81 m = cls.REX_VAL.match(msg)
82 if m:
83 tok.append( m.group(1) )
84 msg = msg[len(m.group(0)):]
85 continue
86 raise SyntaxError("Cannot parse '%s'" % msg)
87 return tok
88
90 if len(tok) & 1:
91 warn('Sensor-update with odd number of tokens; skipping last')
92 tok.pop()
93 while tok:
94 nm = tok.pop(0)
95 val = tok.pop(0)
96 if val=="true": val = True
97 elif val=="false": val = False
98 elif val[0] in "-0123456789": val = float(val)
99 upd[nm] = val
100
103
105 if self._fsk.isConnected(): return True
106 try:
107 self._fsk.connect()
108 return True
109 except IOError, ioe:
110 sys.stderr.write( "Failed to connect: %s\n" % ioe )
111 self._fsk.close()
112 return False
113
115 if not self._autoConnect(): return None,None
116
117 upds = {}
118 evts = set()
119 for msg in self._fsk:
120 tok = self._tokenize(msg)
121 if tok is None:
122 warn("Failed to parse Scratch message '%s'" % msg)
123 continue
124
125 if tok[0][0]=='s':
126 self._doSensorUpdate(tok[1:],upds)
127 elif tok[0][0]=='b':
128 for nm in tok[1:]:
129 evts.add(nm)
130 return upds, evts
131
133 if not self._autoConnect(): return
134 msg = ['sensor-update']
135 for k,v in kw.iteritems():
136 msg.append('"%s"' % k)
137 msg.append(str(v))
138 self._fsk.send( " ".join(msg) )
139
141 if not self._autoConnect(): return
142 for txt in arg:
143 txt = txt.replace('"','""')
144 self._fsk.send( 'broadcast "%s"' % txt )
145
146
147 if __name__=="__main__":
148 print "Connecting to Scratch at default host:port"
149 try:
150 sk = FramedSock()
151 sk.connect()
152 t0 = time.time()
153 while True:
154 msg = sk.recv()
155 sys.stdout.write("%6.2f %s\n" % (time.time()-t0,msg))
156 sys.stdout.flush()
157 finally:
158 sk.close()
159