initial implementation for extern_cmd

This commit is contained in:
Marc Planard 2024-08-19 21:22:38 +02:00
parent a9a89f86c5
commit 7e2d7c4afb
6 changed files with 266 additions and 227 deletions

25
LJ.conf
View File

@ -2,7 +2,7 @@
lasernumber = 1
debug = 0
rediserverip = 0.0.0.0
wwwip = 192.168.1.14
wwwip = 127.0.0.1
nozoscip = 127.0.0.1
oscserverip = 127.0.0.1
autostart = artnet
@ -10,22 +10,23 @@ wstype = ws
wsport = 9001
[laser0]
dac_family = extern_cmd
cmd = ./tracers/lj_rust/lj_rust ./tracers/lj_rust/settings.toml
color = -1
type = LOCAL
dac_family = etherdream
ip = 127.0.0.1
kpps = 10000
centerx = 7.0
centery = 61.0
zoomx = 312.0
zoomy = 1039.0
sizex = 32000.0
sizey = 32000.0
finangle = -0.02263757042605427
type = DS1000
ip = 192.168.1.35
kpps = 25000
intens = 255.0
red = 100
green = 100
blue = 100
centerx = -21504.0
centery = 21504.0
zoomx = 8.90625
zoomy = 20.671875
sizex = 32000.0
sizey = 32000.0
finangle = 0.0
swapx = -1
swapy = -1
lsteps = [ (1.0, 8),(0.25, 3), (0.75, 3), (1.0, 10)]

0
configure.py Normal file → Executable file
View File

View File

