Example #1
0
class Light(Thread):

    def __init__(self, light_state:LightState):
        super().__init__()
        self.state = light_state
        self.periodic = None
        self.refresh_period_or_duty_cycle()

        self.strip = PixelStrip(self.state.get_num_pixels(), 18)

    async def loop(self):
        while True:
            await self.periodic.wait_for_period_boundary()
            self.set_first_half_of_period()
            await self.periodic.wait_for_semi_period_boundary()
            self.set_second_half_of_period()

    def set_first_half_of_period(self):
        if not self.state.get_power():
            self.set_off()
        else:
            self.set_on()

    def set_second_half_of_period(self):
        if not self.state.get_power() or self.state.get_blink():
            self.set_off()
        else:
            self.set_on()

    def set_on(self):
        self.strip.setBrightness(self.state.get_brightness())
        for pixel in range(self.state.get_num_pixels()):
            self.strip.setPixelColorRGB(pixel, self.state.get_red(), self.state.get_green(), self.state.get_blue())
        self.strip.show()

    def set_off(self):
        for pixel in range(self.state.get_num_pixels()):
            self.strip.setPixelColorRGB(pixel, 0, 0, 0)
        self.strip.show()

    def refresh_period_or_duty_cycle(self):
        self.periodic = Periodic(
            period_sec=self.state.get_period(),
            semi_period_percent=self.state.get_duty_cycle()
        )

    def run(self):
        self.strip.begin()
        asyncio.run(self.loop())
Example #2
0
def run():
    prev_animation = None
    prev_brightness = None
    strip = PixelStrip(LED_COUNT, LED_PIN, LED_FREQ_HZ, LED_DMA, LED_INVERT,
                       LED_BRIGHTNESS, LED_CHANNEL, LED_STRIP)
    strip.begin()

    threading.Thread(target=app.run).start()
    print('Press Ctrl-C to quit.')
    len_animations = None
    try:
        while True:
            if len(curr_animations) != len_animations:
                len_animations = len(curr_animations)
                clear(strip)

                generators = []
                for animation in curr_animations:
                    generators.append(animation(VStrip(strip)))

            if curr_brightness != prev_brightness:
                strip.setBrightness(curr_brightness)
                prev_brightness = curr_brightness

            vstrips = []
            for gen in generators:
                vstrips.append(next(gen))
                # vstrip.reverse()

            for pos in range(strip.numPixels()):
                col = np.array([0., 0., 0.])
                transparency = 1
                for v in vstrips:
                    cur_col = np.array(v.getPixelColor(pos))
                    col += cur_col[:3] * transparency
                    transparency *= cur_col[3]

                col = np.maximum(
                    np.minimum(np.array(np.floor(col), dtype=np.int), 255), 0)
                strip.setPixelColor(pos, Color(*col.tolist()))

            strip.show()

    except KeyboardInterrupt:
        clear(strip)
Example #3
0
class LEDController(Component):
    def __init__(self, config: dict):
        super().__init__("leds")
        self.controller = None
        self.leds = {}
        led_config = config['leds']
        if led_config['type'] == "pixelstrip":
            self._process_pixelstrip(led_config)

    def _process_pixelstrip(self, config):
        self.controller = PixelStrip(config['count'], config['pin'], config['frequency'], config['dma'],
                                     config['invert'], config['brightness'], config['channel'])
        self.controller.begin()
        for index, name in config['names'].items():
            self.leds[name] = PixelStripLED(self.controller, index)

    def process_control(self, message):
        updated = False
        for name, led in self.leds.items():
            if name in message:
                state = message[name]
                led.set_color(state.get('red', 0), state.get('green', 0), state.get('blue', 0))
                updated = True

        if "brightness" in message:
            self.controller.setBrightness(message["brightness"])
            updated = True

        if updated:
            self.controller.show()
            self.update_state()

    @property
    def state(self):
        return { "brightness": self.controller.getBrightness(),
                 "leds": {name: led.state for name, led in self.leds.items()}}
Example #4
0
class RGBLight():
    "Simple wrapper for a RGB light device "

    def __init__(self, pin: int, nb_led: int = 5):
        self.pixels = PixelStrip(nb_led, pin)
        self.pixels.begin()
        self._state: bool = False
        self.delay: float = 0.01
        self._mode: int = MODE_RGB

        self.off()

    @property
    def state(self) -> bool:
        return self._state

    @state.setter
    def state(self, state: bool) -> None:
        self._state = state

    @property
    def mode(self) -> int:
        return self._mode

    @mode.setter
    def mode(self, mode) -> None:
        self._mode = mode

    def on(self) -> None:
        self.state = True
        for i in range(self.pixels.numPixels()):
            print(i)
            self.pixels.setPixelColorRGB(i, 50, 50, 50)
            self.pixels.show()
            sleep(0.01)

    def off(self) -> None:
        self.state = False
        for i in range(self.pixels.numPixels()):
            self.pixels.setPixelColorRGB(i, 0, 0, 0)
            self.pixels.show()
            sleep(self.delay)

    def toggle(self) -> None:
        if self.state is True:
            self.off()
        else:
            self.on()

    @property
    def color(self) -> Tuple[int, int, int]:
        if self.mode != MODE_RGB:
            raise Exception("Light is not in RGB mode")
        color_raw = self.pixels.getPixelColorRGB(0)
        color = (color_raw.r, color_raw.g, color_raw.b)
        return color

    @color.setter
    def color(self, color: Tuple[int, int, int]) -> None:
        self.state = True
        self.mode = MODE_RGB
        for i in range(self.pixels.numPixels()):
            self.pixels.setPixelColorRGB(i, *color)
            self.pixels.show()
            sleep(self.delay)

    @property
    def brightness(self) -> int:
        bri = self.pixels.getBrightness()
        return bri

    @brightness.setter
    def brightness(self, value: int) -> None:
        self.pixels.setBrightness(value)

    @property
    def temperature(self) -> int:
        if self.mode != MODE_TEMPERATURE:
            raise Exception("Light is not in temperature mode")
        color_raw = self.pixels.getPixelColorRGB(0)
        rgb = (color_raw.r, color_raw.g, color_raw.b)
        print(rgb)
        for temp in kelvin_table.keys():
            if kelvin_table[temp] == rgb:
                return temp

        return 0

    @temperature.setter
    def temperature(self, temp: int) -> None:
        self.mode = MODE_TEMPERATURE
        safe_temp = temp - (temp % 100)
        rgb: Tuple[int, int, int] = kelvin_table[safe_temp]
        for i in range(self.pixels.numPixels()):
            self.pixels.setPixelColorRGB(i, *rgb)
            self.pixels.show()
            sleep(self.delay)
