mirror of
https://gitlab1.ptb.de/waltem01/Matrix
synced 2024-12-26 03:51:45 +00:00
423 lines
9.9 KiB
Python
Executable File
423 lines
9.9 KiB
Python
Executable File
#!/usr/bin/env python
|
|
|
|
from deps.samplebase import SampleBase
|
|
from rgbmatrix import graphics
|
|
from PIL import Image
|
|
import base64
|
|
import io
|
|
|
|
from flask import Flask, request, jsonify
|
|
from flask_cors import CORS, cross_origin
|
|
from dotenv import load_dotenv
|
|
from waitress import serve
|
|
from pathlib import Path
|
|
import os, time, threading, json
|
|
|
|
|
|
env_path = Path('..') / '.env'
|
|
load_dotenv(dotenv_path=env_path)
|
|
|
|
api = Flask(__name__)
|
|
cors = CORS(api)
|
|
|
|
@api.route('/instructions', methods=['POST'])
|
|
@cross_origin()
|
|
def instructions():
|
|
# prepare response data
|
|
response = { 'success': True }
|
|
try:
|
|
global matrix
|
|
assert matrix is not None
|
|
|
|
# receive client data
|
|
data = request.form
|
|
# try unpacking instruction list
|
|
instructions = data.get('instructions')
|
|
|
|
# parse json data from instructions string
|
|
ins_set = json.loads(instructions)
|
|
|
|
# call respective matrix methods with corresponding data
|
|
for ins in ins_set:
|
|
if ins['endpoint'] == 'upload':
|
|
url = ins['url']
|
|
matrix.set_image(url)
|
|
elif ins['endpoint'] == 'image':
|
|
x = int(ins['x'])
|
|
y = int(ins['y'])
|
|
matrix.display_image(x, y)
|
|
elif ins['endpoint'] == 'text':
|
|
x = int(ins['x'])
|
|
y = int(ins['y'])
|
|
matrix.text(x, y, ins['text'])
|
|
elif ins['endpoint'] == 'pixel':
|
|
x = int(ins['x'])
|
|
y = int(ins['y'])
|
|
matrix.pixel(x, y)
|
|
elif ins['endpoint'] == 'circle':
|
|
x = int(ins['x'])
|
|
y = int(ins['y'])
|
|
r = int(ins['r'])
|
|
matrix.circle(x, y, r)
|
|
elif ins['endpoint'] == 'rectangle':
|
|
x = int(ins['x'])
|
|
y = int(ins['y'])
|
|
w = int(ins['w'])
|
|
h = int(ins['h'])
|
|
matrix.rectangle(x, y, w, h)
|
|
elif ins['endpoint'] == 'line':
|
|
x1 = int(ins['x1'])
|
|
y1 = int(ins['y1'])
|
|
x2 = int(ins['x2'])
|
|
y2 = int(ins['y2'])
|
|
matrix.line(x1, y1, x2, y2)
|
|
elif ins['endpoint'] == 'color':
|
|
r = int(ins['r'])
|
|
g = int(ins['g'])
|
|
b = int(ins['b'])
|
|
matrix.set_color(r, g, b)
|
|
elif ins['endpoint'] == 'clear':
|
|
matrix.clear()
|
|
elif ins['endpoint'] == 'update':
|
|
matrix.update()
|
|
except Exception as e:
|
|
# error handling
|
|
print(e)
|
|
response['success'] = False
|
|
|
|
# respond to client
|
|
return jsonify(response)
|
|
|
|
@api.route('/upload', methods=['POST'])
|
|
@cross_origin()
|
|
def set_image():
|
|
# prepare response data
|
|
response = { 'success': True }
|
|
try:
|
|
global matrix
|
|
assert matrix is not None
|
|
|
|
# receive client data
|
|
data = request.form
|
|
# try unpacking text and x,y coordinates
|
|
url = data.get('url')
|
|
|
|
# call matrix method with data
|
|
matrix.set_image(url)
|
|
except Exception as e:
|
|
# error handling
|
|
print(e)
|
|
response['success'] = False
|
|
|
|
# respond to client
|
|
return jsonify(response)
|
|
|
|
@api.route('/image', methods=['POST'])
|
|
@cross_origin()
|
|
def display_image():
|
|
# prepare response data
|
|
response = { 'success': True }
|
|
try:
|
|
global matrix
|
|
assert matrix is not None
|
|
|
|
# receive client data
|
|
data = request.form
|
|
# try unpacking x,y coordinates
|
|
x_coord = int(data.get('x'))
|
|
y_coord = int(data.get('y'))
|
|
|
|
# call matrix method with data
|
|
matrix.display_image(x_coord, y_coord)
|
|
except Exception as e:
|
|
# error handling
|
|
print(e)
|
|
response['success'] = False
|
|
|
|
# respond to client
|
|
return jsonify(response)
|
|
|
|
@api.route('/text', methods=['POST'])
|
|
@cross_origin()
|
|
def display_text():
|
|
# prepare response data
|
|
response = { 'success': True }
|
|
try:
|
|
global matrix
|
|
assert matrix is not None
|
|
|
|
# receive client data
|
|
data = request.form
|
|
# try unpacking text and x,y coordinates
|
|
text = data.get('text')
|
|
x_coord = int(data.get('x'))
|
|
y_coord = int(data.get('y'))
|
|
|
|
# call matrix method with data
|
|
matrix.text(x_coord, y_coord, text)
|
|
except Exception as e:
|
|
# error handling
|
|
print(e)
|
|
response['success'] = False
|
|
|
|
# respond to client
|
|
return jsonify(response)
|
|
|
|
@api.route('/pixel', methods=['POST'])
|
|
@cross_origin()
|
|
def set_pixel():
|
|
# prepare response data
|
|
response = { 'success': True }
|
|
try:
|
|
global matrix
|
|
assert matrix is not None
|
|
|
|
# receive client data
|
|
data = request.form
|
|
# try unpacking x,y coordinates
|
|
x_coord = int(data.get('x'))
|
|
y_coord = int(data.get('y'))
|
|
|
|
# call matrix method with data
|
|
matrix.pixel(x_coord, y_coord)
|
|
except Exception as e:
|
|
# error handling
|
|
print(e)
|
|
response['success'] = False
|
|
|
|
# respond to client
|
|
return jsonify(response)
|
|
|
|
@api.route('/circle', methods=['POST'])
|
|
@cross_origin()
|
|
def draw_circle():
|
|
# prepare response data
|
|
response = { 'success': True }
|
|
try:
|
|
global matrix
|
|
assert matrix is not None
|
|
|
|
# receive client data
|
|
data = request.form
|
|
# try unpacking radius and x,y coordinates
|
|
radius = int(data.get('r'))
|
|
x_coord = int(data.get('x'))
|
|
y_coord = int(data.get('y'))
|
|
|
|
# call matrix method with data
|
|
matrix.circle(x_coord, y_coord, radius)
|
|
except Exception as e:
|
|
# error handling
|
|
print(e)
|
|
response['success'] = False
|
|
|
|
# respond to client
|
|
return jsonify(response)
|
|
|
|
@api.route('/rectangle', methods=['POST'])
|
|
@cross_origin()
|
|
def draw_rectangle():
|
|
# prepare response data
|
|
response = { 'success': True }
|
|
try:
|
|
global matrix
|
|
assert matrix is not None
|
|
|
|
# receive client data
|
|
data = request.form
|
|
# try unpacking rectangle width and height
|
|
width = int(data.get('w'))
|
|
height = int(data.get('h'))
|
|
# try unpacking x,y coordinates
|
|
x_coord = int(data.get('x'))
|
|
y_coord = int(data.get('y'))
|
|
|
|
# call matrix method with data
|
|
matrix.rectangle(x_coord, y_coord, width, height)
|
|
except Exception as e:
|
|
# error handling
|
|
print(e)
|
|
response['success'] = False
|
|
|
|
# respond to client
|
|
return jsonify(response)
|
|
|
|
@api.route('/line', methods=['POST'])
|
|
@cross_origin()
|
|
def draw_line():
|
|
# prepare response data
|
|
response = { 'success': True }
|
|
try:
|
|
global matrix
|
|
assert matrix is not None
|
|
|
|
# receive client data
|
|
data = request.form
|
|
# try unpacking x,y coordinates
|
|
x1 = int(data.get('x1'))
|
|
y1 = int(data.get('y1'))
|
|
x2 = int(data.get('x2'))
|
|
y2 = int(data.get('y2'))
|
|
|
|
# call matrix method with data
|
|
matrix.line(x1, y1, x2, y2)
|
|
except Exception as e:
|
|
# error handling
|
|
print(e)
|
|
response['success'] = False
|
|
|
|
# respond to client
|
|
return jsonify(response)
|
|
|
|
@api.route('/color', methods=['POST'])
|
|
@cross_origin()
|
|
def set_color():
|
|
# prepare response data
|
|
response = { 'success': True }
|
|
try:
|
|
global matrix
|
|
assert matrix is not None
|
|
|
|
# receive client data
|
|
data = request.form
|
|
# try unpacking red, green and blue color values
|
|
red = int(data.get('r'))
|
|
green = int(data.get('g'))
|
|
blue = int(data.get('b'))
|
|
|
|
# call matrix method with data
|
|
matrix.set_color(red, green, blue)
|
|
except Exception as e:
|
|
# error handling
|
|
print(e)
|
|
response['success'] = False
|
|
|
|
# respond to client
|
|
return jsonify(response)
|
|
|
|
@api.route('/clear', methods=['GET'])
|
|
@cross_origin()
|
|
def clear_canvas():
|
|
# prepare response data
|
|
response = { 'success': True }
|
|
try:
|
|
global matrix
|
|
assert matrix is not None
|
|
|
|
# clear matrix canvas
|
|
matrix.clear()
|
|
except Exception as e:
|
|
# error handling
|
|
print(e)
|
|
response['success'] = False
|
|
|
|
# respond to client
|
|
return jsonify(response)
|
|
|
|
@api.route('/update', methods=['GET'])
|
|
@cross_origin()
|
|
def update_matrix():
|
|
response = { 'success': True }
|
|
try:
|
|
global matrix
|
|
assert matrix is not None
|
|
|
|
# swap matrix canvas
|
|
matrix.update()
|
|
except Exception as e:
|
|
print(e)
|
|
response['success'] = False
|
|
|
|
# respond to client
|
|
return jsonify(response)
|
|
|
|
|
|
# derived class to access rgb-led-matrix
|
|
class Matrix(SampleBase):
|
|
def __init__(self, *args, **kwargs):
|
|
super(Matrix, self).__init__(*args, **kwargs)
|
|
self.parser.set_defaults(led_rows=int(os.getenv('PUBLIC_LED_WIDTH', 64)))
|
|
self.parser.set_defaults(led_cols=int(os.getenv('PUBLIC_LED_HEIGHT', 64)))
|
|
self.parser.set_defaults(led_chain=int(os.getenv('PUBLIC_LED_CHAIN', 1)))
|
|
self.parser.set_defaults(led_parallel=int(os.getenv('PUBLIC_LED_PARALLEL', 1)))
|
|
|
|
# run display program
|
|
def run(self):
|
|
# initialize font
|
|
self.font = graphics.Font()
|
|
self.font.LoadFont("deps/fonts/9x18B.bdf")
|
|
# initialize color
|
|
self.color = graphics.Color(255, 255, 255)
|
|
# initialize image
|
|
self.image = None
|
|
|
|
# initialize canvas
|
|
self.canvas = self.matrix.CreateFrameCanvas()
|
|
self.canvas.Clear()
|
|
|
|
# wait in idle
|
|
while True:
|
|
time.sleep(.05)
|
|
|
|
# clear canvas
|
|
def clear(self):
|
|
self.canvas.Clear()
|
|
|
|
# swap canvas with buffer
|
|
def update(self):
|
|
self.canvas = self.matrix.SwapOnVSync(self.canvas)
|
|
self.clear()
|
|
|
|
# set current color
|
|
def set_color(self, r: int, g: int, b: int):
|
|
self.color = graphics.Color(r, g, b)
|
|
|
|
# set specified pixel to current color
|
|
def pixel(self, x: int, y: int):
|
|
self.canvas.SetPixel(x, y, self.color.red, self.color.green, self.color.blue)
|
|
|
|
# display text at position with current color
|
|
def text(self, x: int, y: int, t: int):
|
|
graphics.DrawText(self.canvas, self.font, x*9, (y+1)*18, self.color, t)
|
|
|
|
# display circle at position with radius in current color
|
|
def circle(self, x: int, y: int, r: int):
|
|
graphics.DrawCircle(self.canvas, x, y, r, self.color)
|
|
|
|
# display rectangle at position with dimensions in current color
|
|
def rectangle(self, x: int, y: int, w: int, h: int):
|
|
# loop through each point in dimensions
|
|
for i in range(w):
|
|
for j in range(h):
|
|
# set next pixel in rectangle
|
|
self.canvas.SetPixel(x+i, y+j, self.color.red, self.color.green, self.color.blue)
|
|
|
|
# display line from (x1,y1) to (x2,y2) in current color
|
|
def line(self, x1: int, y1: int, x2: int, y2: int):
|
|
graphics.DrawLine(self.canvas, x1, y1, x2, y2, self.color)
|
|
|
|
# set current image
|
|
def set_image(self, url: str):
|
|
_, data = url.split(',')
|
|
data = base64.b64decode(data)
|
|
self.image = Image.open(io.BytesIO(data)).convert('RGB')
|
|
|
|
# display image at position with dimensions in current color
|
|
def display_image(self, x: int, y: int):
|
|
if self.image is None: return
|
|
# set image at position
|
|
self.canvas.SetImage(self.image, x, y)
|
|
|
|
|
|
# initialize global matrix variable
|
|
matrix = None
|
|
if __name__ == "__main__":
|
|
# set matrix to instance
|
|
matrix = Matrix()
|
|
# run rest api in thread, serving with 'waitress'
|
|
threading.Thread(target=lambda: serve(api, host="0.0.0.0", port=8080)).start()
|
|
|
|
# help menu on call
|
|
if not matrix.process():
|
|
matrix.print_help()
|