newUI, python3,...

This commit is contained in:
sam 2020-09-19 14:28:56 +02:00
parent 0bb0049f02
commit e9d3009ffb
551 changed files with 22992 additions and 787437 deletions

448
main.py
View file

@ -1,8 +1,8 @@
#!/usr/bin/python2.7
#!/usr/bin/python3
# -*- coding: utf-8 -*-
# -*- mode: Python -*-
'''
LJ Laser Server v0.8.1
LJ Laser Server v0.8.2
Inspiration for new WebUI icon menu :
https://codepen.io/AlbertFeynman/pen/mjXeMV
@ -11,74 +11,97 @@ Laser server + webUI servers (ws + OSC)
- get point list to draw : /pl/lasernumber
- for report /lstt/lasernumber /lack/lasernumber /cap/lasernumber
- A nice ws debug tool : websocat
- a nice ws debug tool : websocat
- a "plugin" is a generator that send points to LJ. Plugins if they have an open OSC port can be checked and restart if in the same computer.
Todo :
- If no plugin ping is not received, restart the plugin.
- upgrade to python3
All used ports:
8002 OSC incoming
9001 WS communication with WebGUI
9001 Websocket communication with WebGUI
Plugins OSC Ports (see LJ.conf)
'''
#import pdb
print ""
print ""
print "LJ Laser Server"
print "v0.8.2"
print ""
from libs3 import log
print("")
print("")
log.infog("LJ Laser Server")
log.infog("v0.8.2")
print("")
print("-h will display help")
print("")
import redis
import os
ljpath = r'%s' % os.getcwd().replace('\\','/')
from libs import gstt, settings
import sys
#sys.path.append('libs3/')
from libs3 import gstt, settings
gstt.ljpath= ljpath
log.info("Reading " + gstt.ConfigName + " setup file...")
settings.Read()
# Arguments may alter .conf file so import settings first then cli
from libs import cli
from libs3 import cli
settings.Write()
from multiprocessing import Process, Queue, TimeoutError
from multiprocessing import Process, set_start_method
import random, ast
from libs import plugins, tracer, homographyp, commands, font1
from libs3 import plugins
from libs3 import tracer3 as tracer
from libs3 import homographyp, commands, font1
#from webui import build
#import subprocess
import subprocess
import sys
import os
#import midi
from OSC import OSCServer, OSCClient, OSCMessage
from libs3 import OSC3
from websocket_server import WebsocketServer
#import socket
import types, thread, time
import types, _thread, time
r = redis.StrictRedis(host=gstt.LjayServerIP , port=6379, db=0)
# r = redis.StrictRedis(host=gstt.LjayServerIP , port=6379, db=0, password='-+F816Y+-')
args =[0,0]
def dac_process(number, pl):
import sys
from libs3 import gstt
print("Starting dac process", number)
while True:
try:
d = tracer.DAC(number,pl)
d.play_stream()
except Exception as e:
import sys, traceback
if gstt.debug == 2:
print '\n---------------------'
print 'Exception: %s' % e
print '- - - - - - - - - - -'
import sys
import traceback
if gstt.debug > 0:
log.err('\n---------------------')
log.err('Exception: %s' % e)
log.err('- - - - - - - - - - -')
traceback.print_tb(sys.exc_info()[2])
print "\n"
print("\n")
pass
except KeyboardInterrupt:
@ -87,24 +110,24 @@ def dac_process(number, pl):
#
# webUI server
# Servers init variables
#
print "Laser client number :",gstt.SceneNumber
print("Start Scene number :",gstt.SceneNumber)
print("WebUI connect to :", gstt.wwwIP)
serverIP = gstt.LjayServerIP
print "Redis IP :", serverIP
print("Redis IP :", serverIP)
oscserverIP = gstt.oscIPin
print "OSCserver IP :", oscserverIP
print("OSCserver IP :", oscserverIP)
nozoscIP = gstt.nozoscip
print "Nozosc IP :", nozoscIP
print("Nozosc IP :", nozoscIP)
debug = gstt.debug
print "Debug :", debug
lasernumber = gstt.LaserNumber -1
print "Lasers requested :", gstt.LaserNumber
print("Debug :", debug)
# Websocket listening port
@ -115,7 +138,7 @@ wsPORT = 9001
#oscIPin = "192.168.1.10"s
oscserverIPin = serverIP
print "oscserverIPin", oscserverIPin
print("oscserverIPin", oscserverIPin)
oscserverPORTin = 8002
# OSC Client : to send OSC message to an IP port 8001
@ -132,12 +155,29 @@ NozoscPORTout = plugins.Port("nozoid")
planetIPout = nozoscIP
planetPORTout = plugins.Port("planet")
'''
# Bank0 OSC Client : to send OSC message to bank0 inport 8010
bank0IPout = nozoscIP
bank0PORTout = plugins.Port("bank0")
'''
oscserver = OSCServer( (oscserverIPin, oscserverPORTin) )
#
# DACs available checks ?
#
import socket
#retry = 1
#delay = 1
#
# OSC
#
oscserver = OSC3.OSCServer( (oscserverIPin, oscserverPORTin) )
oscserver.timeout = 0
OSCRunning = True
@ -153,8 +193,8 @@ def handler(path, tags, args, source):
oscpath = path.split("/")
if gstt.debug > 0:
print ""
print "OSC handler in main said : path", path," oscpath ", oscpath," args", args
print("")
print("OSC handler in main said : path", path," oscpath ", oscpath," args", args)
if oscpath[1] != "pong":
sendWSall(path + " " + str(args[0]))
@ -172,10 +212,12 @@ def osc_frame():
def PingAll():
print ("Pinging all plugins...")
for plugin in gstt.plugins.keys():
print("pinging", plugin)
if gstt.debug > 0:
print("Pinging all plugins...")
for plugin in list(gstt.plugins.keys()):
if gstt.debug > 0:
print("pinging", plugin)
#sendWSall("/"+ plugin + "/start 0")
plugins.Ping(plugin)
@ -192,49 +234,59 @@ def osc_thread():
osc_frame()
for laserid in range(0,gstt.LaserNumber): # Laser not used -> led is not lit
lstt = r.get('/lstt/'+ str(laserid))
#print "laserid", laserid,"lstt",lstt
if lstt == "0": # Dac IDLE state(0) -> led is blue (3)
lstate = {'0': 'IDLE', '1': 'PREPARE', '2': "PLAYING", '64': "NOCONNECTION ?" }
lstt = r.get('/lstt/'+ str(laserid)).decode('ascii')
#print ("laserid", laserid,"lstt",lstt, type(lstt))
if gstt.debug >1:
print("DAC", laserid, "is in (lstt) :", lstt , lstate[str(lstt)])
if lstt == "0": # Dac IDLE state(0) -> led is blue (3)
sendWSall("/lstt/" + str(laserid) + " 3")
if lstt == "1": # Dac PREPARE state (1) -> led is cyan (2)
if lstt == "1": # Dac PREPARE state (1) -> led is cyan (2)
sendWSall("/lstt/" + str(laserid) + " 2")
if lstt == "2": # Dac PLAYING (2) -> led is green (1)
if lstt == "2": # Dac PLAYING (2) -> led is green (1)
sendWSall("/lstt/" + str(laserid) + " 1")
lack= r.get('/lack/'+str(laserid))
ackstate = {'61': 'ACK', '46': 'FULL', '49': "INVALID", '21': 'STOP', '64': "NOCONNECTION ?", '35': "NOCONNECTION ?" , '97': 'ACK', '70': 'FULL', '73': "INVALID", '33': 'STOP', '100': "NOCONNECTION", '48': "NOCONNECTION", 'a': 'ACK', 'F': 'FULL', 'I': "INVALID", '!': 'STOP', 'd': "NOCONNECTION", '0': "NOCONNECTION"}
lack= r.get('/lack/'+str(laserid)).decode('ascii')
if gstt.debug >1:
print "laserid", laserid, "lack", lack
if lack == 'a': # Dac sent ACK ("a") -> led is green (1)
print("DAC", laserid, "answered (lack):", lack, chr(int(lack)), ackstate[str(lack)])
if chr(int(lack)) == 'a': # Dac sent ACK ("a") -> led is green (1)
sendWSall("/lack/" + str(laserid) +" 1")
if lack == 'F': # Dac sent FULL ("F") -> led is orange (5)
if chr(int(lack)) == 'F': # Dac sent FULL ("F") -> led is orange (5)
sendWSall("/lack/" + str(laserid) +" 5")
if lack == 'I': # Dac sent INVALID ("I") -> led is yellow (4)
if chr(int(lack)) == 'I': # Dac sent INVALID ("I") -> led is yellow (4)
sendWSall("/lack/" + str(laserid)+" 4")
#print lack
if lack == "64" or lack =="35": # no connection to dac -> leds are red (6)
sendWSall("/lack/" + str(laserid) + " 0")
sendWSall("/lstt/" + str(laserid) + " 0")
if lack == "64" or lack =="35": # no connection to dac -> leds are red (6)
sendWSall("/lack/" + str(laserid) + " 6")
sendWSall("/lstt/" + str(laserid) + " 6")
#sendWSall("/lstt/" + str(laserid) + " 0")
sendWSall("/points/" + str(laserid) + " 0")
sendWSall("/points/" + str(laserid) + " 6")
else:
# last number of points sent to etherdream buffer
sendWSall("/points/" + str(laserid) + " " + str(r.get('/cap/'+str(laserid))))
sendWSall("/points/" + str(laserid) + " " + str(r.get('/cap/'+str(laserid)).decode('ascii')))
#print "Sending simu frame from",'/pl/'+str(gstt.SceneNumber)+'/'+str(gstt.Laser)
#print r.get('/pl/'+str(gstt.SceneNumber)+'/'+str(gstt.Laser))
sendWSall("/simul" +" "+ r.get('/pl/'+str(gstt.SceneNumber)+'/'+str(gstt.Laser)))
sendWSall("/simul" +" "+ str(r.get('/pl/'+str(gstt.SceneNumber)+'/'+str(gstt.Laser)).decode('ascii')))
except Exception as e:
import sys, traceback
print '\n---------------------'
print 'Exception: %s' % e
print '- - - - - - - - - - -'
print('\n---------------------')
print('Exception: %s' % e)
print('- - - - - - - - - - -')
traceback.print_tb(sys.exc_info()[2])
print "\n"
print("\n")
#
# Websocket part
@ -244,13 +296,21 @@ def osc_thread():
def new_client(client, wserver):
print("New WS client connected and was given id %d" % client['id'])
sendWSall("/status Hello %d" % client['id'])
sendWSall("/status Hello " + str(client['id']))
for laserid in range(0,gstt.LaserNumber):
sendWSall("/ip/" + str(laserid) + " " + str(gstt.lasersIPS[laserid]))
sendWSall("/kpps/" + str(laserid)+ " " + str(gstt.kpps[laserid]))
sendWSall("/laser"+str(laserid)+"/start 1")
#sendWSall("/laser"+str(laserid)+"/start 1")
sendWSall("/laser "+str(laserid))
#print("/laser "+str(laserid))
sendWSall("/lack/" + str(laserid) + " 6")
#print("/lack/" + str(laserid) + " 6")
sendWSall("/lstt/" + str(laserid) + " 6")
#print("/lstt/" + str(laserid) + " 6")
sendWSall("/points/" + str(laserid) + " 0")
#print("/points/" + str(laserid) + " 0")
if gstt.swapX[laserid] == 1:
sendWSall("/swap/X/" + str(laserid)+ " 1")
@ -270,33 +330,33 @@ def client_left(client, wserver):
# Called for each WS received message.
def message_received(client, wserver, message):
if len(message) > 200:
message = message[:200]+'..'
#if len(message) > 200:
# message = message[:200]+'..'
#if gstt.debug >0:
# print ("")
# print("WS Client(%d) said: %s" % (client['id'], message))
print("")
oscpath = message.split(" ")
#print "WS Client", client['id'], "said :", message, "splitted in an oscpath :", oscpath
if gstt.debug > 0:
print "WS Client", client['id'], "said :", message, "splitted in an oscpath :", oscpath
print("WS Client", client['id'], "said :", message, "splitted in an oscpath :", oscpath)
PingAll()
message4plugin = False
# WS received Message is for a plugin ?
for plugin in gstt.plugins.keys():
for plugin in list(gstt.plugins.keys()):
if oscpath[0].find(plugin) != -1:
message4plugin = True
if plugins.Send(plugin,oscpath):
print "message sent correctly to", plugin
#print(oscpath)
if plugins.Send(plugin, oscpath):
print("plugins sent incoming WS correctly to", plugin)
else:
print"plugin was offline"
print("plugins detected", plugin, "offline.")
# WS received message is an LJ command
@ -307,16 +367,13 @@ def message_received(client, wserver, message):
args[0] = "noargs"
#print "noargs command"
elif len(oscpath) > 1:
args[0] = str(oscpath[1])
#print "arg",oscpath[1]
commands.handler(oscpath[0].split("/"),args)
print ""
# if needed a loop back : WS Client -> server -> WS Client
#sendWSall("ws"+message)
@ -337,116 +394,169 @@ midi.InConfig()
midi.OutConfig()
'''
# Creating a startup point list for each client : 0,1,2,...
# Creating a startup point list for each laser : 0,1,2,...
print ""
for clientid in range(0,gstt.MaxScenes+1):
print "Creating startup point lists for client",clientid,"..."
digit_points = font1.DigitsDots(clientid,65280)
print("")
log.info("Creating startup point lists...")
if r.set("/clientkey","/pl/"+str(gstt.SceneNumber)+"/")==True:
print("sent clientkey : /pl/"+str(gstt.SceneNumber)+"/")
#pdb.set_trace()
for sceneid in range(0,gstt.MaxScenes+1):
print("Scene "+ str(sceneid))
#digit_points = font1.DigitsDots(sceneid,65280)
# Order all lasers to show the laser client number at startup -> tell all 4 laser process to USER PLs
for laserid in range(0,gstt.LaserNumber):
if r.set('/pl/'+str(clientid)+'/'+str(laserid), str(digit_points)) == True:
print "/pl/"+str(clientid)+"/"+str(laserid)+" ", ast.literal_eval(r.get('/pl/'+str(clientid)+'/'+str(laserid)))
digit_points = font1.DigitsDots(laserid,65280)
if r.set('/pl/'+str(sceneid)+'/'+str(laserid), str(digit_points)) == True:
pass
#print( ast.literal_eval(r.get('/pl/'+str(sceneid)+'/'+str(laserid)).decode('ascii')))
#print("/pl/"+str(sceneid)+"/"+str(laserid)+" "+str(ast.literal_eval(r.get('/pl/'+str(sceneid)+'/'+str(laserid)).decode('ascii'))))
r.set('/order/'+str(laserid), 0)
if r.set("/clientkey","/pl/"+str(gstt.SceneNumber)+"/")==True:
print "sent clientkey : /pl/"+str(gstt.SceneNumber)+"/"
#
# Starts one DAC process per requested Laser
#
print ""
print "Etherdream connection check is NOT DISPLAYED"
def fff(name):
print()
print('HELLO', name ) #indent
print()
# Launch one process (a newdacp instance) by etherdream
if __name__ == '__main__':
print ""
dac_worker0= Process(target=dac_process,args=(0,0))
print "Launching Laser 0 Process..."
dac_worker0.start()
# Bug in 3.8.4 MacOS default multiprocessing start method is spawn. Spawn doesn't work properly
set_start_method('fork')
if lasernumber >0:
dac_worker1= Process(target=dac_process,args=(1,0))
print "Launching Laser 1 Process..."
dac_worker1.start()
print("")
if gstt.LaserNumber == -1:
log.infog("Autodetected DACs mode")
commands.DAChecks()
print("dacs", gstt.dacs)
if lasernumber >1:
dac_worker2= Process(target=dac_process,args=(2,0))
print "Launching Laser 2 Process..."
dac_worker2.start()
else:
log.infog("Resquested DACs mode")
if lasernumber >2:
dac_worker3= Process(target=dac_process,args=(3,0))
print "Launching Laser 3 Process..."
dac_worker3.start()
lasernumber = gstt.LaserNumber -1
print("LaserNumber = ", gstt.LaserNumber)
# Main loop do nothing. Maybe do the webui server ?
try:
#while True:
# Websocket startup
wserver = WebsocketServer(wsPORT,host=serverIP)
plugins.Init(wserver)
log.info("Starting "+str(gstt.LaserNumber) + " DACs process...")
# Launch OSC thread listening to oscserver
print ""
print "Launching OSC server..."
print "at", oscserverIPin, "port",str(oscserverPORTin)
print "Will update webUI dac status every second"
oscserver.addMsgHandler( "/noteon", commands.NoteOn )
# Default OSC handler for all OSC incoming message
oscserver.addMsgHandler("default", handler)
thread.start_new_thread(osc_thread, ())
# Launch one process (a newdacp instance) by etherdream
dac_worker0= Process(target=dac_process, args=(0,0,))
dac_worker0.start()
print("Tracer 0 : name", dac_worker0.name , "pid", dac_worker0.pid )
#print wserver
print ""
print "Launching webUI Websocket server..."
print "at", serverIP, "port",wsPORT
wserver.set_fn_new_client(new_client)
wserver.set_fn_client_left(client_left)
wserver.set_fn_message_received(message_received)
print ""
print "Resetting all Homographies.."
for laserid in range(0,gstt.LaserNumber):
homographyp.newEDH(laserid)
print ""
print "WS server running forever..."
wserver.run_forever()
except KeyboardInterrupt:
pass
# Gently stop on CTRL C
finally:
dac_worker0.join()
if lasernumber >0:
dac_worker1.join()
dac_worker1= Process(target=dac_process, args=(1,0,))
print("Tracer 1 : name", dac_worker1.name , "pid", dac_worker1.pid )
dac_worker1.start()
if lasernumber >1:
dac_worker2.join()
dac_worker2= Process(target=dac_process, args=(2,0,))
dac_worker2.start()
print("Tracer 2 : name", dac_worker2.name , "pid", dac_worker2.pid )
if lasernumber >2:
dac_worker3.join()
dac_worker3= Process(target=dac_process, args=(3,0,))
print("Tracer 3 : name", dac_worker3.name , "pid", dac_worker3.pid )
dac_worker3.start()
print("")
#def Run():
#
# Main loop do nothing. Maybe do the webui server ?
#
try:
#while True:
# Websocket startup
wserver = WebsocketServer(wsPORT,host=serverIP)
plugins.Init(wserver)
log.info("Starting servers...")
# Launch OSC thread listening to oscserver
print("Launching OSC server...")
print("at", oscserverIPin, "port",str(oscserverPORTin))
#print("Will update webUI dac status every second")
oscserver.addMsgHandler( "/noteon", commands.NoteOn)
oscserver.addMsgHandler( "/scim", commands.Scim)
oscserver.addMsgHandler( "/line1", commands.Line1)
oscserver.addMsgHandler( "/forwardui", commands.ForwardUI)
# Default OSC handler for all OSC incoming message
oscserver.addMsgHandler("default", handler)
_thread.start_new_thread(osc_thread, ())
#print wserver
print("Launching webUI Websocket server...")
print("at", serverIP, "port",wsPORT)
wserver.set_fn_new_client(new_client)
wserver.set_fn_client_left(client_left)
wserver.set_fn_message_received(message_received)
print("")
log.info("Resetting all Homographies...")
for laserid in range(0,gstt.LaserNumber):
homographyp.newEDH(laserid)
# plugins autostart
print("")
log.info("Plugins startup...")
if gstt.autostart != "":
for pluginname in gstt.autostart.split(","):
print("Autostarting", pluginname, "...")
plugins.Start(pluginname)
print("")
log.infog("LJ server running...")
wserver.run_forever()
except Exception:
log.err("Exception")
traceback.print_exc()
except Restart(moment):
print("Autokill asked at", moment)
# Gently stop on CTRL C
finally:
for laserid in range(0,lasernumber+1):
print "Laser",laserid,"feedbacks reset."
r.set('/lack/'+str(laserid),64)
r.set('/lstt/'+str(laserid),64)
r.set('/cap/'+str(laserid),0)
print "Fin de LJ."
'''
Some code previously used, for reference :
random_points = [(300.0+random.randint(-100, 100), 200.0+random.randint(-100, 100), 0), (500.0+random.randint(-100, 100), 200.0+random.randint(-100, 100), 65280), (500.0+random.randint(-100, 100), 400.0+random.randint(-100, 100), 65280), (300.0+random.randint(-100, 100), 400.0+random.randint(-100, 100), 65280), (300.0+random.randint(-100, 100), 200.0+random.randint(-100, 100), 65280)]
'''
dac_worker0.join()
if lasernumber >0:
dac_worker1.join()
if lasernumber >1:
dac_worker2.join()
if lasernumber >2:
dac_worker3.join()
for laserid in range(0,lasernumber+1):
print("Laser",laserid,"feedbacks resetting...")
r.set('/lack/'+str(laserid),64)
r.set('/lstt/'+str(laserid),64)
r.set('/cap/'+str(laserid),0)
print("Fin de LJ.")
#if __name__ == "__main__":
# Run()
'''
Some code previously used, for reference :
random_points = [(300.0+random.randint(-100, 100), 200.0+random.randint(-100, 100), 0), (500.0+random.randint(-100, 100), 200.0+random.randint(-100, 100), 65280), (500.0+random.randint(-100, 100), 400.0+random.randint(-100, 100), 65280), (300.0+random.randint(-100, 100), 400.0+random.randint(-100, 100), 65280), (300.0+random.randint(-100, 100), 200.0+random.randint(-100, 100), 65280)]
'''