Example #1
0
def exc():
    import os
    import json
    import math
    import time
    from copy import deepcopy
    from neopixel import Adafruit_NeoPixel
    basedir = os.path.dirname(os.path.realpath(__file__))

    steps = 120
    neopixel = Adafruit_NeoPixel(1, 18)
    neopixel.begin()

    setting = {'threat': 0, 'cautioning': 0, 'optimum': 1}
    changelog = [0, 0, 0]

    if setting['threat'] > 0:
        changelog[0] = 255
    elif setting['cautioning'] > 0:
        changelog[0] = 255
        changelog[1] = 255
    elif setting['optimum'] > 0:
        changelog[1] = 255

    if os.path.isfile(basedir + '/ledstate.json'):
        with open(basedir + '/ledstate.json', 'r') as out:
            current = json.loads(out.read())
    else:
        raw = neopixel.getPixelColor(0)
        current = []

        for _ in range(3):
            calc = divmod(raw, 256)
            raw = calc[0]
            current.append(calc[1])

        current = current[::-1]
    print(current)
    bcurrent = []
    bchange = []

    for pointer in range(len(current)):
        bcurrent.append(
            True if current[pointer] > changelog[pointer] else False)
        bchange.append(
            True if current[pointer] != changelog[pointer] else False)

    old = deepcopy(current)
    for i in range(0, steps + 1):
        color = []
        for pointer in range(len(bchange)):
            if bchange[pointer]:
                if not bcurrent[pointer]:
                    x = i
                    offset = current[pointer]
                else:
                    x = steps - i
                    offset = changelog[pointer]
                color.append(offset + int(
                    abs(current[pointer] - changelog[pointer]) / steps * x))
                # color.append(offset + int(math.cos((1 / steps) * math.pi * x) * (abs(current[pointer] - changelog[pointer]) / 2) + (abs(current[pointer] - changelog[pointer]) / 2)))
            else:
                color.append(old[pointer])
        print(color)
        neopixel.setPixelColorRGB(0, color[0], color[1], color[2])
        neopixel.show()
        old = deepcopy(color)
        # time.sleep(1 / 30)
        print(color)

    with open(basedir + '/ledstate.json', 'w') as out:
        out.write(json.dumps(old))
Example #2
0
  def run(steps=120):
    result = VariousTools.offline_check('generalleds', hardware=False)
    changelog = [0, 0, 0]
    if result:
      setting = {'threat': 0, 'cautioning': 0, 'optimum': 0}
      plant = Plant.get(localhost=True)

      all_status = SensorStatus.select().where(SensorStatus.plant == plant)

      for status in all_status:
        setting[status.level.label] += 1

      if setting['threat'] > 0:
        changelog[0] = 255
      elif setting['cautioning'] > 0:
        changelog[0] = 255
        changelog[1] = 255
      elif setting['optimum'] > 0:
        changelog[1] = 255

    basedir = os.path.dirname(os.path.realpath(__file__))
    neopixel = Adafruit_NeoPixel(1, 18)
    neopixel.begin()

    if os.path.isfile(basedir + '/ledstate.json'):
      with open(basedir + '/ledstate.json', 'r') as out:
        current = json.loads(out.read())
    else:
      raw = neopixel.getPixelColor(0)
      current = []

      for _ in range(3):
        calc = divmod(raw, 256)
        raw = calc[0]
        current.append(calc[1])

      current = current[::-1]

    if changelog == current:
      return True

    bcurrent = []
    bchange = []

    for pointer in range(len(current)):
      bcurrent.append(True if current[pointer] >= changelog[pointer] else False)
      bchange.append(True if current[pointer] != changelog[pointer] else False)

    old = deepcopy(current)
    for i in range(0, steps + 1):
      color = []
      for pointer in range(len(bchange)):
        if bchange[pointer]:
          if not bcurrent[pointer]:
            x = i
            offset = current[pointer]
          else:
            x = steps - i
            offset = changelog[pointer]
          color.append(offset + int(abs(current[pointer] - changelog[pointer]) / steps * x))
        else:
          color.append(old[pointer])

      print(color)
      neopixel.setPixelColorRGB(0, color[0], color[1], color[2])
      neopixel.show()
      old = deepcopy(color)
      time.sleep(1 / 15)

    with open(basedir + '/ledstate.json', 'w') as out:
      out.write(json.dumps(color))

    time.sleep(1)
    neopixel.setPixelColorRGB(0, changelog[0], changelog[1], changelog[2])
    neopixel.show()

    return True
