예제 #1
0
def main(trellis: NeoTrellis):
    for i in range(BUTTON_COUNT):
        trellis.activate_key(i, NeoTrellis.EDGE_RISING)
        trellis.activate_key(i, NeoTrellis.EDGE_FALLING)
        trellis.callbacks[i] = button_callback(trellis, i)

    while True:
        for i in range(BUTTON_COUNT):
            trellis.pixels[i] = button_target_color(i)

        trellis.sync()
        time.sleep(0.02)
예제 #2
0
def blink(event):
    # turn the LED on when a rising edge is detected
    if event.edge == NeoTrellis.EDGE_RISING:
        if not button.value:
            print("try redraw board")

    elif event.edge == NeoTrellis.EDGE_FALLING:
        print("falling")
        redrawBoard(COLORS)
        pass


for i in range(16):
    # activate rising edge events on all keys
    trellis.activate_key(i, NeoTrellis.EDGE_RISING)
    # activate falling edge events on all keys
    trellis.activate_key(i, NeoTrellis.EDGE_FALLING)
    # set all keys to trigger the blink callback
    trellis.callbacks[i] = blink
    time.sleep(.02)
    trellis.pixels[i] = (0, 0, 0)
    time.sleep(.02)

while True:
    # TODO debounce
    if not button.value:
        resetBoard()
    # call the sync function call any triggered callbacks
    trellis.sync()
    # try:
예제 #3
0
class Nightstand:
    def __init__(self):
        self.config = NightStandConfig(CONFIGFILE)
        self.audioPlayer = None
        self.states = NightstandStates()
        self.btctl = None
        self.states.registerMenuStateChangeListener(self.onMenuChanged)
        self.states.registerResetListener(self.reset)
        self.states.registerSleepListener(self.onGoToSleep)
        self.timer = RepeatedTimer(TIMER_INTERVAL, self.onTimerTick)

    def init(self):
        self.states.enterMenu(MENUSTATE_INIT)
        self.config.load()
        self.states.sleepEnabled = self.config.isSleepEnabled()
        self.config.registerFilechangedListener(self.onConfigChanged)

        self.btctl = BluetoothCtl(self.config.getBluetoothMacs())
        # create the i2c object for the trellis
        i2c_bus = busio.I2C(SCL, SDA)
        # create the trellis
        self.trellis = NeoTrellis(i2c_bus)
        for i in range(16):
            # activate rising edge events on all keys
            self.trellis.activate_key(i, NeoTrellis.EDGE_RISING)
            # activate falling edge events on all keys
            self.trellis.activate_key(i, NeoTrellis.EDGE_FALLING)
            # set all keys to trigger the blink callback
            self.trellis.callbacks[i] = self.onKeyPressed

    def doConnect(self):
        self.btctl.doConnectAsync(BTCONNECT_RETRIES, self.onConnectFinished,
                                  self.onConnectFailed)

    def doDisconnect(self):
        self.btctl.doDisconnect()

    def onConnectFinished(self):
        print("bt connections established")
        self.states.enterMenu(MENUSTATE_IDLE)

    def onConnectFailed(self):
        print("failed to connect to bt devices")
        self.states.enterMenu(MENUSTATE_ERROR)

    def onMenuChanged(self, oldMenuState, newMenuState):
        print("menu changed from " + str(oldMenuState) + " to " +
              str(newMenuState))
        if oldMenuState == MENUSTATE_SLEEPCONFIG:
            self.states.setSleepConfig(self.config.isSleepEnabled(),
                                       self.config.getSleepTime())
            self.states.enterMenu(
                MENUSTATE_PLAYING
                if self.audioPlayer is not None else MENUSTATE_IDLE, True)
            return

        self.initColors()

    def reset(self, startupSequence=True, stopAudio=False):
        self.states.enterMenu(MENUSTATE_INIT)
        self.states.resetCounter = RESET_COUNTER_START
        self.btctl = BluetoothCtl(self.config.getBluetoothMacs())
        if stopAudio:
            self.playAudio(None)
        if startupSequence:
            for i in range(16):
                self.trellis.pixels[i] = RED
                time.sleep(INIT_DELAY)
            for i in range(16):
                self.trellis.pixels[i] = YELLOW
                time.sleep(INIT_DELAY)
            for i in range(16):
                self.trellis.pixels[i] = GREEN
                time.sleep(INIT_DELAY)
            for i in range(16):
                self.trellis.pixels[i] = OFF
                time.sleep(INIT_DELAY)
        self.initColors()
        if self.config.doBluetoothAutoConnect():
            self.states.enterMenu(MENUSTATE_CONNECTING)
            self.doConnect()
        else:
            self.states.enterMenu(MENUSTATE_IDLE)

    def onGoToSleep(self):
        self.enterMenu(MENUSTATE_SLEEPING)
        self.playAudio(None)
        self.doDisconnect()

    def getKeyColor(self, index):
        if self.states.menuState == MENUSTATE_SLEEPCONFIG:
            time = self.config.getSleepTime()
            if index < 12:
                return YELLOW if time > index * 300 else OFF
            elif index == 12:
                return WHITE
            elif index == 13:
                return GREEN if self.config.isSleepEnabled() else RED
            elif index == 14:
                return GREEN if self.config.isSleepEnabled() else RED
            elif index == 15:
                return WHITE
        elif self.states.menuState == MENUSTATE_DIMMING or self.states.menuState == MENUSTATE_STOPPED or self.states.menuState == MENUSTATE_SLEEPING:
            return OFF
        else:
            kc = self.config.getKeyConfig(index)
            if not kc.isPlayerButton(
            ) or self.states.menuState == MENUSTATE_PLAYING:
                return kc.color
            else:
                return OFF

    def initColors(self):
        for i in range(16):
            self.trellis.pixels[i] = self.getKeyColor(i)

    def onTimerTick(self):
        self.states.onResetTimerTick()
        self.states.onSleepTimerTick()
        self.states.onDimmingTimerTick()

    def onConfigChanged(self):
        print("config changed")
        self.reset(False)

    def onKeyPressed(self, event):
        self.states.resetDimmingTimer()

        # turn the LED on when a rising edge is detected
        if event.edge == NeoTrellis.EDGE_RISING:
            self.trellis.pixels[event.number] = self.config.getKeyConfig(
                event.number).keyPressedColor
            self.states.keyStates[event.number] = KEYSTATE_PRESSED
        # turn the LED off when a rising edge is detected
        elif event.edge == NeoTrellis.EDGE_FALLING:
            if self.states.menuState == MENUSTATE_DIMMING:
                self.states.menuBack()
                return
            kc = self.config.getKeyConfig(event.number)
            if not kc.isPlayerButton(
            ) or self.states.menuState == MENUSTATE_PLAYING:
                self.trellis.pixels[event.number] = kc.color
            else:
                self.trellis.pixels[event.number] = OFF
            if self.states.menuState == MENUSTATE_SLEEPCONFIG:
                self.onSleepConfigKeyPressed(event.number)
            else:
                self.onAudioKeyPressed(event.number)
            self.states.keyStates[event.number] = KEYSTATE_NONE

    def onSleepConfigKeyPressed(self, index):
        curSleep = self.config.getSleepTime()
        incdec = 300
        if index == 12:
            self.config.setSleepTime(curSleep -
                                     incdec if curSleep > incdec else 0)
            if self.config.getSleepTime() == 0:
                self.config.enableSleep(False)
        if index == 15:
            self.config.setSleepTime(curSleep +
                                     incdec if curSleep < 11 * incdec else 12 *
                                     incdec)
            if curSleep == 0:
                self.config.enableSleep(True)
        if index == 13 or index == 14:
            self.config.enableSleep(not self.config.isSleepEnabled())
        self.states.stayinSleepConfig()
        self.initColors()

    def onAudioKeyPressed(self, index):
        if self.states.menuState == MENUSTATE_IDLE or (
                self.states.menuState == MENUSTATE_PLAYING
                and not self.config.getKeyConfig(index).isPlayerButton()):
            print("start audio")
            self.playAudio(self.config.getMedia(index))
        elif self.states.menuState == MENUSTATE_PLAYING:
            keyConfig = self.config.getKeyConfig(index)
            if keyConfig.isPlayerButton():
                self.audioPlayerButtonClick(keyConfig.playerButton)

    def audioPlayerButtonClick(self, button):
        print("exec audio button ", button)
        if not self.audioPlayer is None:
            if button == KeyConfig.AUDIOBUTTON_PLAY_PAUSE:
                if self.audioPlayer.is_playing():
                    self.audioPlayer.pause()
                else:
                    self.audioPlayer.play()
            elif button == KeyConfig.AUDIOBUTTON_STOP:
                self.playAudio(None)
            elif button == KeyConfig.AUDIOBUTTON_VOLUMEUP:
                vol = self.audioPlayer.audio_get_volume() + VOL_INCDEC
                self.audioPlayer.audio_set_volume(vol)
            elif button == KeyConfig.AUDIOBUTTON_VOLUMEDOWN:
                vol = self.audioPlayer.audio_get_volume() - VOL_INCDEC
                self.audioPlayer.audio_set_volume(vol)
            elif button == KeyConfig.AUDIOBUTTON_NEXT:
                self.audioPlayer.next_chapter()
            elif button == KeyConfig.AUDIOBUTTON_PREV:
                self.audioPlayer.previous_chapter()

    def playAudio(self, audio):
        if not self.audioPlayer is None:
            print("stopping current audio")
            self.audioPlayer.stop()
            self.states.enterMenu(MENUSTATE_IDLE)
        if audio is None:
            return
        self.states.enterMenu(MENUSTATE_PLAYING)
        print("start playing ", audio)
        self.audioPlayer = vlc.MediaPlayer(audio)
        self.audioPlayer.play()

    def startServer(self):
        print('Hello from the Nightstand Service')
        try:
            while True:
                # call the sync function call any triggered callbacks
                self.trellis.sync()
                # the trellis can only be read every 17 millisecons or so
                time.sleep(0.02)
        except:
            self.config.stop()
        self.stop()

    def startCLI(self):
        print('Hello from the Nightstand Server')
        self.reset()
        self.timer.start()
        try:
            while True:
                # call the sync function call any triggered callbacks
                self.trellis.sync()
                # the trellis can only be read every 17 millisecons or so
                time.sleep(0.02)
        except KeyboardInterrupt:
            self.config.stop()
        self.stop()

    def stop(self):
        self.config.join()
        self.timer.stop()
        self.states.enterMenu(MENUSTATE_STOPPED)
        self.doDisconnect()
        self.states.unregisterMenuStateChangeListener(self.onMenuChanged)
