renaming folders and files to python format

This commit is contained in:
dezeyer 2019-05-11 14:28:42 +00:00
parent ade378d128
commit 798775805c
19 changed files with 509 additions and 268 deletions

View File

@ -18,7 +18,6 @@ class ThreadedUDPServer(threading.Thread):
self.start()
self.udpClientGuardian = self.UDPClientGuardian()
self.udpClientGuardian.start()
UDPClients
def run(self):
@ -86,13 +85,6 @@ class UDPClient():
self.lastping = time()
def handle(self, request):
clientdata = request[0].decode()
self.socket = request[1]
#print(time(),"{} wrote:".format(self.client_address))
#print(time(),"clientdata -> ", clientdata)
# socket.sendto(bytes("pong","utf-8"),self.client_address)
# Client Types:
# CLIENT_TYPE_CONTROLLER = 0
# CLIENT_TYPE_STRIPE = 1
@ -104,8 +96,9 @@ class UDPClient():
# s:ping
# UDP
self.socket = request[1]
try:
data = clientdata.split(':')
data = request[0].decode().split(':')
#print(data)
# r:1:srg strip name
if data[0] == "r" and int(data[1]) == CLIENT_TYPE_STRIPE and data[2] != None and self.registered is False:

View File

@ -22,8 +22,8 @@ class ThreadedWebSocketServer(Thread):
import json
from rgbUtils import effectControllerJsonHelper
from rgbUtils import rgbStripControllerJsonHelper
from BackendProvider.Helper import effectControllerJsonHelper
from BackendProvider.Helper import rgbStripControllerJsonHelper
import traceback
import logging
@ -63,12 +63,6 @@ class HTTPWebSocketsHandler(WebSocket):
ledcount=1
if "led_count" in data:
ledcount = int(data["led_count"])
self.nojson=0
if "nojson" in data:
self.nojson = int(data["nojson"])
self.nosend=0
if "nosend" in data:
self.nosend = int(data["nosend"])
# registers the strip with websocket object and name. the onRGBStripValueUpdate(rgbStrip) is called by
# by the rgbStrip when an effectThread updates it
@ -87,13 +81,9 @@ class HTTPWebSocketsHandler(WebSocket):
})
)
return
# the stripe should usualy not send any data, i do not know why it should...
elif self.client_type is CLIENT_TYPE_STRIPE:
if self.nosend == 1:
respdata = "d"
for i in range(self.rgbStrip.STRIP_LENGHT):
respdata += ":" + str(i) + ":"+str(self.rgbStrip.red[i])+":"+str(self.rgbStrip.green[i])+":"+str(self.rgbStrip.blue[i])
self.sendMessage(respdata)
return
# audio recorder responses are handled by the effectControllerJsonHandler
elif self.client_type is CLIENT_TYPE_RECORDER:
@ -139,15 +129,8 @@ class HTTPWebSocketsHandler(WebSocket):
# when a rgbStrip value is changed, send json data to client
def onRGBStripValueUpdate(self,rgbStrip):
if self.nosend == 0:
if self.nojson == 0:
self.sendMessage(
json.dumps({
'data': rgbStripControllerJsonHelper.getRGBData(rgbStrip)
})
)
if self.nojson == 1:
respdata = "d"
for i in range(rgbStrip.STRIP_LENGHT):
respdata += ":" + str(i) + ":"+str(rgbStrip.red[i])+":"+str(rgbStrip.green[i])+":"+str(rgbStrip.blue[i])
self.sendMessage(respdata)

View File

