|
|
@@ -0,0 +1,76 @@
|
|
|
+import socket
|
|
|
+
|
|
|
+class Matrix(object):
|
|
|
+ '''A Framebuffer display interface that sends a frame via UDP.
|
|
|
+ see https://github.com/hzeller/flaschen-taschen/blob/master/doc/protocols.md
|
|
|
+ '''
|
|
|
+
|
|
|
+ def __init__(self, host, width, height, layer=0, x_offset=0, y_offset=0, transparent=False, port=1337):
|
|
|
+ '''
|
|
|
+ Args:
|
|
|
+ host: The flaschen taschen server hostname or ip address.
|
|
|
+ port: The flaschen taschen server port number.
|
|
|
+ width: The width of the flaschen taschen display in pixels.
|
|
|
+ height: The height of the flaschen taschen display in pixels.
|
|
|
+ layer: The layer of the flaschen taschen display to write to.
|
|
|
+ transparent: If true, black(0, 0, 0) will be transparent and show the layer below.
|
|
|
+ '''
|
|
|
+ self.width = width
|
|
|
+ self.height = height
|
|
|
+ self.layer = layer
|
|
|
+ self.transparent = transparent
|
|
|
+ self.x_offset = x_offset
|
|
|
+ self.y_offset = y_offset
|
|
|
+
|
|
|
+ self._sock = socket.socket(socket.AF_INET, socket.SOCK_DGRAM)
|
|
|
+ self._sock.connect((host, port))
|
|
|
+ self._init_data()
|
|
|
+
|
|
|
+ def _init_data(self):
|
|
|
+ header = ''.join(["P6\n",
|
|
|
+ "%d %d\n" % (self.width, self.height),
|
|
|
+ "255\n"]).encode('utf-8')
|
|
|
+ footer = ''.join(["%d\n" % self.x_offset,
|
|
|
+ "%d\n" % self.y_offset,
|
|
|
+ "%d\n" % self.layer]).encode('utf-8')
|
|
|
+ self._data = bytearray(self.width * self.height * 3 + len(header) + len(footer))
|
|
|
+ self._data[0:len(header)] = header
|
|
|
+ self._data[-1 * len(footer):] = footer
|
|
|
+ self._header_len = len(header)
|
|
|
+
|
|
|
+ def set(self, x, y, color):
|
|
|
+ '''Set the pixel at the given coordinates to the specified color.
|
|
|
+ Args:
|
|
|
+ x: x offset of the pixel to set
|
|
|
+ y: y offset of the piyel to set
|
|
|
+ color: A 3 tuple of (r, g, b) color values, 0-255
|
|
|
+ '''
|
|
|
+ if x >= self.width or y >= self.height or x < 0 or y < 0:
|
|
|
+ return
|
|
|
+ if color == (0, 0, 0) and not self.transparent:
|
|
|
+ color = (1, 1, 1)
|
|
|
+
|
|
|
+ offset = (x + y * self.width) * 3 + self._header_len
|
|
|
+ self._data[offset] = color[0]
|
|
|
+ self._data[offset + 1] = color[1]
|
|
|
+ self._data[offset + 2] = color[2]
|
|
|
+
|
|
|
+ def set_offset(self, x, y):
|
|
|
+ self.x_offset = x
|
|
|
+ self.y_offset = y
|
|
|
+ self._init_data()
|
|
|
+
|
|
|
+ def send(self):
|
|
|
+ '''Send the updated pixels to the display.'''
|
|
|
+ self._sock.send(self._data)
|
|
|
+
|
|
|
+if __name__ == '__main__':
|
|
|
+ f = Matrix('192.168.178.144', 50, 50)
|
|
|
+ import time
|
|
|
+
|
|
|
+ for j in range(10):
|
|
|
+ time.sleep(1)
|
|
|
+ f.set_offset(j*2, j)
|
|
|
+ for i in range(100):
|
|
|
+ f.set(i, i, (200, 0, 0))
|
|
|
+ f.send()
|