diff --git a/rpi/main.py b/rpi/main.py index 95401d4..e17bd4d 100644 --- a/rpi/main.py +++ b/rpi/main.py @@ -7,6 +7,7 @@ Run with: sudo python3 main.py import time import random +import socket import sys from rpi_ws281x import PixelStrip, ws @@ -32,6 +33,23 @@ strip = PixelStrip( strip.begin() low_level.strip = strip +_udp_sock = socket.socket(socket.AF_INET, socket.SOCK_DGRAM) +_udp_addr = ('127.0.0.1', 4210) + + +def _send_frame(): + buf = bytearray(48 * 16 * 3) + off = 0 + for y in range(16): + for x in range(48): + r, g, b = low_level.get_pixel_color(x, y) + buf[off] = r + buf[off + 1] = g + buf[off + 2] = b + off += 3 + _udp_sock.sendto(buf, _udp_addr) + + # --------------------------------------------------------------------------- # Global state # --------------------------------------------------------------------------- @@ -419,6 +437,7 @@ def loop(): handle_disappear_timers() strip.show() + _send_frame() if __name__ == '__main__': diff --git a/rpi/server.py b/rpi/server.py index 6663c4f..9976c28 100644 --- a/rpi/server.py +++ b/rpi/server.py @@ -1,10 +1,15 @@ from flask import Flask, request, jsonify, Response import threading +import socket import json -import low_level from config import DISPLAY_MAX_X, DISPLAY_MAX_Y +UDP_PORT = 4210 +COLS = DISPLAY_MAX_X + 1 # 48 +ROWS = DISPLAY_MAX_Y + 1 # 16 +FRAME_SIZE = COLS * ROWS * 3 # 2304 bytes + app = Flask(__name__) # Shared state — written by Flask thread, read by main loop @@ -17,6 +22,20 @@ state = { } _lock = threading.Lock() +_frame = b'\x00' * FRAME_SIZE +_frame_lock = threading.Lock() + + +def _udp_listener(): + global _frame + sock = socket.socket(socket.AF_INET, socket.SOCK_DGRAM) + sock.bind(('127.0.0.1', UDP_PORT)) + while True: + data, _ = sock.recvfrom(FRAME_SIZE + 1) + if len(data) == FRAME_SIZE: + with _frame_lock: + _frame = data + INDEX_HTML = """ LED Panel Control @@ -167,11 +186,15 @@ def index(): @app.route('/display', methods=['GET']) def handle_display(): + with _frame_lock: + data = _frame pixels = [] - for y in range(DISPLAY_MAX_Y + 1): + off = 0 + for y in range(ROWS): row = [] - for x in range(DISPLAY_MAX_X + 1): - row.append(low_level.get_pixel_color(x, y)) + for x in range(COLS): + row.append([data[off], data[off + 1], data[off + 2]]) + off += 3 pixels.append(row) return Response(json.dumps(pixels), mimetype='application/json') @@ -224,5 +247,5 @@ def handle_status(): def start_server(host='0.0.0.0', port=80): - t = threading.Thread(target=lambda: app.run(host=host, port=port, use_reloader=False), daemon=True) - t.start() + threading.Thread(target=_udp_listener, daemon=True).start() + threading.Thread(target=lambda: app.run(host=host, port=port, use_reloader=False), daemon=True).start()