Example #5
0
class LedManager:
    """ Class that controlles the led matrix

    Also parses incomming data
    Uses the config file

    """
    matrix = []
    top_row = []
    # Coloumns and Frets #####################################################
    LED_STRIP = None
    STRING_CNT = 6
    FRET_CNT = 4
    CONFIG = {}
    logger = None
    has_logger = False
    FILE_CONFIG = "ledconfig.json"
    BROKEN_PCB = True

    def __init__(self, logger=None):
        self.logger = logger
        if self.logger is not None:
            self.has_logger = True
        self.reloadconfig()
        self.preparematrix()
        self.preparetop()
        self.dosetup()

    # LED CONTROL

    def colorwipe(self, color=Color(0, 0, 0)):
        """ Sets one color for the hole strip """
        wait_time = self.CONFIG["WAIT_MS"]
        for i in range(self.LED_STRIP.numPixels()):
            if (self.BROKEN_PCB and i == 24):
                continue
            self.LED_STRIP.setPixelColor(i, color)
            self.LED_STRIP.show()
            time.sleep(wait_time / 1000)

    def colorwipeTop(self, color=Color(0, 0, 0)):
        """ If top installed, clear it """
        wait_time = self.CONFIG["WAIT_MS"]
        if (self.CONFIG["TOP_INSTALLED"]):
            for i in range(6):
                self.LED_STRIP.setPixelColor(i, color)
                self.LED_STRIP.show()
                time.sleep(wait_time / 1000)

    def applydata(self):
        self.applymatrix()
        self.applytop()

    def applymatrix(self):
        """ State matrix applied on the strip
        """
        cur_mat = self.matrix
        offset = 0
        ## DEBUG:
        for line in cur_mat:
            print(str(list(line)))
        if (self.CONFIG["TOP_INSTALLED"]):
            offset = 6
        for y in range(len(cur_mat)):
            for x in range(len(cur_mat[y])):
                tmp_index = offset + (y * 6 + x)
                if (tmp_index >= 24 and self.BROKEN_PCB):
                    tmp_index += 1
                self.LED_STRIP.setPixelColor(tmp_index, cur_mat[y][x])
                self.LED_STRIP.show()
                time.sleep(self.CONFIG["WAIT_MS"] / 1000)

    def applytop(self):
        """ TopRow-State applied to the strip """
        wait_time = self.CONFIG["WAIT_MS"]
        for x in range(len(self.top_row)):
            self.LED_STRIP.setPixelColor(x, self.top_row[x])
            self.LED_STRIP.show()
            time.sleep(wait_time / 1000)

    def dosetup(self):
        """ Init. of a default rgb strip

        Note:
            The config file need to be loaded before calling this method

        """
        fix = 0
        if self.BROKEN_PCB:
            fix = 1
        LED_COUNT = (
            (self.FRET_CNT + self.CONFIG["TOP_INSTALLED"]) * self.STRING_CNT +
            fix)
        LED_PIN = 18
        LED_FREQ = 800000
        LED_DMA = 10
        LED_BRIGHTNESS = self.CONFIG["BRIGHTNESS"]
        self.LED_STRIP = PixelStrip(\
                                    LED_COUNT,\
                                    LED_PIN,\
                                    LED_FREQ,\
                                    LED_DMA,\
                                    False,\
                                    LED_BRIGHTNESS)
        self.LED_STRIP.begin()

    def clean_up(self):
        """ Calls spooky cleanup on strip

        Maybe neccessary

        """
        self.LED_STRIP._cleanup()

    # DATA MANAGMENT

    def preparematrix(self):
        """ Init. dark matrix """
        ROW = [Color(0, 0, 0)] * self.STRING_CNT
        mat = [[]] * self.FRET_CNT
        for idx in range(len(mat)):
            # Copy the list to create the complete matrix
            mat[idx] = ROW.copy()
        self.matrix = mat
        self.ilog(__name__ + " Matrix Prep Done", 10)

    def preparetop(self):
        self.top_row = [Color(0, 0, 0)] * self.STRING_CNT

    def reloadconfig(self):
        """ Reloads LED Config File """
        self.ilog(__name__ + " Starting config reload...", 10)
        curconfig = {}
        if (os.path.isfile(self.FILE_CONFIG)):
            with open(self.FILE_CONFIG, "r", encoding="utf-8") as f:
                curconfig = json.load(f)
            self.CONFIG = curconfig
            self.ilog(__name__ + " Config reload done!", 20)
        else:
            self.ilog(__name__ + " No config file found. Creating default", 10)
            default_colors = {
                "-2": Color(255, 0, 0),
                "-1": Color(52, 255, 13),
                "0": Color(255, 255, 255),
                "1": Color(255, 0, 0),
                "2": Color(0, 255, 0),
                "3": Color(0, 0, 255),
                "4": Color(255, 255, 0)
            }
            default_config = {
                "TOP_INSTALLED": False,
                "WAIT_MS": 10,
                "BRIGHTNESS": 20,
                "finger_color": default_colors
            }
            with open(self.FILE_CONFIG, "w", encoding="utf-8") as f:
                json.dump(default_config, f, ensure_ascii=False, indent=4)
            self.ilog(__name__ + " Default config created!", 20)
            self.reloadconfig()

    def store_config(self):
        """ Stores current config to file """
        self.ilog(__name__ + " Start saving config to file", 10)
        with open("ledconfig.json", "w", encoding="utf-8") as f:
            json.dump(self.CONFIG, f, ensure_ascii=False, indent=4)
        self.ilog(__name__ + " Currenct config successfully saved!", 20)

    def set_strings_to_hit(self, strings):
        """ For each one in a binary six digit string the corresponding
        string will be activated

        """
        for charIDx in range(len(strings)):
            if (strings[charIDx] == "1"):
                self.top_row[charIDx] = self.CONFIG["finger_color"]["0"]
            else:
                self.top_row[charIDx] = Color(0, 0, 0)

    def set_single_in_matrix(self, pos, string, finger):
        """ Adds given data to internal matrix

        Note:
            Use applymatrix to activate the changes

        """
        cur_mat = self.matrix
        tmpColor = self.get_finger_color(finger)
        cur_mat[pos][string] = tmpColor

    def set_array_in_matrix(self, data_array):
        """ Adding a collection through set_single_in_matrix

        Needs fret, string, finger per element

        Note:
            Use applymatrix to activate the changes

        """
        for values in data_array:
            self.set_single_in_matrix(values[0], values[1], values[2])

    # MODIFIER

    def setbrightness(self, brightness=20):
        """ Sets brightness value

        Also applies the brightness to the LED strip
        """
        self.CONFIG["BRIGHTNESS"] = brightness
        self.LED_STRIP.setBrightness(self.CONFIG["BRIGHTNESS"])
        self.ilog(
            __name__ + " Applied new brightness: {} (~{}%)".format(
                brightness, (brightness / 255) * 100), 10)

    def setinstalled(self, intalled=True):
        """ (De)activates first row skip """
        self.CONFIG["TOP_INSTALLED"] = installed
        self.ilog(__name__ + "Top installed...", 10)

    def setwaittime(self, time=10):
        """ Sets wait time for the LEDs

        Note:
            Wait time between every led change
        """
        self.CONFIG["WAIT_MS"] = time
        self.ilog(__name__ + "{} ms wait time applied".format(time), 10)

    # Threadfunctions

    def thread_load_indicator(self, sharedVariable):
        """ Thread task, use utils.sharedVariable to indicate finish """
        if (self.CONFIG["TOP_INSTALLED"]):
            accentColor = Color(136, 176, 75)  # 2017 Greenery
            mainColor = Color(255, 0, 0)
            secondColor = Color(140, 0, 0)
            thirdColor = Color(60, 0, 0)
            baseValue = sharedVariable.get_storage() + 1
            lowerBound = baseValue
            current_position = lowerBound
            upwards = True
            upperBound = 5

            while (not sharedVariable.get_task_done()):

                if (sharedVariable.has_changed()):
                    self.ilog(__name__ + " thread, new value!")
                    baseValue = sharedVariable.get_storage() + 1
                    lowerBound = baseValue
                    current_position = lowerBound

                for idx in range(self.STRING_CNT):
                    if (idx < baseValue):
                        self.top_row[idx] = accentColor
                    else:
                        self.top_row[idx] = Color(0, 0, 0)
                if (upwards):
                    delta = current_position - baseValue
                    if (delta > 0):
                        self.top_row[current_position - 1] = secondColor
                        if (delta > 1):
                            self.top_row[current_position - 2] = thirdColor
                else:
                    delta = upperBound - current_position
                    if (delta > 0):
                        self.top_row[current_position + 1] = secondColor
                        if (delta > 1):
                            self.top_row[current_position + 2] = thirdColor
                self.top_row[current_position] = mainColor
                self.applytop()
                if (upwards):
                    #Todo inc or dec counter
                    if (current_position == upperBound):
                        upwards = False
                    else:
                        current_position = current_position + 1
                else:
                    if (current_position == lowerBound):
                        upwards = True
                    else:
                        current_position = current_position - 1
            else:
                self.colorwipeTop()

    #END thread_load_indicator

    def thread_idle_indicator(self, sharedVariable):
        """ Thread task, use utils.sharedVariable to indicate finish """
        if (not self.CONFIG["TOP_INSTALLED"]):
            return
        mainColor = Color(0, 140, 0)

        position = 0

        while (not sharedVariable.get_task_done()):
            self.colorwipeTop()
            if (position > 5):
                position = 0
            self.top_row[position] = mainColor
            self.applytop()
            position = position + 1

        self.colorwipe()

    # Tools

    def ilog(self, msg, level=30):
        """ If logger given, logs on given level """
        if self.has_logger:
            self.logger.log(level, msg)
        else:
            #print(msg)
            pass

    def get_finger_color(self, finger):
        """ Returns the correct color for a finger index

        """
        return self.CONFIG["finger_color"][str(finger)]

    def cleanup(self):
        """ Reset the tempory internal state and clears LED Strip """
        self.preparematrix()
        self.preparetop()
        self.colorwipe()