@ -14,13 +14,13 @@ Commands reference. Use commands from websocket (webUI) or OSC, do not set value
DAChecks()
UpdateAllwww()
/forwardui "htmlid args"
/forwardui "htmlid args"
/scale/X/lasernumber value (0-200)
/scale/Y/lasernumber value (0-200)
/client or note on < 8 : change client displayed for Current Laser
23 < /noteon < 32 : PL number displayed on webUI simulator
23 < /noteon < 32 : PL number displayed on webUI simulator
/grid/lasernumber value (0 or 1) : switch given laser with grid display on or off
@ -34,15 +34,15 @@ Live change of kpps is not implemented in newdac.py. Change will effect next sta
/angle/lasernumber value : angle correction for given laser by value (0-360)
/intens/lasernumber value : increase/decrease intensity for given laser by value
/intens/lasernumber value : increase/decrease intensity for given laser by value
/resampler/lasernumber lsteps : change resampling strategy (glitch art) for given laser
lsteps is a string like "[ (1.0, 8),(0.25, 3), (0.75, 3), (1.0, 10)]"
/mouse/lasernumber value (0 or 1)
/swap/X/lasernumber value (0 or 1)
/swap/Y/lasernumber value (0 or 1)
/mouse/lasernumber value (0 or 1)
/swap/X/lasernumber value (0 or 1)
/swap/Y/lasernumber value (0 or 1)
/loffset/X/lasernumber value : change X offset of given laser to value (-32000/32000)
/loffset/Y/lasernumber value : change Y offset of given laser to value (-32000/32000)
@ -50,10 +50,10 @@ lsteps is a string like "[ (1.0, 8),(0.25, 3), (0.75, 3), (1.0, 10)]"
/order value : instruct tracer what to do.
0 : display user pointlist with current client key. See below for client key.
1 : pull in redis a new correction matrix (EDH)
2 : display black
1 : pull in redis a new correction matrix (EDH)
2 : display black
3 : display grid
4 : resampler
4 : resampler
5 : pull in redis a new client key
6 : Max Intensity Change = reread redis key /intensity
7 : kpps change = reread redis key /kpps
@ -74,12 +74,12 @@ lsteps is a string like "[ (1.0, 8),(0.25, 3), (0.75, 3), (1.0, 10)]"
Example : client 0 send 2 point lists one for laser 0 and one for laser 1 by sending in redis :
/pl/0/0 and /pl/0/1
The "client key" when client 0 is selected to be displayed by lasers is "/pl/0/".
Each tracer pull its pointlist by using the current client key "/pl/0/"
The "client key" when client 0 is selected to be displayed by lasers is "/pl/0/".
Each tracer pull its pointlist by using the current client key "/pl/0/"
and add its laser number at startup : /pl0/0 ant /pl/0/1
"Client" is a concept. Imagine in a demoparty there is 4 lasers.
John and Paul want to draw on all lasers.
"Client" is a concept. Imagine in a demoparty there is 4 lasers.
John and Paul want to draw on all lasers.
Let's give John client 0, he will send points to /pl/0/0, /pl/0/1, /pl/0/2 and /pl/0/3.
Paul is client 1, so he will use /pl/1/0, /pl/1/1, /pl/1/2 and /pl/1/3.
@ -87,7 +87,7 @@ Paul is client 1, so he will use /pl/1/0, /pl/1/1, /pl/1/2 and /pl/1/3.
Both can send their pointlists to redis server.
When John get the lasers switch to client 0, when it's Paul turn switch to client 1.
But say Bob and Lisa needs only 2 lasers each. Give them client 2.
But say Bob and Lisa needs only 2 lasers each. Give them client 2.
Bob could use /pl/2/0 and /pl/2/1 and Lisa could use /pl/2/2 and /pl/2/3.
@ -96,17 +96,18 @@ Bob could use /pl/2/0 and /pl/2/1 and Lisa could use /pl/2/2 and /pl/2/3.
import types, time, socket, math
from libs3 import gstt
import redis
from libs3 import OSC3
from libs3 import OSC3
from libs3 import settings, plugins, homographyp,log
r = redis.StrictRedis(host=gstt.RediServerIP , port=6379, db=0)
#r = redis.StrictRedis(host=gstt.RediServerIP , port=6379, db=0, password='-+F816Y+-')
workers = []
GenericCommands = ["start", "align", "ljclient", "scene", "addest", "deldest", "dest", "clientnumber", "vcvrack", "fft", "mitraille", "faceosc", "midigen", "viewgen", "audiogen", "noteon", "cc", "ljpong", "ljwars", "mouse", "emergency", "simu", "status", "run", "nozoid", "planet", "live", "words", "ai", "bank0", "pose", "lj", "cycl", "glyph", "pong", "maxw", "custom1", "square", "regen", "trckr", "aurora", "line1", "ForwardUI", "settings", "debug", "pl", "plugins"]
def UserOn(laser):
print("User for laser ", laser)
@ -130,7 +131,7 @@ def BlackOn(laser):
plugins.sendWSall("/status Black on laser " + str(laser))
sendOSCUI('/black/'+str(laser),1)
r.set('/order/'+str(laser), 2)
def GridOn(laser):
@ -164,7 +165,7 @@ def LasClientChange(clientnumber):
r.set('/order/'+str(laserid), 5)
else:
print("ERROR : Maximum number of scenes is set to ", gstt.MaxScenes)
def SceneChange(newscene):
@ -190,7 +191,7 @@ def NoteOn(note):
# Change laser client
if note < 8:
LasClientChange(note)
# Change PL displayed on webui
if note > 23 and note < 32:
if note - 24 > gstt.LaserNumber -1:
@ -198,8 +199,8 @@ def NoteOn(note):
plugins.sendWSall("/redstatus No Laser"+str(note-24))
plugins.sendWSall("/laser "+str(gstt.LaserNumber-1))
plugins.SendAll("/laser "+str(gstt.LaserNumber-1))
else:
else:
gstt.Laser = note -24
print("Current Laser switched to", gstt.Laser)
plugins.sendWSall("/status Laser " + str(gstt.Laser))
@ -209,7 +210,7 @@ def NoteOn(note):
plugins.sendWSall("/loffset/Y/" + str(gstt.Laser) +" " +str(gstt.centerY[gstt.Laser]))
plugins.sendWSall("/scale/X/" + str(gstt.Laser) +" " + str(gstt.zoomX[gstt.Laser]))
plugins.sendWSall("/scale/Y/" + str(gstt.Laser) +" " +str(gstt.zoomY[gstt.Laser]))
def Scim(path, tags, args, source):
@ -223,7 +224,7 @@ def Scim(path, tags, args, source):
plugins.sendWSall("/redstatus No Laser"+str(note-24))
plugins.sendWSall("/laser "+str(gstt.LaserNumber-1))
else:
else:
gstt.Laser = laser -24
plugins.sendWSall("/status Laser " + str(gstt.Laser))
print("Current Laser switched to", gstt.Laser)
@ -232,15 +233,15 @@ def Scim(path, tags, args, source):
def Line1(path, tags, args, source):
line1 = args[0]
print("OSC /line1", line1)
print("OSC /line1", line1)
plugins.sendWSall("/line1 " +"Fx "+line1)
# forward
# forward
def ForwardUI(path, tags, args, source):
line = args[0]
print("OSC /forwardui to WebUI :", line)
print("OSC /forwardui to WebUI :", line)
print('from path', path, 'args', args)
plugins.sendWSall(line)
sendOSCUI('/status',line)
@ -264,12 +265,12 @@ def handler(oscpath, args):
# 2 incoming cases : generic or specific for a given lasernumber :
#
# Generic : Commands without a laser number
#
if oscpath[1] in GenericCommands:
if oscpath[1] in GenericCommands:
if gstt.debug > 0:
print("GenericCommand :", oscpath[1], "with args", args)
@ -286,7 +287,7 @@ def handler(oscpath, args):
r.set("/"+oscpath[1]+"/"+oscpath[2]+"/"+oscpath[3], args[0])
if oscpath[0] == "pl" :
if oscpath[0] == "pl" :
r.set(oscpath, args[0])
@ -314,7 +315,7 @@ def handler(oscpath, args):
if gstt.debug >0:
print(("/" + args[0] + "/start 1"))
print(("/status got pong from "+ args[0] +"."))
plugins.sendWSall("/" + args[0] + "/start 1")
#plugins.sendWSall("/status got pong from "+ args[0] +".")
@ -333,25 +334,25 @@ def handler(oscpath, args):
elif oscpath[1] == "mouse":
Mouse(int(args[0]),int(args[1]),int(args[2]),int(args[3]))
# /emergency value (0 or 1)
# /emergency value (0 or 1)
elif oscpath[1] == "emergency":
if args[0] == "1":
for laser in range(gstt.lasernumber):
print("Black requested for laser ", laser)
BlackOn(laser)
print("EMERGENCY MODE")
plugins.sendWSall("/status EMERGENCY MODE")
plugins.sendWSall("/status EMERGENCY MODE")
else:
for laser in range(gstt.lasernumber):
print("Back to normal for laser ", laser)
UserOn(laser)
# Plugins commands :
# Plugins commands :
elif oscpath[1] == "plugins":
# /plugins/start pluginame
if oscpath[2] == "start":
@ -373,9 +374,9 @@ def handler(oscpath, args):
print("Restarting plugin :",args[0])
print()
plugins.Restart(args[0])
# Settings commands :
# Settings commands :
elif oscpath[1] == "settings":
if oscpath[2] == "lasers":
print()
@ -420,7 +421,7 @@ def handler(oscpath, args):
print("** RESTART LJ **")
#LJautokill()
if oscpath[2] == "restart":
print()
print("Restarting", args[0], "...")
@ -457,25 +458,25 @@ def handler(oscpath, args):
else:
laser = int(oscpath[3])
#print "args[0] :",args[0]," ", type(args[0])
# /black/lasernumber value (0 or 1)
# /black/lasernumber value (0 or 1)
if oscpath[1] == "black":
if args[0] == "1":
print("Black requested for laser ", laser)
BlackOn(laser)
BlackOn(laser)
else:
print("User mode for laser ", laser)
UserOn(laser)
# /grid/lasernumber value (0 or 1)
# /grid/lasernumber value (0 or 1)
if oscpath[1] == "grid":
if args[0] == "1":
print("Grid requested for laser ", laser)
GridOn(laser)
GridOn(laser)
else:
print("No grid for laser ", laser)
UserOn(laser)
@ -485,7 +486,7 @@ def handler(oscpath, args):
print("New IP for laser ", laser)
gstt.lasersIPS[laser]= args[0]
settings.Write()
# /kpps/lasernumber value
# Live change of kpps is not implemented in newdac.py. Change will effect next startup.
if oscpath[1] == "kpps":
@ -495,59 +496,59 @@ def handler(oscpath, args):
sendOSCUI('/kpps/' + str(laser), args[0])
r.set('/kpps/' + str(laser), str(args[0]))
r.set('/order/'+str(laser), 7)
# /angle/lasernumber value
# /angle/lasernumber value
if oscpath[1] == "angle":
print("New Angle modification for laser ", oscpath[2], ":", float(args[0]))
gstt.finANGLE[laser] = math.radians(float(args[0]))
sendOSCUI('/angle/' + str(laser), gstt.finANGLE[laser])
NewEDH(laser)
print("New angle", gstt.finANGLE[laser])
# /intens/lasernumber value
# /intens/lasernumber value
if oscpath[1] == "intens":
print("LJ2 : New intensity requested for laser ", laser, ":", int(args[0]))
plugins.sendWSall("/status Intensity " + str(args[0]))
sendOSCUI('/intens/' + str(laser), args[0])
r.set('/intensity/' + str(laser), str(args[0]))
r.set('/order/'+str(laser), 6)
# /resampler/lasernumber lsteps
# lsteps is a string like "[ (1.0, 8),(0.25, 3), (0.75, 3), (1.0, 10)]"
if oscpath[1] == "resampler":
#print"resampler with args", args
Resampler(laser,args)
# /mouse/lasernumber value (0 or 1)
# /mouse/lasernumber value (0 or 1)
if oscpath[1] == "mouse":
if args[0] == "1":
print("Mouse requested for laser ", oscpath[2])
gstt.Laser = oscpath[2]
else:
print("No mouse for laser ", oscpath[2])
# /swap/X/lasernumber value (0 or 1)
# /swap/X/lasernumber value (0 or 1)
if oscpath[1] == "swap" and oscpath[2] == "X":
print("swapX was", gstt.swapX[laser])
if args[0] == "0":
print("swap X -1 for laser ", laser)
gstt.swapX[laser]= -1
NewEDH(laser)
else:
print("swap X 1 for laser ", laser)
gstt.swapX[laser]= 1
NewEDH(laser)
# /swap/Y/lasernumber value (0 or 1)
# /swap/Y/lasernumber value (0 or 1)
if oscpath[1] == "swap" and oscpath[2] == "Y":
print("swapY was", gstt.swapX[laser])
if args[0] == "0":
print("swap Y -1 for laser ", laser)
@ -557,7 +558,7 @@ def handler(oscpath, args):
print("swap Y 1 for laser ", laser)
gstt.swapY[laser]= 1
NewEDH(laser)
# /loffset/X/lasernumber value
if oscpath[1] == "loffset" and oscpath[2] == "X":
@ -565,7 +566,7 @@ def handler(oscpath, args):
print("offset/X laser", laser, "modified to", args[0])
gstt.centerX[laser] = float(args[0])
NewEDH(laser)
# /loffset/Y/lasernumber value
if oscpath[1] == "loffset" and oscpath[2] == "Y":
@ -573,18 +574,18 @@ def handler(oscpath, args):
print("offset/Y laser", laser, "modified to", args[0])
gstt.centerY[laser] = float(args[0])
NewEDH(laser)
# /scale/X/lasernumber value
if oscpath[1] == "scale" and oscpath[2] == "X":
gstt.zoomX[laser] = float(args[0])
print("scale/X laser", laser , "modified to", gstt.zoomX[laser])
NewEDH(laser)
# /scale/Y/lasernumber value
if oscpath[1] == "scale" and oscpath[2] == "Y":
gstt.zoomY[laser] = float(args[0])
print("scale/Y laser", laser, "modified to", gstt.zoomY[laser])
NewEDH(laser)
@ -592,22 +593,22 @@ def handler(oscpath, args):
# OSC UI feedback
def sendOSCUI(oscaddress,oscargs=''):
if gstt.TouchOSCUI == True:
oscmsg = OSC3.OSCMessage()
oscmsg.setAddress(oscaddress)
oscmsg.append(oscargs)
oscui = OSC3.OSCClient()
oscui.connect((gstt.TouchOSCIP, 8001))
oscui.connect((gstt.TouchOSCIP, 8001))
#print("main sending OSC UI message :", oscmsg, "to", gstt.TouchOSCIP, ":8001")
if gstt.debug >0:
print("main sending OSC UI message :", oscmsg, "to", gstt.TouchOSCIP, ":8001")
try:
oscui.sendto(oscmsg, (gstt.TouchOSCIP, 8001))
oscmsg.clearData()
except:
print ('Connection to OSC UI refused : died ?')
pass
@ -639,7 +640,7 @@ def UpdateOSCUI(laserid):
sendOSCUI("/swap/Y/" + str(laserid), 0)
#
#
# Different useful codes for some commands
#
@ -700,7 +701,7 @@ def isOpen(ip):
time.sleep(1)
finally:
dacksock.close()
return istate
@ -726,22 +727,27 @@ def LJautokill():
print('Shutdown order for tracer '+str(laser), 9)
r.set('/order/'+str(laser), 9)
for (n,dac_worker) in enumerate(workers):
log.warn(f'Entering tracer{n} ...')
dac_worker.join()
lasernumber= gstt.LaserNumber -1
log.warn("Ending tracer0...")
worker0.join()
if lasernumber >0:
log.warn("Ending tracer1...")
worker1.join()
if lasernumber >1:
log.warn("Ending tracer2...")
worker2.join()
if lasernumber >2:
log.warn("Ending tracer3...")
worker3.join()
# log.warn("Ending tracer0...")
# worker0.join()
# if lasernumber >0:
# log.warn("Ending tracer1...")
# worker1.join()
# if lasernumber >1:
# log.warn("Ending tracer2...")
# worker2.join()
# if lasernumber >2:
# log.warn("Ending tracer3...")
# worker3.join()
log.warn("Laser feedbacks resetting...")
for laserid in range(0,lasernumber+1):
r.set('/lack/'+str(laserid),64)
r.set('/lstt/'+str(laserid),64)
r.set('/cap/'+str(laserid),0)
@ -759,9 +765,9 @@ def DAChecks():
if isOpen(gstt.lasersIPS[dac]):
print("DAC", dac, "at", gstt.lasersIPS[dac], ": UP")
gstt.dacs[gstt.dacnumber] = dac
gstt.dacs[gstt.dacnumber] = dac
gstt.dacnumber +=1
else:
print("DAC", dac, "at", gstt.lasersIPS[dac], ": DOWN")
@ -786,19 +792,19 @@ For reference values of EDH modifier if assign to keyboard keys (was alignp)
gstt.zoomX[gstt.Laser] += 0.1
gstt.zoomY[gstt.Laser] -= 0.1
gstt.zoomY[gstt.Laser] += 0.1
gstt.sizeX[gstt.Laser] -= 50
gstt.sizeX[gstt.Laser] += 50
gstt.sizeY[gstt.Laser] -= 50
gstt.sizeY[gstt.Laser] += 50
gstt.finANGLE[gstt.Laser] -= 0.001
gstt.finANGLE[gstt.Laser] += 0.001
Code for bit analysis 2 bits / laser to encode order.
@ -813,7 +819,7 @@ Code for bit analysis 2 bits / laser to encode order.
#order = r.get('/order')
#neworder = order & ~(1<< laser*2)
#neworder = neworder & ~(1<< 1+ laser*2)
#r.set('/order', str(neworder))
#r.set('/order', str(neworder))
# Laser bit 0 = 0 and bit 1 = 1 : New EDH
#order = r.get('/order')

