Esempio n. 1
0
def heat_to_rgb(temperature):
    t192 = round((temperature / 255.0) * 191)
    heatramp = t192 & 0x3F
    heatramp <<= 2

    if t192 > 0x80:
        return RGB(r=255, g=255, b=heatramp, a=255)
    elif t192 > 0x40:
        return RGB(r=255, g=heatramp, b=0, a=255)
    else:
        return RGB(r=heatramp, g=0, b=0, a=255)
Esempio n. 2
0
    def __init__(self, **kwargs):
        super().__init__(**kwargs)
        self.pattern_name = "Storm"

        self.rain = Modifier('rain intensity', 10.0, minimum=0, maximum=0.2)
        self.thunder = Modifier('thunder intensity', 5.0, minimum=0, maximum=0.2)
        self.thunder_size = Modifier('thunder size', 80, minimum=0, maximum=self.strip_length)

        self.thunder_color = RGB(white=True)
        self.rain_color = RGB(r=70, g=100, b=255, a=255)
        self.thunder_centers = {}

        for idx in range(self.strip_length):
            self.pixels[idx]['rain'] = 0
Esempio n. 3
0
    def __init__(self, **kwargs):

        kwargs['color'] = RGB()

        super().__init__(**kwargs)

        self.pattern_name = "FireWork"
        self.increment = Modifier('fire power',
                                  10.0,
                                  minimum=0.001,
                                  maximum=0.25)
        self.spark = Modifier('sparks',
                              10.0,
                              minimum=0,
                              maximum=1 / self.strip_length)

        for idx in range(self.strip_length):
            self.pixels[idx]['timestep'] = 0

        self.centers = []

        self.modifiers = dict(
            increment=self.increment,
            spark=self.spark,
        )
Esempio n. 4
0
    def fill(self):

        r_phi = self.r_phi()
        b_phi = self.b_phi()
        g_phi = self.g_phi()

        if not self.r_phi() == 0:
            r_phi = pi / r_phi
        if not self.b_phi() == 0:
            b_phi = pi / b_phi
        if not self.g_phi() == 0:
            g_phi = pi / g_phi

        for idx in range(self.strip_length):
            idx2degree = scale(idx + self.counter, 0, self.max_range(), 0,
                               self.strip_length)

            r = sin(idx2degree + r_phi)
            g = sin(idx2degree + g_phi)
            b = sin(idx2degree + b_phi)

            r = scale(r, 0, 255, -1, 1)
            g = scale(g, 0, 255, -1, 1)
            b = scale(b, 0, 255, -1, 1)

            r = floor(r)
            g = floor(g)
            b = floor(b)

            self.pixels[idx]['color'] = RGB(r=r, g=g, b=b, a=self.color.a)

        self.counter += 1
        self.counter %= self.strip_length * 255
Esempio n. 5
0
    def empty_center(self):
        """
        Return an empty center point as a dict with fields
        :return:
        """

        if self.randomize_color:
            default_dict = dict(color=RGB(random=True), alpha=0, delay=randint(0, 100), increasing=True)
        else:
            default_dict = dict(color=RGB(rgb=self.color), alpha=0, delay=randint(0, 100), increasing=True)

        # if there is no start in delay then alpha is maximum
        if not self.rate_start:
            default_dict['alpha'] = 255

        return default_dict
Esempio n. 6
0
    def __init__(self, handler, rate, pixels, color=RGB()):
        """

        :param handler: The handler for the led strip, either a DotStar_Emulator.emulator.send_test_data.App or a
        rpi.pi_handler.PiHandler
        :param rate:(float) the rate for the pixel update
        :param pixels: (int) the number of pixels
        :param color: (default RGB), the initial color for the leds
        """

        # init the thread and the handler
        threading.Thread.__init__(self, name="PatternThread")

        self.handler = handler
        self.rate = Modifier("rate", float(rate), minimum=0.0, maximum=1.5)
        self.stop = False

        self.strip_length = pixels
        self.color = color
        self.alpha = 255

        # boolean value to randomize color
        self.randomize_color = False

        # string for patter name
        self.pattern_name = None

        # dictionary storing the modifiers to be implemented in the web app
        self.modifiers = dict()

        # init and set the pixels to the default color
        self.pixels = {idx: Pixel(index=idx, color=self.color.copy(), set_func=self.color_set) for idx in
                       range(self.strip_length + 1)}
