271 lines
7.0 KiB
Python
271 lines
7.0 KiB
Python
#!/usr/bin/python3
|
|
# -*- coding: utf-8 -*-
|
|
# -*- mode: Python -*-
|
|
|
|
'''
|
|
LJnano
|
|
|
|
v0.1b
|
|
|
|
Open localhost websocket 9001
|
|
|
|
Write Redis keys :
|
|
|
|
- '/trckr/frame/WSclientid' : TrckrPts
|
|
- 'WSclients' : [{'id': 1, 'handler': <websocket_server.WebSocketHandler object at 0x114d35880>, 'address': ('127.0.0.1', 62718)}, {'id': 2, 'handler': <websocket_server.WebSocketHandler object at 0x114d35d60>, 'address': ('127.0.0.1', 62720)}]
|
|
|
|
'''
|
|
from __future__ import print_function
|
|
import websocket
|
|
import time
|
|
import argparse
|
|
import traceback
|
|
import sys
|
|
import random
|
|
from websocket_server import WebsocketServer
|
|
import redis
|
|
from socket import *
|
|
|
|
try:
|
|
import thread
|
|
except ImportError:
|
|
import _thread as thread
|
|
|
|
name = "exports::ljnano"
|
|
|
|
def debug(*args, **kwargs):
|
|
if( verbose == False ):
|
|
return
|
|
print(*args, file=sys.stderr, **kwargs)
|
|
|
|
argsparser = argparse.ArgumentParser(description="ljnano v0.1b help mode")
|
|
argsparser.add_argument("-v","--verbose",action="store_true",help="Verbose output")
|
|
argsparser.add_argument("-s","--server",help="WS server IP (127.0.0.1 by default)", type=str)
|
|
argsparser.add_argument("-p","--port",help="WS port to bind to (9001 by default)", type=str)
|
|
argsparser.add_argument("-k","--key",help="Redis key to update",default="0",type=str)
|
|
args = argsparser.parse_args()
|
|
|
|
key = args.key
|
|
|
|
if args.verbose:
|
|
verbose = True
|
|
else:
|
|
verbose = False
|
|
|
|
if args.server:
|
|
serverIP = args.server
|
|
else:
|
|
serverIP = "127.0.0.1"
|
|
|
|
if args.port:
|
|
wsPORT = args.port
|
|
else:
|
|
wsPORT = 9001
|
|
|
|
print("")
|
|
print("LJnano v0.1b")
|
|
|
|
points0 = "[(-150.0, 230.0, 65280), (-70.0, -170.0, 65280), (310.0, -170.0, 65280), (210.0, 230.0, 65280), (-150.0, 230.0, 65280)]"
|
|
points1 = "[(200.0, 170.0, 65280), (-180.0, -230.0, 65280)]"
|
|
points2 = "[(170.0, 190.0, 65280), (200.0, 170.0, 65280), (230.0, 190.0, 65280), (230.0, 200.0, 65280), (170.0, 230.0, 65280), (230.0, 230.0, 65280)]"
|
|
points3 = "[(170.0, 170.0, 65280), (200.0, 170.0, 65280), (230.0, 190.0, 65280), (200.0, 200.0, 65280), (230.0, 210.0, 65280), (200.0, 230.0, 65280), (170.0, 230.0, 65280)]"
|
|
points = [points0, points1, points2, points3]
|
|
|
|
LaserNumber = 1
|
|
SceneNumber = 0
|
|
Laser = 0
|
|
|
|
|
|
#
|
|
# Redis
|
|
#
|
|
|
|
r = redis.StrictRedis(host=serverIP , port=6379, db=0)
|
|
|
|
# read from redis key
|
|
def fromKey(keyname):
|
|
|
|
return r.get(keyname)
|
|
|
|
# Write to redis key
|
|
def toKey(keyname,keyvalue):
|
|
|
|
#print(keyname,keyvalue)
|
|
# Store encoded data in Redis
|
|
return r.set(keyname,keyvalue)
|
|
|
|
# event key can be like "/midi/last_event"
|
|
# Send en event to eventkey (publish)
|
|
def toKeyevent(eventkey,eventname):
|
|
|
|
print("redis midi event key :", eventname)
|
|
r.publish(eventkey, eventname)
|
|
|
|
# examples
|
|
#if toKey("/clientkey","/pl/"+str(gstt.SceneNumber)+"/")==True:
|
|
# print("sent clientkey : /pl/"+str(gstt.SceneNumber)+"/")
|
|
|
|
# toKeyevent("/midi/noteon/"+str(MidiChannel)+"/"+str(MidiNote)+"/"+str(MidiVel))
|
|
|
|
|
|
def custom_handler(message):
|
|
# do_something with the message
|
|
print(message)
|
|
'''
|
|
p.psubscribe(**{'hello*':custom_handler})
|
|
thread = p.run_in_thread(sleep_time=0.001)
|
|
'''
|
|
|
|
|
|
|
|
# Change current laser.
|
|
def NoteOn(note):
|
|
debug("NoteOn", note)
|
|
|
|
# Change laser client
|
|
if note < 8:
|
|
|
|
Laser = note
|
|
debug("Current Laser switched to", Laser)
|
|
sendWSall("/status Laser " + str(Laser))
|
|
sendWSall("/simul" +" "+ points[Laser])
|
|
|
|
# Change PL displayed on webui
|
|
if note > 23 and note < 32:
|
|
if note - 24 > LaserNumber -1:
|
|
debug("Only",LaserNumber,"lasers asked, you dum ass !")
|
|
sendWSall("/redstatus No Laser"+str(note-24))
|
|
sendWSall("/laser "+str(LaserNumber-1))
|
|
sendWSall("/simul" +" "+ points[LaserNumber-1])
|
|
else:
|
|
Laser = note -24
|
|
debug("Current Laser switched to", Laser)
|
|
sendWSall("/status Laser " + str(Laser))
|
|
sendWSall("/simul" +" "+ points[Laser])
|
|
|
|
|
|
def sendbroadcast():
|
|
|
|
debug("Sending broadcast")
|
|
cs = socket(AF_INET, SOCK_DGRAM)
|
|
cs.setsockopt(SOL_SOCKET, SO_REUSEADDR, 1)
|
|
cs.setsockopt(SOL_SOCKET, SO_BROADCAST, 1)
|
|
cs.sendto("LJ nano 0.1".encode(), ("255.255.255.255", 54545))
|
|
|
|
|
|
#
|
|
# Websocket server
|
|
#
|
|
|
|
def client_list():
|
|
|
|
clients = []
|
|
for client in wserver.clients_list():
|
|
clients.append(client['id'])
|
|
#print(clients)
|
|
return str(clients)
|
|
|
|
# Called for every WS client connecting (after handshake)
|
|
def new_client(client, wserver):
|
|
|
|
debug("WS server got new client connected and was given id %d" % client['id'])
|
|
toKey('WSclients', client_list())
|
|
sendWSall("/status nano:Hello " + str(client['id']))
|
|
sendWSall("/laser "+str(0))
|
|
sendWSall("/lack/" + str(0) + " 3")
|
|
sendWSall("/lstt/" + str(0) + " 3")
|
|
sendWSall("/simul" +" "+ points[0])
|
|
|
|
|
|
# Called for every WS client disconnecting
|
|
def client_left(client, wserver):
|
|
|
|
try:
|
|
debug("WS server had client(%d) disconnected" % client['id'])
|
|
|
|
except:
|
|
debug("Something weird if coming from",client,"on the wire...")
|
|
pass
|
|
|
|
|
|
|
|
# Called for each WS received message.
|
|
def message_received(client, wserver, message):
|
|
|
|
#if len(message) > 200:
|
|
# message = message[:200]+'..'
|
|
|
|
oscpath = message.split(" ")
|
|
#print("WS Client", client['id'], "said :", message, "splitted in an oscpath :", oscpath)
|
|
#if( verbose == True ):
|
|
# debug("WS server's client", client['id'], "said :", message)
|
|
|
|
if message[0:5] == "/simu":
|
|
debug("WS server sending to simu page :",message)
|
|
sendWSall(message)
|
|
|
|
if message[0:7] == "/noteon":
|
|
oscpath = message.split(" ")
|
|
debug("WS server got new laser", int(oscpath[1]))
|
|
NoteOn(int(oscpath[1]))
|
|
|
|
|
|
# Get WS /aurora/trckr/frame layernumber framenumber points
|
|
# Set redis /trckr/frame/WSclientID points
|
|
if message.find('trckr/frame') > 0:
|
|
|
|
args = message.split(" ")
|
|
TrckrPts = []
|
|
for dot in range(3,len(args)-1,2):
|
|
TrckrPts.append([float(args[dot]), float(args[dot+1])])
|
|
|
|
debug('/trckr/frame/'+str(client['id'])+" "+str(TrckrPts))
|
|
toKey('/trckr/frame/'+str(client['id']),str(TrckrPts))
|
|
|
|
def sendWSall(message):
|
|
if ( verbose == True ):
|
|
debug("WS server is sending to all : %s" % (message))
|
|
wserver.send_message_to_all(message)
|
|
|
|
|
|
def LaunchServer(*args):
|
|
global wserver
|
|
|
|
try:
|
|
|
|
# Websocket server
|
|
wserver = WebsocketServer(wsPORT,host=serverIP)
|
|
|
|
print("Launching Websocket server 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("Nano is running. Open/reload www/simulocal.html in a browser !")
|
|
print()
|
|
|
|
# websocket server loop
|
|
wserver.run_forever()
|
|
|
|
|
|
except EOFError:
|
|
debug("break")# no more information
|
|
|
|
finally:
|
|
|
|
debug("sendWS terminating...")
|
|
|
|
|
|
#
|
|
# Launch WS server
|
|
#
|
|
|
|
if __name__ == "__main__":
|
|
|
|
try:
|
|
|
|
LaunchServer()
|
|
|
|
except Exception:
|
|
debug("nano Exception")
|
|
traceback.print_exc()
|
|
|