matrix_ft.py 2.9 KB

1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374757677787980818283
  1. import socket
  2. class Matrix(object):
  3. '''A Framebuffer display interface that sends a frame via UDP.
  4. see https://github.com/hzeller/flaschen-taschen/blob/master/doc/protocols.md
  5. '''
  6. def __init__(self, host, width, height, layer=1, x_offset=0, y_offset=0, transparent=False, port=1337):
  7. '''
  8. Args:
  9. host: The flaschen taschen server hostname or ip address.
  10. port: The flaschen taschen server port number.
  11. width: The width of the flaschen taschen display in pixels.
  12. height: The height of the flaschen taschen display in pixels.
  13. layer: The layer of the flaschen taschen display to write to. (layer=0 is permanent, layer > 0 decays, see --layer-timeout server opt)
  14. transparent: If true, black(0, 0, 0) will be transparent and show the layer below.
  15. '''
  16. self.width = width
  17. self.height = height
  18. self.layer = layer
  19. self.transparent = transparent
  20. self.x_offset = x_offset
  21. self.y_offset = y_offset
  22. self._sock = socket.socket(socket.AF_INET, socket.SOCK_DGRAM)
  23. self._sock.connect((host, port))
  24. self._init_data()
  25. def _init_data(self):
  26. header = ''.join(["P6\n",
  27. "%d %d\n" % (self.width, self.height),
  28. "255\n"]).encode('utf-8')
  29. footer = ''.join(["%d\n" % self.x_offset,
  30. "%d\n" % self.y_offset,
  31. "%d\n" % self.layer]).encode('utf-8')
  32. self._data = bytearray(self.width * self.height * 3 + len(header) + len(footer))
  33. self._data[0:len(header)] = header
  34. self._data[-1 * len(footer):] = footer
  35. self._header_len = len(header)
  36. def set(self, x, y, color):
  37. '''Set the pixel at the given coordinates to the specified color.
  38. Args:
  39. x: x offset of the pixel to set
  40. y: y offset of the piyel to set
  41. color: A 3 tuple of (r, g, b) color values, 0-255
  42. '''
  43. if x >= self.width or y >= self.height or x < 0 or y < 0:
  44. return
  45. # [dr]: inverted logic
  46. if color == (0, 0, 0) and self.transparent:
  47. color = (1, 1, 1)
  48. offset = (x + y * self.width) * 3 + self._header_len
  49. self._data[offset] = color[0]
  50. self._data[offset + 1] = color[1]
  51. self._data[offset + 2] = color[2]
  52. def set_offset(self, x, y):
  53. self.x_offset = x
  54. self.y_offset = y
  55. self._init_data()
  56. def send(self):
  57. '''Send the updated pixels to the display.'''
  58. self._sock.send(self._data)
  59. def clear(self):
  60. '''clear pane with black (reinit self._data)
  61. '''
  62. self._init_data()
  63. if __name__ == '__main__':
  64. f = Matrix('192.168.178.144', 50, 50)
  65. import time
  66. for j in range(10):
  67. time.sleep(1)
  68. f.set_offset(j*2, j)
  69. for i in range(100):
  70. f.set(i, i, (200, 0, 0))
  71. f.send()