View File

@ -49,13 +49,13 @@ Laser = 0
# Can be changed with /noteon 24-31
simuPL = 1
# gstt.laserIPS.
# gstt.laserIPS.
lasersIPS = ['192.168.1.5','192.168.1.6','192.168.1.3','192.168.1.4']
maxdacs = 4
# Autodetected by DAChecks() in main3 :
# Store connected dacs. Maybe laser 1 in LJ.conf is not connected but Laser 2 is.
# Store connected dacs. Maybe laser 1 in LJ.conf is not connected but Laser 2 is.
dacs = [-1, -1, -1, -1]
# Actual number of connected DACs
dacnumber = 0
@ -63,8 +63,9 @@ dacnumber = 0
# gstt.kpps stores kpps for each laser.
# ** Will be overridden by LJ.conf file values **
kpps = [25000,25000,25000,25000]
lasertype = ["LOCAL","LOCAL","LOCAL","LOCAL"]
dacfamily = ["etherdream","etherdream","etherdream","etherdream"]
lasertype = ["LOCAL","LOCAL","LOCAL","LOCAL"]
dacfamily = ["etherdream","etherdream","etherdream","etherdream"]
cmd = [None,None,None,None]
intensity = [-1,-1,-1,-1]
intens = [-1,-1,-1,-1]
red = [100,100,100,100]
@ -74,17 +75,17 @@ blue = [100,100,100,100]
# gstt.GridDisplay : if = 1 Curve points actually sent to PL are replaced by a grid
GridDisplay = [0,0,0,0]
# Transformation Matrix for each laser
# Transformation Matrix for each laser
EDH = [[], [], [], []]
# Etherdreams reports
# Etherdreams reports
# ipconn is initial newdac to its etherdream
lstt_ipconn = [[-1], [-1], [-1], [-1]]
# dacstt is dac light engine state
lstt_dacstt = [[-1], [-1], [-1], [-1]]
# store last dac answers : ACK, not ACK,...
# store last dac answers : ACK, not ACK,...
lstt_dacanswers = [[-1], [-1], [-1], [-1]]
# store last number of points sent to etherdreams buffer
# store last number of points sent to etherdreams buffer
lstt_points = [[0], [0], [0], [0]]
swapX = [1,1,1,-1]
@ -93,7 +94,7 @@ swapY = [1,1,1,-1]
lsteps = [[],[],[],[]]
# For glitch art : change position and number of points added by tracer.py
# shortline is for distance with next point, shorter than 4000 (in etherdream coordinates)
# shortline is for distance with next point, shorter than 4000 (in etherdream coordinates)
# i.e (0.25,3) means add 3 points at 25% on the line.
stepshortline = [(1.0, 8)]
stepslongline = [(0.25, 3), (0.75, 3), (1.0, 10)]
@ -114,7 +115,7 @@ knob = [0] * 33
cc[21]=60
viewer_distance = cc[21] * 8
# fov (cc 22)
# fov (cc 22)
cc[22]= 60
fov = 4 * cc[22]
@ -130,7 +131,7 @@ nozoport=8001 #nozosc.py sending port to LJay (main.py)
nozuport=0 #linux serial usb port connecting nozoid devices ACM0 by default
angleX = 0
angleX = 0
angleY = 0
angleZ = 0

