+
Gamma:
-
Flip:
-
Filterimage:
-
Filter expression:
-
-
-
Crash Log:
-
-
+
+
Crash Log:
+
+
+
- Log:
-
-
+ Log:
+
+
+
-
-
+ function updateCrashLog() {
+ getRaw("/apps/crashlog", function (text) {
+ document.getElementById('crashlogs').value = text;
+ });
+ }
+ function enableCrashLog() {
+ document.getElementById("crashlogbtn").remove();
+ document.getElementById("crashlogs").style.display = "block";
+ updateCrashLog();
+ setInterval(updateCrashLog, 1000);
+ return false;
+ }
+ function enableLog() {
+ document.getElementById("logbtn").remove();
+ document.getElementById("logs").style.display = "block";
+ updateLog();
+ setInterval(updateLog, 1000);
+ return false;
+ }
+ getJSON("/apps/list", populateForm);
+
+
+
diff --git a/main.py b/main.py
index 9956f88..0a20679 100755
--- a/main.py
+++ b/main.py
@@ -4,7 +4,6 @@ import json
import logging
import math
import os
-import string
import subprocess
import threading
import time
@@ -12,13 +11,12 @@ from collections import OrderedDict
import bottle
import numpy as np
-import scipy.misc
import serial
import config
+import filters
logging.basicConfig(filename='pixelserver.log', level=config.LogLevel)
-running = True
########################################################################
@@ -151,7 +149,7 @@ if config.UseGui:
def join(self, **kwargs):
with self.cv:
self.cv.notify_all()
- super().join()
+ super().join(**kwargs)
########################################################################
@@ -162,6 +160,7 @@ class SerialWriter(threading.Thread):
super().__init__(daemon=True)
self.cv = threading.Condition()
self.datasource = datasource.addListener(self.cv)
+ self.gamma_rgbw = 0, 0, 0, 0
self.updateGamma = False
def run(self):
@@ -179,13 +178,15 @@ class SerialWriter(threading.Thread):
frame = self.datasource.getData()
data = frame.buffer.reshape((config.ScreenX * config.ScreenY * frame.channels,)).astype(np.uint8).tobytes()
if self.updateGamma:
- buf = bytearray(b"\x00") * 4 * 256
+ r, g, b, w = self.gamma_rgbw
+ apply = lambda x, g: max(0, min(255, int(math.pow(x / 255, g) * 255)))
+
+ buf = bytearray(4 * 256)
for i in range(256):
- apply = lambda x, g: max(0, min(255, int(math.pow(x / 255, g) * 255)))
- buf[i] = apply(i, self.r)
- buf[i + 256] = apply(i, self.g)
- buf[i + 512] = apply(i, self.b)
- buf[i + 512 + 256] = apply(i, self.w)
+ buf[i] = apply(i, r)
+ buf[i + 256] = apply(i, g)
+ buf[i + 256 * 2] = apply(i, b)
+ buf[i + 256 * 3] = apply(i, w)
ser.write(b"\x02")
ser.write(buf)
self.updateGamma = False
@@ -195,7 +196,7 @@ class SerialWriter(threading.Thread):
elif frame.channels == 4:
ser.write(b"\03")
ser.write(data)
- logging.debug("Time to gui: " + str(time.time() - frame.created))
+ logging.debug(f"Time to gui: {time.time() - frame.created}")
ser.flush()
except Exception as e:
if ser is not None:
@@ -209,11 +210,11 @@ class SerialWriter(threading.Thread):
def join(self, **kwargs):
with self.cv:
self.cv.notify_all()
- super().join()
+ super().join(**kwargs)
def setGamma(self, r, g, b, w):
with self.cv:
- self.r, self.g, self.b, self.w = r, g, b, w
+ self.gamma_rgbw = r, g, b, w
self.updateGamma = True
self.cv.notify_all()
@@ -317,7 +318,7 @@ class AppRunner(threading.Thread):
self.requestedApp = app
self.param = param
self.cv.notify_all()
- logging.info("Requesting app: " + str(app))
+ logging.info(f"Requesting app: {app}")
def startApp(self, i, param=""):
app = config.Apps[i]
@@ -373,90 +374,14 @@ class AppRunner(threading.Thread):
def setGamma(self, r, g, b, w):
self.serial.setGamma(r, g, b, w)
- def setFilter(self, name, filter):
- self.filters[name] = filter
+ def setFilter(self, name, filter_):
+ self.filters[name] = filter_
def removeFilter(self, name):
if name in self.filters.keys():
del self.filters[name]
-########################################################################
-# Filter Api #
-########################################################################
-def MakeBrightnessFilter(intensity):
- def filter(img):
- return (img * intensity).astype(np.uint8)
-
- return filter
-
-
-def FlipXFilter(intensity):
- return intensity[:, ::-1, :]
-
-
-def FlipYFilter(intensity):
- return intensity[::-1, :, :]
-
-
-def MakeBrightnessImageFilter(name):
- img = scipy.misc.imread("filter/" + name + ".png", flatten=True) / 255
-
- # img = np.transpose(img)
- def filter(intensity):
- intensity = intensity.astype(float)
- for i in range(intensity.shape[2]):
- intensity[:, :, i] *= img
- return intensity.astype(np.uint8)
-
- return filter
-
-
-def strings(s):
- allowed_chars = string.ascii_letters + string.digits + "+-*/()."
- i = 0
- outlist = []
- while i != len(s):
- if s[i] not in allowed_chars:
- raise Exception("Unexpected char " + s[i])
- if s[i] not in string.ascii_letters:
- i += 1
- continue
- out = ""
- while i != len(s) and s[i] in string.ascii_letters + string.digits:
- out += s[i]
- i += 1
- outlist.append(out)
- return outlist
-
-
-def eval_safer(expr, x, y, t):
- symbols = {"x": x, "y": y, "t": t,
- "sin": np.sin, "cos": np.cos, "exp": np.exp, "tan": np.tan}
- strs = strings(expr)
- for s in strs:
- if s not in symbols.keys():
- raise Exception("unexpected symbol: " + s)
- return eval(expr, {}, symbols)
-
-
-def MakeBrightnessExprFilter(expr):
- t0 = time.time()
- x, y = np.meshgrid(np.arange(config.ScreenX), np.arange(config.ScreenY))
- eval_safer(expr, 0, 0, 0)
-
- def filter(intensity):
- t = time.time() - t0
- intensity = intensity.astype(float)
- filter = 0 * x + eval_safer(expr, x, y, t)
- filter = np.clip(np.nan_to_num(filter), 0, 1)
- for i in range(intensity.shape[2]):
- intensity[:, :, i] *= filter
- return intensity.astype(np.uint8)
-
- return filter
-
-
########################################################################
# Web Api #
########################################################################
@@ -530,17 +455,15 @@ def apps_running():
def index():
return bottle.static_file("index.html", root='html')
+
@bottle.route("/
")
def serve_static(filepath):
return bottle.static_file(filepath, root='html')
+
@bottle.route("/setgamma////")
def setGamma(r, g, b, w):
- r = float(r)
- g = float(g)
- b = float(b)
- w = float(w)
- runner.setGamma(r, g, b, w)
+ runner.setGamma(float(r), float(g), float(b), float(w))
return "ok"
@@ -549,14 +472,14 @@ def setIntensity(i):
i = float(i)
if not 0 <= i <= 1:
return "bad_value"
- runner.setFilter("0_intensity", MakeBrightnessFilter(i))
+ runner.setFilter("0_intensity", filters.MakeBrightnessFilter(i))
return "ok"
@bottle.route("/filter/flipx/")
def flipx(do):
if do == "true":
- runner.setFilter("1_flipx", FlipXFilter)
+ runner.setFilter("1_flipx", filters.FlipXFilter)
else:
runner.removeFilter("1_flipx")
return "ok"
@@ -565,7 +488,7 @@ def flipx(do):
@bottle.route("/filter/flipy/")
def flipy(do):
if do == "true":
- runner.setFilter("1_flipy", FlipYFilter)
+ runner.setFilter("1_flipy", filters.FlipYFilter)
else:
runner.removeFilter("1_flipy")
return "ok"
@@ -576,7 +499,7 @@ def setfilter(name):
if name == "none":
runner.removeFilter("3_imgfilter")
else:
- runner.setFilter("3_imgfilter", MakeBrightnessImageFilter(name))
+ runner.setFilter("3_imgfilter", filters.MakeBrightnessImageFilter(name))
return "ok"
@@ -586,21 +509,23 @@ def filter_expr():
if expr == "" or expr == "none":
runner.removeFilter("5_brightnessfunction")
else:
- runner.setFilter("5_brightnessfunction", MakeBrightnessExprFilter(expr))
+ runner.setFilter("5_brightnessfunction", filters.MakeBrightnessExprFilter(expr))
return "ok"
-########################################################################
-# Startup #
-########################################################################
-runner = AppRunner()
-runner.start()
+if __name__ == '__main__':
+ ########################################################################
+ # Startup #
+ ########################################################################
+ running = True
+ runner = AppRunner()
+ runner.start()
-# runner.setFilter("5_crazy", MakeBrightnessExprFilter("0.5+0.25*sin(x/3)/x"))
-bottle.run(host=config.WebHost, port=config.WebPort)
+ # runner.setFilter("5_crazy", MakeBrightnessExprFilter("0.5+0.25*sin(x/3)/x"))
+ bottle.run(host=config.WebHost, port=config.WebPort)
-########################################################################
-# Shutdown #
-########################################################################
-running = False
-runner.join()
+ ########################################################################
+ # Shutdown #
+ ########################################################################
+ running = False
+ runner.join()