Code cleanup
This commit is contained in:
parent
8dc0480c18
commit
c38a840d42
@ -6,6 +6,7 @@ import random
|
|||||||
import time
|
import time
|
||||||
import math
|
import math
|
||||||
import numpy as np
|
import numpy as np
|
||||||
|
|
||||||
# Groesse des Bildschirms bestimmen
|
# Groesse des Bildschirms bestimmen
|
||||||
Nx = int(sys.argv[1])
|
Nx = int(sys.argv[1])
|
||||||
Ny = int(sys.argv[2])
|
Ny = int(sys.argv[2])
|
||||||
@ -21,18 +22,18 @@ except:
|
|||||||
|
|
||||||
curPixel = 0
|
curPixel = 0
|
||||||
|
|
||||||
phase = np.random.uniform(0, 2*np.pi, (Ny, Nx))
|
phase = np.random.uniform(0, 2 * np.pi, (Ny, Nx))
|
||||||
t = 0
|
t = 0
|
||||||
f_min = 0.08
|
f_min = 0.08
|
||||||
f_max = 0.10
|
f_max = 0.10
|
||||||
f = np.random.uniform(f_min, f_max, (Ny, Nx))
|
f = np.random.uniform(f_min, f_max, (Ny, Nx))
|
||||||
while True:
|
while True:
|
||||||
t += time_ms/1000.0
|
t += time_ms / 1000.0
|
||||||
s = 0.80 +0.2*np.sin(phase+2*np.pi*t*f)
|
s = 0.80 + 0.2 * np.sin(phase + 2 * np.pi * t * f)
|
||||||
img = np.zeros([Ny, Nx, 4])
|
img = np.zeros([Ny, Nx, 4])
|
||||||
img[:,:,3] = 255*s
|
img[:, :, 3] = 255 * s
|
||||||
# Zeige den Puffer an
|
# Zeige den Puffer an
|
||||||
out = img.reshape((Nx*Ny*4,)).astype(np.uint8)
|
out = img.reshape((Nx * Ny * 4,)).astype(np.uint8)
|
||||||
os.write(1, out.tobytes())
|
os.write(1, out.tobytes())
|
||||||
# warte time_ms ms
|
# warte time_ms ms
|
||||||
time.sleep(time_ms*0.001)
|
time.sleep(time_ms * 0.001)
|
||||||
|
126
config.py
126
config.py
@ -1,8 +1,25 @@
|
|||||||
import logging
|
import logging
|
||||||
|
from dataclasses import dataclass
|
||||||
|
from typing import Union, List
|
||||||
|
|
||||||
#width
|
|
||||||
|
@dataclass
|
||||||
|
class AppConfig:
|
||||||
|
guiname: str
|
||||||
|
name: str
|
||||||
|
cmd: Union[List[str], str]
|
||||||
|
path: str = "./apps/"
|
||||||
|
persistent: bool = False
|
||||||
|
white: bool = False
|
||||||
|
|
||||||
|
def __post_init__(self):
|
||||||
|
if not isinstance(self.cmd, list):
|
||||||
|
self.cmd = [self.cmd]
|
||||||
|
|
||||||
|
|
||||||
|
# width
|
||||||
ScreenX = 80
|
ScreenX = 80
|
||||||
#height
|
# height
|
||||||
ScreenY = 40
|
ScreenY = 40
|
||||||
|
|
||||||
DefaultBrightness = 0.6
|
DefaultBrightness = 0.6
|
||||||
@ -14,81 +31,66 @@ NoDataTimeout = 40
|
|||||||
|
|
||||||
LogLevel = logging.DEBUG
|
LogLevel = logging.DEBUG
|
||||||
|
|
||||||
UseGui = True
|
UseGui = False
|
||||||
GuiFPS = 20
|
GuiFPS = 20
|
||||||
GuiScaleFactor = 15
|
GuiScaleFactor = 15
|
||||||
|
|
||||||
WebHost = "0.0.0.0"
|
WebHost = "0.0.0.0"
|
||||||
WebPort = 8000
|
WebPort = 8000
|
||||||
|
|
||||||
# first app is always running as default
|
|
||||||
Apps = [
|
Apps = [
|
||||||
|
# first app is always running as default
|
||||||
|
AppConfig(guiname="Backlight", name="backlight", cmd="./backlight.py", white=True),
|
||||||
|
|
||||||
{"name": "backlight", "cmd": "apps/backlight.py", "white": True},
|
AppConfig(guiname="Lines", name="lines", cmd="./lines.py"),
|
||||||
|
AppConfig(guiname="Wolfram", name="wolfram", cmd="./wolfram.py"),
|
||||||
{"guiname": "Lines", "name": "lines", "cmd": "./lines.py", "persistent": False, "path": "./apps/"},
|
AppConfig(guiname="Digi Clock", name="digiclock", cmd="./digi_clock.py"),
|
||||||
{"guiname": "Wolfram", "name": "wolfram", "cmd": "./wolfram.py", "persistent": False, "path": "./apps/"},
|
AppConfig(guiname="Text Scroller MQTT", name="textscroll", cmd="./textscroll.py"),
|
||||||
{"guiname": "Digi Clock", "name": "digiclock", "cmd": "./digi_clock.py", "persistent": False, "path": "./apps/"},
|
AppConfig(guiname="Flicker", name="flicker", cmd="./flicker"),
|
||||||
{"guiname": "Text Scroller MQTT", "name": "textscroll", "cmd": "./textscroll.py", "persistent": False, "path": "./apps/"},
|
|
||||||
{"guiname": "Flicker", "name": "flicker", "cmd": "apps/flicker"},
|
|
||||||
|
|
||||||
{"guiname": "Pixelflut", "name": "pixelflut", "cmd": "apps/pixelflut", "persistent": True},
|
|
||||||
# {"guiname": "Pong", "name": "pong", "cmd": "apps/pong.py"},
|
|
||||||
{"guiname": "YoutubeDL", "name": "youtubedl", "cmd": "apps/youtubedl.sh", "persistent": False},
|
|
||||||
# {"guiname": "Show Framebuffer", "name": "fbcp", "cmd": ["apps/fbcp", "/dev/fb0"]},
|
|
||||||
{"guiname": "Strobo", "name": "strobo", "cmd": "apps/strobo.py"},
|
|
||||||
# {"guiname": "Beispiel", "name": "example", "cmd": "apps/example.py"},
|
|
||||||
# {"guiname": "Beispiel2", "name": "example2", "cmd": "apps/example2.py", "white": True},
|
|
||||||
{"guiname": "Fibonacci Clock", "name": "fibonacci-clock", "cmd": "apps/fibonacci-clock.py"},
|
|
||||||
{"guiname": "Wget Video/Gif/Images", "name": "wget", "cmd": "apps/wget.sh", "persistent": False},
|
|
||||||
|
|
||||||
|
AppConfig(guiname="Pixelflut", name="pixelflut", cmd="./pixelflut", persistent=True),
|
||||||
|
# App(guiname="Pong", name="pong", cmd="pong.py"),
|
||||||
|
AppConfig(guiname="YoutubeDL", name="youtubedl", cmd="./youtubedl.sh"),
|
||||||
|
# App(guiname="Show Framebuffer", name="fbcp", cmd=["fbcp", "/dev/fb0"]),
|
||||||
|
AppConfig(guiname="Strobo", name="strobo", cmd="./strobo.py"),
|
||||||
|
# App(guiname="Beispiel", name="example", cmd="example.py"),
|
||||||
|
# App(guiname="Beispiel2", name="example2", cmd="example2.py", white=True),
|
||||||
|
AppConfig(guiname="Fibonacci Clock", name="fibonacci-clock", cmd="./fibonacci-clock.py"),
|
||||||
|
AppConfig(guiname="Wget Video/Gif/Images", name="wget", cmd="./wget.sh"),
|
||||||
|
|
||||||
# juergen/pixelfoo
|
# juergen/pixelfoo
|
||||||
{"guiname": "Congress noise", "name": "cnoise", "cmd": "pixelfoo/target/release/cnoise", "persistent": False},
|
AppConfig(guiname="Congress noise", name="cnoise", cmd="./cnoise", path="pixelfoo/target/release/"),
|
||||||
{"guiname": "Game of Life", "name": "life", "cmd": "pixelfoo/target/release/life", "persistent": False},
|
AppConfig(guiname="Game of Life", name="life", cmd="./life", path="pixelfoo/target/release/"),
|
||||||
{"guiname": "Matrix Code", "name": "matrix-code", "cmd": "pixelfoo/target/release/matrix-code", "persistent": False},
|
AppConfig(guiname="Matrix Code", name="matrix-code", cmd="./matrix-code", path="pixelfoo/target/release/"),
|
||||||
{"guiname": "Lorenz Attractor", "name": "lorenz", "cmd": "pixelfoo/target/release/lorenz", "persistent": False},
|
AppConfig(guiname="Lorenz Attractor", name="lorenz", cmd="./lorenz", path="pixelfoo/target/release/"),
|
||||||
{"guiname": "Dual Moodlight", "name": "bimood", "cmd": "pixelfoo/target/release/bimood", "persistent": False},
|
AppConfig(guiname="Dual Moodlight", name="bimood", cmd="./bimood", path="pixelfoo/target/release/"),
|
||||||
{"guiname": "Maze", "name": "maze", "cmd": "pixelfoo/target/release/maze", "persistent": False},
|
AppConfig(guiname="Maze", name="maze", cmd="./maze", path="pixelfoo/target/release/"),
|
||||||
{"guiname": "Dual Maze", "name": "dualmaze", "cmd": "pixelfoo/target/release/dualmaze", "persistent": False, "persistent": False},
|
AppConfig(guiname="Dual Maze", name="dualmaze", cmd="./dualmaze", path="pixelfoo/target/release/"),
|
||||||
{"guiname": "Predator & Prey", "name": "predprey", "cmd": "pixelfoo/target/release/predprey", "persistent": False},
|
AppConfig(guiname="Predator & Prey", name="predprey", cmd="./predprey", path="pixelfoo/target/release/"),
|
||||||
|
|
||||||
# { "guiname": "Beat Saber Ceiling", "name": "beatsaberceiling", "cmd": "./beatsaberceiling.py", "path": "apps/beatsaberceiling" },
|
# App(guiname="Beat Saber Ceiling", name="beatsaberceiling", cmd="./beatsaberceiling.py", path="beatsaberceiling"),
|
||||||
|
|
||||||
# mathpixel
|
# mathpixel
|
||||||
{"guiname": "Structure formation", "name": "swifthohenberg", "cmd": "apps/swifthohenberg.py", "persistent": False},
|
AppConfig(guiname="Structure formation", name="swifthohenberg", cmd="./swifthohenberg.py"),
|
||||||
{"guiname": "Quadratisch", "name": "quadratic", "cmd": "apps/quadratic.py"},
|
AppConfig(guiname="Quadratisch", name="quadratic", cmd="./quadratic.py"),
|
||||||
{"guiname": "Pendel", "name": "pendulum", "cmd": "apps/pendlum.py"},
|
AppConfig(guiname="Pendel", name="pendulum", cmd="./pendlum.py"),
|
||||||
{"guiname": "Konvergenz", "name": "convergence", "cmd": "apps/convergence.py"},
|
AppConfig(guiname="Konvergenz", name="convergence", cmd="./convergence.py"),
|
||||||
{"guiname": "Sinic", "name": "sinic", "cmd": "apps/sinic.py"},
|
AppConfig(guiname="Sinic", name="sinic", cmd="./sinic.py"),
|
||||||
{"guiname": "Sinic 2", "name": "sinic2", "cmd": "apps/sinic2.py"},
|
AppConfig(guiname="Sinic 2", name="sinic2", cmd="./sinic2.py"),
|
||||||
|
|
||||||
# pixelthud
|
# pixelthud
|
||||||
{"guiname": "Fading Pixels", "name": "fadingpxls", "cmd": "apps/fading_pixels.py", "persistent": False},
|
AppConfig(guiname="Fading Pixels", name="fadingpxls", cmd="./fading_pixels.py"),
|
||||||
{"guiname": "Plane Wave", "name": "planewave", "cmd": "apps/plane_wave.py", "persistent": False},
|
AppConfig(guiname="Plane Wave", name="planewave", cmd="./plane_wave.py"),
|
||||||
{"guiname": "Rock-paper-scissors-spock-lizard", "name": "rps", "cmd": "apps/rps.py", "persistent": False},
|
AppConfig(guiname="Rock-paper-scissors-spock-lizard", name="rps", cmd="./rps.py"),
|
||||||
{"guiname": "Doom Fire", "name": "doomfire", "cmd": "apps/doom_fire_psx2.py", "persistent": False},
|
AppConfig(guiname="Doom Fire", name="doomfire", cmd="./doom_fire_psx2.py"),
|
||||||
# {"guiname": "Maxwell FDTD", "name": "fdtd", "cmd": "apps/fdtd.py", "persistent": False},
|
# App(guiname="Maxwell FDTD", name="fdtd", cmd="./fdtd.py"),
|
||||||
|
|
||||||
#{"guiname": "Stream", "name": "stream", "cmd": "apps/stream.sh", "persistent": False},
|
# App(guiname="Stream", name="stream", cmd="./stream.sh"),
|
||||||
#{"guiname": "Wget Video/Gif/Images", "name": "wget", "cmd": "apps/wget.sh", "persistent": False},
|
# App(guiname="Wget Video/Gif/Images", name="wget", cmd="./wget.sh"),
|
||||||
#{"guiname": "Tetris", "name": "tetris", "cmd": "apps/deckentetris/deckentetris.py", "persistent": False},
|
# App(guiname="Tetris", name="tetris", cmd="./deckentetris/deckentetris.py"),
|
||||||
#{"guiname": "SkyScrapper", "name": "sky", "cmd": "apps/weather/main.py"},
|
# App(guiname="SkyScrapper", name="sky", cmd="./weather/main.py"),
|
||||||
#{"guiname": "Strobo", "name": "strobo", "cmd": "apps/strobo.py", "persistent": False},
|
# App(guiname="Strobo", name="strobo", cmd="./strobo.py"),
|
||||||
#{"guiname": "Snake", "name": "snake", "cmd": "apps/snake.py", "persistent": False},
|
# App(guiname="Snake", name="snake", cmd="./snake.py"),
|
||||||
#{"name": "gif", "cmd": "apps/gif.sh"},
|
# App(name="gif", cmd="./gif.sh"),
|
||||||
#{"name": "colormap", "cmd": "apps/colormap.py"},
|
# App(name="colormap", cmd="./colormap.py"),
|
||||||
]
|
]
|
||||||
|
|
||||||
# load additional apps from config/
|
|
||||||
# import os
|
|
||||||
# import os.path
|
|
||||||
# configs = os.listdir("configs/")
|
|
||||||
# import importlib
|
|
||||||
# for config in configs:
|
|
||||||
# file, ext = os.path.splitext(os.path.basename(config))
|
|
||||||
# if ext != ".py" or file[0] == "_":
|
|
||||||
# continue
|
|
||||||
# modname = "configs."+file
|
|
||||||
# lib = importlib.import_module(modname)
|
|
||||||
# Apps += lib.Apps
|
|
||||||
|
328
main.py
328
main.py
@ -1,24 +1,26 @@
|
|||||||
#!/usr/bin/env python3
|
#!/usr/bin/env python3
|
||||||
import config
|
|
||||||
import subprocess
|
|
||||||
import os
|
|
||||||
import os.path
|
|
||||||
import serial
|
|
||||||
import threading
|
|
||||||
import json
|
import json
|
||||||
import bottle
|
|
||||||
from bottle import route, run, request, post
|
|
||||||
import time
|
|
||||||
import sys
|
|
||||||
import logging
|
import logging
|
||||||
import math
|
import math
|
||||||
import numpy as np
|
import os
|
||||||
import string
|
import string
|
||||||
|
import subprocess
|
||||||
|
import threading
|
||||||
|
import time
|
||||||
from collections import OrderedDict
|
from collections import OrderedDict
|
||||||
|
|
||||||
|
import bottle
|
||||||
|
import numpy as np
|
||||||
import scipy.misc
|
import scipy.misc
|
||||||
|
import serial
|
||||||
|
|
||||||
|
import config
|
||||||
|
|
||||||
logging.basicConfig(filename='pixelserver.log', level=config.LogLevel)
|
logging.basicConfig(filename='pixelserver.log', level=config.LogLevel)
|
||||||
running = True
|
running = True
|
||||||
|
|
||||||
|
|
||||||
########################################################################
|
########################################################################
|
||||||
# Utils #
|
# Utils #
|
||||||
########################################################################
|
########################################################################
|
||||||
@ -26,42 +28,52 @@ class DataSource:
|
|||||||
def __init__(self, initial):
|
def __init__(self, initial):
|
||||||
self.data = initial
|
self.data = initial
|
||||||
self.listeners = []
|
self.listeners = []
|
||||||
|
|
||||||
def getData(self):
|
def getData(self):
|
||||||
return self.data
|
return self.data
|
||||||
|
|
||||||
def addListener(self, listener):
|
def addListener(self, listener):
|
||||||
self.listeners.append(listener)
|
self.listeners.append(listener)
|
||||||
return self
|
return self
|
||||||
|
|
||||||
def pushData(self, data):
|
def pushData(self, data):
|
||||||
self.data = data
|
self.data = data
|
||||||
for listener in self.listeners:
|
for listener in self.listeners:
|
||||||
with listener:
|
with listener:
|
||||||
listener.notify_all()
|
listener.notify_all()
|
||||||
|
|
||||||
|
|
||||||
class WatchDog(threading.Thread):
|
class WatchDog(threading.Thread):
|
||||||
def __init__(self, check, action):
|
def __init__(self, check, action):
|
||||||
super().__init__()
|
super().__init__(daemon=True)
|
||||||
self.check = check
|
self.check = check
|
||||||
self.action = action
|
self.action = action
|
||||||
self.running = True
|
self.running = True
|
||||||
|
|
||||||
def run(self):
|
def run(self):
|
||||||
while running and self.running:
|
while running and self.running:
|
||||||
if self.check():
|
if self.check():
|
||||||
logging.error("Watchdog: Executed")
|
logging.error("Watchdog: Executed")
|
||||||
self.action()
|
self.action()
|
||||||
time.sleep(1)
|
time.sleep(1)
|
||||||
|
|
||||||
def stop(self):
|
def stop(self):
|
||||||
self.running = False
|
self.running = False
|
||||||
|
|
||||||
|
|
||||||
class LogReader(threading.Thread):
|
class LogReader(threading.Thread):
|
||||||
def __init__(self, runner):
|
def __init__(self, runner):
|
||||||
super().__init__()
|
super().__init__(daemon=True)
|
||||||
self.runner = runner
|
self.runner = runner
|
||||||
self.log = ""
|
self.log = ""
|
||||||
self.running = True
|
self.running = True
|
||||||
|
|
||||||
def clear(self):
|
def clear(self):
|
||||||
self.log = ""
|
self.log = ""
|
||||||
|
|
||||||
def getLog(self):
|
def getLog(self):
|
||||||
return self.log
|
return self.log
|
||||||
|
|
||||||
def run(self):
|
def run(self):
|
||||||
logging.info("LogReader started")
|
logging.info("LogReader started")
|
||||||
while running and self.running:
|
while running and self.running:
|
||||||
@ -72,35 +84,42 @@ class LogReader(threading.Thread):
|
|||||||
logging.error(str(e))
|
logging.error(str(e))
|
||||||
time.sleep(1)
|
time.sleep(1)
|
||||||
logging.info("LogReader closed")
|
logging.info("LogReader closed")
|
||||||
|
|
||||||
def stop(self):
|
def stop(self):
|
||||||
self.running = False
|
self.running = False
|
||||||
|
|
||||||
|
|
||||||
class Frame:
|
class Frame:
|
||||||
def __init__(self, buffer, channels=3):
|
def __init__(self, buffer, channels=3):
|
||||||
self.buffer = buffer
|
self.buffer = buffer
|
||||||
self.created = time.time()
|
self.created = time.time()
|
||||||
self.channels = channels
|
self.channels = channels
|
||||||
|
|
||||||
def clone(self):
|
def clone(self):
|
||||||
f = Frame(self.buffer+0, self.channels)
|
f = Frame(self.buffer + 0, self.channels)
|
||||||
f.created = self.created
|
f.created = self.created
|
||||||
return f
|
return f
|
||||||
|
|
||||||
|
|
||||||
########################################################################
|
########################################################################
|
||||||
# GUI #
|
# GUI #
|
||||||
########################################################################
|
########################################################################
|
||||||
if config.UseGui:
|
if config.UseGui:
|
||||||
import pygame
|
import pygame
|
||||||
|
|
||||||
|
|
||||||
class Gui(threading.Thread):
|
class Gui(threading.Thread):
|
||||||
def __init__(self, datasource):
|
def __init__(self, datasource):
|
||||||
super().__init__()
|
super().__init__(daemon=True)
|
||||||
self.cv = threading.Condition()
|
self.cv = threading.Condition()
|
||||||
self.datasource = datasource.addListener(self.cv)
|
self.datasource = datasource.addListener(self.cv)
|
||||||
|
|
||||||
def run(self):
|
def run(self):
|
||||||
last_frame = time.time()
|
last_frame = time.time()
|
||||||
logging.info("Starting GUI")
|
logging.info("Starting GUI")
|
||||||
sf = config.GuiScaleFactor
|
sf = config.GuiScaleFactor
|
||||||
screen = pygame.display.set_mode((sf*config.ScreenX, sf*config.ScreenY))
|
pygame.init()
|
||||||
|
screen = pygame.display.set_mode((sf * config.ScreenX, sf * config.ScreenY))
|
||||||
pygame.display.set_caption("Pixelserver - GUI Vis")
|
pygame.display.set_caption("Pixelserver - GUI Vis")
|
||||||
while running:
|
while running:
|
||||||
for event in pygame.event.get():
|
for event in pygame.event.get():
|
||||||
@ -113,35 +132,38 @@ if config.UseGui:
|
|||||||
for x in range(config.ScreenX):
|
for x in range(config.ScreenX):
|
||||||
for y in range(config.ScreenY):
|
for y in range(config.ScreenY):
|
||||||
color = (frame.buffer[y, x, 0], frame.buffer[y, x, 1], frame.buffer[y, x, 2])
|
color = (frame.buffer[y, x, 0], frame.buffer[y, x, 1], frame.buffer[y, x, 2])
|
||||||
pygame.draw.rect(screen, color, pygame.Rect(sf*x, sf*y, sf, sf))
|
pygame.draw.rect(screen, color, pygame.Rect(sf * x, sf * y, sf, sf))
|
||||||
elif frame.channels == 4:
|
elif frame.channels == 4:
|
||||||
for x in range(config.ScreenX):
|
for x in range(config.ScreenX):
|
||||||
for y in range(config.ScreenY):
|
for y in range(config.ScreenY):
|
||||||
w = frame.buffer[y, x, 3]//2
|
w = frame.buffer[y, x, 3] // 2
|
||||||
color = (frame.buffer[y, x, 0]//2+w, frame.buffer[y, x, 1]//2+w, frame.buffer[y, x, 2]//2+w)
|
color = (frame.buffer[y, x, 0] // 2 + w, frame.buffer[y, x, 1] // 2 + w, frame.buffer[y, x, 2] // 2 + w)
|
||||||
pygame.draw.rect(screen, color, pygame.Rect(sf*x, sf*y, sf, sf))
|
pygame.draw.rect(screen, color, pygame.Rect(sf * x, sf * y, sf, sf))
|
||||||
#logging.debug("Time to gui: "+str(time.time()-frame.created))
|
# logging.debug("Time to gui: " + str(time.time() - frame.created))
|
||||||
pygame.display.flip()
|
pygame.display.flip()
|
||||||
if time.time() < last_frame+1/config.GuiFPS:
|
if time.time() < last_frame + 1 / config.GuiFPS:
|
||||||
time.sleep(time.time()-(last_frame+1/config.GuiFPS))
|
time.sleep(max(0.01, time.time() - (last_frame + 1 / config.GuiFPS)))
|
||||||
#time.sleep(0.01)
|
# time.sleep(0.01)
|
||||||
last_frame = time.time()
|
last_frame = time.time()
|
||||||
|
|
||||||
logging.info("Closing GUI")
|
logging.info("Closing GUI")
|
||||||
def join(self):
|
|
||||||
|
def join(self, **kwargs):
|
||||||
with self.cv:
|
with self.cv:
|
||||||
self.cv.notify_all()
|
self.cv.notify_all()
|
||||||
super().join()
|
super().join()
|
||||||
|
|
||||||
|
|
||||||
########################################################################
|
########################################################################
|
||||||
# Serial #
|
# Serial #
|
||||||
########################################################################
|
########################################################################
|
||||||
class SerialWriter(threading.Thread):
|
class SerialWriter(threading.Thread):
|
||||||
def __init__(self, datasource):
|
def __init__(self, datasource):
|
||||||
super().__init__()
|
super().__init__(daemon=True)
|
||||||
self.cv = threading.Condition()
|
self.cv = threading.Condition()
|
||||||
self.datasource = datasource.addListener(self.cv)
|
self.datasource = datasource.addListener(self.cv)
|
||||||
self.updateGamma = False
|
self.updateGamma = False
|
||||||
|
|
||||||
def run(self):
|
def run(self):
|
||||||
should_connect = True
|
should_connect = True
|
||||||
ser = None
|
ser = None
|
||||||
@ -153,17 +175,17 @@ class SerialWriter(threading.Thread):
|
|||||||
should_connect = False
|
should_connect = False
|
||||||
logging.info("Serial Opened")
|
logging.info("Serial Opened")
|
||||||
with self.cv:
|
with self.cv:
|
||||||
self.cv.wait(timeout = 1/30)
|
self.cv.wait(timeout=1 / 30)
|
||||||
frame = self.datasource.getData()
|
frame = self.datasource.getData()
|
||||||
data = frame.buffer.reshape((config.ScreenX*config.ScreenY*frame.channels,)).astype(np.uint8).tobytes()
|
data = frame.buffer.reshape((config.ScreenX * config.ScreenY * frame.channels,)).astype(np.uint8).tobytes()
|
||||||
if self.updateGamma:
|
if self.updateGamma:
|
||||||
buf = bytearray(b"\x00")*4*256
|
buf = bytearray(b"\x00") * 4 * 256
|
||||||
for i in range(256):
|
for i in range(256):
|
||||||
apply = lambda x, g: max(0, min(255, int(math.pow(x/255, g)*255)))
|
apply = lambda x, g: max(0, min(255, int(math.pow(x / 255, g) * 255)))
|
||||||
buf[i] = apply(i, self.r)
|
buf[i] = apply(i, self.r)
|
||||||
buf[i+256] = apply(i, self.g)
|
buf[i + 256] = apply(i, self.g)
|
||||||
buf[i+512] = apply(i, self.b)
|
buf[i + 512] = apply(i, self.b)
|
||||||
buf[i+512+256] = apply(i, self.w)
|
buf[i + 512 + 256] = apply(i, self.w)
|
||||||
ser.write(b"\x02")
|
ser.write(b"\x02")
|
||||||
ser.write(buf)
|
ser.write(buf)
|
||||||
self.updateGamma = False
|
self.updateGamma = False
|
||||||
@ -173,36 +195,37 @@ class SerialWriter(threading.Thread):
|
|||||||
elif frame.channels == 4:
|
elif frame.channels == 4:
|
||||||
ser.write(b"\03")
|
ser.write(b"\03")
|
||||||
ser.write(data)
|
ser.write(data)
|
||||||
logging.debug("Time to gui: "+str(time.time()-frame.created))
|
logging.debug("Time to gui: " + str(time.time() - frame.created))
|
||||||
ser.flush()
|
ser.flush()
|
||||||
except Exception as e:
|
except Exception as e:
|
||||||
if ser != None:
|
if ser is not None:
|
||||||
ser.close()
|
ser.close()
|
||||||
ser = None
|
ser = None
|
||||||
logging.warning("Serial was close because: "+str(e))
|
logging.warning(f"Serial was close because: {e}")
|
||||||
should_connect = True
|
should_connect = True
|
||||||
time.sleep(5)
|
time.sleep(5)
|
||||||
logging.info("Closing SerialWriter")
|
logging.info("Closing SerialWriter")
|
||||||
def join(self):
|
|
||||||
|
def join(self, **kwargs):
|
||||||
with self.cv:
|
with self.cv:
|
||||||
self.cv.notify_all()
|
self.cv.notify_all()
|
||||||
super().join()
|
super().join()
|
||||||
|
|
||||||
def setGamma(self, r, g, b, w):
|
def setGamma(self, r, g, b, w):
|
||||||
with self.cv:
|
with self.cv:
|
||||||
self.r, self.g, self.b, self.w = r, g, b, w
|
self.r, self.g, self.b, self.w = r, g, b, w
|
||||||
self.updateGamma = True
|
self.updateGamma = True
|
||||||
self.cv.notify_all()
|
self.cv.notify_all()
|
||||||
|
|
||||||
|
|
||||||
########################################################################
|
########################################################################
|
||||||
# App #
|
# App #
|
||||||
########################################################################
|
########################################################################
|
||||||
class App(threading.Thread):
|
class App(threading.Thread):
|
||||||
def __init__(self, cmd, param, listener, is_persistent, is_white=False, path="."):
|
def __init__(self, cmd, param, listener, is_persistent, is_white=False, path="."):
|
||||||
super().__init__()
|
super().__init__(daemon=True)
|
||||||
#start app
|
# start app
|
||||||
if type(cmd) != list:
|
args = cmd + [str(config.ScreenX), str(config.ScreenY), param]
|
||||||
cmd = [cmd,]
|
|
||||||
args = cmd+[str(config.ScreenX), str(config.ScreenY), param]
|
|
||||||
self.app = subprocess.Popen(args, stdout=subprocess.PIPE, stderr=subprocess.PIPE, close_fds=True, cwd=path)
|
self.app = subprocess.Popen(args, stdout=subprocess.PIPE, stderr=subprocess.PIPE, close_fds=True, cwd=path)
|
||||||
self.last_update = time.time()
|
self.last_update = time.time()
|
||||||
self.cv = threading.Condition()
|
self.cv = threading.Condition()
|
||||||
@ -215,20 +238,21 @@ class App(threading.Thread):
|
|||||||
self.listener = listener
|
self.listener = listener
|
||||||
self.is_persistent = is_persistent
|
self.is_persistent = is_persistent
|
||||||
self.is_white = is_white
|
self.is_white = is_white
|
||||||
|
|
||||||
def run(self):
|
def run(self):
|
||||||
while running and self.running and self.alive():
|
while running and self.running and self.alive():
|
||||||
oshandle = self.app.stdout.fileno()
|
oshandle = self.app.stdout.fileno()
|
||||||
try:
|
try:
|
||||||
bytes = 4 if self.is_white else 3
|
channels = 4 if self.is_white else 3
|
||||||
data = os.read(oshandle, config.ScreenX*config.ScreenY*bytes)
|
data = os.read(oshandle, config.ScreenX * config.ScreenY * channels)
|
||||||
assert len(data) == config.ScreenX*config.ScreenY*bytes
|
assert len(data) == config.ScreenX * config.ScreenY * channels
|
||||||
buffer = np.frombuffer(data, dtype=np.uint8, count=config.ScreenX*config.ScreenY*bytes)
|
buffer = np.frombuffer(data, dtype=np.uint8, count=config.ScreenX * config.ScreenY * channels)
|
||||||
buffer = buffer.reshape((config.ScreenY, config.ScreenX, bytes))
|
buffer = buffer.reshape((config.ScreenY, config.ScreenX, channels))
|
||||||
|
|
||||||
frame = Frame(buffer, channels=bytes)
|
frame = Frame(buffer, channels=channels)
|
||||||
self.last_update = time.time()
|
self.last_update = time.time()
|
||||||
self.datasource.pushData(frame)
|
self.datasource.pushData(frame)
|
||||||
except Exception as e:
|
except:
|
||||||
logging.debug("Exception in App.run")
|
logging.debug("Exception in App.run")
|
||||||
with self.listener:
|
with self.listener:
|
||||||
self.listener.notify_all()
|
self.listener.notify_all()
|
||||||
@ -238,8 +262,10 @@ class App(threading.Thread):
|
|||||||
self.logreader.join()
|
self.logreader.join()
|
||||||
self.app.wait()
|
self.app.wait()
|
||||||
logging.debug("App stopped")
|
logging.debug("App stopped")
|
||||||
|
|
||||||
def alive(self):
|
def alive(self):
|
||||||
return self.app.poll() == None
|
return self.app.poll() is None
|
||||||
|
|
||||||
def stop(self):
|
def stop(self):
|
||||||
self.running = False
|
self.running = False
|
||||||
self.app.kill()
|
self.app.kill()
|
||||||
@ -249,20 +275,24 @@ class App(threading.Thread):
|
|||||||
self.logreader.stop()
|
self.logreader.stop()
|
||||||
self.app.wait()
|
self.app.wait()
|
||||||
logging.debug("App stopped")
|
logging.debug("App stopped")
|
||||||
|
|
||||||
def getLog(self):
|
def getLog(self):
|
||||||
return self.logreader.getLog()
|
return self.logreader.getLog()
|
||||||
|
|
||||||
def terminateApp(self):
|
def terminateApp(self):
|
||||||
logging.error("Terminate app!")
|
logging.error("Terminate app!")
|
||||||
self.stop()
|
self.stop()
|
||||||
|
|
||||||
def isAppTimedOut(self):
|
def isAppTimedOut(self):
|
||||||
return time.time()-self.last_update > config.NoDataTimeout
|
return time.time() - self.last_update > config.NoDataTimeout
|
||||||
|
|
||||||
|
|
||||||
########################################################################
|
########################################################################
|
||||||
# Main #
|
# Main #
|
||||||
########################################################################
|
########################################################################
|
||||||
class AppRunner(threading.Thread):
|
class AppRunner(threading.Thread):
|
||||||
def __init__(self):
|
def __init__(self):
|
||||||
super().__init__()
|
super().__init__(daemon=True)
|
||||||
self.last_crashlog = ""
|
self.last_crashlog = ""
|
||||||
self.currentApp = -1
|
self.currentApp = -1
|
||||||
self.requestedApp = 0
|
self.requestedApp = 0
|
||||||
@ -274,137 +304,159 @@ class AppRunner(threading.Thread):
|
|||||||
self.serial.start()
|
self.serial.start()
|
||||||
self.persistent_apps = {}
|
self.persistent_apps = {}
|
||||||
self.filters = OrderedDict()
|
self.filters = OrderedDict()
|
||||||
#start persistent apps
|
# start persistent apps
|
||||||
for app, i in zip(config.Apps, range(len(config.Apps))):
|
for i, app in enumerate(config.Apps):
|
||||||
if app["persistent"]:
|
if app.persistent:
|
||||||
self.startApp(i)
|
self.startApp(i)
|
||||||
if config.UseGui:
|
if config.UseGui:
|
||||||
self.gui = Gui(self.datasource)
|
self.gui = Gui(self.datasource)
|
||||||
self.gui.start()
|
self.gui.start()
|
||||||
|
|
||||||
def requestApp(self, app, param=""):
|
def requestApp(self, app, param=""):
|
||||||
with self.cv:
|
with self.cv:
|
||||||
self.requestedApp = app
|
self.requestedApp = app
|
||||||
self.param = param
|
self.param = param
|
||||||
self.cv.notify_all()
|
self.cv.notify_all()
|
||||||
logging.info("Requesting app: "+str(app))
|
logging.info("Requesting app: " + str(app))
|
||||||
|
|
||||||
def startApp(self, i, param=""):
|
def startApp(self, i, param=""):
|
||||||
app = config.Apps[i]
|
app = config.Apps[i]
|
||||||
newapp = App(app["cmd"], param, self.cv, is_persistent=app["persistent"], is_white=app["white"], path=app["path"])
|
newapp = App(app.cmd, param, self.cv, is_persistent=app.persistent, is_white=app.white, path=app.path)
|
||||||
newapp.datasource.addListener(self.cv)
|
newapp.datasource.addListener(self.cv)
|
||||||
newapp.start()
|
newapp.start()
|
||||||
if app["persistent"]:
|
if app.persistent:
|
||||||
self.persistent_apps[self.currentApp] = newapp
|
self.persistent_apps[self.currentApp] = newapp
|
||||||
return newapp
|
return newapp
|
||||||
|
|
||||||
def updateApp(self):
|
def updateApp(self):
|
||||||
try:
|
try:
|
||||||
if self.app != None and not self.app.is_persistent:
|
if self.app is not None and not self.app.is_persistent:
|
||||||
self.app.stop()
|
self.app.stop()
|
||||||
self.currentApp = self.requestedApp
|
self.currentApp = self.requestedApp
|
||||||
if (self.currentApp in self.persistent_apps.keys()
|
if self.currentApp in self.persistent_apps.keys() and self.persistent_apps[self.currentApp].alive():
|
||||||
and self.persistent_apps[self.currentApp].alive()):
|
|
||||||
self.app = self.persistent_apps[self.currentApp]
|
self.app = self.persistent_apps[self.currentApp]
|
||||||
else:
|
else:
|
||||||
self.app = self.startApp(self.requestedApp, self.param)
|
self.app = self.startApp(self.requestedApp, self.param)
|
||||||
except FileNotFoundError as e:
|
except FileNotFoundError as e:
|
||||||
print(e)
|
print(e)
|
||||||
|
|
||||||
def run(self):
|
def run(self):
|
||||||
logging.info("Starting Apprunner")
|
logging.info("Starting Apprunner")
|
||||||
while running:
|
while running:
|
||||||
with self.cv:
|
with self.cv:
|
||||||
if self.app == None or not self.app.alive():
|
if self.app is None or not self.app.alive():
|
||||||
if self.app != None:
|
if self.app is not None:
|
||||||
self.last_crashlog = self.app.getLog()
|
self.last_crashlog = self.app.getLog()
|
||||||
self.requestedApp = 0
|
self.requestedApp = 0
|
||||||
if self.requestedApp != None:
|
if self.requestedApp is not None:
|
||||||
self.updateApp()
|
self.updateApp()
|
||||||
self.requestedApp = None
|
self.requestedApp = None
|
||||||
|
|
||||||
|
if self.app is not None:
|
||||||
frame = self.app.datasource.getData().clone()
|
frame = self.app.datasource.getData().clone()
|
||||||
#logging.debug("Runner in time: "+str(time.time()-frame.created))
|
# logging.debug("Runner in time: " + str(time.time() - frame.created))
|
||||||
for _, f in self.filters.items():
|
for _, f in self.filters.items():
|
||||||
frame.buffer = f(frame.buffer)
|
frame.buffer = f(frame.buffer)
|
||||||
#logging.debug("Runner out time: "+str(time.time()-frame.created))
|
# logging.debug("Runner out time: " + str(time.time() - frame.created))
|
||||||
self.datasource.pushData(frame)
|
self.datasource.pushData(frame)
|
||||||
self.cv.wait()
|
self.cv.wait()
|
||||||
self.serial.join()
|
self.serial.join()
|
||||||
if config.UseGui:
|
if config.UseGui:
|
||||||
self.gui.join()
|
self.gui.join()
|
||||||
logging.info("Close Apprunner")
|
logging.info("Close Apprunner")
|
||||||
|
|
||||||
def getLog(self):
|
def getLog(self):
|
||||||
if self.app == None:
|
if self.app is None:
|
||||||
return ""
|
return ""
|
||||||
return self.app.getLog()
|
return self.app.getLog()
|
||||||
|
|
||||||
def setGamma(self, r, g, b, w):
|
def setGamma(self, r, g, b, w):
|
||||||
self.serial.setGamma(r, g, b, w)
|
self.serial.setGamma(r, g, b, w)
|
||||||
|
|
||||||
def setFilter(self, name, filter):
|
def setFilter(self, name, filter):
|
||||||
self.filters[name] = filter
|
self.filters[name] = filter
|
||||||
|
|
||||||
def removeFilter(self, name):
|
def removeFilter(self, name):
|
||||||
if name in self.filters.keys():
|
if name in self.filters.keys():
|
||||||
del self.filters[name]
|
del self.filters[name]
|
||||||
|
|
||||||
|
|
||||||
########################################################################
|
########################################################################
|
||||||
# Filter Api #
|
# Filter Api #
|
||||||
########################################################################
|
########################################################################
|
||||||
def MakeBrightnessFilter(intensity):
|
def MakeBrightnessFilter(intensity):
|
||||||
def filter(img):
|
def filter(img):
|
||||||
return (img*intensity).astype(np.uint8)
|
return (img * intensity).astype(np.uint8)
|
||||||
|
|
||||||
return filter
|
return filter
|
||||||
|
|
||||||
|
|
||||||
def FlipXFilter(intensity):
|
def FlipXFilter(intensity):
|
||||||
return intensity[:,::-1,:]
|
return intensity[:, ::-1, :]
|
||||||
|
|
||||||
|
|
||||||
def FlipYFilter(intensity):
|
def FlipYFilter(intensity):
|
||||||
return intensity[::-1,:,:]
|
return intensity[::-1, :, :]
|
||||||
|
|
||||||
|
|
||||||
def MakeBrightnessImageFilter(name):
|
def MakeBrightnessImageFilter(name):
|
||||||
img = scipy.misc.imread("filter/"+name+".png", flatten=True)/255
|
img = scipy.misc.imread("filter/" + name + ".png", flatten=True) / 255
|
||||||
#img = np.transpose(img)
|
|
||||||
|
# img = np.transpose(img)
|
||||||
def filter(intensity):
|
def filter(intensity):
|
||||||
intensity = intensity.astype(float)
|
intensity = intensity.astype(float)
|
||||||
for i in range(intensity.shape[2]):
|
for i in range(intensity.shape[2]):
|
||||||
intensity[:,:,i] *= img
|
intensity[:, :, i] *= img
|
||||||
return intensity.astype(np.uint8)
|
return intensity.astype(np.uint8)
|
||||||
|
|
||||||
return filter
|
return filter
|
||||||
|
|
||||||
def strings(str):
|
|
||||||
allowed_chars = string.ascii_letters+string.digits+"+-*/()."
|
def strings(s):
|
||||||
|
allowed_chars = string.ascii_letters + string.digits + "+-*/()."
|
||||||
i = 0
|
i = 0
|
||||||
outlist = []
|
outlist = []
|
||||||
while i != len(str):
|
while i != len(s):
|
||||||
if str[i] not in allowed_chars:
|
if s[i] not in allowed_chars:
|
||||||
raise Exception("Unexpected char "+str[i])
|
raise Exception("Unexpected char " + s[i])
|
||||||
if str[i] not in string.ascii_letters:
|
if s[i] not in string.ascii_letters:
|
||||||
i+=1
|
i += 1
|
||||||
continue
|
continue
|
||||||
out = ""
|
out = ""
|
||||||
while i != len(str) and str[i] in string.ascii_letters+string.digits:
|
while i != len(s) and s[i] in string.ascii_letters + string.digits:
|
||||||
out += str[i]
|
out += s[i]
|
||||||
i+=1
|
i += 1
|
||||||
outlist.append(out)
|
outlist.append(out)
|
||||||
return outlist
|
return outlist
|
||||||
|
|
||||||
|
|
||||||
def eval_safer(expr, x, y, t):
|
def eval_safer(expr, x, y, t):
|
||||||
symbols = {"x": x, "y": y, "t": t,
|
symbols = {"x": x, "y": y, "t": t,
|
||||||
"sin": np.sin, "cos": np.cos, "exp": np.exp, "tan": np.tan}
|
"sin": np.sin, "cos": np.cos, "exp": np.exp, "tan": np.tan}
|
||||||
strs = strings(expr)
|
strs = strings(expr)
|
||||||
for s in strs:
|
for s in strs:
|
||||||
if s not in symbols.keys():
|
if s not in symbols.keys():
|
||||||
raise Exception("unexpected symbol: "+s)
|
raise Exception("unexpected symbol: " + s)
|
||||||
return eval(expr, {}, symbols)
|
return eval(expr, {}, symbols)
|
||||||
|
|
||||||
|
|
||||||
def MakeBrightnessExprFilter(expr):
|
def MakeBrightnessExprFilter(expr):
|
||||||
t0 = time.time()
|
t0 = time.time()
|
||||||
x, y = np.meshgrid(np.arange(config.ScreenX), np.arange(config.ScreenY))
|
x, y = np.meshgrid(np.arange(config.ScreenX), np.arange(config.ScreenY))
|
||||||
eval_safer(expr, 0, 0, 0)
|
eval_safer(expr, 0, 0, 0)
|
||||||
|
|
||||||
def filter(intensity):
|
def filter(intensity):
|
||||||
t = time.time()-t0
|
t = time.time() - t0
|
||||||
intensity = intensity.astype(float)
|
intensity = intensity.astype(float)
|
||||||
filter = 0*x+eval_safer(expr, x, y, t)
|
filter = 0 * x + eval_safer(expr, x, y, t)
|
||||||
filter = np.clip(np.nan_to_num(filter), 0, 1)
|
filter = np.clip(np.nan_to_num(filter), 0, 1)
|
||||||
for i in range(intensity.shape[2]):
|
for i in range(intensity.shape[2]):
|
||||||
intensity[:,:,i] *= filter
|
intensity[:, :, i] *= filter
|
||||||
return intensity.astype(np.uint8)
|
return intensity.astype(np.uint8)
|
||||||
|
|
||||||
return filter
|
return filter
|
||||||
|
|
||||||
|
|
||||||
########################################################################
|
########################################################################
|
||||||
# Web Api #
|
# Web Api #
|
||||||
########################################################################
|
########################################################################
|
||||||
@ -412,63 +464,74 @@ def MakeBrightnessExprFilter(expr):
|
|||||||
def enable_cors_generic_route():
|
def enable_cors_generic_route():
|
||||||
add_cors_headers()
|
add_cors_headers()
|
||||||
|
|
||||||
|
|
||||||
@bottle.hook('after_request')
|
@bottle.hook('after_request')
|
||||||
def enable_cors_after_request_hook():
|
def enable_cors_after_request_hook():
|
||||||
add_cors_headers()
|
add_cors_headers()
|
||||||
|
|
||||||
|
|
||||||
def add_cors_headers():
|
def add_cors_headers():
|
||||||
bottle.response.headers['Access-Control-Allow-Origin'] = '*'
|
bottle.response.headers['Access-Control-Allow-Origin'] = '*'
|
||||||
bottle.response.headers['Access-Control-Allow-Methods'] = \
|
bottle.response.headers['Access-Control-Allow-Methods'] = 'GET, POST, PUT, OPTIONS'
|
||||||
'GET, POST, PUT, OPTIONS'
|
bottle.response.headers['Access-Control-Allow-Headers'] = 'Origin, Accept, Content-Type, X-Requested-With, X-CSRF-Token'
|
||||||
bottle.response.headers['Access-Control-Allow-Headers'] = \
|
|
||||||
'Origin, Accept, Content-Type, X-Requested-With, X-CSRF-Token'
|
|
||||||
|
|
||||||
def startApp(name, param=""):
|
def startApp(name, param=""):
|
||||||
for i in range(len(config.Apps)):
|
for i, app in enumerate(config.Apps):
|
||||||
if config.Apps[i]["name"] == name:
|
if app.name == name:
|
||||||
runner.requestApp(i, param)
|
runner.requestApp(i, param)
|
||||||
return "ok"
|
return "ok"
|
||||||
return "not_found"
|
return "not_found"
|
||||||
|
|
||||||
@route("/apps/list")
|
|
||||||
def apps_list():
|
|
||||||
s = []
|
|
||||||
for app in config.Apps:
|
|
||||||
s.append({"name": app["name"],
|
|
||||||
"guiname": app["guiname"],
|
|
||||||
"persistent": app["persistent"]})
|
|
||||||
return json.dumps(s)
|
|
||||||
|
|
||||||
@route("/apps/start/<name>")
|
@bottle.route("/apps/list")
|
||||||
|
def apps_list():
|
||||||
|
return json.dumps([
|
||||||
|
{
|
||||||
|
"name": app.name,
|
||||||
|
"guiname": app.guiname,
|
||||||
|
"persistent": app.persistent,
|
||||||
|
} for app in config.Apps
|
||||||
|
])
|
||||||
|
|
||||||
|
|
||||||
|
@bottle.route("/apps/start/<name>")
|
||||||
def apps_start_param(name):
|
def apps_start_param(name):
|
||||||
return startApp(name)
|
return startApp(name)
|
||||||
|
|
||||||
@post("/apps/start/<name>")
|
|
||||||
|
@bottle.post("/apps/start/<name>")
|
||||||
def apps_start_post(name):
|
def apps_start_post(name):
|
||||||
param = request.forms.get('param')
|
param = bottle.request.forms.get('param')
|
||||||
return startApp(name, param)
|
return startApp(name, param)
|
||||||
|
|
||||||
@route("/apps/start/<name>/<param>")
|
|
||||||
|
@bottle.route("/apps/start/<name>/<param>")
|
||||||
def apps_start(name, param):
|
def apps_start(name, param):
|
||||||
return startApp(name, param)
|
return startApp(name, param)
|
||||||
|
|
||||||
@route("/apps/log")
|
|
||||||
|
@bottle.route("/apps/log")
|
||||||
def apps_log():
|
def apps_log():
|
||||||
return runner.getLog()
|
return runner.getLog()
|
||||||
|
|
||||||
@route("/apps/crashlog")
|
|
||||||
|
@bottle.route("/apps/crashlog")
|
||||||
def apps_log():
|
def apps_log():
|
||||||
return runner.last_crashlog
|
return runner.last_crashlog
|
||||||
|
|
||||||
@route("/apps/running")
|
|
||||||
def apps_running():
|
|
||||||
return config.Apps[runner.currentApp]["name"]
|
|
||||||
|
|
||||||
@route("/")
|
@bottle.route("/apps/running")
|
||||||
|
def apps_running():
|
||||||
|
return config.Apps[runner.currentApp].name
|
||||||
|
|
||||||
|
|
||||||
|
@bottle.route("/")
|
||||||
def index():
|
def index():
|
||||||
return bottle.static_file("index.html", root='html')
|
return bottle.static_file("index.html", root='html')
|
||||||
|
|
||||||
@route("/setgamma/<r>/<g>/<b>/<w>")
|
|
||||||
|
@bottle.route("/setgamma/<r>/<g>/<b>/<w>")
|
||||||
def setGamma(r, g, b, w):
|
def setGamma(r, g, b, w):
|
||||||
r = float(r)
|
r = float(r)
|
||||||
g = float(g)
|
g = float(g)
|
||||||
@ -477,15 +540,17 @@ def setGamma(r, g, b, w):
|
|||||||
runner.setGamma(r, g, b, w)
|
runner.setGamma(r, g, b, w)
|
||||||
return "ok"
|
return "ok"
|
||||||
|
|
||||||
@route("/setbrightness/<i>")
|
|
||||||
|
@bottle.route("/setbrightness/<i>")
|
||||||
def setIntensity(i):
|
def setIntensity(i):
|
||||||
i = float(i)
|
i = float(i)
|
||||||
if i < 0 or i > 1:
|
if not 0 <= i <= 1:
|
||||||
return "bad_value"
|
return "bad_value"
|
||||||
runner.setFilter("0_intensity", MakeBrightnessFilter(i))
|
runner.setFilter("0_intensity", MakeBrightnessFilter(i))
|
||||||
return "ok"
|
return "ok"
|
||||||
|
|
||||||
@route("/filter/flipx/<do>")
|
|
||||||
|
@bottle.route("/filter/flipx/<do>")
|
||||||
def flipx(do):
|
def flipx(do):
|
||||||
if do == "true":
|
if do == "true":
|
||||||
runner.setFilter("1_flipx", FlipXFilter)
|
runner.setFilter("1_flipx", FlipXFilter)
|
||||||
@ -493,7 +558,8 @@ def flipx(do):
|
|||||||
runner.removeFilter("1_flipx")
|
runner.removeFilter("1_flipx")
|
||||||
return "ok"
|
return "ok"
|
||||||
|
|
||||||
@route("/filter/flipy/<do>")
|
|
||||||
|
@bottle.route("/filter/flipy/<do>")
|
||||||
def flipy(do):
|
def flipy(do):
|
||||||
if do == "true":
|
if do == "true":
|
||||||
runner.setFilter("1_flipy", FlipYFilter)
|
runner.setFilter("1_flipy", FlipYFilter)
|
||||||
@ -501,16 +567,19 @@ def flipy(do):
|
|||||||
runner.removeFilter("1_flipy")
|
runner.removeFilter("1_flipy")
|
||||||
return "ok"
|
return "ok"
|
||||||
|
|
||||||
@route("/filter/img/<name>")
|
|
||||||
|
@bottle.route("/filter/img/<name>")
|
||||||
def setfilter(name):
|
def setfilter(name):
|
||||||
if name == "none":
|
if name == "none":
|
||||||
runner.removeFilter("3_imgfilter")
|
runner.removeFilter("3_imgfilter")
|
||||||
else:
|
else:
|
||||||
runner.setFilter("3_imgfilter", MakeBrightnessImageFilter(name))
|
runner.setFilter("3_imgfilter", MakeBrightnessImageFilter(name))
|
||||||
return "ok"
|
return "ok"
|
||||||
@post("/filter/expr/")
|
|
||||||
|
|
||||||
|
@bottle.post("/filter/expr/")
|
||||||
def filter_expr():
|
def filter_expr():
|
||||||
expr = request.forms.get('expr')
|
expr = bottle.request.forms.get('expr')
|
||||||
if expr == "" or expr == "none":
|
if expr == "" or expr == "none":
|
||||||
runner.removeFilter("5_brightnessfunction")
|
runner.removeFilter("5_brightnessfunction")
|
||||||
else:
|
else:
|
||||||
@ -521,28 +590,11 @@ def filter_expr():
|
|||||||
########################################################################
|
########################################################################
|
||||||
# Startup #
|
# Startup #
|
||||||
########################################################################
|
########################################################################
|
||||||
#normalize config
|
|
||||||
for app in config.Apps:
|
|
||||||
if "persistent" not in app.keys():
|
|
||||||
app["persistent"] = False
|
|
||||||
if "guiname" not in app.keys():
|
|
||||||
app["guiname"] = app["name"]
|
|
||||||
if "white" not in app.keys():
|
|
||||||
app["white"] = False
|
|
||||||
if "path" not in app.keys():
|
|
||||||
app["path"] = "."
|
|
||||||
cmd = app["cmd"]
|
|
||||||
#remove non existing apps
|
|
||||||
#if type(cmd) == str and not os.path.isfile(cmd):
|
|
||||||
#config.Apps.remove(app)
|
|
||||||
#logging.warning("Removed app "+app["name"])
|
|
||||||
|
|
||||||
|
|
||||||
runner = AppRunner()
|
runner = AppRunner()
|
||||||
runner.start()
|
runner.start()
|
||||||
|
|
||||||
#runner.setFilter("5_crazy", MakeBrightnessExprFilter("0.5+0.25*sin(x/3)/x"))
|
# runner.setFilter("5_crazy", MakeBrightnessExprFilter("0.5+0.25*sin(x/3)/x"))
|
||||||
run(host=config.WebHost, port=config.WebPort)
|
bottle.run(host=config.WebHost, port=config.WebPort)
|
||||||
|
|
||||||
########################################################################
|
########################################################################
|
||||||
# Shutdown #
|
# Shutdown #
|
||||||
|
Loading…
Reference in New Issue
Block a user