Example #3
0
class BinaryClock:

    '''
    The class, which makes the binary clock run...
    '''

    def __init__(self):

        GPIO.setmode(GPIO.BOARD)

        # absolute path to current file old: os.getcwd()
        self.basePath = os.path.dirname(
            os.path.abspath(
                inspect.getfile(
                    inspect.currentframe()
                )
            )
        )
        # Number of columns in clock
        self.clock_width = 6
        # Number of rows in clock
        self.clock_height = 4

        self.curr_fg_color = Color(0, 0, 0)
        self.curr_bg_color = Color(0, 0, 0)
        self.flag_clockIndent = False

        # Number of LED pixels.
        LED_COUNT = self.clock_width * self.clock_height
        # GPIO pin connected to the pixels (18 uses PWM!).
        LED_PIN = 18
        # LED signal frequency in hertz (usually 800khz)
        LED_FREQ_HZ = 800000
        # DMA channel to use for generating signal (try 5)
        LED_DMA = 5
        # Set to 0 for darkest and 255 for brightest
        LED_BRIGHTNESS = 128
        # True to invert the signal (when using NPN transistor level shift)
        LED_INVERT = False
        # set to '1' for GPIOs 13, 19, 41, 45 or 53
        LED_CHANNEL = 0
        # Strip type and colour ordering
        LED_STRIP = ws.WS2811_STRIP_GRB

        # path to configuration file
        cfgFilePath = os.path.join(self.basePath, 'config', 'clockConfig.cfg')
        if not os.path.exists(cfgFilePath):
            cfgFilePathDefault = os.path.join(self.basePath,
                                              'config',
                                              'clockConfig_default.cfg')
            copyfile(cfgFilePathDefault, cfgFilePath)

        # configuration setup
        self.configuration = bcc.ConfigFile(cfgFilePath)
        self.configuration.readConfigFile()

        self.helpers = bch.Helpers(self.configuration)

        # Create NeoPixel object with appropriate configuration.
        self.strip = Adafruit_NeoPixel(LED_COUNT,
                                       LED_PIN,
                                       LED_FREQ_HZ,
                                       LED_DMA,
                                       LED_INVERT,
                                       LED_BRIGHTNESS,
                                       LED_CHANNEL,
                                       LED_STRIP)

        # Intialize the library (must be called once before other functions).
        self.strip.begin()

        # LED Functions
        self.stripFunctions = bcl.LEDFunctions(self.strip,
                                               self.clock_width,
                                               self.clock_height)

        # Plugins
        self.plugin2 = p_TimeAsText.ShowTimeAsText(self.strip,
                                                   self.clock_width,
                                                   self.clock_height,
                                                   self.basePath)

        self.plugin3 = p_MatrixEffect.ShowMatrixEffect(self.strip,
                                                       self.clock_width,
                                                       self.clock_height,
                                                       self.configuration)

        self.plugin4 = p_SplashScreen.ShowSplashScreen(self.strip,
                                                       self.clock_width,
                                                       self.clock_height)

        self.plugin5 = p_RainbowAllLEDs.ShowRainbowAllLEDs(self.strip,
                                                           self.configuration)

        self.plugin6 = p_Fire.ShowFire(self.strip,
                                       self.clock_width,
                                       self.clock_height,
                                       self.configuration)

        # initialize the observer event
        watchedDir = os.path.join(self.basePath, 'config')
        self.event_handler = PatternMatchingEventHandler(
            patterns=["*.cfg"],
            ignore_patterns=[],
            ignore_directories=True)
        self.event_handler.on_any_event = self.on_any_event
        self.observer = Observer()
        self.observer.schedule(self.event_handler, watchedDir, recursive=False)
        self.observer.start()

        # ldr gpio pin number
        self.pin_to_circuit = 7
        self.brightness = self.configuration.brightness_general
        self.arr_ldrValues = []

    '''-------------------------------------------------------------------------
    # O T H E R   F U N C T I O N S ----------------------------------------'''

    def rc_time(self):

        while True:

            if self.configuration.running == self.configuration.stop == 1:
                break

            if self.configuration.sensitive == 1:

                GPIO.setup(self.pin_to_circuit, GPIO.OUT)
                GPIO.output(self.pin_to_circuit, GPIO.LOW)

                time.sleep(0.1)

                GPIO.setup(self.pin_to_circuit, GPIO.IN)

                c = 0
                while (GPIO.input(self.pin_to_circuit) == GPIO.LOW):
                    c += 1
                    if c >= 20000:
                        break

                self.arr_ldrValues.append(c)
                # print "c: " + str(c)

                if len(self.arr_ldrValues) == 10:
                    ldrValue = (sum(self.arr_ldrValues) - max(self.arr_ldrValues) -
                                min(self.arr_ldrValues)) / (len(self.arr_ldrValues) - 2)
                    del self.arr_ldrValues[:]

                    self.brightness = int(math.floor(
                        (238 / (1 + math.exp(0.000475 * (2.25 * ldrValue - 10000)))) + 19))
                    print str(self.brightness)

            else:

                self.brightness = self.configuration.brightness_general
                print str(self.brightness)
                time.sleep(0.5)

    # --------------------------------------------------------------------------

    def on_any_event(self, event):
        self.configuration.readConfigFile()
        if self.configuration.flag_whipeLEDs:
            self.stripFunctions.wipeLEDs()

    # --------------------------------------------------------------------------

    def upInTheSky(self):

        backgroundNoSeconds = [1, 2, 3, 4,
                               7, 8, 9, 10,
                               13, 14, 15, 16,
                               19, 20, 21, 22]

        arr = []
        # get current xy coordinates of lit LEDs
        for i in range(self.strip.numPixels()):
            if self.strip.getPixelColor(i) == self.curr_fg_color:
                arr.append(i)

        for j in range(4):
            for i, p in enumerate(arr):
                x, y = self.stripFunctions.get2DCoordinateFrom1D(p)
                self.stripFunctions.setColorBy2DCoordinates(x,
                                                            y - j,
                                                            self.curr_fg_color)
            self.strip.show()
            time.sleep(0.2)
            if self.configuration.show_seconds == 1:
                for i in range(self.strip.numPixels()):
                    self.stripFunctions.setColorBy1DCoordinate(
                        i,
                        self.curr_bg_color,
                        flag_forClock=self.flag_clockIndent)
            else:
                for i in range(len(backgroundNoSeconds)):
                    self.stripFunctions.setColorBy1DCoordinate(
                        backgroundNoSeconds[i],
                        self.curr_bg_color,
                        flag_forClock=self.flag_clockIndent)

        self.strip.show()
        time.sleep(1)

    '''-------------------------------------------------------------------------
    # B I N A R Y   C L O C K   F U N C T I O N S --------------------------'''

    def runClockBinary(self):

        while True:

            # get current time from system
            now = datetime.datetime.now()

            # get current minute and second Value for color within hour
            currTimeValue = now.second + (now.minute * 60)

            # 3600 iterations per hour over Rainbow colors
            for j in range(currTimeValue, 3600):

                if self.configuration.running == self.configuration.stop == 1:

                    # closing animtion
                    self.upInTheSky()
                    self.stripFunctions.wipeLEDs(Color(0, 0, 0))
                    self.configuration.saveConfigFile()
                    return

                # check if plugin should run
                if self.configuration.plugin != 1:
                    return

                # every hue devided into 3600 steps
                h = j / 3600.0

                self.binaryTime(h)

                # sleep for 1 second
                time.sleep(1)

    # --------------------------------------------------------------------------

    def binaryTime(self, hue):

        # foreground color
        colorForeground = self.helpers.getRainbowColor(
            self.configuration.rainbow,
            hue)

        self.curr_fg_color = colorForeground

        backgroundNoSeconds = [1, 2, 3, 4,
                               7, 8, 9, 10,
                               13, 14, 15, 16,
                               19, 20, 21, 22]

        # set background color
        if self.configuration.background == 1:
            colorBackground = Color(self.configuration.background_value,
                                    self.configuration.background_value,
                                    self.configuration.background_value)
        else:
            colorBackground = Color(0, 0, 0)

        self.curr_bg_color = colorBackground

        # show / hide seconds
        if self.configuration.show_seconds == 1:
            for i in range(self.strip.numPixels()):
                self.stripFunctions.setColorBy1DCoordinate(
                    i,
                    colorBackground,
                    flag_forClock=self.flag_clockIndent)
        else:
            for i in range(len(backgroundNoSeconds)):
                self.stripFunctions.setColorBy1DCoordinate(
                    backgroundNoSeconds[i],
                    colorBackground,
                    flag_forClock=self.flag_clockIndent)

        # get current Time
        curTime = datetime.datetime.now()

        # separate date elements
        year = curTime.year
        month = curTime.month
        day = curTime.day

        # separate time elements
        hour = curTime.hour
        minute = curTime.minute
        second = curTime.second

        # new year countdown
        if day == 31 and month == 12 and hour == 23 and minute == 59 and second = 50:
            open(os.path.join(self.basePath, 'other', 'customText.txt'), 'w').close()
            with open(os.path.join(self.basePath, 'other', 'customText.txt'), "a") as myfile:
                myfile.write("10 9 8 7 6 5 4 3 2 1 0 Frohes Neues Jahr " + str(year + 1))
            self.plugin2.showTimeAsText(fg_color=self.curr_fg_color,
                                        bg_color=self.curr_bg_color,
                                        fps=10)
        # ldr log file
        if hour == 0 and minute == 0 and second == 0:
            open(os.path.join(self.basePath, 'config', 'ldrValues.log'), 'w').close()

        if second == 0:
            with open(os.path.join(self.basePath, 'config', 'ldrValues.log'), "a") as myfile:
                myfile.write(str(hour) + ":" + str(minute) +
                             "  -  " + str(self.brightness) + "\n")

        print(str(hour) + ":" + str(minute) + ":" + str(second))

        # column values for hour, minues and seconds
        # if seconds should not be shown, hour and minute columns += 1
        y_posH = 0 if self.configuration.show_seconds == 1 else 1
        y_posM = 2 if self.configuration.show_seconds == 1 else 3
        y_posS = 4

        # hour
        self.columnValuesWithPixel(hour, y_posH, colorForeground)
        # minute
        self.columnValuesWithPixel(minute, y_posM, colorForeground)
        # second
        if self.configuration.show_seconds == 1:
            self.columnValuesWithPixel(second, y_posS, colorForeground)

        self.strip.setBrightness(self.brightness)

        self.strip.show()