Esempio n. 7
0
 def color_idx(self, idx):
     # if the current one is alive then color it
     if self.alive[idx]:
         if self.randomize_color:
             self.pixels[idx]['color'] = RGB(random=True)
         else:
             self.pixels[idx]['color'] = self.color
     # else kill it
     else:
         self.pixels[idx]['color'] = (0, 0, 0, 0)
Esempio n. 8
0
    def get_rgba(self, data=None):
        """
        Return rgb class from the database
        :param data: dict, optional database
        :return: RGB class
        """

        if data is None:
            data = self.get("RGBA")

        return RGB(r=data["r"], g=data['g'], b=data['b'], a=data['a'], random=data['random'])
Esempio n. 9
0
    def fill(self):

        new_pixels = copy(self.pixels)

        # increase tails for every center
        for idx in range(len(self.centers)):
            cntr, stop = self.centers[idx]

            ### back motion
            prev_pixel = new_pixels[(cntr - stop + 1) % self.strip_length]
            cur_pixel = new_pixels[(cntr - stop) % self.strip_length]

            color, timestep = drop([prev_pixel, cur_pixel], self.increment())
            ts = max(timestep - self.increment(), 0.0)
            cur_pixel['timestep'] = ts
            cur_pixel['color'] = color
            new_pixels[(cntr - stop) % self.strip_length] = cur_pixel

            ### forward motion
            prev_pixel = new_pixels[(cntr + stop - 1) % self.strip_length]
            cur_pixel = new_pixels[(cntr + stop) % self.strip_length]

            color, timestep = drop([prev_pixel, cur_pixel], self.increment())
            ts = max(timestep - self.increment(), 0.0)
            cur_pixel['timestep'] = ts
            cur_pixel['color'] = color
            new_pixels[(cntr + stop) % self.strip_length] = cur_pixel

            # increment stop for next iteration
            self.centers[idx] = (cntr, stop + 1)

        # remove all centers with a maximum stop
        self.centers = [
            elem for elem in self.centers if elem[1] < 1 // self.increment()
        ]

        # fade all leds
        for idx in range(self.strip_length):
            new_pixels[idx]['color'].fade(self.increment())

        # either update pixels or spark
        for idx in range(self.strip_length):
            if random() < self.spark():
                c = RGB(random=True)
                self.pixels[idx]['color'] = c
                self.pixels[idx]['timestep'] = 1.0
                self.centers.append((idx, 1))

            else:
                self.pixels[idx]['color'] = new_pixels[idx]['color']
                self.pixels[idx]['timestep'] = new_pixels[idx]['timestep']
Esempio n. 10
0
    def fill(self):

        step = self.step
        color = self.color

        if self.reverse:
            color = RGB()

        for idx in range(self.strip_length):
            if idx < step:
                self.pixels[idx]['color'] = color

        self.step += 1

        if self.step > self.strip_length:
            self.reverse = not self.reverse
            self.step = 0
Esempio n. 11
0
def drop(pixels, inc):
    """
    Perform an average on a list of pixels
    :param pixels: list[dict], list of pixels with 'color' and 'timestep' keys
    :param inc: float, increment
    :return: tuple[RGB,int]: color, timestep
    """
    tots = [
        elem['timestep'] for elem in pixels if not elem['color'].is_black()
    ]

    tot = sum(tots)
    if tot == 0: tot = 0.000001

    # perform weighed average for rgba
    red = [elem['color'].r * elem['timestep'] for elem in pixels]
    red = sum(red) / tot

    green = [elem['color'].g * elem['timestep'] for elem in pixels]
    green = sum(green) / tot

    blue = [elem['color'].b * elem['timestep'] for elem in pixels]
    blue = sum(blue) / tot

    alpha = [elem['color'].a * elem['timestep'] for elem in pixels]
    alpha = sum(alpha) / tot

    # bound max and min
    red = max(red, 0)
    green = max(green, 0)
    blue = max(blue, 0)
    alpha = max(alpha, 0)

    red = min(red, 255)
    green = min(green, 255)
    blue = min(blue, 255)
    alpha = min(alpha, 255)

    # if there are no tots, use zero as average timestep
    try:
        ts = max(tots)
    except ValueError:
        ts = 0

    return RGB(r=red, g=green, b=blue, a=alpha).fade(inc), ts