예제 #4
0
class Trellis:
    """
    relays button presses by adding them to a queue
    buttons can be referred to by name, index, or color group name
    """
    def __init__(self, startup_color='random', debug=True):

        self.debug = debug
        self.nbuttons = 16
        self.colors = {
            'off': (0, 0, 0),
            'purple': (180, 0, 255),
            'red': (255, 0, 0),
            'orange': (255, 164, 0),
            'green': (0, 255, 0),
            'yellow': (158, 152, 17),
            'gray': (100, 100, 100),
            'blue': (0, 0, 255),
            'lightblue': (7, 34, 81),
            'blueish': (33, 211, 237),
            'darkgray': (10, 10, 10),
            'seagreen': (30, 255, 30),
            'lightseagreen': (39, 239, 120),
            'salmon': (206, 28, 41),
            'lightorange': (176, 76, 9),
            'lightpurple': (87, 20, 174),
            'lighterpurple': (70, 27, 87),
            'pink': (100, 0, 100)
        }

        # create the i2c object for the trellis
        self.i2c_bus = busio.I2C(SCL, SDA)

        # create the trellis
        self.trellis = NeoTrellis(
            self.i2c_bus)  # can set interrupt=True here...

        # for handling colors of groups of buttons
        self.startup_color = startup_color
        self.color_map = {}

        # to ensure callback set
        self.button_handler = None

    def set_color_map(self, color_map):
        self.color_map = color_map

    def set_callback(self, fcn):
        # callback for when buttons are pressed
        self.button_handler = fcn
        # set handlers for button press
        self.activate(self.startup_color, lightshow=True)

    def activate(self, startup_color=None, lightshow=False):
        if self.button_handler is None:
            print("Error: callback must be set using 'set_callback'")

        for i in range(self.nbuttons):
            # activate rising edge events on all keys
            self.trellis.activate_key(i, BUTTON_PRESSED)
            # activate falling edge events on all keys
            self.trellis.activate_key(i, BUTTON_RELEASED)
            # set all keys to trigger the blink callback
            self.trellis.callbacks[i] = self.button_handler

            if not lightshow:
                continue
            #cycle the LEDs on startup
            if startup_color is not None:
                if startup_color == 'random':
                    color = random_color()
                else:
                    color = self.colors[startup_color]
                self.trellis.pixels[i] = color
                time.sleep(.03)

        for i in range(self.nbuttons):
            self.trellis.pixels[i] = self.colors['off']
            if lightshow:
                time.sleep(.03)

    def end_lightshow(self, event=None):
        # reset callbacks and turn lights off
        if event is None or event.edge == BUTTON_PRESSED:
            self.activate()
            self.lightshow_on = False

    def lightshow(self):
        self.lightshow_on = True
        # first, set callback to interrupt the show
        for i in range(self.nbuttons):
            self.trellis.callbacks[i] = self.end_lightshow
        # now pick buttons and flash lights on/off in random order
        while True:
            button_indices = list(range(self.nbuttons))
            random.shuffle(button_indices)
            for i in button_indices:
                self.trellis.pixels[i] = random_color()
                time.sleep(.07)
                if not self.lightshow_on:
                    return
            for i in button_indices:
                self.trellis.pixels[i] = self.colors['off']
                time.sleep(.07)
                if not self.lightshow_on:
                    return
            self.sync()
            time.sleep(.02)

    def set_color_all_buttons(self, color):
        for i in range(self.nbuttons):
            self.set_color(i, color)

    def set_color(self, index, color):
        if color in self.color_map:
            color = self.color_map[color]
        self.trellis.pixels[index] = self.colors[color]

    def sync(self):
        self.trellis.sync()

    def terminate(self):
        for i in range(self.nbuttons):
            self.trellis.pixels[i] = self.colors['off']
        self.sync()
예제 #5
0
CYAN = (0, 255, 255)
BLUE = (0, 0, 255)
PURPLE = (180, 0, 255)

#this will be called when button events are received
def blink(event):
    #turn the LED on when a rising edge is detected
    if event.edge == NeoTrellis.EDGE_RISING:
        trellis.pixels[event.number] = CYAN
    #turn the LED off when a rising edge is detected
    elif event.edge == NeoTrellis.EDGE_FALLING:
        trellis.pixels[event.number] = OFF

for i in range(16):
    #activate rising edge events on all keys
    trellis.activate_key(i, NeoTrellis.EDGE_RISING)
    #activate falling edge events on all keys
    trellis.activate_key(i, NeoTrellis.EDGE_FALLING)
    #set all keys to trigger the blink callback
    trellis.callbacks[i] = blink

    #cycle the LEDs on startup
    trellis.pixels[i] = PURPLE
    time.sleep(.05)

for i in range(16):
    trellis.pixels[i] = OFF
    time.sleep(.05)

while True:
    #call the sync function call any triggered callbacks