View File

@ -16,7 +16,7 @@ import ast
import numpy as np
def Write():
def Write():
config.set('General', 'lasernumber', str(gstt.LaserNumber))
config.set('General', 'rediserverip', str(gstt.RediServerIP))
@ -51,8 +51,8 @@ def Write():
def Read():
def Read():
gstt.LaserNumber = config.getint('General', 'lasernumber')
gstt.RediServerIP= config.get('General', 'rediserverip')
gstt.wwwIP= config.get('General', 'wwwip')
@ -69,6 +69,8 @@ def Read():
gstt.lasersIPS[i]= config.get(laser, 'ip')
gstt.lasertype[i]= config.get(laser, 'type')
gstt.dacfamily[i] = config.get(laser, 'dac_family')
if gstt.dacfamily[i] == "extern_cmd":
gstt.cmd[i] = config.get(laser, 'cmd')
gstt.kpps[i] = config.getint(laser, 'kpps')
gstt.intens[i] = config.getfloat(laser, 'intens')
gstt.red[i] = config.getint(laser, 'red')
@ -90,4 +92,3 @@ def Read():
config = configparser.ConfigParser()
config.read(gstt.ConfigName)

220
main.py
View File

@ -11,14 +11,14 @@ 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 "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.
- 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.
All used ports:
All used ports:
8002 OSC incoming
9001 Websocket communication with WebGUI
9001 Websocket communication with WebGUI
Plugins OSC Ports (see LJ.conf)
'''
@ -52,14 +52,14 @@ settings.Write()
from multiprocessing import Process, set_start_method
import random, ast
from libs3 import plugins
#from libs3 import lasytracer as tracer
from libs3 import tracer3 as tracer
#from libs3 import niptracer3 as tracer
#from libs3 import lasytracer as tracer
from libs3 import tracer3 as tracer
#from libs3 import niptracer3 as tracer
from libs3 import homographyp, commands, font1
#import subprocess
import os
#from libs3 import midi3
from libs3 import OSC3
from libs3 import OSC3
from websocket_server import WebsocketServer
#import socket
import types, _thread, time
@ -82,7 +82,6 @@ elif os_name == "Darwin": # macOS
elif os_name == "Linux":
print("Plateform: Linux")
def dac_process(number, pl):
import sys
@ -90,6 +89,7 @@ def dac_process(number, pl):
print("Starting dac process", number)
while True:
try:
d = tracer.DAC(number,pl)
@ -110,20 +110,20 @@ def dac_process(number, pl):
except KeyboardInterrupt:
sys.exit(0)
#
# Init variables
#
debug = gstt.debug
debug = gstt.debug
print("Debug :", debug)
print("Start Scene number :",gstt.SceneNumber)
print("Laser feedbacks resetting...")
for laserid in range(0,gstt.LaserNumber):
r.set('/lack/'+str(laserid),64)
r.set('/lstt/'+str(laserid),64)
r.set('/cap/'+str(laserid),0)
@ -156,13 +156,13 @@ import socket
# oscserver
oscserverIP = gstt.oscIPin
# OSC Server : accept OSC message on port 8002
# OSC Server : accept OSC message on port 8002
#oscIPin = "192.168.1.10"s
oscserverIPin = serverIP
oscserverPORTin = 8002
# OSC Client : to send OSC message to an IP port 8001
oscserverIPout = oscserverIP
oscserverIPout = oscserverIP
oscserverPORTout = 8101
oscserver = OSC3.OSCServer( (oscserverIPin, oscserverPORTin) )
@ -200,7 +200,7 @@ def handler(path, tags, args, source):
commands.handler(oscpath,args)
# RAW OSC Frame available ?
# RAW OSC Frame available ?
def osc_frame():
#print 'oscframe'
# clear timed_out flag
@ -213,7 +213,7 @@ def PingAll():
if gstt.debug > 0:
print("Pinging all plugins...")
for plugin in list(gstt.plugins.keys()):
if gstt.debug > 0:
print("pinging", plugin)
@ -223,28 +223,28 @@ def PingAll():
'''
gstt.lasertype[i
gstt.sizeX[i] =
gstt.sizeY[i] =
gstt.sizeX[i] =
gstt.sizeY[i] =
'''
'''
# OSC UI feedback
def sendOSCUI(oscaddress,oscargs=''):
if gstt.TouchOSCUI == True:
oscmsg = OSC3.OSCMessage()
oscmsg.setAddress(oscaddress)
oscmsg.append(oscargs)
oscui = OSC3.OSCClient()
oscui.connect((gstt.TouchOSCIP, 8001))
oscui.connect((gstt.TouchOSCIP, 8001))
print("main sending OSC UI message :", oscmsg, "to", gstt.TouchOSCIP, ":8001")
if gstt.debug >0:
print("main sending OSC UI message :", oscmsg, "to", gstt.TouchOSCIP, ":8001")
try:
oscui.sendto(oscmsg, (gstt.TouchOSCIP, 8001))
oscmsg.clearData()
except:
print ('Connection to OSC UI refused : died ?')
pass
@ -276,7 +276,7 @@ def osc_thread():
if lstt == "2": # Dac PLAYING (2) -> led is green (1)
sendWSall("/lstt/" + str(laserid) + " 1")
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')
@ -293,13 +293,13 @@ def osc_thread():
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) + " 6")
sendWSall("/lstt/" + str(laserid) + " 6")
#sendWSall("/lstt/" + str(laserid) + " 0")
sendWSall("/lack/" + str(laserid) + " 6")
sendWSall("/lstt/" + str(laserid) + " 6")
#sendWSall("/lstt/" + 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)).decode('ascii')))
@ -322,17 +322,17 @@ def osc_thread():
#
# Websocket part
#
#
def get_Host_name_IP():
try:
host_name = socket.gethostname()
host_name = "localhost" #socket.gethostname()
host_ip = socket.gethostbyname(host_name)
print("Hostname : ", host_name)
print("IP : ", host_ip)
except:
print("Unable to get Hostname and IP")
return host_ip
# Called for every WS client connecting (after handshake)
def new_client(client, wserver):
@ -340,7 +340,7 @@ def new_client(client, wserver):
sendWSall("/status Hello " + str(client['id']))
#commands.sendOSCUI("/status", "Hello " + str(client['id']))
for laserid in range(0,gstt.LaserNumber):
for laserid in range(0,gstt.LaserNumber):
sendWSall("/ip/" + str(laserid) + " " + str(gstt.lasersIPS[laserid]))
sendWSall("/kpps/" + str(laserid)+ " " + str(gstt.kpps[laserid]))
@ -348,8 +348,8 @@ def new_client(client, wserver):
sendWSall("/laser "+str(laserid))
#print("/laser "+str(laserid))
sendWSall("/lack/" + str(laserid) + " 6")
#print("/lack/" + str(laserid) + " 6")
sendWSall("/lstt/" + 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")
@ -379,25 +379,25 @@ def client_left(client, wserver):
def message_received(client, wserver, message):
#if len(message) > 200:
# message = message[:200]+'..'
# message = message[:200]+'..'
#if gstt.debug >0:
# print ("")
# print("WS Client(%d) said: %s" % (client['id'], message))
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)
PingAll()
message4plugin = False
# WS received Message is for a plugin ?
for plugin in list(gstt.plugins.keys()):
if oscpath[0].find(plugin) != -1:
message4plugin = True
#print(oscpath)
if plugins.Send(plugin, oscpath):
@ -411,13 +411,13 @@ def message_received(client, wserver, message):
if len(oscpath) == 1:
args[0] = "noargs"
#print "noargs command"
elif len(oscpath) > 1:
args[0] = str(oscpath[1])
args[0] = str(oscpath[1])
#print "arg",oscpath[1]
commands.handler(oscpath[0].split("/"),args)
# if needed a loop back : WS Client -> server -> WS Client
#sendWSall("ws"+message)
@ -431,7 +431,7 @@ def sendWSall(message):
#if gstt.debug >0:
#print("WS sending %s" % (message))
wserver.send_message_to_all(message)
if gstt.TouchOSCUI == True:
if message[:7] == '/status':
print("Main WSall", message, message[:6])
@ -440,8 +440,8 @@ def sendWSall(message):
print("Main WSall", message, message[:6])
commands.sendOSCUI('/line1', message[6:])
'''
'''
print ("")
log.info("Midi Configuration...")
midi3.check()
@ -462,7 +462,7 @@ 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))
@ -480,10 +480,32 @@ for sceneid in range(0,gstt.MaxScenes+1):
r.set('/order/'+str(laserid), 0)
#
# For tracer as external command
#
import subprocess
import select
def spawn(cmd):
p = subprocess.Popen(cmd,
shell=True,
stdin=subprocess.DEVNULL,
stdout=subprocess.DEVNULL,
stderr=subprocess.DEVNULL)
return p
#
# Starts one DAC process per requested Laser
#
import signal
import sys
def signal_handler(sig, frame):
print('You pressed Ctrl+C!')
commands.LJautokill()
sys.exit(0)
signal.signal(signal.SIGINT, signal_handler)
if __name__ == '__main__':
# Bug in 3.8.4 MacOS default multiprocessing start method is spawn. Spawn doesn't work properly
@ -495,44 +517,55 @@ if __name__ == '__main__':
commands.DAChecks()
print("dacs", gstt.dacs)
else:
else:
log.infog("Resquested DACs mode")
lasernumber = gstt.LaserNumber -1
#lasernumber = gstt.LaserNumber -1
print("LaserNumber = ", gstt.LaserNumber)
log.info("Starting "+str(gstt.LaserNumber) + " DACs process...")
# Launch one process (a tracer3 instance) by laser
dac_worker0= Process(target=dac_process, args=(0,0,))
dac_worker0.start()
commands.worker0 = dac_worker0
print("Tracer 0 : name", dac_worker0.name , "pid", dac_worker0.pid )
if lasernumber >0:
dac_worker1= Process(target=dac_process, args=(1,0,))
commands.worker1 = dac_worker1
print("Tracer 1 : name", dac_worker1.name , "pid", dac_worker1.pid )
dac_worker1.start()
if lasernumber >1:
dac_worker2= Process(target=dac_process, args=(2,0,))
dac_worker2.start()
commands.worker2 = dac_worker2
print("Tracer 2 : name", dac_worker2.name , "pid", dac_worker2.pid )
if lasernumber >2:
dac_worker3= Process(target=dac_process, args=(3,0,))
print("Tracer 3 : name", dac_worker3.name , "pid", dac_worker3.pid )
commands.worker3 = dac_worker3
dac_worker3.start()
commands.workers = []
for lasernumber in range(0,gstt.LaserNumber):
# Launch one process (a tracer3 instance) by laser
if gstt.dacfamily[lasernumber] == "extern_cmd":
dac_worker0 = spawn(gstt.cmd[lasernumber]) #Process(target=spawn, args=(gstt.cmd[0],))
dac_worker0.name = f'ExternCmd{lasernumber}'
dac_worker0.join = dac_worker0.wait
else:
dac_worker0= Process(target=dac_process, args=(lasernumber,0,))
dac_worker0.start()
#commands.worker0 = dac_worker0 # ???
commands.workers.append(dac_worker0)
print("Tracer 0 : name", dac_worker0.name , "pid", dac_worker0.pid )
print("DAC Family:", gstt.dacfamily[lasernumber]);
# if lasernumber >0:
# dac_worker1= Process(target=dac_process, args=(1,0,))
# commands.worker1 = dac_worker1
# print("Tracer 1 : name", dac_worker1.name , "pid", dac_worker1.pid )
# dac_worker1.start()
# if lasernumber >1:
# dac_worker2= Process(target=dac_process, args=(2,0,))
# dac_worker2.start()
# commands.worker2 = dac_worker2
# print("Tracer 2 : name", dac_worker2.name , "pid", dac_worker2.pid )
# if lasernumber >2:
# dac_worker3= Process(target=dac_process, args=(3,0,))
# print("Tracer 3 : name", dac_worker3.name , "pid", dac_worker3.pid )
# commands.worker3 = dac_worker3
# dac_worker3.start()
print("")
#
# start WS and OSC servers
#
try:
log.info("Starting servers...")
hostIP= get_Host_name_IP()
if hostIP != gstt.wwwIP:
@ -542,8 +575,8 @@ if __name__ == '__main__':
print("python3 configure.py")
log.err('Exiting...')
#gstt.wwwIP = hostIP
commands.LJautokill()
sys.exit()
#commands.LJautokill()
#sys.exit()
# Launch OSC thread listening to oscserver
print("OSC server to receive messages (UI,...)")
@ -559,13 +592,13 @@ if __name__ == '__main__':
#print()
# Websocket listening port
print("WebUI WS server...")
#hostIP= get_Host_name_IP()
if hostIP != gstt.wwwIP:
log.err("wwwIP in config is not set to "+str(hostIP))
gstt.wwwIP = hostIP
#commands.LJautokill()
print("binded at", gstt.wwwIP, "port",str(gstt.wsPORT))
wserver = WebsocketServer(gstt.wsPORT,host= gstt.wwwIP)
plugins.Init(wserver)
@ -575,43 +608,40 @@ if __name__ == '__main__':
print("")
log.info("Resetting all Homographies...")
for laserid in range(0,gstt.LaserNumber):
for laserid in range(0,gstt.LaserNumber):
homographyp.newEDH(laserid)
#midi3.check()
# 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...")
# websocket loop
wserver.run_forever()
except Exception:
log.err("Exception")
traceback.print_exc()
# Gently stop on CTRL C
finally:
commands.LJautokill()
'''
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)]
'''