Esempio n. 12
0
    def fill(self):

        # reset counter
        if self.counter == sys.maxsize - 1:
            self.counter = 0

        # color
        for idx in range(self.strip_length):
            val = self.op.noise2d(idx / self.x_div(),
                                  self.counter / self.y_div())
            val = scale(val, 0, 255, -1, 1)

            # add base value + deepness
            val = bound_add(val, self.deepness())
            self.pixels[idx]['color'] = RGB(b=val, g=255 - val, a=self.color.a)

        # update counter
        self.counter += 1
Esempio n. 13
0
    def listener_method(self, event):
        """
        Main listener, called when db is updated
        :param event: dict
        :return: None
        """

        if not super(FireBaseController, self).listener_method(event):
            return

        to_log = f"{event.event_type}\n{event.path}\n{event.data}"
        fire_logger.debug(to_log)

        path = event.path
        data = event.data

        if "rate" in path:
            self.pattern.set_rate(data)

        # stop and restart pattern if required
        elif "cur_pattern" in path:
            # get values
            pattern_choice = data
            rate = self.get_rate()
            rgba = self.get_rgba()
            # stop and restart
            self.pattern.close()
            self.pattern = Patterns[pattern_choice](rate=rate,
                                                    color=rgba,
                                                    handler=self.handler,
                                                    pixels=self.pixels)
            self.pattern.color_all(RGB())
            self.pattern.start()

        # update rgba
        elif "RGBA" in path:
            self.process_rgba(path, data)

        # update pattern attributes
        elif "pattern_attributes" in path:
            self.ps_attrs_getter(path, data)

        else:
            raise NotImplementedError(f"No such field for {event.path}")
Esempio n. 14
0
    def __init__(self, **kwargs):

        super().__init__(**kwargs)
        self.counter = 0
        self.color = RGB(white=True)
        self.r_phi = Modifier('red shift', 0.0, minimum=0, maximum=pi)
        self.b_phi = Modifier('blue shift', 35.0, minimum=0, maximum=pi)
        self.g_phi = Modifier('green shift', 70.0, minimum=0, maximum=pi)
        self.max_range = Modifier('max range',
                                  1,
                                  minimum=1,
                                  maximum=self.strip_length)
        self.pattern_name = "Rainbow"

        self.modifiers = dict(
            r_phi=self.r_phi,
            b_phi=self.b_phi,
            g_phi=self.g_phi,
            max_range=self.max_range,
        )