Example #6
0
class Ledstrip:
    def __init__(self):
        self.onGoingTask = None
        self.cancelTask = False
        self.brightness = constants.LED_BRIGHTNESS
        self.pixels = PixelStrip(constants.LED_COUNT, constants.LED_PIN,
                                 constants.LED_FREQ_HZ, constants.LED_DMA,
                                 constants.LED_INVERT,
                                 constants.LED_BRIGHTNESS,
                                 constants.LED_CHANNEL, constants.LED_STRIP)
        self.pixels.begin()
        LedUtil.clear(self.pixels)
        self.pixels.setPixelColor(0, Color(255, 255, 255, 255))
        self.pixels.show()

        print("Controlling ledstrip on pin ", constants.LED_PIN)

    def pixel_rainbow_colors(self, args):
        wait, isFloat = Util.floatTryParse(args["wait"])
        loop_forever, isBool = Util.boolTryParse(args["loop_forever"])
        if (isFloat and isBool):
            self.__execute_task(
                LedUtil.rainbow_colors,
                (self.pixels, lambda: self.cancelTask, wait, loop_forever))

    def pixel_rainbow_cycle(self, args):
        loop_forever, isBool = Util.boolTryParse(args["loop_forever"])
        wait, isFloat = Util.floatTryParse(args["wait"])
        loop, isInt = Util.intTryParse(args["loop"])
        if (isBool and isFloat and isInt):
            self.__execute_task(LedUtil.rainbow_cycle,
                                (self.pixels, lambda: self.cancelTask, wait,
                                 loop, loop_forever))

    def pixel_rainbow_cycle_successive(self, args):
        wait, isFloat = Util.floatTryParse(args["wait"])
        if (isFloat):
            self.__execute_task(LedUtil.rainbow_cycle_successive,
                                (self.pixels, lambda: self.cancelTask, wait))

    def pixel_brightness_decrease(self, args):
        wait, isFloat = Util.floatTryParse(args["wait"])
        step, isInt = Util.intTryParse(args["step"])
        if (isFloat and isInt):
            self.__execute_task(
                LedUtil.brightness_decrease,
                (self.pixels, lambda: self.cancelTask, wait, step))

    def pixel_blink_color(self, args):
        color, isColor = Util.colorTryParse(args["color"])
        wait, isFloat = Util.floatTryParse(args["wait"])
        blink_time, isInt = Util.intTryParse(args["blink_time"])
        if (isColor and isFloat and isInt):
            self.__execute_task(LedUtil.blink_color,
                                (self.pixels, lambda: self.cancelTask,
                                 blink_time, wait, color))

    def pixel_appear_from_back(self, args):
        color, isColor = Util.colorTryParse(args["color"])
        wait, isFloat = Util.floatTryParse(args["wait"])
        size, isInt = Util.intTryParse(args["size"])
        if (isColor and isFloat and isInt):
            self.__execute_task(
                LedUtil.appear_from_back,
                (self.pixels, lambda: self.cancelTask, color, wait, size))

    def pixel_color_wipe(self, args):
        color, isColor = Util.colorTryParse(args["color"])
        wait, isFloat = Util.floatTryParse(args["wait"])
        should_clear, isBool = Util.boolTryParse(args["should_clear"])
        if (isColor and isFloat and isBool):
            self.__execute_task(LedUtil.color_wipe,
                                (self.pixels, lambda: self.cancelTask, wait,
                                 color, should_clear))

    def pixel_color_wipe_cycle(self, args):
        color, isColor = Util.colorTryParse(args["color"])
        wait, isFloat = Util.floatTryParse(args["wait"])
        fade_step, isInt = Util.intTryParse(args["fade_step"])
        loop_forever, isBool = Util.boolTryParse(args["loop_forever"])
        if (isColor and isFloat and isInt and isBool):
            self.__execute_task(LedUtil.color_wipe_cycle,
                                (self.pixels, lambda: self.cancelTask, wait,
                                 color, fade_step, loop_forever))

    def pixel_theater_chase(self, args):
        color, isColor = Util.colorTryParse(args["color"])
        wait, isFloat = Util.floatTryParse(args["wait"])
        is_rainbow, isBool = Util.boolTryParse(args["is_rainbow"])
        if (isColor and isFloat and isBool):
            self.__execute_task(LedUtil.theaterChase,
                                (self.pixels, lambda: self.cancelTask, color,
                                 wait, is_rainbow))

    def pixel_color_wipe_rainbow(self, args):
        wait, isFloat = Util.floatTryParse(args["wait"])
        fade_step, isInt = Util.intTryParse(args["fade_step"])
        color_step, isInt2 = Util.intTryParse(args["color_step"])
        if (isFloat and isInt and isInt2):
            self.__execute_task(LedUtil.color_wipe_rainbow,
                                (self.pixels, lambda: self.cancelTask, wait,
                                 fade_step, color_step))

    def pixel_breathing(self, args):
        color, isColor = Util.colorTryParse(args["color"])
        move_factor, isFloat = Util.floatTryParse(args["move_factor"])
        if (isFloat and isColor):
            self.__execute_task(
                LedUtil.breathing,
                (self.pixels, lambda: self.cancelTask, color, move_factor))

    def pixel_breathing_lerp(self, args):
        color_to, isColor1 = Util.colorTryParse(args["color_to"])
        color_from, isColor2 = Util.colorTryParse(args["color_from"])
        move_factor, isFloat = Util.floatTryParse(args["move_factor"])
        if (isColor1 and isColor2 and isFloat):
            self.__execute_task(LedUtil.breathing_lerp,
                                (self.pixels, lambda: self.cancelTask,
                                 color_from, color_to, move_factor))

    def pixel_breathing_rainbow(self, args):
        move_factor, isFloat = Util.floatTryParse(args["move_factor"])
        color_step, isInt = Util.intTryParse(args["color_step"])
        if (isInt and isFloat):
            self.__execute_task(LedUtil.breathing_rainbow,
                                (self.pixels, lambda: self.cancelTask,
                                 color_step, move_factor))

    def pixel_fireworks(self, args):
        size, isInt = Util.intTryParse(args["size"])
        color, isColor = Util.colorTryParse(args["color"])
        is_rainbow, isBool = Util.boolTryParse(args["is_rainbow"])
        number_of_fireworks, isInt1 = Util.intTryParse(
            args["number_of_fireworks"])
        chance_of_explosion, isInt2 = Util.intTryParse(
            args["chance_of_explosion"])
        fade_step, isInt3 = Util.intTryParse(args["fade_step"])
        firework_fade, isInt4 = Util.intTryParse(args["firework_fade"])
        if (isColor and isBool and isInt and isInt1 and isInt2 and isInt3
                and isInt4):
            self.__execute_task(
                LedUtil.fireworks,
                (self.pixels, lambda: self.cancelTask, size, color, is_rainbow,
                 number_of_fireworks, chance_of_explosion, fade_step,
                 firework_fade))

    def pixel_labyrinth(self, args):
        wait, isFloat = Util.floatTryParse(args["wait"])
        color, isColor = Util.colorTryParse(args["color"])
        contact_color, isColor2 = Util.colorTryParse(args["contact_color"])
        count, isInt = Util.intTryParse(args["count"])
        turn_chance, isInt2 = Util.intTryParse(args["turn_chance"])
        if (isColor and isColor2 and isFloat and isInt and isInt2):
            self.__execute_task(LedUtil.labyrinth,
                                (self.pixels, lambda: self.cancelTask, wait,
                                 count, turn_chance, color, contact_color))

    def pixel_color_pair(self, args):
        wait, isFloat = Util.floatTryParse(args["wait"])
        color1, isColor1 = Util.colorTryParse(args["color1"])
        color2, isColor2 = Util.colorTryParse(args["color2"])
        size1, isInt1 = Util.intTryParse(args["size1"])
        size2, isInt2 = Util.intTryParse(args["size2"])
        with_animation, isBool = Util.boolTryParse(args["with_animation"])
        fade_step, isInt = Util.intTryParse(args["fade_step"])
        if (isColor1 and isColor2 and isFloat and isInt1 and isInt2 and isInt
                and isBool):
            self.__execute_task(
                LedUtil.color_pair,
                (self.pixels, lambda: self.cancelTask, wait, color1, color2,
                 size1, size2, with_animation, fade_step))

    def set_brightness(self, args):
        brightness, isInt = Util.intTryParse(args["brightness"])
        if (isInt):
            self.brightness = brightness
            self.pixels.setBrightness(brightness)
            self.pixels.show()

    def set_settings(self, args):
        self.__cancel_task()

        led_pixel_count, isInt = Util.intTryParse(args["led_pixel_count"])
        if (isInt):
            self.led_count = led_pixel_count
            self.led_type = args["led_type"]
            ledType = constants.LED_STRIP
            if (self.led_type == constants.LED_STRIP_SK6812):
                ledType = ws.SK6812W_STRIP
            elif (self.led_type == constants.LED_STRIP_WS2811):
                ledType = ws.WS2811_STRIP_RGB
            elif (self.led_type == constants.LED_STRIP_WS2812B):
                ledType = ws.WS2811_STRIP_RGB

            self.pixels = PixelStrip(self.led_count, constants.LED_PIN,
                                     constants.LED_FREQ_HZ, constants.LED_DMA,
                                     constants.LED_INVERT, self.brightness,
                                     constants.LED_CHANNEL, ledType)
            self.pixels.begin()

    def pixel_off(self, args):
        self.__cancel_task()
        LedUtil.clear(self.pixels)
        self.pixels.show()

    def __execute_task(self, task, args):
        self.__cancel_task()
        self.onGoingTask = threading.Thread(target=task, args=args)
        self.onGoingTask.start()

    def __cancel_task(self):
        if (self.onGoingTask != None):
            self.cancelTask = True
            self.onGoingTask.join()
            self.cancelTask = False