Example #4
0
class ColoramaDisplay(ApplicationSession):
    @inlineCallbacks
    def onJoin(self, details):

        self._serial = get_serial()
        self._prefix = 'io.crossbar.demo.iotstarterkit.{}.pixelstrip'.format(
            self._serial)

        self.log.info("Crossbar.io IoT Starterkit Serial No.: {serial}",
                      serial=self._serial)
        self.log.info("ColoramaDisplay connected: {details}", details=details)

        # get custom configuration
        cfg = self.config.extra

        self._leds = Adafruit_NeoPixel(cfg['led_count'], cfg['led_pin'],
                                       cfg['led_freq_hz'], cfg['led_dma'],
                                       cfg['led_invert'],
                                       cfg['led_brightness'])

        self._leds.begin()

        for proc in [
            (self.set_color, 'set_color'),
            (self.get_color, 'get_color'),
            (self.flash, 'flash'),
            (self.lightshow, 'lightshow'),
            (self.color_wipe, 'color_wipe'),
            (self.theater_chase, 'theater_chase'),
            (self.rainbow, 'rainbow'),
            (self.rainbow_cycle, 'rainbow_cycle'),
            (self.theater_chaserainbow, 'theater_chaserainbow'),
        ]:
            yield self.register(proc[0], '{}.{}'.format(self._prefix, proc[1]))

        self.flash()

        self.log.info("ColoramaDisplay ready!")

    @inlineCallbacks
    def flash(self, delay=50, repeat=5):
        delay = float(delay) / 1000.
        for i in range(repeat):
            self.set_color(0xe1, 0xda, 0x05)
            yield sleep(2 * delay)
            self.set_color(0x52, 0x42, 0x00)
            yield sleep(delay)

    @inlineCallbacks
    def lightshow(self):
        # Color wipe animations.
        yield self.color_wipe(255, 0, 0)  # Red wipe
        yield self.color_wipe(0, 255, 0)  # Blue wipe
        yield self.color_wipe(0, 0, 255)  # Green wipe
        # Theater chase animations.
        yield self.theater_chase(127, 127, 127)  # White theater chase
        yield self.theater_chase(127, 0, 0)  # Red theater chase
        yield self.theater_chase(0, 0, 127)  # Blue theater chase
        # Rainbow animations.
        yield self.rainbow()
        yield self.rainbow_cycle()
        #yield self.theater_chase_rainbow()
        yield self.flash()

    # Define functions which animate LEDs in various ways.
    @inlineCallbacks
    def color_wipe(self, r, g, b, wait_ms=50):
        """Wipe color across display a pixel at a time."""
        for i in range(self._leds.numPixels()):
            self.set_color(r, g, b, i)
            yield sleep(wait_ms / 1000.0)

    @inlineCallbacks
    def theater_chase(self, r, g, b, 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._leds.numPixels(), 3):
                    self.set_color(r, g, b, i + q)
                yield sleep(wait_ms / 1000.0)
                for i in range(0, self._leds.numPixels(), 3):
                    self.set_color(0, 0, 0, i + q)

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

    @inlineCallbacks
    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._leds.numPixels()):
                r, g, b = self.wheel((i + j) & 255)
                self.set_color(r, g, b, i)
            yield sleep(wait_ms / 1000.0)

    @inlineCallbacks
    def rainbow_cycle(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._leds.numPixels()):
                r, g, b = self.wheel(((i * 256 / self._leds.numPixels()) + j)
                                     & 255)
                self.set_color(r, g, b, i)
            yield sleep(wait_ms / 1000.0)

    @inlineCallbacks
    def theater_chaserainbow(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._leds.numPixels(), 3):
                    r, g, b = self.wheel((i + j) % 255)
                    self.set_color(r, g, b, i + q)
                yield sleep(wait_ms / 1000.0)
                for i in range(0, self._leds.numPixels(), 3):
                    self.set_color(0, 0, 0, i)

    def set_color(self, red, green, blue, k=None):
        if k is None:
            for i in range(self._leds.numPixels()):
                # FIXME: not sure, but we need to swap this here. maybe it is the specific neopixels?
                self._leds.setPixelColorRGB(i, green, red, blue)
                color_change = {'led': i, 'r': red, 'g': green, 'b': blue}
                self.publish('{}.on_color_set'.format(self._prefix),
                             color_change)
        else:
            # FIXME: not sure, but we need to swap this here. maybe it is the specific neopixels?
            self._leds.setPixelColorRGB(k, green, red, blue)
            color_change = {'led': k, 'r': red, 'g': green, 'b': blue}
            self.publish('{}.on_color_set'.format(self._prefix), color_change)
        self._leds.show()

    def get_color(self, k):
        c = self._leds.getPixelColor(k)
        color = {
            'g': c >> 16,
            'r': (c >> 8) & 0xff,
            'b': c & 0xff,
        }
        return color

    def onLeave(self, details):
        self.log.info("Session closed: {details}", details=details)
        self.disconnect()

    def onDisconnect(self):
        self.log.info("Connection closed")
        for i in range(self._leds.numPixels()):
            self._leds.setPixelColorRGB(i, 0, 0, 0)
        self._leds.show()
        try:
            reactor.stop()
        except ReactorNotRunning:
            pass