@ -1,15 +1,13 @@
from rgbUtils.BaseEffect import BaseEffect
from rgbUtils.EffectParameter import slider, colorpicker
from rgbUtils.debug import debug
from Utils.BaseEffect import BaseEffect
from Utils.EffectParameter import slider, colorpicker
import time
import sys
import numpy
from rgbUtils.pyAudioRecorder import pyAudioRecorder
from time import perf_counter, sleep
from random import randint, shuffle
class musikEffect(BaseEffect):
class MusikEffect(BaseEffect):
name = "musikEffect"
desc = "LED-Band *sollte* nach musik blinken"
@ -18,7 +16,7 @@ class musikEffect(BaseEffect):
# Something that will be used to show descriptions and value options
# of the parameters the effect will accept, in a way, that eg the webclient can decide,
# if the parameters can be toggeled by a button/checkbox/slider/whatever
effectParameters = [
effectParameters: list = [
# radio(\
# "Shuffle LED to Freq Order",\
# "Off -> Mapping ",\
@ -42,12 +40,14 @@ class musikEffect(BaseEffect):
self.fft_random_keys = [0,1,2,3]
self.fft_random = [0,0,0,0]
self.y_max_freq_avg_list = []
self.low_freq_avg_list = []
self.bpm_list = []
self.prev_beat = 0 # timestamp
# used by strobe()
self.lastmode = 0
self.recorderClient = pyAudioRecorder.recorderClient()
self.rgbStripController.pyAudioRecorder.registerRecorderClient(self.recorderClient)
return
#loop effect as long as not stopped
@ -67,17 +67,17 @@ class musikEffect(BaseEffect):
# b=0
# RGBStrip.RGB(r,g,b)
#self.lastTime = time.time()
sleep(.001)
sleep(0.00833333333)
def end(self):
self.rgbStripController.pyAudioRecorder.unregisterRecorderClient(self.recorderClient)
pass
def plot_audio_and_detect_beats(self):
if not self.rgbStripController.pyAudioRecorder.has_new_audio:
if not self.hasNewFttValues:
return
# get x and y values from FFT
xs, ys = self.rgbStripController.pyAudioRecorder.fft()
xs, ys = self.ftt
# calculate average for all frequency ranges
y_avg = numpy.mean(ys)
@ -88,9 +88,9 @@ class musikEffect(BaseEffect):
#mid_freq = numpy.mean(ys[88:115])
#hig_freq = numpy.mean(ys[156:184])
low_freq = numpy.mean(ys[0:67])
mid_freq = numpy.mean(ys[68:135])
hig_freq = numpy.mean(ys[136:204])
low_freq = numpy.mean(ys[0:int(ys.__len__() / 3 * 1)])
mid_freq = numpy.mean(ys[int(ys.__len__() / 3 * 1):int(ys.__len__() / 3 * 2)])
hig_freq = numpy.mean(ys[int(ys.__len__() / 3 * 2):int(ys.__len__() / 3 * 3)])
#get the maximum of all freq
if len(self.y_max_freq_avg_list) < 250 or y_avg > 10 and numpy.amax([low_freq,mid_freq,hig_freq])/2 > numpy.amin(self.y_max_freq_avg_list):
@ -166,6 +166,16 @@ class musikEffect(BaseEffect):
self.fft_random[1],
self.fft_random[2]
)
"""
rgbStrip: RGBStrip
for rgbStrip in self.effectRGBStrips():
for i in range(rgbStrip.STRIP_LENGHT):
if rgbStrip.STRIP_LENGHT-1-10 is not i:
rgbStrip.WS2812b(rgbStrip.STRIP_LENGHT-i-1, rgbStrip.red[rgbStrip.STRIP_LENGHT-i-2], rgbStrip.green[rgbStrip.STRIP_LENGHT-i-2], rgbStrip.blue[rgbStrip.STRIP_LENGHT-i-2])
else:
rgbStrip.WS2812b(rgbStrip.STRIP_LENGHT-i-1, self.fft_random[0], self.fft_random[1], self.fft_random[2])
rgbStrip.show()
"""
# shorten the cumulative list to account for changes in dynamics
if len(self.low_freq_avg_list) > 500:
@ -187,8 +197,7 @@ class musikEffect(BaseEffect):
self.low_freq_avg_list = []
print("new song")
self.off()
self.rgbStripController.pyAudioRecorder.newAudio = False
self.hasNewFttValues = False
# print(self.bpm_list)250
def strobe(self):

View File

@ -0,0 +1,184 @@
from Utils.BaseEffect import BaseEffect
from Utils.RGBStrip import RGBStrip
from Utils.EffectParameter import slider, colorpicker
import time
import sys
import numpy
from time import perf_counter, sleep
from random import randint, shuffle
import typing
import matplotlib
import matplotlib.pyplot as plt
#matplotlib.use('TkAgg') # THIS MAKES IT FAST!
matplotlib.get_backend()
class MusikEffect2(BaseEffect):
name = "musikEffect2"
desc = "LED-Band *sollte* nach musik blinken"
# Something that will be used to show descriptions and value options
# of the parameters the effect will accept, in a way, that eg the webclient can decide,
# if the parameters can be toggeled by a button/checkbox/slider/whatever
"""radio(
"Shuffle LED to Freq Order",
"Off -> Mapping ",
[
[0,255,255,"red"],
[0,255,255,"green"],
[0,255,255,"blue"]
]
),"""
effectParameters: list = [
slider(
"Effect Brightnes",
"Choose a brightness for your LED's",
[
[0,100,100,"brightness"],
]
)
]
def init(self):
self.fft_random_keys = [0,1,2,3]
self.fft_random = [0,0,0,0]
self.y_max_freq_avg_list = [0]
self.low_freq_avg_list = [0]
self.bpm_list = []
self.prev_beat = 0 # timestamp
'''
self.fig = plt.gcf()
self.fig.show()
'''
return
#loop effect as long as not stopped
def effect(self):
'''plt.clf()
#plt.ylim(-.5, numpy.amax(self.y_max_freq_avg_list))
plt.xlabel('xs')
plt.ylabel('ys')
plt.plot(self.ftt[0],self.ftt[1])
self.fig.canvas.draw()
self.fig.canvas.flush_events()'''
self.plot_audio_and_detect_beats()
#self.freqtocolor()
#if(time.time() - self.lastTime >= 0.002):
#for RGBStrip in self.effectRGBStrips():
# r= RGBStrip.red-1
# if(r<0):
# r=0
# g= RGBStrip.green-1
# if(g<0):
# g=0
# b= RGBStrip.blue-1
# if(b<0):
# b=0
# RGBStrip.RGB(r,g,b)
#self.lastTime = time.time()
sleep(0.00833333333)
def end(self):
pass
def plot_audio_and_detect_beats(self):
if not self.hasNewFttValues:
return
# get x and y values from FFT
xs, ys = self.ftt
amax = numpy.amax(ys)
if amax > 0:
self.y_max_freq_avg_list.append(amax)
if len(self.y_max_freq_avg_list ) > 50000:
self.y_max_freq_avg_list = self.y_max_freq_avg_list[25000:]
calc = numpy.amax(ys) / numpy.amax(self.y_max_freq_avg_list) * 765
"""print(amax)
print(numpy.amax(self.y_max_freq_avg_list))
print(calc)
print("-----------")
"""
c: self.Color = self.pitchRainbow(calc)
rgbStrip: RGBStrip
for rgbStrip in self.effectRGBStrips():
"""
for i in range(rgbStrip.STRIP_LENGHT):
if rgbStrip.STRIP_LENGHT-1-10 is not i:
rgbStrip.WS2812b(rgbStrip.STRIP_LENGHT-i-1, rgbStrip.red[rgbStrip.STRIP_LENGHT-i-2], rgbStrip.green[rgbStrip.STRIP_LENGHT-i-2], rgbStrip.blue[rgbStrip.STRIP_LENGHT-i-2])
else:
rgbStrip.WS2812b(rgbStrip.STRIP_LENGHT-i-1, c.red, c.green, c.blue)
rgbStrip.show()
"""
rgbStrip.RGB(int(c.red),int(c.green),int(c.blue))
# shorten the cumulative list to account for changes in dynamics
def pitchRainbow(self,p: float):
if p < 1:
return self.Color(0,0,0)
elif p < 255:
return self.Color(255 - p % 255,p % 255,0)
elif p < 510:
return self.Color(0,255 - p % 255,p % 255)
else:
return self.Color(p % 255,0,255 - p % 255)
def pitchConv(self,p: float):
r:float
g:float
b:float
if p < 40:
return self.Color(255,0,0)
elif p >= 40 and p <= 77 :
b = (p - 40) * (255/37.0000)
return self.Color(255,0,b)
elif p > 77 and p <= 205:
r = 255 - ((p - 78) * 2)
return self.Color(r,0,255)
elif p >= 206 and p <= 238:
g = (p - 206) * (255/32.0000)
return self.Color(0,g,255)
elif p <= 239 and p <= 250:
r = (p - 239) * (255/11.0000)
return self.Color(r, 255, 255)
elif p >= 251 and p <= 270:
return self.Color(255, 255, 255)
elif p >= 271 and p <= 398:
rb = 255-((p-271)*2)
return self.Color(rb, 255, rb)
elif p >= 398 and p <= 650:
return self.Color(0, 255-(p-398), (p-398))
else:
return self.Color(255, 0, 0)
class Color:
red: float
green: float
blue: float
def __init__(self,red:float,green:float,blue:float) -> None:
self.red = red
self.green = green
self.blue = blue

View File

@ -1,9 +1,8 @@
from rgbUtils.BaseEffect import BaseEffect
from rgbUtils.debug import debug
from Utils.BaseEffect import BaseEffect
import time
class offEffect(BaseEffect):
class OffEffect(BaseEffect):
name = "offEffect"
desc = "LED-Band *sollte* nicht an sein"

View File

@ -1,9 +1,8 @@
from rgbUtils.BaseEffect import BaseEffect
from rgbUtils.EffectParameter import slider, colorpicker
from rgbUtils.debug import debug
from Utils.BaseEffect import BaseEffect
from Utils.EffectParameter import slider, colorpicker
import time
class onEffect(BaseEffect):
class OnEffect(BaseEffect):
name = "onEffect"
desc = "LED-Band *sollte* an sein"

View File

@ -1,8 +1,7 @@
from rgbUtils.BaseEffect import BaseEffect
from rgbUtils.debug import debug
from Utils.BaseEffect import BaseEffect
import time
class rainbowEffect(BaseEffect):
class RainbowEffect(BaseEffect):
name = "rainbowEffect"
desc = "LED-Band *sollte* rainbowEffect sein"
@ -13,7 +12,6 @@ class rainbowEffect(BaseEffect):
#loop effect as long as not stopped
def effect(self):
debug(self)
"""Draw rainbow that fades across all pixels at once."""
for j in range(256*75):
for rgbStrip in self.effectRGBStrips():

View File

@ -1,9 +1,8 @@
from rgbUtils.BaseEffect import BaseEffect
from rgbUtils.debug import debug
from Utils.BaseEffect import BaseEffect
from random import randint
import time
class strobeEffect(BaseEffect):
class StrobeEffect(BaseEffect):
name = "strobeEffect"
desc = "*Strobe*"

View File

@ -1,21 +1,26 @@
import time
import threading
import typing
import copy
from rgbUtils.debug import debug
class BaseEffect(threading.Thread):
# The Name and the Description of the Effect,
# should be overwritten by the inheritancing Effect
name = "Undefined"
desc = "No Description"
name: str = "Undefined"
desc: str = "No Description"
# Something that will be used to show descriptions and value options
# of the parameters the effect will accept, in a way, that eg the webclient can decide,
# if the parameters can be toggeled by a button/checkbox/slider/whatever
effectParameters = []
effectParameters: list = []
stop = False
# musiceffect things
# TODO we need a recorderController where the effect binds to and gets its values, this is shit...
hasNewFttValues = False
ftt: typing.Tuple[typing.List[float],typing.List[float]] = ([],[])
stop:bool = False
def __init__(self):
threading.Thread.__init__(self)
@ -48,7 +53,7 @@ class BaseEffect(threading.Thread):
# to avoid two effects accessing the rgbStrip
def effect(self):
while 1:
debug("ET "+self.name+" effect() function needs to be replaced in inheritancing Effect")
print("ET "+self.name+" effect() function needs to be replaced in inheritancing Effect")
# called when the effect is stopped
def end(self):
@ -75,6 +80,10 @@ class BaseEffect(threading.Thread):
def onEffectParameterValuesUpdated(self):
return
def updateFttValues(self,ftt: typing.Tuple[typing.List[float],typing.List[float]]):
self.hasNewFttValues = True
self.ftt = ftt
# returns a list of the RGBStrips used by this effect
def effectRGBStrips(self):
return self.effectRGBStripList

View File

@ -0,0 +1,245 @@
# import offEffect
from Effects.OffEffect import OffEffect
from Utils.BaseEffect import BaseEffect
import time
import threading
import os
import sys
#TypeCheck
from typing import Type, List
from Utils.RGBStrip import RGBStrip
from Utils.RGBStripController import RGBStripController
class EffectController:
'''
the effectController handles the effects and pushes the values to the rgbStripContoller
it also calls the backendProvider's onChange function when there are changes made on the effects:
- start/stop effects
- changes parameters of specific effects
- moves the rgbStrips to the effects
- runs a guardian that detects dead effectThreads and moves Strips to offEffect
'''
rememberRGBStripEffectThreads: dict = {}
# list of current running effects
effectThreads: List[BaseEffect] = []
# the always running base effect
offEffectThreadObject: BaseEffect
# maybe i will seperate this later
onControllerChangeHandler: List[Type[object]] = []
#rgbStripController
rgbStripController: RGBStripController
def __init__(self,rgbStripController: RGBStripController) -> None:
'''Init the EffectController with the RGBStripController'''
self.rgbStripController = rgbStripController
# load the effects
self.effectsList: List[Type[BaseEffect]] = self.getEffectsListFromDir()
# start the offEffect by default
self.offEffectThreadObject = self.startEffect(OffEffect,[])
# - a bit of failover handling, remove dead threads from effectThread array
# - move strips without an effect to the offEffect
self.effectGuardian = self.EffectGuardian(self)
self.effectGuardian.start()
def startEffect(self, effectClass: Type[BaseEffect], rgbStrips: list, params: list = []) -> BaseEffect: #TODO params as a object -> EffectParams
'''starts a effect by given class, rgbStrips and params ([[index,[param,param,param]],[index,[param,param,param]]])'''
newEffect = effectClass()
if len(self.effectThreads) > 0 and len(rgbStrips) > 0 or len(self.effectThreads) == 0:
newEffect.start()
self.updateEffectParameters(newEffect, params)
self.effectThreads.append(newEffect)
for rgbStrip in rgbStrips:
self.moveRGBStripToEffectThread(rgbStrip, newEffect)
self.noticeControllerChange()
return newEffect
def getEffects(self) -> List[Type[BaseEffect]]:
'''
returns all effectClasses but offEffect, since offEffect will never be killed
and should not be running twice
'''
# alle außer offEffect
return self.effectsList
def getEffectThreads(self) -> List[BaseEffect]:
'''returns all running effectThreads'''
return self.effectThreads
def getEffectRGBStrips(self, effectThreadObject: BaseEffect) -> List[RGBStrip]:
'''returns a list of the RGBStrips used by this effect'''
return effectThreadObject.effectRGBStrips()
def moveRGBStripToEffectThread(self, rgbStrip: RGBStrip, effectThreadObject: BaseEffect) -> None:
'''move a rgbStip to a running effectThread'''
# cycle throught all effects and
# remove Strip from effect if added
for et in self.effectThreads:
if rgbStrip in et.effectRGBStrips():
et.removeRGBStrip(rgbStrip)
if effectThreadObject.isAlive():
self.rememberRGBStripEffectThreads[rgbStrip.STRIP_NAME] = et
effectThreadObject.addRGBStrip(rgbStrip)
# check if any effectThread has no more rgbStrips and if so, stop it
# if the effectThread has no more strips, we stop it and remove it.
for x, effectThread in enumerate(self.effectThreads):
# but ignore the first effectthread, since that is our offeffect that should never be killed
if len(effectThread.effectRGBStrips()) == 0 and x is not 0:
effectThread.stopEffect()
self.effectThreads.remove(effectThread)
self.noticeControllerChange()
def updateEffectParameters(self, effectThreadObject: BaseEffect, effectParameters: list):
'''updates parameter of a running effectThread ([[index,[param,param,param]],[index,[param,param,param]]])'''
for effectParameter in effectParameters:
effectThreadObject.updateEffectParameterValues(
effectParameter[0], effectParameter[1])
self.noticeControllerChange()
def stopAll(self):
'''stops all effectThreads and set the rgbStrips to off'''
print("effectController stopAll()")
for effectThread in self.effectThreads:
print("effectController killing... "+str(effectThread))
effectThread.stopEffect()
print("effectController killed "+str(effectThread))
print("effectController stopping Guardian... ")
self.effectGuardian.stop()
print("effectController stopped Guardian")
time.sleep(0.5)
def noticeControllerChange(self) -> None:
'''inform the controllerChangeHandler to update the client'''
for controllerChangeHandler in self.onControllerChangeHandler:
controllerChangeHandler()
def addOnControllerChangeHandler(self, hander: Type[object]) -> None: #TODO class instead of function for OnControllerChangeHandler?
'''add onControllerChangeHandler'''
print("addOnControllerChangeHandler", str(hander))
self.onControllerChangeHandler.append(hander)
# send data to this client
hander()
def removeOnControllerChangeHandler(self, hander: Type[object]): #TODO class instead of function for OnControllerChangeHandler?
'''remove onControllerChangeHandler'''
print("removeOnControllerChangeHandler", str(hander))
if hander in self.onControllerChangeHandler:
self.onControllerChangeHandler.remove(hander)
else:
print('\n\n -> client was never registered!')
def getEffectsListFromDir(self) -> List[Type[BaseEffect]]:
'''automaticly loads all modules from effects subdir and adds them to the list of effects if they have the BaseEffect as subclass'''
effectsList: List[Type[BaseEffect]] = []
for raw_module in os.listdir(os.path.abspath(os.path.join(os.path.join(os.path.dirname(__file__), os.pardir),"Effects"))):
if raw_module == '__init__.py' or raw_module == 'OffEffect.py' or raw_module[-3:] != '.py':
continue
effectModule = __import__("Effects."+raw_module[:-3], fromlist=[raw_module[:-3]])
effectClass = getattr(effectModule, raw_module[:-3])
if issubclass(effectClass,BaseEffect):
effectsList.append(effectClass)
print("Loaded effects: ",effectsList)
return effectsList
def onRGBStripRegistered(self,rgbStrip: RGBStrip):
''' moves new rgbStrip to the offEffectThread and notice all Controller Clients'''
if rgbStrip.STRIP_NAME in self.rememberRGBStripEffectThreads:
restoredEffect: BaseEffect = self.rememberRGBStripEffectThreads[rgbStrip.STRIP_NAME]
if restoredEffect.isAlive():
print("stripname in rememberRGBStripEffectThreads -> same effect was never stopped, move to")
self.moveRGBStripToEffectThread(rgbStrip,restoredEffect)
else:
print("stripname in rememberRGBStripEffectThreads -> create new effect")
effectParamValueList: list = []
for x in range(len(restoredEffect.effectParameterValues)):
valdict: dict = {}
for y in range(len(restoredEffect.effectParameterValues[x])):
valdict[y] = restoredEffect.effectParameterValues[x][y]
effectParamValueList.append([x,valdict])
self.startEffect(restoredEffect.__class__,[rgbStrip],effectParamValueList)
self.rememberRGBStripEffectThreads.pop(rgbStrip.STRIP_NAME)
else:
print("stripname was not in rememberRGBStripEffectThreads")
self.offEffectThreadObject.addRGBStrip(rgbStrip)
self.noticeControllerChange()
def onRGBStripUnRegistered(self,rgbStrip: RGBStrip):
'''
cycle throught all effectThreadss and
remove Strip from effect if added
'''
et: BaseEffect
for et in self.effectThreads:
if rgbStrip in et.effectRGBStrips():
et.removeRGBStrip(rgbStrip)
# if the effectThread has no more strips, we stop it and remove it.
for x, effectThread in enumerate(self.effectThreads):
# but ignore the first effectthread, since that is our offeffect that should never be killed
if len(effectThread.effectRGBStrips()) == 0 and x is not 0:
effectThread.stopEffect()
self.effectThreads.remove(effectThread)
self.noticeControllerChange()
def updateFttValues(self,ftt: tuple):
''' TODO this is a themorary funtion util a recorderController is build'''
effectThread: BaseEffect
for effectThread in self.effectThreads:
effectThread.updateFttValues(ftt)
class EffectGuardian(threading.Thread):
'''
a bit of failover handling, remove dead threads from effectThread array
move strips without an effect to the offEffect
This Guardian detects Effect Threads that are killed in some unnormal way
This is not the procedere how effects are stoped
Something went wrong when the guarian is removing dead threads!
'''
def __init__(self, effectController):
threading.Thread.__init__(self, name='EffectGuardian')
self.effectController = effectController
self.stopped = False
def run(self):
while not self.stopped:
for effectThread in self.effectController.effectThreads:
# if Thread was killed by something else, we remove it from the list
if not effectThread.isAlive():
for rgbStrip in effectThread.effectRGBStrips():
self.effectController.moveRGBStripToEffectThread(rgbStrip,self.effectController.offEffectThreadObject)
self.effectController.effectThreads.remove(effectThread)
print("effectController:effectGuardian removed dead Thread " +
str(effectThread) + ". There must be an error in code!")
self.effectController.noticeControllerChange()
time.sleep(1)
def stop(self):
self.stopped = True

View File

@ -1,6 +1,6 @@
import threading
class effectParameter(object):
class EffectParameter(object):
# The Name and the Description of the EffectParameter,
# should be overwritten by the inheritancing EffectParameter
name="Undefined"
@ -12,7 +12,7 @@ class effectParameter(object):
# [min/off,max/on,current,"description"],
# [min/off,max/on,current,"description"],
# ]
options = []
options: list = []
def __init__(self,name,desc,initOptions = []):
self.name = name
@ -27,7 +27,7 @@ class effectParameter(object):
else:
return False
class colorpicker(effectParameter):
class colorpicker(EffectParameter):
name="UndefinedColorpicker"
desc="No Description"
type="colorpicker"
@ -36,7 +36,7 @@ class colorpicker(effectParameter):
def testValue(self,index,value):
return True
class slider(effectParameter):
class slider(EffectParameter):
name="UndefinedSlider"
desc="No Description"
type="slider"

View File

@ -11,14 +11,13 @@
import numpy
import scipy
import pyaudio
import threading
import time
class pyAudioRecorder:
class PyAudioRecorder:
"""Simple, cross-platform class to record from the default input device."""
def __init__(self):

View File

@ -1,16 +1,19 @@
from rgbUtils.debug import debug
import uuid
import typing
class RGBStrip:
# name = the name off the the strip, defined by the client connecting to the server
# uid = unique id, if the strip sends one, use this (later maybe, or never, whatever)
# lenght = the lenght off the strip, for future use of eg WS2812b strips, will be 1 by default
def __init__(self,name,onValuesUpdateHandler,lenght=1):
STRIP_NAME: str
STRIP_LENGHT: int
def __init__(self,name: str,onValuesUpdateHandler: object,lenght: int=1,address: typing.Tuple[str,int] = ("0.0.0.0",0000)):
# UID should be updateable later, or not?
# when updating, be sure it does not exist
self.STRIP_UID = str(uuid.uuid4())
self.STRIP_NAME = name
self.STRIP_LENGHT = lenght
self.address = address
self.onValuesUpdateHandler = onValuesUpdateHandler
@ -18,7 +21,7 @@ class RGBStrip:
self.green = [0]*self.STRIP_LENGHT
self.blue = [0]*self.STRIP_LENGHT
def RGB(self,red,green,blue,brightness = 100):
def RGB(self,red: int,green: int,blue: int,brightness: int = 100):
if(red < 0):
red = 0
@ -89,7 +92,6 @@ class RGBStrip:
self.onValuesUpdateHandler(self)
def getData(self):
self.hasNewData = False
return [self.red,self.green,self.blue]

View File

@ -1,15 +1,20 @@
from rgbUtils.RGBStrip import RGBStrip
from Utils.RGBStrip import RGBStrip
import time
import threading
import json
class rgbStripController():
class RGBStripController:
'''
rgbStrips register themselves at the rgbStripContoller
the rgbStripController calls the backend Provider's onChange function
when there are new values for the strip
'''
def __init__(self):
#threading.Thread.__init__(self)
self.rgbStrips = []
self.onRGBStripRegisteredHandler = []
self.onRGBStripUnRegisteredHandler = []
def registerRGBStrip(self,rgbStripName,onValuesUpdateHandler,ledcount=1):
def registerRGBStrip(self,rgbStripName: str,onValuesUpdateHandler: object,ledcount=1):
# maybe we can use an unique id if the strip reconnects later, eg push the uid
# to the client on first connect and if he reconnects he sould send it back again.
# the wmos could use the mac adress, if there is a python script it can save the uid

View File

@ -1,183 +0,0 @@
# import offEffect
from effects.offEffect import offEffect
from rgbUtils.debug import debug
from rgbUtils.BaseEffect import BaseEffect
from rgbUtils.RGBStrip import RGBStrip
import time
import threading
import os
import sys
#
# handles all the effects:
# - start/stop effects
# - changes parameters of specific effects
# - moves the rgbStrips to the effects
# - runs a guardian that detects dead effectThreads and moves Strips to offEffect
#
class effectController:
# list of current running effects
effectThreads = []
offEffectThreadObject = None
# maybe i will seperate this later
onControllerChangeHandler = []
def __init__(self,rgbStripController):
self.rgbStripController = rgbStripController
# load the effects
self.effectsList = self.getEffectsListFromDir()
# start the offEffect by default
self.offEffectThreadObject = self.startEffect(offEffect,[])
# - a bit of failover handling, remove dead threads from effectThread array
# - move strips without an effect to the offEffect
self.effectGuardian = self.effectGuardian(self)
self.effectGuardian.start()
# starts a effect by given class, rgbStrips and params ([[index,[param,param,param]],[index,[param,param,param]]])
def startEffect(self, effectClass: BaseEffect, rgbStrips: list, params: list = []):
newEffect = effectClass()
if len(self.effectThreads) > 0 and len(rgbStrips) > 0 or len(self.effectThreads) == 0:
newEffect.start()
self.updateEffectParameters(newEffect, params)
self.effectThreads.append(newEffect)
for rgbStrip in rgbStrips:
self.moveRGBStripToEffectThread(rgbStrip, newEffect)
self.noticeControllerChange()
return newEffect
# returns all effectClasses but offEffect, since offEffect will never be killed
# and should not be running twice
def getEffects(self):
# alle außer offEffect
return self.effectsList
# returns all running effectThreads
def getEffectThreads(self):
return self.effectThreads
# returns a list of the RGBStrips used by this effect
def getEffectRGBStrips(self, effectThreadObject: BaseEffect):
return effectThreadObject.effectRGBStrips()
# move a rgbStip to a running effectThread
def moveRGBStripToEffectThread(self, rgbStrip: RGBStrip, effectThreadObject: BaseEffect):
# cycle throught all effects and
# remove Strip from effect if added
for et in self.effectThreads:
if rgbStrip in et.effectRGBStrips():
et.removeRGBStrip(rgbStrip)
if effectThreadObject.isAlive():
effectThreadObject.addRGBStrip(rgbStrip)
# check if any effectThread has no more rgbStrips and if so, stop it
# if the effectThread has no more strips, we stop it and remove it.
for x, effectThread in enumerate(self.effectThreads):
if len(effectThread.effectRGBStrips()) == 0 and x is not 0:
effectThread.stopEffect()
self.effectThreads.remove(effectThread)
self.noticeControllerChange()
# updates parameter of a running effectThread
def updateEffectParameters(self, effectThreadObject: BaseEffect, effectParameters):
for effectParameter in effectParameters:
effectThreadObject.updateEffectParameterValues(
effectParameter[0], effectParameter[1])
self.noticeControllerChange()
# stops all effectThreads and set the rgbStrips to off
def stopAll(self):
debug("effectController stopAll()")
for effectThread in self.effectThreads:
effectThread.stopEffect()
debug("effectController killed "+str(effectThread))
self.effectGuardian.stop()
time.sleep(0.5)
# GPIO.cleanup()
# inform the controllerChangeHandler to update the client
def noticeControllerChange(self):
for controllerChangeHandler in self.onControllerChangeHandler:
controllerChangeHandler()
# add onControllerChangeHandler
def addOnControllerChangeHandler(self, hander):
print("addOnControllerChangeHandler", str(hander))
self.onControllerChangeHandler.append(hander)
# send data to this client
hander()
# remove onControllerChangeHandler
def removeOnControllerChangeHandler(self, hander):
print("removeOnControllerChangeHandler", str(hander))
if hander in self.onControllerChangeHandler:
self.onControllerChangeHandler.remove(hander)
else:
print('\n\n -> client was never registered!')
# automaticly loads all modules from effects subdir and adds them to the list of effects if they have the BaseEffect as subclass
def getEffectsListFromDir(self):
effectsList = []
for raw_module in os.listdir(os.path.abspath(os.path.join(os.path.join(os.path.dirname(__file__), os.pardir),"effects"))):
if raw_module == '__init__.py' or raw_module == 'offEffect.py' or raw_module[-3:] != '.py':
continue
effectModule = __import__("effects."+raw_module[:-3], fromlist=[raw_module[:-3]])
effectClass = getattr(effectModule, raw_module[:-3])
if issubclass(effectClass,BaseEffect):
effectsList.append(effectClass)
print("Loaded effects: ",effectsList)
return effectsList
def onRGBStripRegistered(self,rgbStrip):
self.offEffectThreadObject.addRGBStrip(rgbStrip)
self.noticeControllerChange()
def onRGBStripUnRegistered(self,rgbStrip):
# cycle throught all effects and
# remove Strip from effect if added
for et in self.effectThreads:
if rgbStrip in et.effectRGBStrips():
et.removeRGBStrip(rgbStrip)
# if the effectThread has no more strips, we stop it and remove it.
for x, effectThread in enumerate(self.effectThreads):
if len(effectThread.effectRGBStrips()) == 0 and x is not 0:
effectThread.stopEffect()
self.effectThreads.remove(effectThread)
self.noticeControllerChange()
# - a bit of failover handling, remove dead threads from effectThread array
# - move strips without an effect to the offEffect
class effectGuardian(threading.Thread):
def __init__(self, effectController):
threading.Thread.__init__(self, name='effectGuardian')
self.effectController = effectController
self.stopped = False
def run(self):
while not self.stopped:
for effectThread in self.effectController.effectThreads:
# if Thread was killed by something else, we remove it from the list
if not effectThread.isAlive():
for rgbStrip in effectThread.effectRGBStrips():
self.effectController.moveRGBStripToEffectThread(rgbStrip,self.effectController.offEffectThreadObject)
self.effectController.effectThreads.remove(effectThread)
print("effectController:effectGuardian removed dead Thread " +
str(effectThread) + ". There must be an error in code!")
self.effectController.noticeControllerChange()
time.sleep(1)
def stop(self):
self.stopped = True