Cleaner code
This commit is contained in:
parent
bc1d3312a8
commit
f200a954b1
181
main.py
181
main.py
@ -1,4 +1,4 @@
|
|||||||
|
#!/usr/bin/env python3
|
||||||
import config
|
import config
|
||||||
import subprocess
|
import subprocess
|
||||||
import os
|
import os
|
||||||
@ -14,11 +14,13 @@ import signal
|
|||||||
import logging
|
import logging
|
||||||
import math
|
import math
|
||||||
|
|
||||||
logging.basicConfig(filename='pixelserver.log',level=config.LogLevel)
|
logging.basicConfig(filename='pixelserver.log', level=config.LogLevel)
|
||||||
|
|
||||||
running = True
|
running = True
|
||||||
|
|
||||||
|
########################################################################
|
||||||
|
# Utils #
|
||||||
|
########################################################################
|
||||||
class DataSource:
|
class DataSource:
|
||||||
def __init__(self, initial):
|
def __init__(self, initial):
|
||||||
self.data = initial
|
self.data = initial
|
||||||
@ -33,6 +35,47 @@ class DataSource:
|
|||||||
with listener:
|
with listener:
|
||||||
listener.notify_all()
|
listener.notify_all()
|
||||||
|
|
||||||
|
class WatchDog(threading.Thread):
|
||||||
|
def __init__(self, check, action):
|
||||||
|
super().__init__()
|
||||||
|
self.check = check
|
||||||
|
self.action = action
|
||||||
|
self.running = True
|
||||||
|
def run(self):
|
||||||
|
while running and self.running:
|
||||||
|
if self.check():
|
||||||
|
logging.error("Watchdog: Executed")
|
||||||
|
self.action()
|
||||||
|
time.sleep(1)
|
||||||
|
def stop(self):
|
||||||
|
self.running = False
|
||||||
|
|
||||||
|
class LogReader(threading.Thread):
|
||||||
|
def __init__(self, runner):
|
||||||
|
super().__init__()
|
||||||
|
self.runner = runner
|
||||||
|
self.log = ""
|
||||||
|
self.running = True
|
||||||
|
def clear(self):
|
||||||
|
self.log = ""
|
||||||
|
def getLog(self):
|
||||||
|
return self.log
|
||||||
|
def run(self):
|
||||||
|
logging.info("LogReader started")
|
||||||
|
while running and self.running:
|
||||||
|
try:
|
||||||
|
self.log += self.runner.app.stderr.read(1).decode("utf-8")
|
||||||
|
except Exception as e:
|
||||||
|
print(e)
|
||||||
|
logging.error(str(e))
|
||||||
|
time.sleep(1)
|
||||||
|
logging.info("LogReader closed")
|
||||||
|
def stop(self):
|
||||||
|
self.running = False
|
||||||
|
|
||||||
|
########################################################################
|
||||||
|
# GUI #
|
||||||
|
########################################################################
|
||||||
if config.UseGui:
|
if config.UseGui:
|
||||||
import pygame
|
import pygame
|
||||||
|
|
||||||
@ -42,7 +85,6 @@ if config.UseGui:
|
|||||||
self.datasource = datasource
|
self.datasource = datasource
|
||||||
self.cv = threading.Condition()
|
self.cv = threading.Condition()
|
||||||
self.datasource.addListener(self.cv)
|
self.datasource.addListener(self.cv)
|
||||||
|
|
||||||
def run(self):
|
def run(self):
|
||||||
global running
|
global running
|
||||||
logging.info("Starting GUI")
|
logging.info("Starting GUI")
|
||||||
@ -63,10 +105,8 @@ if config.UseGui:
|
|||||||
r = (data[i*3+0])
|
r = (data[i*3+0])
|
||||||
g = (data[i*3+1])
|
g = (data[i*3+1])
|
||||||
b = (data[i*3+2])
|
b = (data[i*3+2])
|
||||||
|
|
||||||
pygame.draw.rect(screen, (r, g, b), pygame.Rect(sf*x, sf*y, sf, sf))
|
pygame.draw.rect(screen, (r, g, b), pygame.Rect(sf*x, sf*y, sf, sf))
|
||||||
except:
|
except:
|
||||||
pass
|
|
||||||
raise
|
raise
|
||||||
pygame.display.flip()
|
pygame.display.flip()
|
||||||
logging.info("Closing GUI")
|
logging.info("Closing GUI")
|
||||||
@ -75,6 +115,9 @@ if config.UseGui:
|
|||||||
self.cv.notify_all()
|
self.cv.notify_all()
|
||||||
super().join()
|
super().join()
|
||||||
|
|
||||||
|
########################################################################
|
||||||
|
# Serial #
|
||||||
|
########################################################################
|
||||||
class SerialWriter(threading.Thread):
|
class SerialWriter(threading.Thread):
|
||||||
def __init__(self, datasource):
|
def __init__(self, datasource):
|
||||||
super().__init__()
|
super().__init__()
|
||||||
@ -82,7 +125,6 @@ class SerialWriter(threading.Thread):
|
|||||||
self.datasource = datasource
|
self.datasource = datasource
|
||||||
self.datasource.addListener(self.cv)
|
self.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
|
||||||
@ -124,10 +166,9 @@ class SerialWriter(threading.Thread):
|
|||||||
should_connect = True
|
should_connect = True
|
||||||
time.sleep(5)
|
time.sleep(5)
|
||||||
logging.info("Closing SerialWriter")
|
logging.info("Closing SerialWriter")
|
||||||
def joint(self):
|
def join(self):
|
||||||
self.cv.notify_all()
|
self.cv.notify_all()
|
||||||
super().join()
|
super().join()
|
||||||
|
|
||||||
def setGamma(self, r, g, b):
|
def setGamma(self, r, g, b):
|
||||||
with self.cv:
|
with self.cv:
|
||||||
self.r = r
|
self.r = r
|
||||||
@ -136,46 +177,9 @@ class SerialWriter(threading.Thread):
|
|||||||
self.updateGamma = True
|
self.updateGamma = True
|
||||||
self.cv.notify_all()
|
self.cv.notify_all()
|
||||||
|
|
||||||
class WatchDog(threading.Thread):
|
########################################################################
|
||||||
def __init__(self, check, action):
|
# App #
|
||||||
super().__init__()
|
########################################################################
|
||||||
self.check = check
|
|
||||||
self.action = action
|
|
||||||
self.running = True
|
|
||||||
|
|
||||||
def run(self):
|
|
||||||
while running and self.running:
|
|
||||||
if self.check():
|
|
||||||
logging.error("Watchdog: Executed")
|
|
||||||
self.action()
|
|
||||||
time.sleep(1)
|
|
||||||
def stop(self):
|
|
||||||
self.running = False
|
|
||||||
|
|
||||||
class LogReader(threading.Thread):
|
|
||||||
def __init__(self, runner):
|
|
||||||
super().__init__()
|
|
||||||
self.runner = runner
|
|
||||||
self.log = ""
|
|
||||||
self.running = True
|
|
||||||
def clear(self):
|
|
||||||
self.log = ""
|
|
||||||
|
|
||||||
def getLog(self):
|
|
||||||
return self.log
|
|
||||||
|
|
||||||
def run(self):
|
|
||||||
logging.info("LogReader started")
|
|
||||||
while running and self.running:
|
|
||||||
try:
|
|
||||||
self.log += self.runner.app.stderr.read(1).decode("utf-8")
|
|
||||||
except Exception as e:
|
|
||||||
print(e)
|
|
||||||
time.sleep(1)
|
|
||||||
logging.info("LogReader closed")
|
|
||||||
def stop(self):
|
|
||||||
self.running = False
|
|
||||||
|
|
||||||
class App(threading.Thread):
|
class App(threading.Thread):
|
||||||
def __init__(self, cmd, param, listener, is_persistent):
|
def __init__(self, cmd, param, listener, is_persistent):
|
||||||
super().__init__()
|
super().__init__()
|
||||||
@ -194,7 +198,6 @@ class App(threading.Thread):
|
|||||||
self.running = running
|
self.running = running
|
||||||
self.listener = listener
|
self.listener = listener
|
||||||
self.is_persistent = is_persistent
|
self.is_persistent = is_persistent
|
||||||
|
|
||||||
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()
|
||||||
@ -205,18 +208,14 @@ class App(threading.Thread):
|
|||||||
self.datasource.pushData(data)
|
self.datasource.pushData(data)
|
||||||
except Exception as e:
|
except Exception as e:
|
||||||
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()
|
||||||
self.watchdog.stop()
|
self.watchdog.stop()
|
||||||
self.logreader.stop()
|
self.logreader.stop()
|
||||||
self.watchdog.join()
|
self.watchdog.join()
|
||||||
self.logreader.join()
|
self.logreader.join()
|
||||||
|
|
||||||
|
|
||||||
def alive(self):
|
def alive(self):
|
||||||
return self.app.poll() == None
|
return self.app.poll() == None
|
||||||
|
|
||||||
def stop(self):
|
def stop(self):
|
||||||
self.running = False
|
self.running = False
|
||||||
self.app.kill()
|
self.app.kill()
|
||||||
@ -224,21 +223,19 @@ class App(threading.Thread):
|
|||||||
self.app.stderr.close()
|
self.app.stderr.close()
|
||||||
self.watchdog.stop()
|
self.watchdog.stop()
|
||||||
self.logreader.stop()
|
self.logreader.stop()
|
||||||
|
|
||||||
def getLog(self):
|
def getLog(self):
|
||||||
return self.logreader.getLog()
|
return self.logreader.getLog()
|
||||||
|
|
||||||
def isPersistent(self):
|
def isPersistent(self):
|
||||||
return self.is_persistent
|
return self.is_persistent
|
||||||
|
|
||||||
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 #
|
||||||
|
########################################################################
|
||||||
class AppRunner(threading.Thread):
|
class AppRunner(threading.Thread):
|
||||||
def __init__(self):
|
def __init__(self):
|
||||||
super().__init__()
|
super().__init__()
|
||||||
@ -258,28 +255,23 @@ class AppRunner(threading.Thread):
|
|||||||
newapp.datasource.addListener(self.cv)
|
newapp.datasource.addListener(self.cv)
|
||||||
newapp.start()
|
newapp.start()
|
||||||
self.persistent_apps[i] = newapp
|
self.persistent_apps[i] = newapp
|
||||||
|
|
||||||
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 updateApp(self):
|
def updateApp(self):
|
||||||
if self.app != None and not self.app.isPersistent():
|
if self.app != None and not self.app.isPersistent():
|
||||||
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():
|
||||||
self.app = self.persistent_apps[self.currentApp]
|
self.app = self.persistent_apps[self.currentApp]
|
||||||
else:
|
else:
|
||||||
persistent = config.Apps[self.requestedApp]["persistent"]
|
persistent = config.Apps[self.requestedApp]["persistent"]
|
||||||
|
|
||||||
logging.info("Starting app "+config.Apps[self.requestedApp]["name"])
|
logging.info("Starting app "+config.Apps[self.requestedApp]["name"])
|
||||||
cmd = config.Apps[self.requestedApp]["cmd"]
|
cmd = config.Apps[self.requestedApp]["cmd"]
|
||||||
logging.debug(str(cmd))
|
logging.debug(str(cmd))
|
||||||
@ -288,7 +280,6 @@ class AppRunner(threading.Thread):
|
|||||||
self.app.start()
|
self.app.start()
|
||||||
if persistent:
|
if persistent:
|
||||||
self.persistent_apps[self.currentApp] = self.app
|
self.persistent_apps[self.currentApp] = self.app
|
||||||
|
|
||||||
def run(self):
|
def run(self):
|
||||||
logging.info("Starting Apprunner")
|
logging.info("Starting Apprunner")
|
||||||
while running:
|
while running:
|
||||||
@ -296,10 +287,8 @@ class AppRunner(threading.Thread):
|
|||||||
if self.app == None or not self.app.alive():
|
if self.app == None or not self.app.alive():
|
||||||
self.requestedApp = 0
|
self.requestedApp = 0
|
||||||
if self.requestedApp != None:
|
if self.requestedApp != None:
|
||||||
|
|
||||||
self.updateApp()
|
self.updateApp()
|
||||||
self.requestedApp = None
|
self.requestedApp = None
|
||||||
|
|
||||||
self.cv.wait()
|
self.cv.wait()
|
||||||
if self.app != None:
|
if self.app != None:
|
||||||
data = self.app.datasource.getData()
|
data = self.app.datasource.getData()
|
||||||
@ -308,7 +297,6 @@ class AppRunner(threading.Thread):
|
|||||||
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 == None:
|
||||||
return ""
|
return ""
|
||||||
@ -316,9 +304,9 @@ class AppRunner(threading.Thread):
|
|||||||
def setGamma(self, r, g, b):
|
def setGamma(self, r, g, b):
|
||||||
self.serial.setGamma(r, g, b)
|
self.serial.setGamma(r, g, b)
|
||||||
|
|
||||||
|
########################################################################
|
||||||
|
# Startup #
|
||||||
|
########################################################################
|
||||||
#normalize config
|
#normalize config
|
||||||
for app in config.Apps:
|
for app in config.Apps:
|
||||||
if "persistent" not in app.keys():
|
if "persistent" not in app.keys():
|
||||||
@ -326,7 +314,7 @@ for app in config.Apps:
|
|||||||
if "guiname" not in app.keys():
|
if "guiname" not in app.keys():
|
||||||
app["guiname"] = app["name"]
|
app["guiname"] = app["name"]
|
||||||
|
|
||||||
#remove unavalible apps
|
#remove non existing apps
|
||||||
for app in config.Apps:
|
for app in config.Apps:
|
||||||
cmd = app["cmd"]
|
cmd = app["cmd"]
|
||||||
if type(cmd) == str and not os.path.isfile(cmd):
|
if type(cmd) == str and not os.path.isfile(cmd):
|
||||||
@ -336,6 +324,9 @@ for app in config.Apps:
|
|||||||
runner = AppRunner()
|
runner = AppRunner()
|
||||||
runner.start()
|
runner.start()
|
||||||
|
|
||||||
|
########################################################################
|
||||||
|
# Web Api #
|
||||||
|
########################################################################
|
||||||
@bottle.route('/<:re:.*>', method='OPTIONS')
|
@bottle.route('/<:re:.*>', method='OPTIONS')
|
||||||
def enable_cors_generic_route():
|
def enable_cors_generic_route():
|
||||||
add_cors_headers()
|
add_cors_headers()
|
||||||
@ -351,6 +342,12 @@ def add_cors_headers():
|
|||||||
bottle.response.headers['Access-Control-Allow-Headers'] = \
|
bottle.response.headers['Access-Control-Allow-Headers'] = \
|
||||||
'Origin, Accept, Content-Type, X-Requested-With, X-CSRF-Token'
|
'Origin, Accept, Content-Type, X-Requested-With, X-CSRF-Token'
|
||||||
|
|
||||||
|
def getAppIdx(name):
|
||||||
|
for i in range(len(config.Apps)):
|
||||||
|
if config.Apps[i]["name"] == name:
|
||||||
|
return i
|
||||||
|
return -1
|
||||||
|
|
||||||
@route("/apps/list")
|
@route("/apps/list")
|
||||||
def apps_list():
|
def apps_list():
|
||||||
s = []
|
s = []
|
||||||
@ -364,30 +361,31 @@ def apps_list():
|
|||||||
|
|
||||||
@route("/apps/start/<name>")
|
@route("/apps/start/<name>")
|
||||||
def apps_start_param(name):
|
def apps_start_param(name):
|
||||||
for i in range(len(config.Apps)):
|
i = getAppIdx(name)
|
||||||
if config.Apps[i]["name"] == name:
|
if i >= 0:
|
||||||
runner.requestApp(i)
|
runner.requestApp(i)
|
||||||
return "ok"
|
return "ok"
|
||||||
return "not_found"
|
else:
|
||||||
|
return "not_found"
|
||||||
|
|
||||||
@post("/apps/start/<name>")
|
@post("/apps/start/<name>")
|
||||||
def apps_start_post(name):
|
def apps_start_post(name):
|
||||||
param = request.forms.get('param')
|
param = request.forms.get('param')
|
||||||
for i in range(len(config.Apps)):
|
i = getAppIdx(name)
|
||||||
if config.Apps[i]["name"] == name:
|
if i >= 0:
|
||||||
runner.requestApp(i, param)
|
runner.requestApp(i, param)
|
||||||
return "ok"
|
return "ok"
|
||||||
return "not_found"
|
else:
|
||||||
|
return "not_found"
|
||||||
|
|
||||||
@route("/apps/start/<name>/<param>")
|
@route("/apps/start/<name>/<param>")
|
||||||
def apps_start(name, param):
|
def apps_start(name, param):
|
||||||
for i in range(len(config.Apps)):
|
i = getAppIdx(name)
|
||||||
|
if i >= 0:
|
||||||
if config.Apps[i]["name"] == name:
|
runner.requestApp(i, param)
|
||||||
runner.requestApp(i, param)
|
return "ok"
|
||||||
return "ok"
|
else:
|
||||||
return "not_found"
|
return "not_found"
|
||||||
|
|
||||||
@route("/apps/log")
|
@route("/apps/log")
|
||||||
def apps_log():
|
def apps_log():
|
||||||
@ -401,7 +399,7 @@ def apps_running():
|
|||||||
@route("/")
|
@route("/")
|
||||||
def index():
|
def index():
|
||||||
return bottle.static_file("index.html", root='html')
|
return bottle.static_file("index.html", root='html')
|
||||||
#return open("html/index.html").read()
|
|
||||||
@route("/setgamma/<r>/<g>/<b>")
|
@route("/setgamma/<r>/<g>/<b>")
|
||||||
def setGamma(r, g, b):
|
def setGamma(r, g, b):
|
||||||
r = float(r)
|
r = float(r)
|
||||||
@ -410,6 +408,9 @@ def setGamma(r, g, b):
|
|||||||
runner.setGamma(r, g, b)
|
runner.setGamma(r, g, b)
|
||||||
return "ok"
|
return "ok"
|
||||||
|
|
||||||
|
########################################################################
|
||||||
|
# Shutdown #
|
||||||
|
########################################################################
|
||||||
run(host=config.WebHost, port=config.WebPort)
|
run(host=config.WebHost, port=config.WebPort)
|
||||||
running = False
|
running = False
|
||||||
runner.join()
|
runner.join()
|
||||||
|
Loading…
Reference in New Issue
Block a user