Example #7
0
class Led(Thread):

    # LED strip configuration:
    LED_COUNT = 95  # Number of LED pixels.
    LED_PIN = 18  # GPIO pin connected to the pixels (18 uses PWM!).
    # LED_PIN = 10        # GPIO pin connected to the pixels (10 uses SPI /dev/spidev0.0).
    LED_FREQ_HZ = 800000  # LED signal frequency in hertz (usually 800khz)
    LED_DMA = 10  # DMA channel to use for generating signal (try 10)
    LED_BRIGHTNESS = 170  # Set to 0 for darkest and 255 for brightest
    LED_INVERT = False  # True to invert the signal (when using NPN transistor level shift)
    LED_CHANNEL = 0  # set to '1' for GPIOs 13, 19, 41, 45 or 53
    FRAMERATE = 50

    def __init__(self):
        # Create NeoPixel object with appropriate configuration.
        self.strip = PixelStrip(self.LED_COUNT, \
                                self.LED_PIN, \
                                self.LED_FREQ_HZ, \
                                self.LED_DMA, \
                                self.LED_INVERT, \
                                self.LED_BRIGHTNESS//2, \
                                self.LED_CHANNEL)
        # Intialize the library (must be called once before other functions).
        self.strip.begin()

        # Variables that store what the LEDs will do

        self.loop = False  # whether the current sequence of frames should be
        # repeated after completion

        self.colorSeqs = {}  # a dictionary storing color sequences
        # KEY: the key is arbitrary, to distinguish different color sequences
        #      - It is up to the implementation to determine the key
        # VAL: a list of colors, stored as integers, that form the sequence
        #      - All values in colorSeqs must have the same length

        self.seqLen = 0  # the length of color sequences in colorSeqs

        self.mapping = []  # a list containing integers
        # these integers correspond to indices in colorSeqs
        # length of mapping = number of LEDs in the LightBox

        self.currInd = 0  # an integer marking where in the color sequences the LEDs are

        self.targetBrightness = self.strip.getBrightness(
        )  # value storing brightness to be attained
        # during gradual fade towards it

        # Initialize these variables for the first time (LEDs off)
        self.loop = False
        self.colorSeqs[0] = [0x000000]
        self.seqLen = 1
        self.mapping = [0] * self.strip.numPixels()
        self.currInd = 0
        # These settings will cause the LED's to switch to #000000 (off) once

        # Start thread that will handle LED changes in the background
        Thread.__init__(self)
        self.daemon = True

        print("Led Strip Initialized")

    # Continuous loop that handles LED changes registered in mapping and colorSeqs
    def run(self):
        while True:
            refreshStrip = True
            time.sleep(1.0 / self.FRAMERATE)

            if self.currInd == self.seqLen:  #reached end of sequence
                if self.loop:
                    self.currInd = 0  #loop to beginning of sequence
                else:
                    refreshStrip = False

            if refreshStrip:
                try:
                    for i in range(self.strip.numPixels()):
                        self.strip.setPixelColor(
                            i, self.colorSeqs[self.mapping[i]][self.currInd])
                except KeyError:
                    print("Error: invalid key %d" % self.mapping[i])
                    continue
                self.currInd += 1

            if self.strip.getBrightness() != self.targetBrightness:
                self.strip.setBrightness( max( min(
                        self.strip.getBrightness() + (self.FRAMERATE//25) * \
                        (1 if self.targetBrightness > self.strip.getBrightness() else -1) \
                    , 255), 0) \
                )
                if (abs(self.targetBrightness -
                        self.strip.getBrightness())) < (self.FRAMERATE // 25):
                    self.strip.setBrightness(self.targetBrightness)
                refreshStrip = True

            if refreshStrip:
                self.strip.show()

    # Color Manipulation functions...

    def solidColor(self, color):
        ''' Changes LightBox to a solid color, defined by color '''

        colorSeqs = {}
        mapping = [0] * self.strip.numPixels()

        # Iterate through each led in the strip
        for currLed in range(self.strip.numPixels()):
            # Add entry to mapping for the color sequence
            mapping[currLed] = self.strip.getPixelColor(currLed)

            # Add sequence to colorSeqs if it doesn't exist already
            if mapping[currLed] not in colorSeqs:
                colorSeqs[mapping[currLed]] = \
                    colorUtil.linear_gradient(mapping[currLed], \
                                              color, \
                                              self.FRAMERATE//4)

        self.loop = False
        self.seqLen = self.FRAMERATE // 4
        self.currInd = 0
        self.mapping = mapping
        self.colorSeqs = colorSeqs

    def clear(self):
        '''clears all leds'''
        self.solidColor(0)

    def changeBrightness(self, newBrightnessValue):
        '''sets brightness of LEDs (0-100)'''
        self.targetBrightness = int(self.LED_BRIGHTNESS *
                                    newBrightnessValue**1.5 /
                                    1000)  #1000=100^1.5

    def rainbow(self):
        '''creates a rainbow sequence that loops'''

        #generates list of colors that cycle in hue
        numFrames = self.FRAMERATE * 10  # the number is how many seconds per rainbow cycle
        rainbowColors = [
            colorUtil.HSV_to_hex(k / numFrames * 360, 1, 1)
            for k in range(0, numFrames, 1)
        ]

        colorSeqs = {}
        seqLen = len(rainbowColors)
        mapping = [0] * self.strip.numPixels()

        for led in range(self.strip.numPixels()):
            mapping[led] = led  #unique mapping for each led
            colorSeqs[led] = [0] * seqLen

        for colorPos in range(seqLen):
            for led in range(self.strip.numPixels()):
                colorSeqs[led][colorPos] = rainbowColors[(colorPos + led) %
                                                         seqLen]

        self.loop = True
        self.seqLen = seqLen
        self.currInd = 0
        self.colorSeqs = colorSeqs
        self.mapping = mapping

    def sparkle(self, seqLenSeconds=30):
        '''creates a sparkle sequence that loops'''

        numFrames = self.FRAMERATE * 1  # the number is how many seconds for average flash
        deviation = self.FRAMERATE // 2  # random deviation of the flash lengths
        satChoice = ([0.0]) + ([0.5] * 5) + (
            [1] * 50)  # weighted probability for saturation
        # prevents too many 'white' LEDs
        valChoice = ([0.2]) + ([0.5] * 5) + (
            [1] * 10)  # weighted probability for value
        # prevents too many dim LED's

        colorSeqs = {}
        seqLen = numFrames * seqLenSeconds
        mapping = [0] * self.strip.numPixels()

        for led in range(self.strip.numPixels()):
            mapping[led] = led  # unique mapping for each led
            colorSeqs[led] = [0] * seqLen

        for colorPos in range(seqLen):

            for i in range(random.randrange(
                    0, 4)):  # repeat a random number of times
                # to create variety

                led = random.randrange(0, self.strip.numPixels())
                if colorSeqs[led][colorPos] != 0:  # already a flash at that led
                    continue  # don't overwrite it
                duration = random.randint(numFrames - deviation,
                                          numFrames + deviation)
                hue = random.uniform(0, 360)
                sat = random.choice(satChoice)
                val = random.choice(valChoice)

                for k in range(duration):
                    # fill in colorSeqs for the flash, given by the piecewise function
                    # at https://www.desmos.com/calculator/lmsoc2uoif
                    colorSeqs[led][(colorPos+k)%seqLen] = colorUtil.HSV_to_hex(hue, sat, \
                        val * ( (3/duration)*k if k < duration/3 \
                        else (-3/(2*duration))*(k-duration) ) \
                    )

        self.loop = True
        self.seqLen = seqLen
        self.currInd = 0
        self.colorSeqs = colorSeqs
        self.mapping = mapping
                        '--clear',
                        action='store_true',
                        help='clear the display on exit')
    args = parser.parse_args()

    # Create NeoPixel object with appropriate configuration.
    strip = PixelStrip(LED_COUNT, LED_PIN, LED_FREQ_HZ, LED_DMA, LED_INVERT,
                       LED_BRIGHTNESS, LED_CHANNEL)
    # Intialize the library (must be called once before other functions).
    strip.begin()

    print('Press Ctrl-C to quit.')
    if not args.clear:
        print('Use "-c" argument to clear LEDs on exit')

    try:

        #while True:
        for countdown in range(LED_BRIGHTNESS, 0, -1):
            print countdown
            strip.setBrightness(countdown)
            sleepyTimeCycle(strip)
            print 'Going to sleep'
            time.sleep(10)
            print 'waking up'
        colorWipe(strip, Color(0, 0, 0))

    except KeyboardInterrupt:
        if args.clear:
            colorWipe(strip, Color(0, 0, 0), 10)
class LedRingAnimations:
    """
    Object which implements control method for the Led ring
    """
    def __init__(self):

        # - Parameters
        self.__is_simulation = rospy.get_param("~simulation_mode")

        # LED self.strip configuration:
        self.LED_COUNT = rospy.get_param('~led_count')  # Number of LED pixels.
        self.LED_PIN = rospy.get_param(
            '~led_pin')  # GPIO pin connected to the pixels (must support PWM!)
        self.LED_FREQ_HZ = rospy.get_param(
            '~led_freq_hs')  # LED signal frequency in hertz (usually 800khz)
        self.LED_DMA = rospy.get_param(
            '~led_dma')  # DMA channel to use for generating signal (try 10)
        self.LED_BRIGHTNESS = rospy.get_param(
            '~led_brightness')  # Set to 0 for darkest and 255 for brightest
        self.LED_INVERT = rospy.get_param(
            '~led_invert'
        )  # True to invert the signal (when using NPN transistor level shift)
        self.LED_CHANNEL = rospy.get_param('~led_channel')
        self.__led_offset = rospy.get_param("~led_offset")

        if not self.__is_simulation:
            self.LED_STRIP = ws.WS2811_STRIP_GRB

        # default param for led ring control methods
        self.default_flashing_period = rospy.get_param(
            '~default_flashing_period')
        self.default_alternate_period = rospy.get_param(
            '~default_alternate_period')
        self.default_chase_period = rospy.get_param('~default_chase_period')
        self.default_colorwipe_period = rospy.get_param(
            '~default_colorwipe_period')
        self.default_rainbow_period = rospy.get_param(
            '~default_rainbow_period')
        self.default_rainbowcycle_period = rospy.get_param(
            '~default_rainbowcycle_period')
        self.default_rainbowchase_period = rospy.get_param(
            '~default_rainbowchase_period')
        self.default_goup_period = rospy.get_param('~default_goup_period')
        self.default_goupanddown_period = rospy.get_param(
            '~default_goupanddown_period')
        self.default_breath_period = rospy.get_param('~default_breath_period')
        self.default_snake_period = rospy.get_param('~default_snake_period')

        self.__stop_func = False
        self.__animation_lock = Lock()

        self._observers = []

        self.current_animation_color = BLACK
        self.current_animation = LedRingAnimation.NONE
        self.set_current_anim_and_color(
            self.current_animation,
            self.current_animation_color,
        )

        if not self.__is_simulation:
            self.strip = PixelStrip(self.LED_COUNT, self.LED_PIN,
                                    self.LED_FREQ_HZ, self.LED_DMA,
                                    self.LED_INVERT, self.LED_BRIGHTNESS,
                                    self.LED_CHANNEL, self.LED_STRIP)
            self.strip.begin()

        if self.__is_simulation:
            self.led_count = self.LED_COUNT
        else:
            self.led_count = self.strip.numPixels()

        self.off_color = GREY if self.__is_simulation else BLACK

        # for real mode
        # list used to store the current state of the real led ring, as a list of ColorRGBA objects
        self.current_real_led_ring_state = []

        self.led_ring_makers = LedRingSimulation(self.led_count)

        self.blackout()

    def __del__(self):
        self.set_and_show_leds(self.off_color)
        if not self.__is_simulation:
            del self.strip

    def stop_animation(self):
        """
        Stop iteration (and endless iteration) for functions that perform continous action like alternate_color, and
        wait until the previous function is finished.
        Used when launched in robot status display mode. Indeed, when used by the user,
        the previous function is stopped before, in the start thread function
        """
        if self.is_animation_running():
            self.__stop_func = True
            with self.__animation_lock:  # wait the end of the running animation
                self.blackout()

    def init_animation(self):
        self.__stop_func = False

    def is_animation_running(self):
        return self.__animation_lock.locked()

    def was_function_interrupted(self):
        return self.__stop_func  # if true, function was interrupted

    def __play_cycle_animation(self, color_cycle, period, iterations,
                               animation_function):
        # start playing animation :
        loop_period = period * 1.0 / len(color_cycle)
        next_loop_time = rospy.Time.now()

        count = 1 if not iterations else iterations
        while count > 0:
            for cycle_index in range(len(color_cycle)):
                if self.__stop_func:
                    break

                animation_function(color_cycle, cycle_index)
                next_loop_time += rospy.Duration(loop_period)
                self.__sleep_animation(next_loop_time)

            if self.__stop_func:
                break

            if iterations:
                count -= 1

        self.blackout()

    def none(self):
        """
        Turn off leds, in simu and in real, with the "solid" method
        """
        self.solid(self.off_color)

    def solid(self, color_rgba):
        """
        Sets all Leds to a color at once
        """
        self.init_animation()
        with self.__animation_lock:
            self.set_and_show_leds(color_rgba)

            mode = LedRingAnimation.NONE if color_rgba == self.off_color else LedRingAnimation.SOLID
            self.set_current_anim_and_color(mode, color_rgba)

    def custom(self, color_rgba):
        """
        Sets all Leds to a color at once
        """
        self.init_animation()
        with self.__animation_lock:
            colors = color_rgba[:self.led_count] if len(
                color_rgba) > self.led_count else color_rgba + (
                    len(color_rgba) - self.led_count) * [BLACK]

            for led_id, led_color in enumerate(colors):
                # set color led by led
                self.set_led(led_id, led_color)
            self.show_leds()  # display all leds

            self.set_current_anim_and_color(LedRingAnimation.CUSTOM)

    def set_led_color(self, led_id, color_rgba):
        self.init_animation()
        with self.__animation_lock:
            self.set_led(led_id, color_rgba)
        self.show_leds()
        self.set_current_anim_and_color(LedRingAnimation.CUSTOM)

    def flashing(self, color_rgba, period=None, iterations=0):
        """
        Flash a color according to a frequency
        """
        def animation_function(anim_color_cycle, anim_cycle_index):
            self.set_and_show_leds(anim_color_cycle[anim_cycle_index])

        self.init_animation()

        # set default frequency
        if not period:
            period = self.default_flashing_period

        # configure the animation
        color_cycle = [color_rgba, self.off_color]

        # start the animation
        with self.__animation_lock:
            self.set_current_anim_and_color(LedRingAnimation.FLASHING,
                                            color_rgba)
            self.__play_cycle_animation(color_cycle, period, iterations,
                                        animation_function)

    def alternate(self, color_list_rgba, period=None, iterations=0):
        """
        The different colors are alternated one after the other.
        If iterations is 0, do it indefinitely
        """
        def animation_function(anim_color_cycle, anim_cycle_index):
            self.set_current_anim_and_color(LedRingAnimation.ALTERNATE,
                                            anim_color_cycle[anim_cycle_index])
            self.set_and_show_leds(anim_color_cycle[anim_cycle_index])

        self.init_animation()

        # configure the animation
        if not period:
            period = self.default_alternate_period
        color_cycle = color_list_rgba[:]

        # start the animation
        with self.__animation_lock:
            self.__play_cycle_animation(color_cycle, period, iterations,
                                        animation_function)

    def chase(self, color_rgba, period=None, iterations=0):
        """
        Movie theater light style chaser animation.
        If iterations is 0, do it indefinitely
        """
        def animation_function(anim_color_cycle, anim_cycle_index):
            for led_id in range(self.led_count):
                # set color led by led
                self.set_led(
                    led_id, anim_color_cycle[led_id % len(anim_color_cycle) -
                                             anim_cycle_index])
            self.show_leds()  # display all leds

        self.init_animation()
        # configure the animation
        if not period:
            period = self.default_chase_period
        color_cycle = [self.off_color, self.off_color, color_rgba]

        # start the animation
        with self.__animation_lock:
            self.set_and_show_leds(self.off_color)
            self.set_current_anim_and_color(LedRingAnimation.CHASE, color_rgba)
            self.__play_cycle_animation(color_cycle, period, iterations,
                                        animation_function)

    def color_wipe(self, color_rgba, duration=None):
        """
        Wipe color across, light a Led at a time.
        Similar to goUp, but Leds are not turned off at the end.
        """
        self.init_animation()

        if not duration:
            duration = self.default_colorwipe_period

        with self.__animation_lock:
            self.set_current_anim_and_color(LedRingAnimation.COLOR_WIPE,
                                            color_rgba)
            self.__wipe_animation(color_rgba, duration)

            if self.__stop_func:
                self.blackout()  # turn off leds

    def __wipe_animation(self, color_rgba, duration):
        next_loop = rospy.Time.now()
        period = rospy.Duration(duration * 1.0 / self.led_count)

        for led_id in range(self.led_count):
            if self.__stop_func:
                break
            self.set_led((led_id + self.__led_offset) % self.led_count,
                         color_rgba)
            self.show_leds()

            next_loop += period
            self.__sleep_animation(next_loop)

    def breath_animation(self, color_rgba, duration):
        next_loop = rospy.Time.now()

        gamma = 0.2  # affects the width of peak (more or less darkness)
        beta = 0.5  # shifts the gaussian to be symmetric

        nb_steps = 255
        anim_period = rospy.Duration(duration * 1.0 / nb_steps)

        self.current_animation_color = color_rgba
        for counter in range(nb_steps):
            if self.__stop_func:
                break

            # value = 255 * math.sin(2 * math.pi * (counter * 1.0 / smoothness_pts))
            factor = math.exp(-(pow(
                ((counter * 1.0 / nb_steps) - beta) / gamma, 2.0)) / 2.0)

            # self.set_brightness(value)
            self.set_and_show_leds(
                ColorRGBA(self.current_animation_color.r * factor,
                          self.current_animation_color.g * factor,
                          self.current_animation_color.b * factor, 0))

            next_loop += anim_period
            rospy.sleep(next_loop - rospy.Time.now())

    def breath(self, color_rgba, period=None, iterations=0):
        """
        Leds turn on like a loading circle, and are all turned off at the same time
        If iterations is 0, do it indefinitely
        """
        self.init_animation()
        if period == 0 or period is None:
            period = self.default_breath_period

        # start playing animation :
        with self.__animation_lock:
            self.set_current_anim_and_color(LedRingAnimation.BREATH,
                                            color_rgba)
            if not iterations:
                while not self.__stop_func:
                    self.breath_animation(color_rgba, period)
            else:
                for _i in range(iterations):
                    if self.__stop_func:
                        break
                    self.breath_animation(color_rgba, period)

            self.blackout()

    def snake(self, color_rgba, period=None, iterations=0):
        def animation_function(anim_color_cycle, anim_cycle_index):
            for led_id in range(self.led_count):
                # set color led by led
                self.set_led(
                    led_id, anim_color_cycle[(led_id + anim_cycle_index) %
                                             len(anim_color_cycle)])
            self.show_leds()  # display all leds

        self.init_animation()
        # configure the animation
        if not period:
            period = self.default_snake_period

        attenuated_color = ColorRGBA(color_rgba.r * 0.5, color_rgba.g * 0.5,
                                     color_rgba.b * 0.5, 0)
        snake_length = 10
        snake_pattern = [
            attenuated_color
        ] + (snake_length - 2) * [color_rgba] + [
            attenuated_color
        ] + (self.LED_COUNT - snake_length) * [self.off_color]

        # start the animation
        with self.__animation_lock:
            self.set_and_show_leds(self.off_color)
            self.set_current_anim_and_color(LedRingAnimation.SNAKE, color_rgba)
            self.__play_cycle_animation(snake_pattern, period, iterations,
                                        animation_function)

    def go_up(self, color_rgba, period=None, iterations=0):
        """
        Leds turn on like a loading circle, and are all turned off at the same time
        If iterations is 0, do it indefinitely
        """
        def animation(duration):
            end_time = rospy.Time.now() + rospy.Duration(duration)

            self.__wipe_animation(
                color_rgba, duration * self.led_count / (self.led_count + 1))
            self.set_and_show_leds(self.off_color)
            rospy.sleep(end_time - rospy.Time.now())

        self.init_animation()
        if period == 0 or period is None:
            period = self.default_goup_period

        # start playing animation :
        with self.__animation_lock:
            self.set_current_anim_and_color(LedRingAnimation.GO_UP, color_rgba)
            if not iterations:
                while not self.__stop_func:
                    animation(period)
            else:
                for _ in range(iterations):
                    if self.__stop_func:
                        break
                    animation(period)

            self.blackout()

    def go_up_and_down(self, color_rgba, period=None, iterations=0):
        """
        Leds turn on like a loading circle, and turn off the same way
        If iterations is 0, do it indefinitely
        """
        def animation(duration):
            self.__wipe_animation(color_rgba, duration / 2.0)
            self.__wipe_animation(self.off_color, duration / 2.0)

        self.init_animation()
        if period == 0 or period is None:
            period = self.default_goupanddown_period

        with self.__animation_lock:
            self.set_current_anim_and_color(LedRingAnimation.GO_UP_AND_DOWN,
                                            color_rgba)

            # start playing animation :
            if not iterations:
                while not self.__stop_func:
                    animation(period)
            else:
                for _ in range(iterations):
                    if self.__stop_func:
                        break
                    animation(period)

            self.blackout()

    def __rainbow_animation(self, duration, animation_function):
        next_loop = rospy.Time.now()

        anim_period = rospy.Duration(duration / 256.0)
        for color_counter in range(256):
            if self.__stop_func:
                break

            animation_function(color_counter)

            next_loop += anim_period
            rospy.sleep(next_loop - rospy.Time.now())

    def rainbow(self, period=None, iterations=0):
        """
        Draw rainbow that fades across all Leds at once
        If iterations is 0, do it indefinitely
        """
        def animation(color_counter):
            # for led_id in range(self.led_count):
            #   self.set_led(led_id, wheel_rgba((led_id + color_counter) & 255))
            # self.show_leds()
            self.set_and_show_leds(wheel_rgba(color_counter & 255))

        self.init_animation()
        # configure the animation
        if not period:
            period = self.default_rainbow_period

        with self.__animation_lock:
            # no color info in led_ring_status topic, so we just notify that the animation changed
            self.set_current_anim_and_color(LedRingAnimation.RAINBOW)

            # start playing animation :

            if not iterations:
                while not self.__stop_func:
                    self.__rainbow_animation(period, animation)
            else:
                for _ in range(iterations):
                    if self.__stop_func:
                        break
                    self.__rainbow_animation(period, animation)

            self.blackout()  # turn off leds after all iterations

    def rainbow_cycle(self, period=None, iterations=0):
        """
        Draw rainbow that uniformly distributes itself across all Leds
        If iterations is 0, do it indefinitely
        """
        def animation(color_counter):
            for led_id in range(self.led_count):
                self.set_led(
                    led_id,
                    wheel_rgba(
                        int((led_id * 256.0 // self.led_count + color_counter))
                        & 255))
            self.show_leds()

        self.init_animation()
        if not period:
            period = self.default_rainbowcycle_period

        with self.__animation_lock:
            self.set_current_anim_and_color(LedRingAnimation.RAINBOW_CYLE)

            # start playing animation :
            if not iterations:
                while not self.__stop_func:
                    self.__rainbow_animation(period, animation)
            else:
                for _ in range(iterations):
                    if self.__stop_func:
                        break
                    self.__rainbow_animation(period, animation)

            self.blackout()  # turn off leds after all iterations

    def rainbow_chase(self, period=None, iterations=0):
        """
        Rainbow chase animation
        If iterations is 0, do it indefinitely
        """
        def animation(color_counter):
            for led_id in range(self.led_count):
                offset = color_counter % 3

                if (led_id + offset) % 3 == 0:
                    self.set_led(led_id,
                                 wheel_rgba((led_id + color_counter) & 255))
                else:
                    self.set_led(led_id, self.off_color)  # don't show
            self.show_leds()

        self.init_animation()
        if not period:
            period = self.default_rainbowchase_period

        with self.__animation_lock:
            self.set_current_anim_and_color(LedRingAnimation.RAINBOW_CHASE)
            self.set_and_show_leds(self.off_color)

            # start playing animation :
            if not iterations:
                while not self.__stop_func:
                    self.__rainbow_animation(period, animation)
            else:
                for _ in range(iterations):
                    if self.__stop_func:
                        break
                    self.__rainbow_animation(period, animation)

            self.blackout()  # turn off leds after all iterations

    def blackout(self):
        """
        Black out every led, without stopping previous function
        """
        self.set_and_show_leds(self.off_color)
        self.set_current_anim_and_color(LedRingAnimation.NONE, BLACK)

    def fade(self, color_rgba, duration=3.5, steps=100):
        current_color = self.current_animation_color
        step_r = (color_rgba.r - current_color.r) / float(steps)
        step_g = (color_rgba.g - current_color.g) / float(steps)
        step_b = (color_rgba.b - current_color.b) / float(steps)

        sleep_duration = duration / float(steps)
        for _ in range(steps):
            self.current_animation_color = ColorRGBA(
                self.current_animation_color.r + step_r,
                self.current_animation_color.g + step_g,
                self.current_animation_color.b + step_b, 0)
            rospy.sleep(sleep_duration)

    # - Real Led ring related method

    def get_state_list_from_pixel_strip(self):
        """
        Return a list of size self.led_count, containing the current rgb color [r, g, b] of each Led in the
        real led ring
        """
        real_leds_state = []
        if not self.__is_simulation:
            for i in range(self.led_count):
                # read back the state from the library memory buffer
                # (can't read directly Led state, they are Write-only)
                color_i = self.strip.getPixelColorRGB(i)
                real_leds_state.append([color_i.r, color_i.g, color_i.b])
        return real_leds_state

    # - Generic methods usable for simulation and real robot

    def set_led(self, index, color_rgba):
        """
        Set the color of a pixel, in simu or in real
        """
        if not self.__is_simulation:
            color = get_24bits_color_from_msg(color_rgba)
            self.strip.setPixelColor(index, color)
        self.led_ring_makers.set_one_led_marker(index, color_rgba)

    def show_leds(self):
        """
        Display all Led's values previously set, in simu or in real
        """
        if not self.__is_simulation:
            self.strip.show()

            # update value of current led state
            current_rgb_array_led_state = self.get_state_list_from_pixel_strip(
            )
            current_color_rgba_led_state = []
            # transform a list like [[r, g, b], [r, g, b], ...] to a list like [ColorRGBA, ColorRGBA, ...]
            for elem in current_rgb_array_led_state:
                current_color_rgba_led_state.append(
                    get_rgba_color_from_list(elem))
            self.set_current_real_leds_state(current_color_rgba_led_state)
        self.led_ring_makers.show_led_ring_markers()

    def set_and_show_leds(self, color, range_=None, index_delta=0):
        """
        Iterate over all leds, set them to the chosen color and show them all at once.
        "range_" must be filled only if we want to iterate over a part of the led ring.
        "index_delta" is used by "chase" methods only.
        """

        if range_ is None:
            range_ = self.led_count
            for i in range(range_):
                self.set_led(i + index_delta, color)
            self.show_leds()

        elif isinstance(range_, list) and len(range_) == 3:
            for i in range(range_[0], range_[1], range_[2]):
                self.set_led(i + index_delta, color)
            self.show_leds()

    def set_brightness(self, brightness):
        if not self.__is_simulation:
            self.strip.setBrightness(brightness)

    def __sleep_animation(self, until_time):
        while (until_time - rospy.Time.now()).to_sec() > 0.1:
            rospy.sleep(0.1)
            if self.__stop_func:
                break
        else:
            rospy.sleep(until_time - rospy.Time.now())

    # Observable related methods
    def set_current_anim_and_color(self, animation, color=None):
        self.current_animation_color = color if color is not None else BLACK
        self.current_animation = animation
        self.notify_observers()

    def set_current_real_leds_state(self, rgb_list):
        self.current_real_led_ring_state = rgb_list

    def notify_observers(self):
        """
        trigger a function in the observer (led ring node) class
        """
        for obs in self._observers:
            obs.notify_current_anim_and_color(self)

    def register_observer(self, observer):
        """
        Used to add the led ring node as an observer of this class
        """
        self._observers.append(observer)
Example #10
0
class lbhtest():
    def __init__(self, rows, columns, serial_type=1, led_pin=18):
        ##
        # serial_type 信号线连接方式, 1表示弓字形连线,2表示Z字形连线
        ##
        self.rows = rows
        self.columns = columns
        self.led_numbers = rows * columns
        self._mod = 1
        self.leds = []
        for i in range(self.led_numbers):
            self.leds.append(LED(i))

        self.led_index = [[0 for i in range(self.columns)]
                          for i in range(self.rows)]
        if (serial_type == 1):
            for i in range(0, rows, 2):
                for j in range(0, self.columns):
                    self.led_index[i][j] = i * self.columns + j

            for i in range(1, rows, 2):
                for j in range(0, self.columns):
                    self.led_index[i][j] = (i + 1) * self.columns - (j + 1)
        elif (serial_type == 2):
            for i in range(0, rows):
                for j in range(0, columns):
                    self.led_index[i][j] = i * self.columns + j

        self.strip = PixelStrip(self.led_numbers, led_pin)
        self.strip.begin()
        self.strip.setBrightness(255)

    def del_cmd(self, paras):
        self._mod = paras["mod"]

        if (paras["mod"] == 1):  # 全体显示
            if (paras["function"] == 0):
                self._symbolLeftToRight(wan, Color(100, 100, 0), 500)
            elif (paras["function"] == 1):
                self._symbolRightToLeft(wan, Color(100, 100, 0), 500)
            elif (paras["function"] == 2):
                self._leftToRight(Color(100, 100, 0), 50)
            elif (paras["function"] == 3):
                self._symbolLeftToRight(zhong, Color(100, 100, 0), 500)
            elif (paras["function"] == 4):
                self._leftToRight(Color(100, 100, 0), 50)
            elif (paras["function"] == 5):
                self._rightToLeft(Color(100, 100, 0), 50)
            elif (paras["function"] == 6):
                self._bottomToTop(Color(100, 100, 0), 50)
            elif (paras["function"] == 7):
                self._topToBottom(Color(100, 100, 0), 50)
        elif (paras["mod"] == 0):  #单个显示
            row = paras["led_row"] - 1
            col = paras["led_column"] - 1
            led_index = self.led_index[row][col]
            self.leds[led_index]._set_color(0)
            self.leds[led_index]._set_cycle(paras["cycle"])
            self.leds[led_index]._set_delay(paras["delay"])

    def light(self):
        if (self._mod == 0):  # 单个显示
            for i in range(self.led_numbers):
                if (self.leds[i]._recycle > 0):
                    color = self.leds[i].get_cur_color()
                    if (not color is None):
                        self.strip.setPixelColor(i, color)
                        print("第i个灯", i, color)
                        self.strip.show()

    def _showGivenSymbolAt(self, symbol, x, y, color, bgcolor=Color(0, 0, 0)):
        m = len(symbol)
        n = len(symbol[0])
        for i in range(m):
            for j in range(n):
                if (symbol[i][j] == 1):
                    self.strip.setPixelColor(self.led_index[i + x][j + y],
                                             color)
                else:
                    self.strip.setPixelColor(self.led_index[i + x][j + y],
                                             bgcolor)
        self.strip.show()

    def _colorWipe(self, color):
        """Wipe color across display a pixel at a time."""
        for i in range(self.led_numbers):
            self.strip.setPixelColor(i, color)
        self.strip.show()

    def _theaterChase(self, color, wait_ms=50, iterations=10):
        """Movie theater light style chaser animation."""
        for j in range(iterations):
            for q in range(3):
                for i in range(0, self.led_numbers, 3):
                    self.strip.setPixelColor(i + q, color)
                self.strip.show()
                time.sleep(wait_ms / 1000.0)
                for i in range(0, self.led_numbers, 3):
                    self.strip.setPixelColor(i + q, 0)

    def _wheel(self, pos):
        """Generate rainbow colors across 0-255 positions."""
        if pos < 85:
            return Color(pos * 3, 255 - pos * 3, 0)
        elif pos < 170:
            pos -= 85
            return Color(255 - pos * 3, 0, pos * 3)
        else:
            pos -= 170
            return Color(0, pos * 3, 255 - pos * 3)

    def _rainbow(self, wait_ms=20, iterations=1):
        """Draw rainbow that fades across all pixels at once."""
        for j in range(256 * iterations):
            for i in range(self.led_numbers):
                self.strip.setPixelColor(i, self._wheel((i + j)))

            self.strip.show()
            time.sleep(wait_ms / 1000.0)

    def _rainbowCycle(self, wait_ms=20, iterations=5):
        """Draw rainbow that uniformly distributes itself across all pixels."""
        for j in range(256 * iterations):
            for i in range(self.led_numbers):
                self.strip.setPixelColor(
                    i,
                    self._wheel((int(i * 256 / self.strip.numPixels()) + j)
                                & 255))
            self.strip.show()
            time.sleep(wait_ms / 1000.0)

    def _theaterChaseRainbow(self, wait_ms=50):
        """Rainbow movie theater light style chaser animation."""
        for j in range(256):
            for q in range(3):
                for i in range(0, self.led_numbers, 3):
                    self.strip.setPixelColor(i + q, self._wheel((i + j)))
                self.strip.show()
                time.sleep(wait_ms / 1000.0)
                for i in range(0, self.led_numbers, 3):
                    self.strip.setPixelColor(i + q, Color(0, 0, 0))
                self.strip.show()

    def _leftToRight(self, color, wait_ms=50):
        for j in range(self.columns):
            for i in range(self.rows):
                self.strip.setPixelColor(self.led_index[i][j], color)
            self.strip.show()
            time.sleep(wait_ms / 1000.0)

    def _rightToLeft(self, color, wait_ms=50):
        for j in reversed(range(self.columns)):
            for i in range(self.rows):
                self.strip.setPixelColor(self.led_index[i][j], color)
            self.strip.show()
            time.sleep(wait_ms / 1000.0)

    def _topToBottom(self, color, wait_ms=50):
        for i in range(self.rows):
            for j in range(self.columns):
                self.strip.setPixelColor(self.led_index[i][j], color)
            self.strip.show()
            time.sleep(wait_ms / 1000.0)

    def _bottomToTop(self, color, wait_ms=50):
        for i in reversed(range(self.rows)):
            for j in range(self.columns):
                self.strip.setPixelColor(self.led_index[i][j], color)
            self.strip.show()
            time.sleep(wait_ms / 1000.0)

    def _symbolLeftToRight(self, symbol, color, wait_ms):
        for j in range(self.columns - len(symbol[0])):
            self._showGivenSymbolAt(symbol, 0, j, color)
            time.sleep(wait_ms / 1000.0)
            self._colorWipe(Color(0, 0, 0))

    def _symbolRightToLeft(self, symbol, color, wait_ms):
        for j in reversed(range(self.columns - len(symbol[0]))):
            self._showGivenSymbolAt(symbol, 0, j, color)
            time.sleep(wait_ms / 1000.0)
            self._colorWipe(Color(0, 0, 0))
Example #11
0
class Moodlights():
    def __init__(self, led_count, led_pin, led_freq_hz, led_dma, led_invert,
                 led_brightness, led_channel):
        self.strip = PixelStrip(led_count, led_pin, led_freq_hz, led_dma,
                                led_invert, led_brightness, led_channel)
        self.strip.begin()

        self.led_count = led_count
        self.pixels = [Pixel(self.strip, x) for x in range(led_count)]

        signal.signal(signal.SIGINT, self.signal_handler)

    def in_range(self, led_num):
        return led_num >= 0 and led_num < self.led_count

    def shutdown(self):
        self.all_pixels_off()
        sys.exit()

    def signal_handler(self, sig, frame):
        print("You pressed Ctrl-C! Exiting...")
        self.shutdown()

    def all_pixels_off(self):
        for pixel in self.pixels:
            pixel.switch_off()
        self.strip.show()

    def color_wipe(self, colors, iterations=0, wait_ms=0):
        """
        params:

        colors: sequence of colors to display
        wait_ms: wait time between each pixel (0 for instant)
        """
        is_infinite = iterations == 0

        i = 0
        while is_infinite or i < iterations:
            self.all_pixels_off()
            for j in range(self.led_count):
                pixel = self.pixels[j]
                pixel.set_color(colors[j % len(colors)])
                self.strip.show()
                time.sleep(wait_ms / 1000.0)
            i += 1

    def pulse(self, iterations=0, wait_ms=2):
        """
        params:

        iteration: number of pulses (0 means infinite)
        wait_ms: wait time before changing brightness by 1/255 of max brightness
        """
        is_increasing = self.strip.getBrightness() < 255
        is_infinite = iterations == 0

        i = 0
        while is_infinite or i < iterations * 256 * 2:
            if is_increasing:
                next_brightness = self.strip.getBrightness() + 1
                is_increasing = next_brightness != 255
            else:
                next_brightness = self.strip.getBrightness() - 1
                is_increasing = next_brightness == 0

            self.strip.setBrightness(next_brightness)
            time.sleep(wait_ms / 1000.0)
            self.strip.show()
            i += 1

    def wave(self,
             colors,
             iterations,
             intensity,
             wait_ms=50,
             spread=0,
             is_reverse=False):
        """
        params:

        colors: sequence of colors to display
        intensity: brightness of the crest (from 0 to 255)
        wait_ms: wait time before the crest of the wave shifts
        spread: how many pixels away from the crest will be lighted up
        """
        intensity_interval = float(intensity / (spread + 1))
        led_iteration = list(
            range(-1 - spread,
                  self.strip.numPixels() + spread + 1))
        if is_reverse:
            led_iteration.reverse()

        is_infinite = iterations == 0
        k = 0
        while is_infinite or k < iterations:
            for i in led_iteration:
                if self.in_range(i):
                    self.pixels[i].set_color(colors[i % len(colors)])
                    self.pixels[i].set_brightness(intensity)

                for j in range(1, spread + 1):
                    brightness = int(abs(intensity - intensity_interval * j))

                    if self.in_range(i - j):
                        self.pixels[i - j].set_color(colors[(i - j) %
                                                            len(colors)])
                        self.pixels[i - j].set_brightness(brightness)
                    if self.in_range(i + j):
                        self.pixels[i + j].set_color(colors[(i + j) %
                                                            len(colors)])
                        self.pixels[i + j].set_brightness(brightness)

                if self.in_range(i - spread - 1):
                    self.pixels[i - spread - 1].switch_off()
                if self.in_range(i + spread + 1):
                    self.pixels[i + spread + 1].switch_off()
                self.strip.show()

                time.sleep(wait_ms / 1000.0)
            k += 1

    def wheel(self, pos):
        if pos < 85:
            return Color(pos * 3, 255 - pos * 3, 0)
        elif pos < 170:
            pos -= 85
            return Color(255 - pos * 3, 0, pos * 3)
        else:
            pos -= 170
            return Color(0, pos * 3, 255 - pos * 3)

    def rainbow_cycle(self, iterations=0, wait_ms=160):
        is_infinite = iterations == 0

        j = 0
        while is_infinite or j < iterations * 256:
            for i in range(self.strip.numPixels()):
                self.strip.setPixelColor(i, self.wheel((i + j) & 255))
            self.strip.show()
            j += 1
            time.sleep(wait_ms / 1000.0)

    def rainbow_chase(self, iterations=0, wait_ms=100):
        is_infinite = iterations == 0

        j = 0
        while is_infinite or j < iterations * 256:
            for q in range(3):
                for i in range(0, self.strip.numPixels(), 3):
                    self.strip.setPixelColor(i + q, self.wheel((i + j) % 255))
                self.strip.show()
                time.sleep(wait_ms / 1000.0)
                for i in range(0, self.strip.numPixels(), 3):
                    self.strip.setPixelColor(i + q, 0)
            j += 1
Example #12
0
class LEDPanel:
    """Listens to new data on the needed universes

    start_universe: The universe in which the panel starts
    start_channel: Inside the start_universe, the first channel used by the
                    panel. Internally numbered starting from 0.
    """
    def __init__(self, universe, channel, size=17):
        self.address_lock = threading.Lock()
        self.start_universe = universe
        self.start_channel = channel - 1
        self._rows = size
        self._columns = self._rows  # We assume it's a square

        self._old_universes = {}

        self.updateUniversesChannels()

        self._strip = PixelStrip(num=self._led_count, pin=12)  # uses PWM0
        self._strip.begin()

        self._wrapper = ClientWrapper()
        self._client = self._wrapper.Client()

        self.subscribeToUniverses()

    @property
    def columns(self):
        return self._columns

    @property
    def rows(self):
        return self._rows

    def getCallbackForUniverse(self, universe):
        if universe == self.start_universe:
            first_channel = self.start_channel
            last_channel = self._last_channel_used_in_first_universe + 1

            first_pixel_index = 0
        elif universe == self._last_universe:
            first_channel = 0
            last_channel = self._last_channel + 1

            first_pixel_index = self._led_count - (
                self._rows_in_last_universe * self._columns)
        elif universe > self.start_universe and universe < self._last_universe:
            first_channel = 0
            last_channel = self._last_channel + 1

            internal_universe_index = universe - self.start_universe
            pixels_in_first = self._rows_in_first_universe * self._columns
            pixels_in_full = self._rows_per_full_universe * self._columns
            first_pixel_index = pixels_in_first + (
                (internal_universe_index - 1) * pixels_in_full)
        else:
            raise ValueError('universe must be one of the listened universes')

        strip = self._strip
        old_universes = self._old_universes

        def callback(data):
            data = list(data)[first_channel:last_channel]

            if universe not in old_universes or data != old_universes[universe]:
                old_universes[universe] = data

                GPIO.output(STATUS_LED, GPIO.HIGH)

                for i in range(0, last_channel - first_channel, 3):
                    try:
                        r = data[i]
                    except IndexError:
                        r = 0

                    try:
                        g = data[i+1]
                    except IndexError:
                        g = 0

                    try:
                        b = data[i+2]
                    except IndexError:
                        b = 0

                    strip.setPixelColorRGB(int(i/3)+first_pixel_index, r, g, b)
                strip.show()
                print(universe)

                GPIO.output(STATUS_LED, GPIO.LOW)

        return callback

    def updateUniversesChannels(self):
        self._led_count = self._rows * self._columns
        self._channel_count_per_row = self._columns * 3

        self._rows_per_full_universe = DMX_UNIVERSE_SIZE // self._channel_count_per_row
        channels_in_first_universe = DMX_UNIVERSE_SIZE - self.start_channel
        self._rows_in_first_universe = channels_in_first_universe \
            // self._channel_count_per_row

        self._last_channel_used_in_first_universe = self.start_channel + \
            self._rows_in_first_universe * self._channel_count_per_row - 1

        self._universe_count = 1
        rows_left = self._rows - self._rows_in_first_universe
        while rows_left >= self._rows_per_full_universe:
            self._universe_count += 1
            rows_left -= self._rows_per_full_universe

        if rows_left != 0:
            self._universe_count += 1
            self._last_channel = rows_left * self._channel_count_per_row - 1
            self._rows_in_last_universe = rows_left
        else:
            self._last_channel = DMX_UNIVERSE_SIZE

        self._last_universe = self.start_universe + self._universe_count - 1

    def subscribeToUniverses(self):
        self._old_universes.clear()
        for uni in range(self.start_universe, self._last_universe + 1):
            self._client.RegisterUniverse(uni, self._client.REGISTER,
                                          self.getCallbackForUniverse(uni))

    def unsubscribeFromUniverses(self):
        for uni in range(self.start_universe, self._last_universe + 1):
            self._client.RegisterUniverse(uni, self._client.UNREGISTER,
                                          data_callback=None)

    def run(self):
        print("Launched LEDPanel")
        self._wrapper.Run()

    def setOnOff(self, activate=True):
        self._strip.setBrightness(activate * 255)
        self._strip.show()

    def threadSafeSchedule(self, time_in_ms, callback):
        def f():
            self._wrapper.AddEvent(time_in_ms, callback)
        self._wrapper.Execute(f)

    def setAddress(self, universe=None, channel=None):
        """Sets the panel's address

        This method is threadsafe
        """
        with self.address_lock:
            universe = universe if universe is not None else self.start_universe
            channel = channel - 1 if channel is not None else self.start_channel

            self.unsubscribeFromUniverses()

            self.start_universe = universe
            self.start_channel = channel

            self.updateUniversesChannels()
            self.subscribeToUniverses()

    def showFrame(self, frame):
        for i, pixel in enumerate(frame):
            self._strip.setPixelColorRGB(i, *pixel)
        self._strip.show()