]> git.llucax.com Git - z.facultad/66.09/etherled.git/blob - cliente/etherled/protocol.py
ARP implementado y andando (más pequeños bugfixes)!
[z.facultad/66.09/etherled.git] / cliente / etherled / protocol.py
1 #!/usr/bin/env python
2 # -*- coding: utf-8 -*-
3 # vim: set expandtab tabstop=4 shiftwidth=4 :
4 #----------------------------------------------------------------------------
5 #                               Etherled
6 #----------------------------------------------------------------------------
7 # This file is part of etherled.
8 #
9 # etherled is free software; you can redistribute it and/or modify it
10 # under the terms of the GNU General Public License as published by the Free
11 # Software Foundation; either version 2 of the License, or (at your option)
12 # any later version.
13 #
14 # etherled is distributed in the hope that it will be useful, but
15 # WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
16 # or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
17 # more details.
18 #
19 # You should have received a copy of the GNU General Public License along
20 # with etherled; if not, write to the Free Software Foundation, Inc., 59
21 # Temple Place, Suite 330, Boston, MA  02111-1307  USA
22 #----------------------------------------------------------------------------
23 # Creado:  sáb oct 29 00:45:52 ART 2005
24 # Autores: Leandro Lucarella <llucare@fi.uba.ar>
25 #----------------------------------------------------------------------------
26
27 import socket
28 import packet
29
30 __all__ = ('SendError', 'RecvError', 'Client', 'NetworkedDevice', 'DummyServer')
31
32 # Tamaño del buffer
33 _BUFSIZ = 65536
34
35 # Cantidad de bytes de la columna de leds
36 _LED_BYTES = 2
37
38 class SendError(socket.error):
39     pass
40
41 class RecvError(socket.error):
42     pass
43
44 class Client(object):
45
46     def __init__(self, host='localhost', port=9876, timeout=3.0):
47         self._host = host
48         self._port = port
49         self._sock = socket.socket(socket.AF_INET, socket.SOCK_DGRAM)
50         self._sock.connect(self.addr)
51         self._sock.settimeout(timeout)
52         self._ids = {}
53         self._drop = 0
54
55     def send(self, type, var, data=None):
56         pkt = packet.ClientPacket(type, var, self._getId(type, var), data)
57         try:
58             sent = self._sock.send(str(pkt))
59         except socket.timeout:
60             raise SendError, "Tiempo de espera agotado"
61         if sent != len(pkt):
62             raise SendError, "Sólo se enviaron %d bytes de %d" \
63                 % (sent, len(pkt))
64         while True:
65             try:
66                 msg = self._sock.recv(_BUFSIZ)
67             except socket.timeout:
68                 raise RecvError, "Tiempo de espera agotado"
69             pkt_r = packet.ClientPacket(msg)
70             # Verifica ACK
71             if pkt == pkt_r:
72                 break # paquete ok
73             self._drop += 1
74         return pkt_r.data
75
76     def get(self, var):
77         return self.send(packet.TYPE_GET, var)
78
79     def set(self, var, data):
80         self.send(packet.TYPE_SET, var, data)
81
82     def _getId(self, type, var):
83         id = self._ids.get((type, var), 0)
84         self._ids[type, var] = (id + 1) % (packet.MAX_ID + 1)
85         return id
86
87     def _getHost(self):
88         return self._host
89
90     def _getPort(self):
91         return self._port
92
93     def _getAddr(self):
94         return (self._host, self._port)
95
96     def _getDrop(self):
97         return self._drop
98
99     host = property(_getHost, doc='Host al cual enviar datos')
100     port = property(_getPort, doc='Puerto al cual enviar datos')
101     addr = property(_getAddr, doc='Tupla (host, port)')
102     drop = property(_getDrop, doc='Cantidad de paquetes descartados')
103
104 class NetworkedDevice(Client):
105
106     def turn_off(self):
107         self.set(packet.VAR_OFF)
108
109     def _getMatrix(self):
110         stream = self.get(packet.VAR_MATRIX)
111         return _stream2Matrix(stream)
112
113     def _setMatrix(self, matrix):
114         stream = _matrix2Stream(matrix)
115         self.set(packet.VAR_MATRIX, stream)
116
117     def _getPaused(self):
118         return bool(ord(self.get(packet.VAR_PAUSE)))
119
120     def _setPaused(self, paused):
121         self.set(packet.VAR_PAUSE, chr(paused))
122
123     def _getDelay(self):
124         return ord(self.get(packet.VAR_DELAY))
125
126     def _setDelay(self, delay):
127         self.set(packet.VAR_DELAY, chr(delay & 0xFF))
128
129     matrix = property(_getMatrix, _setMatrix, doc='Matriz de leds')
130     paused = property(_getPaused, _setPaused,
131                       doc='Indica si el dispositivo está en pausa')
132     delay  = property(_getDelay, _setDelay,
133                       doc='Timpo de retardo del dibujado')
134
135 class DummyServer:
136
137     def __init__(self, host='localhost', port=9876, timeout=3.0):
138         self._host = host
139         self._port = port
140         self._sock = socket.socket(socket.AF_INET, socket.SOCK_DGRAM)
141         self._sock.setsockopt(socket.SOL_SOCKET, socket.SO_REUSEADDR, 1)
142         self._sock.bind(self.addr)
143         self._vars = [None for i in xrange(8)]
144
145     def run(self):
146         while True:
147             (msg, addr) = self._sock.recvfrom(_BUFSIZ)
148             pkt = packet.ServerPacket(msg)
149             print 'Recibido:', repr(pkt)
150             if pkt.type == packet.TYPE_GET:
151                 pkt.data = self._vars[pkt.var]
152             elif pkt.type == packet.TYPE_SET:
153                 if pkt.var == packet.VAR_MATRIX:
154                     _print_matrix(_stream2Matrix(pkt.data))
155                 self._vars[pkt.var] = pkt.data
156                 pkt = packet.ServerPacket(pkt.type, pkt.var, pkt.id)
157             sent = self._sock.sendto(str(pkt), addr)
158             if sent != len(pkt):
159                 raise SendError, "Sólo se enviaron %d bytes de %d" \
160                     % (sent, len(packet))
161             print 'Enviado:', repr(pkt)
162             if pkt.type == packet.TYPE_GET and pkt.var == packet.VAR_MATRIX:
163                 _print_matrix(_stream2Matrix(pkt.data))
164
165     def _getHost(self):
166         return self._host
167
168     def _getPort(self):
169         return self._port
170
171     def _getAddr(self):
172         return (self._host, self._port)
173
174     host = property(_getHost, doc='Host al cual enviar datos')
175     port = property(_getPort, doc='Puerto al cual enviar datos')
176     addr = property(_getAddr, doc='Tupla (host, port)')
177
178 def _stream2Matrix(stream):
179     cols = ord(stream[0]) # Obtiene tamaño
180     stream = stream[1:1+cols*_LED_BYTES] # me quedo con el resto
181     matrix = {}
182     for col in xrange(cols):
183         for row_byte in xrange(_LED_BYTES):
184             byte = ord(stream[col*_LED_BYTES+_LED_BYTES-row_byte-1])
185             for i in xrange(8):
186                 matrix[row_byte*8+i,col] = (byte >> i) & 1
187     return matrix
188
189 def _matrix2Stream(matrix):
190     cols = len(matrix) / (_LED_BYTES*8)
191     stream = chr(cols) # primero va el tamaño
192     for col in xrange(cols):
193         for i in xrange(_LED_BYTES-1, -1, -1):
194             byte = 0
195             for row in xrange(7, -1, -1):
196                 byte += matrix[row+i*8,col] << row
197             stream += chr(byte)
198     return stream
199
200 def _print_matrix(matrix):
201     for row in xrange(_LED_BYTES*8):
202         for col in xrange(len(matrix)/(_LED_BYTES*8)):
203             print matrix[row,col],
204         print
205     print
206
207 def _print_stream(stream):
208     for c in stream:
209         print '0x%02X' % ord(c),
210     print
211     print
212
213 # Prueba
214 if __name__ == '__main__':
215     import os, sys, time
216     pid = os.fork()
217     if pid:
218         time.sleep(0.1)
219         # Creo dispositivo por red
220         dev = NetworkedDevice()
221         # Creo matriz
222         matrix = {}
223         for col in xrange(16):
224             for row in xrange(16):
225                 matrix[row,col] = row % 2
226         # Mando matriz
227         print 'Matriz enviada:'
228         _print_matrix(matrix)
229         dev.matrix = matrix
230         print 'Matriz recibida:'
231         _print_matrix(dev.matrix)
232         # Verifico resultado
233         assert matrix == dev.matrix
234         ###########################
235         # Creo matriz
236         matrix = {}
237         for col in xrange(16):
238             for row in xrange(16):
239                 matrix[row,col] = col % 2
240         # Mando matriz
241         print 'Matriz enviada:'
242         _print_matrix(matrix)
243         dev.matrix = matrix
244         print 'Matriz recibida:'
245         _print_matrix(dev.matrix)
246         # Verifico resultado
247         assert matrix == dev.matrix
248         ###########################
249         # Creo matriz
250         matrix = {}
251         for col in xrange(16):
252             for row in xrange(16):
253                 matrix[row,col] = (col+row) % 2
254         # Mando matriz
255         print 'Matriz enviada:'
256         _print_matrix(matrix)
257         dev.matrix = matrix
258         print 'Matriz recibida:'
259         _print_matrix(dev.matrix)
260         # Verifico resultado
261         assert matrix == dev.matrix
262         ###########################
263         # Creo matriz
264         matrix = {}
265         for col in xrange(16):
266             for row in xrange(16):
267                 matrix[row,col] = 0
268         matrix[0,0] = 1
269         matrix[0,14] = 1
270         matrix[0,15] = 1
271         matrix[1,15] = 1
272         matrix[13,0] = 1
273         matrix[14,0] = 1
274         matrix[15,0] = 1
275         matrix[15,1] = 1
276         matrix[15,2] = 1
277         matrix[12,15] = 1
278         matrix[13,15] = 1
279         matrix[14,15] = 1
280         matrix[15,15] = 1
281         matrix[15,14] = 1
282         matrix[15,13] = 1
283         matrix[15,12] = 1
284         # Mando matriz
285         print 'Matriz enviada:'
286         _print_matrix(matrix)
287         dev.matrix = matrix
288         print 'Matriz recibida:'
289         _print_matrix(dev.matrix)
290         # Verifico resultado
291         assert matrix == dev.matrix
292         # Probamos con otras cositas
293         dev.paused = True
294         assert dev.paused == True
295         dev.paused = False
296         assert dev.paused == False
297         dev.delay = 0x40
298         assert dev.delay == 0x40
299         dev.delay = 0xff
300         assert dev.delay == 0xff
301         # Matamos al servidor
302         os.kill(pid, 15)
303     else:
304         server = DummyServer()
305         server.run()
306         sys.exit(0)
307     print "OK!"
308