Esempio n. 15
0
    def __init__(self, **kwargs):

        super().__init__(**kwargs)
        # min space between trail end and trail start
        self.centers = Modifier('centers',
                                10,
                                minimum=self.strip_length // 2,
                                maximum=self.strip_length)
        self.trail = Modifier('trail size',
                              3,
                              minimum=1,
                              maximum=self.strip_length // 2)

        self.counter = 0
        self.pattern_name = "Snow"
        self.color = RGB(white=True)

        self.modifiers = dict(
            trail=self.trail,
            centers=self.centers,
        )
Esempio n. 16
0
    def process_rgba(self, path, data):
        """
        Update RGBA values taking them from the database
        :return:
        """
        # get the rgba attribute to update
        rgb_attr = path.split("/")[-1]

        # if is random
        if rgb_attr == "random":
            # update the randomize_color attribute of pattern
            if bool(data):
                color = RGB(random=True)
                self.pattern.update_args(color=color, randomize_color=True)
            else:

                color = self.get_rgba()
                self.pattern.update_args(color=color, randomize_color=False)

        else:
            # if is r,g,b,a, update just the value in the dictionary
            self.pattern.color.__dict__[rgb_attr] = int(data)
Esempio n. 17
0
 def fill(self):
     self.rate.value = 100
     for idx in range(self.strip_length):
         self.pixels[idx]['color'] = RGB()
Esempio n. 18
0
 def fill(self):
     for idx in range(self.strip_length):
         self.pixels[idx]['color'] = RGB()
Esempio n. 19
0
class Storm(Default):
    """
    Steady color
    """

    def __init__(self, **kwargs):
        super().__init__(**kwargs)
        self.pattern_name = "Storm"

        self.rain = Modifier('rain intensity', 10.0, minimum=0, maximum=0.2)
        self.thunder = Modifier('thunder intensity', 5.0, minimum=0, maximum=0.2)
        self.thunder_size = Modifier('thunder size', 80, minimum=0, maximum=self.strip_length)

        self.thunder_color = RGB(white=True)
        self.rain_color = RGB(r=70, g=100, b=255, a=255)
        self.thunder_centers = {}

        for idx in range(self.strip_length):
            self.pixels[idx]['rain'] = 0

    def fill(self):

        def rain_handler(idx):
            rn = self.pixels[idx]['rain']

            if not rn:
                rn = 255 * random() if random() < self.rain() else 0

            else:
                rn = bound_sub(rn, rain_loss)

            self.pixels[idx]['rain'] = rn

            if rn:
                c = self.rain_color.copy()
                c.blend(self.pixels[idx]['color'])
                c.update_single(a=rn)

                self.pixels[idx]['color'] = c

        def thunder_handler(idx):
            """
            Handle thunder
            :param idx:
            :return:
            """
            # if current index is a thunder center
            if idx in self.thunder_centers.keys():
                # get the values
                start, end, alpha = self.thunder_centers[idx]

                # mimic thunder behavior to brighten up with random value
                if random() < 0.1:
                    alpha = bound_add(alpha, thunder_loss * 2)
                else:
                    alpha = bound_sub(alpha, thunder_loss)

                # update alpha
                self.thunder_centers[idx][2] = alpha

                # for every part of the thunder
                for jdx in range(start, end + 1):
                    # copy the thunder color
                    c = self.thunder_color.copy()
                    # estimate the distance from center as a loss + a random term
                    l = 200 * abs(jdx - idx) / self.thunder_size() // 2 + randint(0, 50)
                    # estimate new local alpha
                    v = bound_sub(alpha, thunder_loss + l)
                    # update in color
                    c.update_single(a=v)
                    # set
                    # c.blend(self.pixels[jdx]['color'])
                    self.pixels[jdx]['color'] = c

                # if alpha is zero then remove the center
                if alpha == 0:
                    del self.thunder_centers[idx]

        thunder_loss = 30
        rain_loss = 10

        # if there are not enough thunders
        max_centers = self.strip_length // self.thunder_size()
        if len(self.thunder_centers) < max_centers and random() < self.thunder():

            # get how many more do we need
            max_centers -= len(self.thunder_centers)
            for _ in range(max_centers):
                # if probability is high enough
                # estimate random center
                center = randint(0, self.strip_length)
                size = self.thunder_size()

                # get start and end
                start = center - size // 2 - randint(0, size // 4)
                start = start if start >= 0 else 0

                end = size // 2 + center + randint(0, size // 4)
                end = end if end < self.strip_length else self.strip_length

                # add it to dictionary
                self.thunder_centers[center] = [start, end, 255]

        for i in range(self.strip_length):
            rain_handler(i)
            thunder_handler(i)
Esempio n. 20
0
 def empty_center(self):
     if self.randomize_color:
         return dict(color=RGB(random=True), tail=[], step=0)
     else:
         return dict(color=self.color, tail=[], step=0)
Esempio n. 21
0
    parser.add_argument('--strip_type',
                        type=str,
                        help='rate',
                        default='neopixel',
                        choices=['neopixel', 'dotstar'])
    parser.add_argument('--pixels', type=int, help='rate', default=300)
    parser.add_argument('--profile',
                        nargs='?',
                        const=True,
                        default=False,
                        help='If to start in debug mode')
    args = parser.parse_args()

    # set pattern, color and handler
    pat = Patterns[args.pattern]
    color = RGB(random=True)

    if args.strip_type == "neopixel":
        handler = NeoPixel(args.pixels)
    else:
        handler = Dotstar(args.pixels)

    # init app and run
    app = pat(handler=handler, rate=args.rate, pixels=args.pixels, color=color)

    # start yappi if profile flag
    if args.profile:
        yappi.start()

    try:
        # run while not stopped