renaming folders and files to python format
This commit is contained in:
		
							parent
							
								
									ade378d128
								
							
						
					
					
						commit
						798775805c
					
				| @ -18,7 +18,6 @@ class ThreadedUDPServer(threading.Thread): | |||||||
|         self.start() |         self.start() | ||||||
|         self.udpClientGuardian = self.UDPClientGuardian() |         self.udpClientGuardian = self.UDPClientGuardian() | ||||||
|         self.udpClientGuardian.start() |         self.udpClientGuardian.start() | ||||||
|         UDPClients |  | ||||||
| 
 | 
 | ||||||
| 
 | 
 | ||||||
|     def run(self): |     def run(self): | ||||||
| @ -86,13 +85,6 @@ class UDPClient(): | |||||||
|         self.lastping = time() |         self.lastping = time() | ||||||
| 
 | 
 | ||||||
|     def handle(self, request): |     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 Types: | ||||||
|         # CLIENT_TYPE_CONTROLLER = 0 |         # CLIENT_TYPE_CONTROLLER = 0 | ||||||
|         # CLIENT_TYPE_STRIPE = 1 |         # CLIENT_TYPE_STRIPE = 1 | ||||||
| @ -104,8 +96,9 @@ class UDPClient(): | |||||||
|         # s:ping |         # s:ping | ||||||
|         # UDP  |         # UDP  | ||||||
| 
 | 
 | ||||||
|  |         self.socket = request[1] | ||||||
|         try: |         try: | ||||||
|             data = clientdata.split(':') |             data = request[0].decode().split(':') | ||||||
|             #print(data) |             #print(data) | ||||||
|             # r:1:srg strip name |             # 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: |             if data[0] == "r" and int(data[1]) == CLIENT_TYPE_STRIPE and data[2] != None and self.registered is False: | ||||||
|  | |||||||
| @ -22,8 +22,8 @@ class ThreadedWebSocketServer(Thread): | |||||||
| 
 | 
 | ||||||
| import json | import json | ||||||
| 
 | 
 | ||||||
| from rgbUtils import effectControllerJsonHelper | from BackendProvider.Helper import effectControllerJsonHelper | ||||||
| from rgbUtils import rgbStripControllerJsonHelper | from BackendProvider.Helper import rgbStripControllerJsonHelper | ||||||
| 
 | 
 | ||||||
| import traceback | import traceback | ||||||
| import logging | import logging | ||||||
| @ -63,12 +63,6 @@ class HTTPWebSocketsHandler(WebSocket): | |||||||
|                     ledcount=1 |                     ledcount=1 | ||||||
|                     if "led_count" in data: |                     if "led_count" in data: | ||||||
|                         ledcount = int(data["led_count"]) |                         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  |                     # registers the strip with websocket object and name. the onRGBStripValueUpdate(rgbStrip) is called by  | ||||||
|                     # by the rgbStrip when an effectThread updates it |                     # by the rgbStrip when an effectThread updates it | ||||||
| @ -87,13 +81,9 @@ class HTTPWebSocketsHandler(WebSocket): | |||||||
|                     }) |                     }) | ||||||
|                 ) |                 ) | ||||||
|                 return |                 return | ||||||
|  | 
 | ||||||
