diff --git a/animations/flash.py b/animations/flash.py index ce9542dfb50387ad1e010aa5ac38a88d397df154..b9f856dc319eca81d5c1820722646ac23da8317d 100644 --- a/animations/flash.py +++ b/animations/flash.py @@ -1,7 +1,7 @@ -from animation import Animation -from blinkenroom import BLINKENROOM_LOUNGE +from blinkenbase.animation import Animation +from blinkenbase.blinkenroom import BLINKENROOM_LOUNGE import random -from Color import Color +from blinkenbase.Color import Color import time class flash(Animation): diff --git a/animations/rainbow.py b/animations/rainbow.py new file mode 100644 index 0000000000000000000000000000000000000000..5b8d1ed876e0fb7b5378f3d664431cac3d9dca5d --- /dev/null +++ b/animations/rainbow.py @@ -0,0 +1,26 @@ +from blinkenbase.animation import Animation +from blinkenbase.Color import Color + +class rainbow(Animation): + + required_args = { + "fps": [int, 20] + } + + def init_animation(self): + self.name = "rainbow" + self.length = self.blinkenroom.total_length + step = 360 / self.length + self.set_fps(self.args["fps"]) + + self.gradient = [] + hue = 0 + for i in range(self.length): + self.gradient.append(Color(hsv=(hue, 1, 1))) + hue += step + self.counter = 0 + + def cycle(self): + offset = self.counter % self.length + self.blinkenroom.send_frame(self.gradient, offset) + self.counter += 1 diff --git a/animations/sirene.py b/animations/sirene.py index 955c02a0578e028770c2365d8cd2f70be133e9e8..3989a30e595fc7a78dfb5919b6877aaa7f8e101d 100644 --- a/animations/sirene.py +++ b/animations/sirene.py @@ -1,7 +1,7 @@ from blinkenbase.animation import Animation from blinkenbase.Color import Color -from blinkebase.blinkenroom import Blinkenroom -import blinkenbase.blinkenfoo +from blinkenbase.blinkenroom import Blinkenroom +import blinkenbase.blinkenfoo as blinkenfoo import time class sirene(Animation): @@ -9,9 +9,10 @@ class sirene(Animation): def init_animation(self): red = Color((255, 0, 0)) blue = Color((0, 0, 255)) - white = Color((255, 255, 255)) + #white = Color((255, 255, 255)) black = Color((0, 0, 0)) grey = Color((32, 32, 32)) + white = grey self.flash_left = [ [red, blue, red, grey, grey, black, black, black], [white, white, white, grey, grey, black, black, black], @@ -27,7 +28,7 @@ class sirene(Animation): [black, black, black, grey, grey, blue, red, blue], [black, black, black, grey, grey, white, white, white], [black, black, black, grey, grey, red, blue, red], - [black, black, black, grey, grey, white, white, white] + [black, black, black, grey, grey, white, white, white] ] self.states = [ self.flash_right, diff --git a/blinkenbase/animation.py b/blinkenbase/animation.py index d072693354a6cf562c68f40fed0fd12b8c9c25bf..e61dbc7c675585b7d210d746ea94e452a24d06cb 100644 --- a/blinkenbase/animation.py +++ b/blinkenbase/animation.py @@ -1,6 +1,6 @@ import time from threading import Thread -from blinkenbase.blinkenfoo import DMX, WARP_SIGN, SPHERES, PANEL, CUBES +from blinkenbase.blinkenroom import BLINKENROOM_LOUNGE class Animation(Thread): """ @@ -15,7 +15,7 @@ class Animation(Thread): Thread.__init__(self) self.name = None self.args = None - self.blinkenroom = None + self.blinkenroom = BLINKENROOM_LOUNGE self._frame = None self._fps = 0 self._time_should = 0 @@ -23,30 +23,56 @@ class Animation(Thread): self._running = False self._paused = False self._last_cycle = time.time() + self.adjusted_fps_dict = {} self.set_fps(30) def set_args(self, p_args): + """ + Passes the arguments to this animation before it is started + """ self.args = p_args + #The fps of this animation are adjusted to the physikal width of the + #blinkenfoos pixel. Default value ist 3.5 cm (pixel density of ws2812) + def calc_devices_adjusted_fps(self, p_fps): + """ + Pre-Calculates the adjusted fps of all devices in the specified + blinkenroom. + """ for device in self.blinkenroom.device_list: - device.calc_fps(p_fps) + adjusted_fps = device.calc_fps(p_fps) + self.adjusted_fps_dict[device] = adjusted_fpss def adjust_fps_for_device(self, p_device): - adjusted_fps = p_device.current_fps + """ + Sets the fps of the whole animation to the adjusted fps of the given + device. + """ + adjusted_fps = self.adjusted_fps_dict[p_device] if not self._currently_adjusted_for == p_device: self.set_fps(adjusted_fps) self._currently_adjusted_for = p_device def adjust_fps_for_index(self, p_index): + """ + Determine the device at the given index and sets the fps to the + adjusted value. + """ device = self.blinkenroom.get_device_by_index(p_index) self.adjust_fps_for_device(device) def cycle(self): + """ + Gets overriden by subclass + """ pass def set_fps(self, p_fps): + """ + Sets the fps of the animation. Does not adjust fps. + """ self._fps = p_fps self._time_should = 1 / float(self._fps) @@ -58,7 +84,10 @@ class Animation(Thread): while self._running: if self._paused: continue - self.cycle() + try: + self.cycle() + except: + continue if self._fps: time_spend = time.time() - self._last_cycle sleep_time = self._time_should - time_spend @@ -67,6 +96,9 @@ class Animation(Thread): self._last_cycle = time.time() def stop(self): + """ + Sets the exit condition to true (running to false) + """ self._running = False def pause(self): diff --git a/blinkenbase/animation_handler.py b/blinkenbase/animation_handler.py index 0896f831d559eb69d93f1d8f7e092a752719b366..d01e900b3a4655e0cd7d42338285f73f7269f815 100644 --- a/blinkenbase/animation_handler.py +++ b/blinkenbase/animation_handler.py @@ -5,17 +5,12 @@ import blinkenbase.animation import time from blinkenbase.blinkenroom import BLINKENROOM_LOUNGE import _thread -#from darken import darken class AnimationHandler(object): - ERROR_ANIMATION_RUNNING = 100 - ERROR_ANIMATION_NOT_FOUND = 101 - ERROR_OVERLAPPING = 102 - def __init__(self): self.running_animations = {} - self.known_animations = {} + self.loaded_animation_instances = {} self.last_frame = None ####################### @@ -35,6 +30,7 @@ class AnimationHandler(object): self.running_animations = {} self.last_frame = BLINKENROOM_LOUNGE.get_last_frame() + def pause_animation(self, p_animation_name): if p_animation_name in self.running_animations: animation = self.running_animations[p_animation_name] @@ -44,6 +40,7 @@ class AnimationHandler(object): for animation in self.running_animations.values(): animation.pause() + def resume_animation(self, p_animation_name): if p_animation_name in self.running_animations: animation = self.running_animations[p_animation_name] @@ -53,38 +50,61 @@ class AnimationHandler(object): for animation in self.running_animations.values(): animation.resume() + + def _load_anmation(self, p_name): + """ + Imports the given anmation and returns an instance of that class + """ + print(exec("from animations.%s import %s" % (p_name, p_name))) + animation_class = eval(p_name) + return animation_class() + def start_animation(self, p_name, p_animation_args): + """ + Loads an animation, creates and instance of it if none exists + passes arguments to it and starts it + """ p_name = p_name.lower() - animation_class = None - try: - exec("from animations.%s import %s" % (p_name, p_name)) - animation_class = eval(p_name) - except ImportError: - print("Animation not found '%s'" % p_name) - return self.ERROR_ANIMATION_NOT_FOUND - - animation = animation_class() + animation = None + if p_name not in self.loaded_animation_instances: + try: + animation = self._load_anmation(p_name) + except ImportError: + raise ValueError("Animation not found '%s'" % p_name) + else: + animation = self.loaded_animation_instances[p_name] + + #Loading args; Example pattern: + #required_args = { + # "fps": [int, 20] + #} required_args = animation.required_args for arg in required_args: required = required_args[arg] + #Checking wether the specific arg was passed when calling the anim. if arg not in p_animation_args: + #if not, loading default arg from class p_animation_args[arg] = required[1] else: + #Casting passed arg casting_method = required[0] current_arg = p_animation_args[arg] p_animation_args[arg] = casting_method(current_arg) + #Passing args to animation and doing init stuff animation.set_args(p_animation_args) animation.init_animation() + + #Stopping all animations that overlap to_stop = [] for running in self.running_animations.values(): if animation.blinkenroom.is_overlapping(running.blinkenroom): to_stop.append(running.name) - for running in to_stop: self.stop_animation(running) + #Finaly starting animation self.running_animations[p_name] = animation animation.start() @@ -92,15 +112,21 @@ class AnimationHandler(object): ###Light-Level### ################# - def _thread_handler_darken(self, a, b): + def _thread_handler_darken(self): + """ + Method to be called by thread to darken all blinkendevices + """ f = 100 - while f > 0: + while f >= 0: BLINKENROOM_LOUNGE.set_brightness(f) time.sleep(0.05) f -= 1 self.pause_all_animations() - def _thread_handler_lighten(self, a, b): + def _thread_handler_lighten(self): + """ + Method to be called by thread to light up all blinkendevices + """ f = 1 self.resume_all_animations() while f <= 100: @@ -109,19 +135,7 @@ class AnimationHandler(object): f += 1 def darken(self, p_args): - _thread.start_new_thread(self._thread_handler_darken, (None, None)) + _thread.start_new_thread(self._thread_handler_darken, ()) def lighten(self, p_args): - _thread.start_new_thread(self._thread_handler_lighten, (None, None)) - -# def darken(self, p_args): -# self.stop_all_animations() -# darken_dicts = { -# "frame": self.last_frame, -# "rate": 30, -# "steps": 100 -# } -# animation = darken() -# animation.set_args(darken_dicts) -# animation.init_animation() -# animation.start() + _thread.start_new_thread(self._thread_handler_lighten, ()) diff --git a/blinkenbase/blinkenfoo.py b/blinkenbase/blinkenfoo.py index 2a1ee02b1486381f7b0e2fc7e060a18000dfc892..dd7f7c363f41eeab4a57d23d73d9c81cb0377a6d 100644 --- a/blinkenbase/blinkenfoo.py +++ b/blinkenbase/blinkenfoo.py @@ -27,14 +27,13 @@ class Blinkenfoo(object): self._reset_buffer() self.current_fps = None - #self.brightness_factor = p_brightness / 100.0 - super(Blinkenfoo, self).__setattr__("brightness_factor", 100.0 / p_brightness) + self.brightness_factor = 70 def __setattr__(self, p_key, p_value): if p_key == "brightness_factor": f = 0 if p_value <= 100: - f = (100.0 / p_value) + f = 0.01 * p_value else: f = 100.0 p_value = f @@ -50,8 +49,10 @@ class Blinkenfoo(object): def _generate_package(self, startpixel, endpixel, rgb): """ Generates a udp package the blinkenfoo understands""" pack = bytearray() - pack.extend(self._split_to_byte(startpixel)) - pack.extend(self._split_to_byte(endpixel)) + startpixel = self._split_to_byte(startpixel) + endpixel = self._split_to_byte(endpixel) + pack.extend(startpixel) + pack.extend(endpixel) for color in rgb: r, g, b = color pack.extend([r, g, b]) @@ -106,9 +107,9 @@ class Blinkenfoo(object): self.buffer = p_frame for i in range(len(p_frame)): r, g, b = p_frame[i].rgb_tuple(True) - r = int(r / self.brightness_factor) - g = int(g / self.brightness_factor) - b = int(b / self.brightness_factor) + r = int(r * self.brightness_factor) + g = int(g * self.brightness_factor) + b = int(b * self.brightness_factor) rgb_frame.append((r, g, b)) package = self._generate_package(0, length-1, rgb_frame) else: diff --git a/mqtt.py b/mqtt.py index 7b0fd932db1e496549c5b4bd069cebcb60e32c56..bc2f4defe33934553e7a70ecf1ca90e10be12835 100644 --- a/mqtt.py +++ b/mqtt.py @@ -7,6 +7,7 @@ command_handler_dict = {} client = mqtt.Client() +#The fuck...like....was i drunk when i wrote this?! def on_connect(c, u, f, rc): print("connected") client.subscribe("light/blinkenfoo")