Example #5
0
class ColoramaDisplay(ApplicationSession):

    @inlineCallbacks
    def onJoin(self, details):

        self._serial = get_serial()
        self._prefix = u'io.crossbar.demo.iotstarterkit.{}.pixelstrip'.format(self._serial)

        self.log.info("Crossbar.io IoT Starterkit Serial No.: {serial}", serial=self._serial)
        self.log.info("ColoramaDisplay connected: {details}", details=details)

        # get custom configuration
        cfg = self.config.extra

        self._leds = Adafruit_NeoPixel(
            cfg['led_count'],
            cfg['led_pin'],
            cfg['led_freq_hz'],
            cfg['led_dma'],
            cfg['led_invert'],
            cfg['led_brightness'])

        self._leds.begin()

        for proc in [
            (self.set_color, 'set_color'),
            (self.get_color, 'get_color'),
            (self.flash, 'flash'),
            (self.lightshow, 'lightshow'),
            (self.color_wipe, 'color_wipe'),
            (self.theater_chase, 'theater_chase'),
            (self.rainbow, 'rainbow'),
            (self.rainbow_cycle, 'rainbow_cycle'),
            (self.theater_chaserainbow, 'theater_chaserainbow'),

        ]:
            yield self.register(proc[0], u'{}.{}'.format(self._prefix, proc[1]))

        self.flash()

        self.log.info("ColoramaDisplay ready!")

    @inlineCallbacks
    def flash(self, delay=50, repeat=5):
        delay = float(delay) / 1000.
        for i in range(repeat):
            self.set_color(0xe1, 0xda, 0x05)
            yield sleep(2 * delay)
            self.set_color(0x52, 0x42, 0x00)
            yield sleep(delay)

    @inlineCallbacks
    def lightshow(self):
        # Color wipe animations.
        yield self.color_wipe(255, 0, 0)  # Red wipe
        yield self.color_wipe(0, 255, 0)  # Blue wipe
        yield self.color_wipe(0, 0, 255)  # Green wipe
        # Theater chase animations.
        yield self.theater_chase(127, 127, 127)  # White theater chase
        yield self.theater_chase(127,   0,   0)  # Red theater chase
        yield self.theater_chase(0,   0, 127)  # Blue theater chase
        # Rainbow animations.
        yield self.rainbow()
        yield self.rainbow_cycle()
        #yield self.theater_chase_rainbow()
        yield self.flash()

    # Define functions which animate LEDs in various ways.
    @inlineCallbacks
    def color_wipe(self, r, g, b, wait_ms=50):
        """Wipe color across display a pixel at a time."""
        for i in range(self._leds.numPixels()):
            self.set_color(r, g, b, i)
            yield sleep(wait_ms / 1000.0)

    @inlineCallbacks
    def theater_chase(self, r, g, b, 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._leds.numPixels(), 3):
                    self.set_color(r, g, b, i + q)
                yield sleep(wait_ms / 1000.0)
                for i in range(0, self._leds.numPixels(), 3):
                    self.set_color(0, 0, 0, i + q)

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

    @inlineCallbacks
    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._leds.numPixels()):
                r, g, b = self.wheel((i + j) & 255)
                self.set_color(r, g, b, i)
            yield sleep(wait_ms / 1000.0)

    @inlineCallbacks
    def rainbow_cycle(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._leds.numPixels()):
                r, g, b = self.wheel(((i * 256 / self._leds.numPixels()) + j) & 255)
                self.set_color(r, g, b, i)
            yield sleep(wait_ms / 1000.0)

    @inlineCallbacks
    def theater_chaserainbow(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._leds.numPixels(), 3):
                    r, g, b = self.wheel((i+j) % 255)
                    self.set_color(r, g, b, i + q)
                yield sleep(wait_ms / 1000.0)
                for i in range(0, self._leds.numPixels(), 3):
                    self.set_color(0, 0, 0, i)

    def set_color(self, red, green, blue, k=None):
        if k is None:
            for i in range(self._leds.numPixels()):
                # FIXME: not sure, but we need to swap this here. maybe it is the specific neopixels?
                self._leds.setPixelColorRGB(i, green, red, blue)
                color_change = {
                    u'led': i,
                    u'r': red,
                    u'g': green,
                    u'b': blue
                }
                self.publish(u'{}.on_color_set'.format(self._prefix), color_change)
        else:
                # FIXME: not sure, but we need to swap this here. maybe it is the specific neopixels?
            self._leds.setPixelColorRGB(k, green, red, blue)
            color_change = {
                u'led': k,
                u'r': red,
                u'g': green,
                u'b': blue
            }
            self.publish(u'{}.on_color_set'.format(self._prefix), color_change)
        self._leds.show()

    def get_color(self, k):
        c = self._leds.getPixelColor(k)
        color = {
            u'g': c >> 16,
            u'r': (c >> 8) & 0xff,
            u'b': c & 0xff,
        }
        return color

    def onLeave(self, details):
        self.log.info("Session closed: {details}", details=details)
        self.disconnect()

    def onDisconnect(self):
        self.log.info("Connection closed")
        for i in range(self._leds.numPixels()):
            self._leds.setPixelColorRGB(i, 0, 0, 0)
        self._leds.show()
        try:
            reactor.stop()
        except ReactorNotRunning:
            pass