|             # the stripe should usualy not send any data, i do not know why it should... |             # the stripe should usualy not send any data, i do not know why it should... | ||||||
|             elif self.client_type is CLIENT_TYPE_STRIPE: |             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 |                 return | ||||||
|             # audio recorder responses are handled by the effectControllerJsonHandler |             # audio recorder responses are handled by the effectControllerJsonHandler | ||||||
|             elif self.client_type is CLIENT_TYPE_RECORDER: |             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 |     # when a rgbStrip value is changed, send json data to client | ||||||
|     def onRGBStripValueUpdate(self,rgbStrip): |     def onRGBStripValueUpdate(self,rgbStrip): | ||||||
|         if self.nosend == 0: |         self.sendMessage( | ||||||
|             if self.nojson == 0: |             json.dumps({ | ||||||
|                 self.sendMessage( |                 'data': rgbStripControllerJsonHelper.getRGBData(rgbStrip) | ||||||
|                     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) |  | ||||||
|  | |||||||
| @ -1,15 +1,13 @@ | |||||||
| from rgbUtils.BaseEffect import BaseEffect | from Utils.BaseEffect import BaseEffect | ||||||
| from rgbUtils.EffectParameter import slider, colorpicker | from Utils.EffectParameter import slider, colorpicker | ||||||
| from rgbUtils.debug import debug |  | ||||||
| import time | import time | ||||||
| 
 | 
 | ||||||
| import sys | import sys | ||||||
| import numpy | import numpy | ||||||
| from rgbUtils.pyAudioRecorder import pyAudioRecorder |  | ||||||
| from time import perf_counter, sleep | from time import perf_counter, sleep | ||||||
| from random import randint, shuffle | from random import randint, shuffle | ||||||
| 
 | 
 | ||||||
| class musikEffect(BaseEffect): | class MusikEffect(BaseEffect): | ||||||
|     name = "musikEffect" |     name = "musikEffect" | ||||||
|     desc = "LED-Band *sollte* nach musik blinken" |     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  |     # 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,  |     # 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 |     # if the parameters can be toggeled by a button/checkbox/slider/whatever | ||||||
|     effectParameters = [ |     effectParameters: list = [ | ||||||
|     #     radio(\    |     #     radio(\    | ||||||
|     #         "Shuffle LED to Freq Order",\ |     #         "Shuffle LED to Freq Order",\ | ||||||
|     #         "Off -> Mapping  ",\ |     #         "Off -> Mapping  ",\ | ||||||
| @ -42,12 +40,14 @@ class musikEffect(BaseEffect): | |||||||
|         self.fft_random_keys = [0,1,2,3] |         self.fft_random_keys = [0,1,2,3] | ||||||
|         self.fft_random = [0,0,0,0] |         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()  |         # used by strobe()  | ||||||
|         self.lastmode = 0 |         self.lastmode = 0 | ||||||
| 
 | 
 | ||||||
|         self.recorderClient = pyAudioRecorder.recorderClient() |  | ||||||
|         self.rgbStripController.pyAudioRecorder.registerRecorderClient(self.recorderClient) |  | ||||||
| 
 |  | ||||||
|         return |         return | ||||||
| 
 | 
 | ||||||
|     #loop effect as long as not stopped |     #loop effect as long as not stopped | ||||||
| @ -67,17 +67,17 @@ class musikEffect(BaseEffect): | |||||||
|         #        b=0 |         #        b=0 | ||||||
|         #    RGBStrip.RGB(r,g,b) |         #    RGBStrip.RGB(r,g,b) | ||||||
|         #self.lastTime = time.time() |         #self.lastTime = time.time() | ||||||
|         sleep(.001) |         sleep(0.00833333333) | ||||||
| 
 | 
 | ||||||
|     def end(self): |     def end(self): | ||||||
|        self.rgbStripController.pyAudioRecorder.unregisterRecorderClient(self.recorderClient) |         pass | ||||||
| 
 | 
 | ||||||
|     def plot_audio_and_detect_beats(self): |     def plot_audio_and_detect_beats(self): | ||||||
|         if not self.rgbStripController.pyAudioRecorder.has_new_audio:  |         if not self.hasNewFttValues:  | ||||||
|             return |             return | ||||||
| 
 | 
 | ||||||
|         # get x and y values from FFT |         # get x and y values from FFT | ||||||
|         xs, ys = self.rgbStripController.pyAudioRecorder.fft() |         xs, ys = self.ftt | ||||||
| 
 | 
 | ||||||
|         # calculate average for all frequency ranges |         # calculate average for all frequency ranges | ||||||
|         y_avg = numpy.mean(ys) |         y_avg = numpy.mean(ys) | ||||||
| @ -88,9 +88,9 @@ class musikEffect(BaseEffect): | |||||||
|         #mid_freq = numpy.mean(ys[88:115]) |         #mid_freq = numpy.mean(ys[88:115]) | ||||||
|         #hig_freq = numpy.mean(ys[156:184]) |         #hig_freq = numpy.mean(ys[156:184]) | ||||||
|          |          | ||||||
|         low_freq = numpy.mean(ys[0:67]) |         low_freq = numpy.mean(ys[0:int(ys.__len__() / 3 * 1)]) | ||||||
|         mid_freq = numpy.mean(ys[68:135]) |         mid_freq = numpy.mean(ys[int(ys.__len__() / 3 * 1):int(ys.__len__() / 3 * 2)]) | ||||||
|         hig_freq = numpy.mean(ys[136:204]) |         hig_freq = numpy.mean(ys[int(ys.__len__() / 3 * 2):int(ys.__len__() / 3 * 3)]) | ||||||
|          |          | ||||||
|         #get the maximum of all freq |         #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): |         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[1], | ||||||
|                     self.fft_random[2] |                     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 |         # shorten the cumulative list to account for changes in dynamics | ||||||
|         if len(self.low_freq_avg_list) > 500: |         if len(self.low_freq_avg_list) > 500: | ||||||
| @ -187,8 +197,7 @@ class musikEffect(BaseEffect): | |||||||
|             self.low_freq_avg_list = [] |             self.low_freq_avg_list = [] | ||||||
|             print("new song") |             print("new song") | ||||||
|             self.off() |             self.off() | ||||||
| 
 |         self.hasNewFttValues = False | ||||||
|         self.rgbStripController.pyAudioRecorder.newAudio = False |  | ||||||
|         # print(self.bpm_list)250 |         # print(self.bpm_list)250 | ||||||
| 
 | 
 | ||||||
|     def strobe(self): |     def strobe(self): | ||||||
							
								
								
									
										184
									
								
								server/Effects/MusikEffect2.py
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										184
									
								
								server/Effects/MusikEffect2.py
									
									
									
									
									
										Normal 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 | ||||||
| @ -1,9 +1,8 @@ | |||||||
| from rgbUtils.BaseEffect import BaseEffect | from Utils.BaseEffect import BaseEffect | ||||||
| from rgbUtils.debug import debug |  | ||||||
| 
 | 
 | ||||||
| import time | import time | ||||||
| 
 | 
 | ||||||
| class offEffect(BaseEffect): | class OffEffect(BaseEffect): | ||||||
|     name = "offEffect" |     name = "offEffect" | ||||||
|     desc = "LED-Band *sollte* nicht an sein" |     desc = "LED-Band *sollte* nicht an sein" | ||||||
| 
 | 
 | ||||||
| @ -1,9 +1,8 @@ | |||||||
| from rgbUtils.BaseEffect import BaseEffect | from Utils.BaseEffect import BaseEffect | ||||||
| from rgbUtils.EffectParameter import slider, colorpicker | from Utils.EffectParameter import slider, colorpicker | ||||||
| from rgbUtils.debug import debug |  | ||||||
| import time | import time | ||||||
| 
 | 
 | ||||||
| class onEffect(BaseEffect): | class OnEffect(BaseEffect): | ||||||
|     name = "onEffect" |     name = "onEffect" | ||||||
|     desc = "LED-Band *sollte* an sein" |     desc = "LED-Band *sollte* an sein" | ||||||
|      |      | ||||||
| @ -1,8 +1,7 @@ | |||||||
| from rgbUtils.BaseEffect import BaseEffect | from Utils.BaseEffect import BaseEffect | ||||||
| from rgbUtils.debug import debug |  | ||||||
| import time | import time | ||||||
| 
 | 
 | ||||||
| class rainbowEffect(BaseEffect): | class RainbowEffect(BaseEffect): | ||||||
|     name = "rainbowEffect" |     name = "rainbowEffect" | ||||||
|     desc = "LED-Band *sollte* rainbowEffect sein" |     desc = "LED-Band *sollte* rainbowEffect sein" | ||||||
| 
 | 
 | ||||||
| @ -13,7 +12,6 @@ class rainbowEffect(BaseEffect): | |||||||
| 
 | 
 | ||||||
|     #loop effect as long as not stopped |     #loop effect as long as not stopped | ||||||
|     def effect(self): |     def effect(self): | ||||||
|         debug(self) |  | ||||||
|         """Draw rainbow that fades across all pixels at once.""" |         """Draw rainbow that fades across all pixels at once.""" | ||||||
|         for j in range(256*75): |         for j in range(256*75): | ||||||
|             for rgbStrip in self.effectRGBStrips(): |             for rgbStrip in self.effectRGBStrips(): | ||||||
| @ -1,9 +1,8 @@ | |||||||
| from rgbUtils.BaseEffect import BaseEffect | from Utils.BaseEffect import BaseEffect | ||||||
| from rgbUtils.debug import debug |  | ||||||
| from random import randint | from random import randint | ||||||
| import time | import time | ||||||
| 
 | 
 | ||||||
| class strobeEffect(BaseEffect): | class StrobeEffect(BaseEffect): | ||||||
|     name = "strobeEffect" |     name = "strobeEffect" | ||||||
|     desc = "*Strobe*" |     desc = "*Strobe*" | ||||||
| 
 | 
 | ||||||
| @ -1,21 +1,26 @@ | |||||||
| import time | import time | ||||||
| import threading | import threading | ||||||
|  | import typing | ||||||
| import copy | import copy | ||||||
| from rgbUtils.debug import debug |  | ||||||
| 
 | 
 | ||||||
| class BaseEffect(threading.Thread): | class BaseEffect(threading.Thread): | ||||||
| 
 | 
 | ||||||
|     # The Name and the Description of the Effect,  |     # The Name and the Description of the Effect,  | ||||||
|     # should be overwritten by the inheritancing Effect |     # should be overwritten by the inheritancing Effect | ||||||
|     name = "Undefined" |     name: str = "Undefined" | ||||||
|     desc = "No Description" |     desc: str = "No Description" | ||||||
| 
 | 
 | ||||||
|     # Something that will be used to show descriptions and value options  |     # 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,  |     # 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 |     # 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): |     def __init__(self): | ||||||
|         threading.Thread.__init__(self) |         threading.Thread.__init__(self) | ||||||
| @ -48,7 +53,7 @@ class BaseEffect(threading.Thread): | |||||||
|     # to avoid two effects accessing the rgbStrip |     # to avoid two effects accessing the rgbStrip | ||||||
|     def effect(self): |     def effect(self): | ||||||
|         while 1: |         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 |     # called when the effect is stopped | ||||||
|     def end(self): |     def end(self): | ||||||
| @ -75,6 +80,10 @@ class BaseEffect(threading.Thread): | |||||||
|     def onEffectParameterValuesUpdated(self): |     def onEffectParameterValuesUpdated(self): | ||||||
|         return |         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 |     # returns a list of the RGBStrips used by this effect | ||||||
|     def effectRGBStrips(self): |     def effectRGBStrips(self): | ||||||
|         return self.effectRGBStripList |         return self.effectRGBStripList | ||||||
							
								
								
									
										245
									
								
								server/Utils/EffectController.py
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										245
									
								
								server/Utils/EffectController.py
									
									
									
									
									
										Normal 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 | ||||||
| @ -1,6 +1,6 @@ | |||||||
| import threading | import threading | ||||||
| 
 | 
 | ||||||
| class effectParameter(object): | class EffectParameter(object): | ||||||
|     # The Name and the Description of the EffectParameter,  |     # The Name and the Description of the EffectParameter,  | ||||||
|     # should be overwritten by the inheritancing EffectParameter |     # should be overwritten by the inheritancing EffectParameter | ||||||
|     name="Undefined" |     name="Undefined" | ||||||
| @ -12,7 +12,7 @@ class effectParameter(object): | |||||||
|     #   [min/off,max/on,current,"description"], |     #   [min/off,max/on,current,"description"], | ||||||
|     #   [min/off,max/on,current,"description"], |     #   [min/off,max/on,current,"description"], | ||||||
|     # ] |     # ] | ||||||
|     options = [] |     options: list = [] | ||||||
| 
 | 
 | ||||||
|     def __init__(self,name,desc,initOptions = []): |     def __init__(self,name,desc,initOptions = []): | ||||||
|         self.name = name |         self.name = name | ||||||
| @ -27,7 +27,7 @@ class effectParameter(object): | |||||||
|         else: |         else: | ||||||
|             return False |             return False | ||||||
| 
 | 
 | ||||||
| class colorpicker(effectParameter): | class colorpicker(EffectParameter): | ||||||
|     name="UndefinedColorpicker" |     name="UndefinedColorpicker" | ||||||
|     desc="No Description" |     desc="No Description" | ||||||
|     type="colorpicker" |     type="colorpicker" | ||||||
| @ -36,7 +36,7 @@ class colorpicker(effectParameter): | |||||||
|     def testValue(self,index,value): |     def testValue(self,index,value): | ||||||
|         return True |         return True | ||||||
| 
 | 
 | ||||||
| class slider(effectParameter): | class slider(EffectParameter): | ||||||
|     name="UndefinedSlider" |     name="UndefinedSlider" | ||||||
|     desc="No Description" |     desc="No Description" | ||||||
|     type="slider" |     type="slider" | ||||||
| @ -11,14 +11,13 @@ | |||||||
| 
 | 
 | ||||||
| 
 | 
 | ||||||
| import numpy | import numpy | ||||||
| import scipy |  | ||||||
| import pyaudio | import pyaudio | ||||||
| import threading | import threading | ||||||
| 
 | 
 | ||||||
| import time | import time | ||||||
| 
 | 
 | ||||||
| 
 | 
 | ||||||
| class pyAudioRecorder: | class PyAudioRecorder: | ||||||
|     """Simple, cross-platform class to record from the default input device.""" |     """Simple, cross-platform class to record from the default input device.""" | ||||||
| 
 | 
 | ||||||
|     def __init__(self): |     def __init__(self): | ||||||
| @ -1,16 +1,19 @@ | |||||||
| from rgbUtils.debug import debug |  | ||||||
| import uuid | import uuid | ||||||
|  | import typing | ||||||
| 
 | 
 | ||||||
| class RGBStrip: | class RGBStrip: | ||||||
|     # name = the name off the the strip, defined by the client connecting to the server |     # 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) |     # 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 |     # 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? |         # UID should be updateable later, or not? | ||||||
|         # when updating, be sure it does not exist |         # when updating, be sure it does not exist | ||||||
|         self.STRIP_UID = str(uuid.uuid4()) |         self.STRIP_UID = str(uuid.uuid4()) | ||||||
|         self.STRIP_NAME = name |         self.STRIP_NAME = name | ||||||
|         self.STRIP_LENGHT = lenght |         self.STRIP_LENGHT = lenght | ||||||
|  |         self.address = address | ||||||
| 
 | 
 | ||||||
|         self.onValuesUpdateHandler = onValuesUpdateHandler |         self.onValuesUpdateHandler = onValuesUpdateHandler | ||||||
| 
 | 
 | ||||||
| @ -18,7 +21,7 @@ class RGBStrip: | |||||||
|         self.green = [0]*self.STRIP_LENGHT |         self.green = [0]*self.STRIP_LENGHT | ||||||
|         self.blue = [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): |         if(red < 0): | ||||||
|             red = 0 |             red = 0 | ||||||
| @ -89,7 +92,6 @@ class RGBStrip: | |||||||
|         self.onValuesUpdateHandler(self) |         self.onValuesUpdateHandler(self) | ||||||
| 
 | 
 | ||||||
|     def getData(self): |     def getData(self): | ||||||
|         self.hasNewData = False |  | ||||||
|         return [self.red,self.green,self.blue] |         return [self.red,self.green,self.blue] | ||||||
| 
 | 
 | ||||||
| 
 | 
 | ||||||
| @ -1,15 +1,20 @@ | |||||||
| from rgbUtils.RGBStrip import RGBStrip | from Utils.RGBStrip import RGBStrip | ||||||
| import time | import time | ||||||
| import threading | import threading | ||||||
| import json | 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): |     def __init__(self): | ||||||
|         #threading.Thread.__init__(self) |         #threading.Thread.__init__(self) | ||||||
|         self.rgbStrips = [] |         self.rgbStrips = [] | ||||||
|         self.onRGBStripRegisteredHandler = [] |         self.onRGBStripRegisteredHandler = [] | ||||||
|         self.onRGBStripUnRegisteredHandler = [] |         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 |         # 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. |         # 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 |         # the wmos could use the mac adress, if there is a python script it can save the uid | ||||||
| @ -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 |  | ||||||
		Loading…
	
	
			
			x
			
			
		
	
		Reference in New Issue
	
	Block a user