Changeset - 835bac5d3b3c
[Not reviewed]
tip default
0 7 3
Matthew Reed (matthewreed) - 6 years ago 2019-05-24 13:58:02
matthewreed64@gmail.com
Added new demos and handle splash screens and controller input
10 files changed with 809 insertions and 10 deletions:
0 comments (0 inline, 0 general)
controller.py
Show inline comments
 
### controller.py
 
### Author: Matthew Reed
 
 
import sys
 
import time
 
import signal
 
import logging
 
import threading
 
import configparser
 
from enum import Enum
 
 
from evdev import InputDevice, categorize, ecodes
 
import asyncio
 
from select import select
 
 
class Controller:
 
 
    def __init__(self, config):
 
        self.config = config
 
        self.connect()
 
        
 
    def connect(self):
 
        try:
 
            self.dev = InputDevice('/dev/input/event0')
 
        except FileNotFoundError:
 
            self.dev = None
 
        except PermissionError:
 
            self.dev = None
 
        
 
    def read_input(self):
 
        
 
        if self.dev == None:
 
            self.connect()
 
        
 
        events = []
 
        if self.dev != None:
 
            try:
 
                for event in self.dev.read():
 
                    events.append(event)
 
            except BlockingIOError:
 
                pass
 
            except OSError:
 
                self.dev = None
 
            
 
        return events
 
\ No newline at end of file
demos/__init__.py
Show inline comments
 
__all__ = ['paint', 'rainbow', 'snake']
 
\ No newline at end of file
 
__all__ = ['rainbow', 'paint', 'snake', 'pong', 'tetris', 'clouds']
 
\ No newline at end of file
demos/clouds.py
Show inline comments
 
new file 100644
 
### clouds.py
 
### Author: Matthew Reed
 
### Random noise generated colors
 
### Adapted from https://github.com/scanlime/fadecandy/blob/master/examples/processing/grid24x8z_clouds/grid24x8z_clouds.pde
 
 
import sys
 
import time
 
import signal
 
import logging
 
import configparser
 
from enum import Enum
 
 
import math
 
import matrix
 
import noise
 
import color_utils
 
import random
 
 
class Clouds:
 
 
    def __init__(self, config, parent, matrix, controller):
 
        self.logger = logging.getLogger('paint')
 
        self.config = config
 
        self.parent = parent
 
        self.matrix = matrix
 
        self.controller = controller
 
        
 
    def reset(self):
 
        pass
 
        
 
    def splash(self):
 
    
 
        r = matrix.Colors.RED.value
 
        o = matrix.Colors.ORANGE.value
 
        y = matrix.Colors.YELLOW.value
 
        g = matrix.Colors.GREEN.value
 
        b = matrix.Colors.BLUE.value
 
        p = matrix.Colors.PURPLE.value
 
        w = matrix.Colors.WHITE.value
 
        v = matrix.Colors.VIOLET.value
 
        l = matrix.Colors.LIGHT_BLUE.value
 
        m = matrix.Colors.MAGENTA.value
 
        q = matrix.Colors.OFF.value
 
        
 
        splash = [
 
            [q, q, q, q, q, q, q, q],
 
            [q, q, q, q, q, q, q, q],
 
            [q, q, r, w, p, v, q, q],
 
            [q, q, b, g, o, m, q, q],
 
            [q, q, r, p, y, l, q, q],
 
            [q, q, q, q, q, q, q, q],
 
            [q, q, q, q, q, q, q, q],
 
            [q, q, q, q, q, q, q, q],
 
        ]
 
        
 
        for x in range(0, self.matrix.WIDTH):
 
            for y in range(0, self.matrix.HEIGHT):
 
                self.matrix.set_pixel(x, y, splash[y][x])
 
        
 
        self.matrix.update()
 
        
 
    def hsv_to_rgb(self, h, s, v):
 
        if s == 0.0: return (v, v, v)
 
        i = int(h*6.) # XXX assume int() truncates!
 
        f = (h*6.)-i; p,q,t = v*(1.-s), v*(1.-s*f), v*(1.-s*(1.-f)); i%=6
 
        if i == 0: return (v, t, p)
 
        if i == 1: return (q, v, p)
 
        if i == 2: return (p, v, t)
 
        if i == 3: return (p, q, v)
 
        if i == 4: return (t, p, v)
 
        if i == 5: return (v, p, q)
 
        
 
 
    def fractalNoise(self, x, y, z):
 
      r = 0
 
      amp = 1.0
 
      for octave in range(4):
 
        r += noise.pnoise3(x, y, z) * amp;
 
        amp /= 2;
 
        x *= 2;
 
        y *= 2;
 
        z *= 2;
 
      return r;
 
      
 
    def constrain(self, val, min_val, max_val):
 
        return min(max_val, max(min_val, val))
 
        
 
    def run(self):
 
    
 
        dx = 0.0
 
        dy = 0.0
 
    
 
        #start timers and counters
 
        self.start_time = time.time()
 
        last_time = time.time()
 
        
 
        led_iteration_count = 0
 
        frame_count = 0
 
        
 
        keep_going = True
 
        
 
        while keep_going:
 
            
 
            for event in self.controller.read_input():
 
                if event.code == 313 and event.value == 1:
 
                    keep_going = False
 
            
 
            if time.time() > last_time + 1:
 
                last_time = time.time()
 
                
 
                
 
                now = time.time()
 
                speed = 0.002
 
                angle = math.sin(now)
 
                z = now * 0.08
 
                hue = now * 10
 
                scale = 0.005;
 
 
                dx += math.cos(angle) * speed
 
                dy += math.sin(angle) * speed
 
 
                for x in range(self.matrix.WIDTH):
 
                    for y in range(self.matrix.HEIGHT):
 
 
                        n = self.fractalNoise(dx + x*scale, dy + y*scale, z) - 0.75
 
                        m = self.fractalNoise(dx + x*scale, dy + y*scale, z + 10.0) - 0.75
 
 
                        color = self.hsv_to_rgb(
 
                            (hue + 80.0 * m) % 256.0, 
 
                            256 - 256 * self.constrain(pow(3.0 * abs(n), 3.5), 0, 0.9), 
 
                            256 * self.constrain(pow(3.0 * abs(n), 1.5), 0, 0.9)
 
                        )
 
 
                        self.matrix.set_pixel(x, y, color)
 
                
 
                self.matrix.update()
 
                
 
                led_iteration_count = (led_iteration_count + 1) % self.matrix.NUM_LEDS
 
                frame_count = frame_count + 1
 
                
 
            time.sleep(0.01)
 
\ No newline at end of file
demos/paint.py
Show inline comments
 
### paint.py
 
### Author: Matthew Reed
 
### Draw on the canvas using the D-Pad, A button changes color
 
 
import sys
 
import time
 
import signal
 
import logging
 
import configparser
 
from enum import Enum
 
 
import math
 
import matrix
 
 
class Paint:
 
 
    class DIRECTION(Enum):
 
        NONE = 0
 
        UP = 1
 
        DOWN = 2
 
        LEFT = 3
 
        RIGHT = 4
 
 
    def __init__(self, config, parent, matrix, controller):
 
        self.logger = logging.getLogger('paint')
 
        self.config = config
 
        self.parent = parent
 
        self.matrix = matrix
 
        self.controller = controller
 
        
 
    def reset(self):
 
        pass
 
        
 
    def splash(self):
 
        self.matrix.set_matrix((255,0,0))
 
    
 
        w = matrix.Colors.WHITE.value
 
        r = matrix.Colors.RED.value
 
        g = matrix.Colors.GREEN.value
 
        b = matrix.Colors.BLUE.value
 
        l = matrix.Colors.LIGHT_BLUE.value
 
        p = matrix.Colors.PURPLE.value
 
        O = matrix.Colors.ORANGE.value
 
        y = matrix.Colors.YELLOW.value
 
        v = matrix.Colors.VIOLET.value
 
        m = matrix.Colors.MAGENTA.value
 
        o = matrix.Colors.OFF.value
 
        
 
        splash = [
 
            [o, o, o, o, o, o, o, o],
 
            [o, o, w, w, w, o, o, o],
 
            [o, o, w, o, w, o, o, o],
 
            [o, o, w, w, w, o, o, o],
 
            [o, o, w, o, o, r, O, y],
 
            [o, o, w, o, o, m, w, g],
 
            [o, o, w, o, o, v, b, l],
 
            [o, o, o, o, o, o, o, o],
 
        ]
 
        
 
        for x in range(0, self.matrix.WIDTH):
 
            for y in range(0, self.matrix.HEIGHT):
 
                self.matrix.set_pixel(x, y, splash[y][x])
 
        
 
        self.matrix.update()
 
        
 
    def run(self):
 
    
 
        pointer = 0
 
        direction = self.DIRECTION.NONE
 
        color = matrix.Colors.WHITE.value
 
        color_index = 7
 
    
 
        #start timers and counters
 
        self.start_time = time.time()
 
        last_time = time.time()
 
        
 
        led_iteration_count = 0
 
        frame_count = 0
 
        
 
        keep_going = True
 
        
 
        while keep_going:
 
            
 
            for event in self.controller.read_input():
 
                if event.code == 313 and event.value == 1:
 
                    keep_going = False
 
                elif event.code == 305 and event.value == 1:
 
                    color_index = (color_index + 1) % len(list(matrix.Colors))
 
                    color = list(matrix.Colors)[color_index].value
 
                elif event.code == 16:
 
                    if event.value == 1:
 
                        #dpad right
 
                        direction = self.DIRECTION.RIGHT
 
                    if event.value == 0:
 
                        #dpad none
 
                        direction = self.DIRECTION.NONE
 
                    if event.value == -1:
 
                        #dpad left
 
                        direction = self.DIRECTION.LEFT
 
                elif event.code == 17:
 
                    if event.value == 1:
 
                        #dpad down
 
                        direction = self.DIRECTION.DOWN
 
                    if event.value == 0:
 
                        #dpad none
 
                        direction = self.DIRECTION.NONE
 
                    if event.value == -1:
 
                        #dpad up
 
                        direction = self.DIRECTION.UP
 
            
 
            if time.time() > last_time + 0.1:
 
                last_time = time.time()
 
                    
 
                pointerx = pointer % self.matrix.WIDTH
 
                pointery = math.floor(pointer / self.matrix.HEIGHT)
 
                
 
                if direction == self.DIRECTION.UP:
 
                    pointery = (pointery - 1) % self.matrix.HEIGHT
 
                elif direction == self.DIRECTION.DOWN:
 
                    pointery = (pointery + 1) % self.matrix.HEIGHT
 
                elif direction == self.DIRECTION.LEFT:
 
                    pointerx = (pointerx - 1) % self.matrix.WIDTH
 
                elif direction == self.DIRECTION.RIGHT:
 
                    pointerx = (pointerx + 1) % self.matrix.WIDTH
 
                
 
                pointer = pointery * self.matrix.HEIGHT + pointerx
 
                
 
                self.matrix.set_pixel(pointerx, pointery, color)
 
                
 
                self.matrix.update()
 
                
 
                led_iteration_count = (led_iteration_count + 1) % self.matrix.NUM_LEDS
 
                frame_count = frame_count + 1
 
                
 
            time.sleep(0.01)
 
        
 
\ No newline at end of file
demos/pong.py
Show inline comments
 
new file 100644
 
### pong.py
 
### Author: Matthew Reed
 
### Game of pong, uses the D-Pad 
 
### Adapted from http://trevorappleton.blogspot.com/2014/04/writing-pong-using-python-and-pygame.html
 
 
import sys
 
import time
 
import signal
 
import logging
 
import configparser
 
from enum import Enum
 
 
import math
 
from random import randint
 
import matrix
 
 
class Pong:
 
 
    class Ball:
 
        
 
        def __init__(self, x, y):
 
            self.x = x
 
            self.y = y
 
            self.dir_x = -1 # -1=left 1=right
 
            self.dir_y = -1 # -1=up 1=down
 
            
 
        def move(self):
 
        
 
            self.x += self.dir_x
 
            self.y += self.dir_y
 
            
 
            #check for collision with wall and bounce
 
            if self.y <= 0:
 
                self.y = 0
 
                self.dir_y = 1
 
            elif self.y >= 7:
 
                self.y = 7
 
                self.dir_y = -1
 
            
 
        def draw(self, display):
 
            display.set_pixel(self.x, self.y, matrix.Colors.RED.value)
 
            
 
    
 
    class Paddle:
 
 
        class DIRECTION(Enum):
 
            NONE = 0
 
            UP = 1
 
            DOWN = 2
 
            LEFT = 3
 
            RIGHT = 4
 
        
 
        def __init__(self, x, y):
 
            self.size = 3
 
            self.x = x
 
            self.position = y
 
            self.direction = self.DIRECTION.NONE
 
            
 
        def move(self):
 
            if self.direction == self.DIRECTION.UP:
 
                self.position = self.position - 1
 
                if self.position < 0:
 
                    self.position = 0
 
            elif self.direction == self.DIRECTION.DOWN:
 
                self.position = self.position + 1
 
                if self.position + self.size > 8:
 
                    self.position = 8 - self.size
 
            
 
        def auto_move(self, ball):
 
            #If ball is moving away from paddle, center
 
            if ball.dir_x == -1:
 
                if self.position < 3:
 
                    self.position += 1
 
                elif self.position > 3:
 
                    self.position -= 1
 
            #if ball moving towards paddle, track its movement
 
            elif ball.dir_x == 1:
 
                if self.position + 1 - ball.dir_y < ball.y:
 
                    self.position += 1
 
                elif self.position + 1 - ball.dir_y > ball.y:
 
                    self.position -= 1
 
                    
 
            if self.position < 0:
 
                self.position = 0
 
            elif self.position + self.size > 8:
 
                self.position = 8 - self.size
 
            
 
        def draw(self, display):
 
            for i in range(0, self.size):
 
                display.set_pixel(self.x, self.position + i, matrix.Colors.BLUE.value)
 
 
 
    def __init__(self, config, parent, matrix, controller):
 
        self.logger = logging.getLogger('snake')
 
        self.config = config
 
        self.parent = parent
 
        self.matrix = matrix
 
        self.controller = controller
 
        
 
    def reset(self):
 
        pass
 
        
 
    def splash(self):
 
    
 
        w = matrix.Colors.WHITE.value
 
        l = matrix.Colors.WHITE_LOW.value
 
        r = matrix.Colors.RED.value
 
        b = matrix.Colors.BLUE.value
 
        o = matrix.Colors.OFF.value
 
        
 
        splash = [
 
            [l, l, l, l, l, l, l, l],
 
            [l, o, o, o, o, o, o, l],
 
            [b, o, o, o, o, o, o, l],
 
            [b, o, o, o, r, o, o, b],
 
            [b, o, o, o, o, o, o, b],
 
            [l, o, o, o, o, o, o, b],
 
            [l, o, o, o, o, o, o, l],
 
            [l, l, l, l, l, l, l, l],
 
        ]
 
        
 
        for x in range(0, self.matrix.WIDTH):
 
            for y in range(0, self.matrix.HEIGHT):
 
                self.matrix.set_pixel(x, y, splash[y][x])
 
        
 
        self.matrix.update()
 
        
 
    def run(self):
 
        
 
        #start timers and counters
 
        self.start_time = time.time()
 
        last_time = time.time()
 
        delay_time = 0.1
 
        
 
        led_iteration_count = 0
 
        frame_count = 0
 
            
 
        self.updateBallCountMax = 5
 
        self.updateBallCount = 0
 
        self.updateCompCountMax = 10
 
        self.updateCompCount = 0
 
        
 
        ball = self.Ball(4, 3)
 
        paddle1 = self.Paddle(0, 3)
 
        paddle2 = self.Paddle(7, 3)
 
        
 
        score = 0
 
        
 
        #draw display
 
        self.matrix.set_matrix(matrix.Colors.OFF.value)
 
        
 
        for x in range(0, 8):
 
            self.matrix.set_pixel(x, 0, matrix.Colors.WHITE_LOW.value)
 
            self.matrix.set_pixel(x, 7, matrix.Colors.WHITE_LOW.value)
 
        for y in range(0, 8):
 
            self.matrix.set_pixel(0, y, matrix.Colors.WHITE_LOW.value)
 
            self.matrix.set_pixel(3, y, matrix.Colors.WHITE_LOW.value)
 
            self.matrix.set_pixel(4, y, matrix.Colors.WHITE_LOW.value)
 
            self.matrix.set_pixel(7, y, matrix.Colors.WHITE_LOW.value)
 
            
 
        paddle1.draw(self.matrix)
 
        paddle2.draw(self.matrix)
 
        ball.draw(self.matrix)
 
        
 
        self.matrix.update()
 
        
 
        keep_going = True
 
        
 
        while keep_going:
 
            
 
            for event in self.controller.read_input():
 
                if event.code == 313 and event.value == 1:
 
                    keep_going = False
 
                elif event.code == 17:
 
                    if event.value == 1:
 
                        #dpad down
 
                        paddle1.direction = self.Paddle.DIRECTION.DOWN
 
                    if event.value == 0:
 
                        #dpad none
 
                        paddle1.direction = self.Paddle.DIRECTION.NONE
 
                        pass
 
                    if event.value == -1:
 
                        #dpad up
 
                        paddle1.direction = self.Paddle.DIRECTION.UP
 
            
 
            if time.time() > last_time + delay_time:
 
                last_time = time.time()
 
                
 
                paddle1.move()
 
        
 
                self.updateBallCount = self.updateBallCount + 1
 
                if self.updateBallCount >= self.updateBallCountMax:
 
                    ball.move()
 
                
 
                    self.updateBallCount = 0
 
                
 
                self.updateCompCount = self.updateCompCount + 1
 
                if self.updateCompCount >= self.updateCompCountMax:
 
                    paddle2.auto_move(ball)
 
                
 
                    self.updateCompCount = 0
 
                
 
                #ball hits paddle 1
 
                if ball.dir_x == -1 and ball.x == 1:
 
                    ball.dir_x = ball.dir_x *  -1
 
                    # if the ball bounces off the corner of the paddle, it goes back in the same direction it came from
 
                    if (ball.dir_y == 1 and ball.y == paddle1.position) or (ball.dir_y == -1 and ball.y == paddle1.position + 2):
 
                        ball.dir_y = ball.dir_y *  -1
 
                        
 
                    # if the paddle is in motion, give the ball some translation
 
                    if paddle1.direction == self.Paddle.DIRECTION.DOWN:
 
                        if ball.y < 7:
 
                            ball.y = ball.y + 1
 
                            if ball.y >= 7:
 
                                ball.y = 7
 
                                ball.dir_y = -1
 
                    elif paddle1.direction == self.Paddle.DIRECTION.UP:
 
                        if ball.y > 0:
 
                            ball.y = ball.y - 1
 
                            if ball.y <= 0:
 
                                ball.y = 0
 
                                ball.dir_y = 1
 
                    
 
                elif ball.dir_x == -1 and ball.x == 0:
 
                    if paddle1.position <= ball.y and (paddle1.position + paddle1.size) > ball.y:
 
                        #1 point for hitting the ball
 
                        score += 1
 
                        print("Hit!")
 
                    else:
 
                        #game over if left wall is hit
 
                        print("Miss!")
 
                        keep_going = False
 
                        
 
                elif ball.dir_x == 1 and ball.x == 6:
 
                    ball.dir_x = ball.dir_x *  -1
 
                    if paddle2.position <= ball.y and (paddle2.position + paddle2.size) > ball.y:
 
                        #ball hits paddle2
 
                        pass
 
                elif ball.dir_x == 1 and ball.x == 7:
 
                    #5 points for beating paddle2
 
                    score += 5
 
                    print("Score!")
 
                
 
                #update display
 
                self.matrix.set_matrix(matrix.Colors.OFF.value)
 
                
 
                #draw game background
 
                for x in range(0, 8):
 
                    self.matrix.set_pixel(x, 0, matrix.Colors.WHITE_LOW.value)
 
                    self.matrix.set_pixel(x, 7, matrix.Colors.WHITE_LOW.value)
 
                for y in range(0, 8):
 
                    self.matrix.set_pixel(0, y, matrix.Colors.WHITE_LOW.value)
 
                    self.matrix.set_pixel(3, y, matrix.Colors.WHITE_LOW.value)
 
                    self.matrix.set_pixel(4, y, matrix.Colors.WHITE_LOW.value)
 
                    self.matrix.set_pixel(7, y, matrix.Colors.WHITE_LOW.value)
 
                    
 
                paddle1.draw(self.matrix)
 
                paddle2.draw(self.matrix)
 
                ball.draw(self.matrix)
 
                
 
                self.matrix.update()
 
                
 
                led_iteration_count = (led_iteration_count + 1) % self.matrix.NUM_LEDS
 
                frame_count = frame_count + 1
 
                
 
            time.sleep(0.01)
 
        
 
        #display score before exiting
 
        self.matrix.set_matrix(matrix.Colors.OFF.value)
 
        if score > 750:
 
            for i in range(0, 64):
 
                self.matrix.set_pixel(i % self.matrix.WIDTH, math.floor(i / self.matrix.HEIGHT), matrix.Colors.YELLOW.value)
 
        else:
 
            multiples = math.floor(score / 50)
 
            score = score % 50
 
            for i in range(0, multiples):
 
                self.matrix.set_pixel(i % self.matrix.WIDTH, math.floor(i / self.matrix.HEIGHT), matrix.Colors.YELLOW.value)
 
            for i in range(multiples, score):
 
                self.matrix.set_pixel(i % self.matrix.WIDTH, math.floor(i / self.matrix.HEIGHT), matrix.Colors.WHITE.value)
 
        self.matrix.update()
 
        time.sleep(2)
 
\ No newline at end of file
demos/rainbow.py
Show inline comments
 
### rainbow.py
 
### Author: Matthew Reed
 
### Rainbow array scrolls across the display. Rainbow generated using overlapping sin waves. The frequency, phase shift, center, and width all affect the output.
 
### Inspired by https://krazydad.com/tutorials/makecolors.php
 
 
import sys
 
import time
 
import signal
 
import logging
 
import configparser
 
from enum import Enum
 
 
import math
 
import matrix
 
 
class Rainbow:
 
 
    class MODES(Enum):
 
        TWO_D = 0
 
        LINEAR = 1
 
        SOLID = 2
 
 
    def __init__(self, config, parent, matrix, controller):
 
        self.logger = logging.getLogger('paint')
 
        self.config = config
 
        self.parent = parent
 
        self.matrix = matrix
 
        self.controller = controller
 
        
 
    def reset(self):
 
        pass
 
        
 
    def splash(self):
 
        self.matrix.set_matrix((0,255,0))
 
    
 
        r = matrix.Colors.RED.value
 
        o = matrix.Colors.ORANGE.value
 
        y = matrix.Colors.YELLOW.value
 
        g = matrix.Colors.GREEN.value
 
        b = matrix.Colors.BLUE.value
 
        p = matrix.Colors.PURPLE.value
 
        q = matrix.Colors.OFF.value
 
        
 
        splash = [
 
            [q, q, q, q, q, q, q, q],
 
            [q, q, q, q, q, q, q, q],
 
            [q, q, q, q, q, q, q, q],
 
            [q, r, o, y, g, b, p, q],
 
            [q, r, o, y, g, b, p, q],
 
            [q, q, q, q, q, q, q, q],
 
            [q, q, q, q, q, q, q, q],
 
            [q, q, q, q, q, q, q, q],
 
        ]
 
        
 
        for x in range(0, self.matrix.WIDTH):
 
            for y in range(0, self.matrix.HEIGHT):
 
                self.matrix.set_pixel(x, y, splash[y][x])
 
        
 
        self.matrix.update()
 
        
 
    def run(self):
 
    
 
        center = 128;
 
        width = 100;
 
        width = 127;
 
        frequency = .1;
 
        
 
        mode = self.MODES.TWO_D
 
    
 
        #start timers and counters
 
        self.start_time = time.time()
 
        last_time = time.time()
 
        
 
        led_iteration_count = 0
 
        frame_count = 0
 
        
 
        keep_going = True
 
        
 
        while keep_going:
 
            
 
            for event in self.controller.read_input():
 
                if event.code == 313 and event.value == 1:
 
                    keep_going = False
 
                elif event.code == 305 and event.value == 1:
 
                    mode = self.MODES((mode.value + 1) % len(self.MODES))
 
                elif event.code == 16:
 
                    if event.value == 1:
 
                        #dpad right
 
                        pass
 
                    if event.value == -1:
 
                        #dpad left
 
                        pass
 
                elif event.code == 17:
 
                    if event.value == 1:
 
                        #dpad down
 
                        frequency = frequency - 0.05
 
                        if frequency <= 0.05:
 
                            frequency = 0.05
 
                        print(frequency)
 
                    if event.value == -1:
 
                        #dpad up
 
                        frequency = frequency + 0.05
 
                        if frequency >= 1:
 
                            frequency = 1
 
                        print(frequency)
 
                        
 
            
 
            if time.time() > last_time + 0.1:
 
                last_time = time.time()
 
                    
 
                for y in range(self.matrix.HEIGHT):
 
                    phaseShift = 2*math.pi - y*(1.5*math.pi/(self.matrix.HEIGHT-1))
 
                    if mode == self.MODES.TWO_D:
 
                        phaseShift = 2*math.pi - y*(math.pi/(self.matrix.HEIGHT-1))
 
                    else:
 
                        phaseShift = 4
 
                    for x in range(self.matrix.WIDTH):
 
                        i = (x + frame_count) % 128
 
                        if mode == self.MODES.SOLID:
 
                            i = frame_count % 128
 
                        else:
 
                            i = (x + frame_count) % 128
 
                        red = math.sin(frequency*i + 0) * width + center;
 
                        green = math.sin(frequency*i + phaseShift/2) * width + center;
 
                        blue = math.sin(frequency*i + phaseShift) * width + center;
 
                        
 
                        self.matrix.set_pixel(x, y, (red, green, blue))
 
                
 
                self.matrix.update()
 
                
 
                led_iteration_count = (led_iteration_count + 1) % self.matrix.NUM_LEDS
 
                frame_count = frame_count + 1
 
                
 
            time.sleep(0.01)
 
\ No newline at end of file
 
            time.sleep(0.01)
demos/snake.py
Show inline comments
 
### snake.py
 
### Author: Matthew Reed
 
### Game of snake, uses the D-Pad
 
### Adapted from https://pythonspot.com/snake-with-pygame/ ###
 
### Adapted from https://pythonspot.com/snake-with-pygame/
 
 
import sys
 
import time
 
import signal
 
import logging
 
import configparser
 
from enum import Enum
 
 
import math
 
from random import randint
 
import matrix
 
 
class Snake:
 
 
    class Apple:
 
    
 
        def __init__(self, x, y):
 
            self.x = x
 
            self.y = y
 
     
 
        def draw(self, display):
 
            display.set_pixel(self.x, self.y, matrix.Colors.GREEN.value)
 
    
 
    class Player:
 
 
        class DIRECTION(Enum):
 
            NONE = 0
 
            UP = 1
 
            DOWN = 2
 
            LEFT = 3
 
            RIGHT = 4
 
     
 
        def __init__(self, length):
 
        
 
            self.length = length
 
            self.direction = self.DIRECTION.RIGHT
 
            
 
            self.updateCountMax = 4
 
            self.updateCount = 0
 
 
            # initial positions, no collision
 
            self.x = [2,1,0]
 
            self.y = [0,0,0]
 
            
 
            for i in range(0, 61):
 
                self.x.append(-100)
 
                self.y.append(-100)
 
     
 
        def update(self):
 
     
 
            self.updateCount = self.updateCount + 1
 
            if self.updateCount >= self.updateCountMax:
 
     
 
                # update previous positions
 
                for i in range(self.length, 0, -1):
 
                    self.x[i] = self.x[i-1]
 
                    self.y[i] = self.y[i-1]
 
     
 
                # update position of head of snake
 
                if self.direction == self.DIRECTION.RIGHT:
 
                    self.x[0] = self.x[0] + 1
 
                if self.direction == self.DIRECTION.LEFT:
 
                    self.x[0] = self.x[0] - 1
 
                if self.direction == self.DIRECTION.UP:
 
                    self.y[0] = self.y[0] - 1
 
                if self.direction == self.DIRECTION.DOWN:
 
                    self.y[0] = self.y[0] + 1
 
     
 
                self.updateCount = 0
 
                
 
        def is_overlaping(self, apple):
 
            for i in range(0, self.length):
 
                if apple.x == self.x[i] and apple.y == self.y[i]:
 
                    return True
 
            return False
 
     
 
        def draw(self, display):
 
            for i in range(0, self.length):
 
                #print("l: " + str(self.length) + " i: " + str(i) + " x: " + str(self.x[i]) + " y: " + str(self.y[i]))
 
                if self.x[i] > 7: self.x[i] = 7
 
                if self.x[i] < 0: self.x[i] = 0
 
                if self.y[i] > 7: self.y[i] = 7
 
                if self.y[i] < 0: self.y[i] = 0
 
                display.set_pixel(self.x[i], self.y[i], matrix.Colors.BLUE.value)
 
 
    def __init__(self, config, parent, matrix, controller):
 
        self.logger = logging.getLogger('snake')
 
        self.config = config
 
        self.parent = parent
 
        self.matrix = matrix
 
        self.controller = controller
 
        
 
    def reset(self):
 
        pass
 
        
 
    def splash(self):
 
        self.matrix.set_matrix(matrix.Colors.BLUE.value)
 
    
 
        w = matrix.Colors.WHITE.value
 
        l = matrix.Colors.WHITE_LOW.value
 
        r = matrix.Colors.RED.value
 
        g = matrix.Colors.GREEN.value
 
        b = matrix.Colors.BLUE.value
 
        o = matrix.Colors.OFF.value
 
        
 
        splash = [
 
            [o, o, o, o, o, o, o, o],
 
            [o, o, b, b, b, o, g, o],
 
            [o, o, b, o, o, o, o, o],
 
            [o, o, b, b, b, o, o, o],
 
            [o, o, o, o, b, o, o, o],
 
            [o, o, b, b, b, o, o, o],
 
            [o, o, o, o, o, o, o, o],
 
            [o, o, o, o, o, o, o, o],
 
        ]
 
        
 
        for x in range(0, self.matrix.WIDTH):
 
            for y in range(0, self.matrix.HEIGHT):
 
                self.matrix.set_pixel(x, y, splash[y][x])
 
        
 
        self.matrix.update()
 
        
 
    def run(self):
 
    
 
        self.player = self.Player(3) 
 
        self.apple = self.Apple(5,5)
 
    
 
        #start timers and counters
 
        self.start_time = time.time()
 
        last_time = time.time()
 
        delay_time = 0.2
 
        
 
        led_iteration_count = 0
 
        frame_count = 0
 
        
 
        keep_going = True
 
        
 
        while keep_going:
 
            
 
            for event in self.controller.read_input():
 
                if event.code == 313 and event.value == 1:
 
                    keep_going = False
 
                elif event.code == 16:
 
                    if event.value == 1:
 
                        #dpad right
 
                        self.player.direction = self.player.DIRECTION.RIGHT
 
                    if event.value == 0:
 
                        #dpad none
 
                        pass
 
                    if event.value == -1:
 
                        #dpad left
 
                        self.player.direction = self.player.DIRECTION.LEFT
 
                elif event.code == 17:
 
                    if event.value == 1:
 
                        #dpad down
 
                        self.player.direction = self.player.DIRECTION.DOWN
 
                    if event.value == 0:
 
                        #dpad none
 
                        pass
 
                    if event.value == -1:
 
                        #dpad up
 
                        self.player.direction = self.player.DIRECTION.UP
 
            
 
            if time.time() > last_time + delay_time:
 
                last_time = time.time()
 
                
 
                #determine next move
 
                self.player.update()
 
         
 
                #does snake eat apple?
 
                if self.apple.x == self.player.x[0] and self.apple.y == self.player.y[0]:
 
                    self.player.length = self.player.length + 1
 
                    while self.player.is_overlaping(self.apple):
 
                        self.apple.x = randint(0, 7)
 
                        self.apple.y = randint(0, 7)
 
                    #go faster as the snake gets longer
 
                    delay_time = delay_time - 0.005
 
         
 
                #does snake collide with itself?
 
                for i in range(1, self.player.length):
 
                    if self.player.x[0] == self.player.x[i] and self.player.y[0] == self.player.y[i]:
 
                        print("You lose! Collision: ")
 
                        print("x[0] (" + str(self.player.x[0]) + "," + str(self.player.y[0]) + ")")
 
                        print("x[" + str(i) + "] (" + str(self.player.x[i]) + "," + str(self.player.y[i]) + ")")
 
                        keep_going = False
 
                        
 
                #does snake go off the board?
 
                if self.player.x[0] < 0 or self.player.x[0] > 7 or self.player.y[0] < 0 or self.player.y[0] > 7:
 
                    print("You lose! Off Board: ")
 
                    print("x[0] (" + str(self.player.x[0]) + "," + str(self.player.y[0]) + ")")
 
                    keep_going = False
 
                
 
                #update display
 
                self.matrix.set_matrix(matrix.Colors.OFF.value)
 
                self.player.draw(self.matrix)
 
                self.apple.draw(self.matrix)
 
                self.matrix.update()
 
                
 
                led_iteration_count = (led_iteration_count + 1) % self.matrix.NUM_LEDS
 
                frame_count = frame_count + 1
 
                
 
            time.sleep(0.01)
 
        
 
        #display score before exiting
 
        self.matrix.set_matrix(matrix.Colors.OFF.value)
 
        self.matrix.update()
 
        for i in range(0, self.player.length):
 
            self.matrix.set_pixel(i % self.matrix.WIDTH, math.floor(i / self.matrix.HEIGHT), matrix.Colors.WHITE.value)
 
        self.matrix.update()
 
        time.sleep(2)
 
\ No newline at end of file
demos/tetris.py
Show inline comments
 
new file 100644
 
### tetris.py
 
### Author: Matthew Reed
 
### Game of tetris, uses the D-Pad
 
### Adapted from https://gist.github.com/silvasur/565419/d9de6a84e7da000797ac681976442073045c74a4
 
 
import sys
 
import time
 
import signal
 
import logging
 
import configparser
 
from enum import Enum
 
 
import math
 
from random import randrange as rand
 
import matrix
 
 
class Tetris:
 
 
    # Define the shapes of the single parts
 
    tetris_shapes = [
 
        [[1, 1, 1],
 
         [0, 1, 0]],
 
 
        [[0, 2, 2],
 
         [2, 2, 0]],
 
 
        [[3, 3, 0],
 
         [0, 3, 3]],
 
 
        [[4, 0, 0],
 
         [4, 4, 4]],
 
 
        [[0, 0, 5],
 
         [5, 5, 5]],
 
 
        [[6, 6, 6, 6]],
 
 
        [[7, 7],
 
         [7, 7]]
 
    ]
 
    
 
    colors = [
 
        matrix.Colors.OFF.value,
 
        matrix.Colors.RED.value,
 
        matrix.Colors.GREEN.value,
 
        matrix.Colors.BLUE.value,
 
        matrix.Colors.ORANGE.value,
 
        matrix.Colors.YELLOW.value,
 
        matrix.Colors.MAGENTA.value,
 
        matrix.Colors.LIGHT_BLUE.value
 
    ]
 
    
 
    def rotate_clockwise(self, shape):
 
        return [[ shape[y][x] for y in range(len(shape)) ] for x in range(len(shape[0]) - 1, -1, -1)]
 
 
    def check_collision(self, board, shape, offset):
 
        off_x, off_y = offset
 
        for cy, row in enumerate(shape):
 
            for cx, cell in enumerate(row):
 
                try:
 
                    if cell and board[ cy + off_y ][ cx + off_x ]:
 
                        return True
 
                except IndexError:
 
                    return True
 
        return False
 
 
    def remove_row(self, board, row):
 
        del board[row]
 
        self.score += 1
 
        return [[0 for i in range(self.width)]] + board
 
 
    def join_matrixes(self, mat1, mat2, mat2_off):
 
        off_x, off_y = mat2_off
 
        for cy, row in enumerate(mat2):
 
            for cx, val in enumerate(row):
 
                mat1[cy+off_y-1	][cx+off_x] += val
 
        return mat1
 
 
    def new_board(self):
 
        board = [[0 for x in range(self.width)] for y in range(self.height)]
 
        board += [[1 for x in range(self.width)]]
 
        return board
 
        
 
    def new_stone(self):
 
        self.stone = self.tetris_shapes[rand(len(self.tetris_shapes))]
 
        self.stone_x = int(self.width / 2 - len(self.stone[0])/2)
 
        self.stone_y = 0
 
        
 
        if self.check_collision(self.board, self.stone, (self.stone_x, self.stone_y)):
 
            self.gameover = True
 
 
    def draw(self, matrix, board, offset):
 
        off_x, off_y  = offset
 
        for y, row in enumerate(board):
 
            for x, val in enumerate(row):
 
                if val and y < self.height:
 
                    matrix.set_pixel(off_x + x, off_y + y, self.colors[val])
 
 
    def move(self, delta_x):
 
        if not self.gameover and not self.paused:
 
            new_x = self.stone_x + delta_x
 
            if new_x < 0:
 
                new_x = 0
 
            if new_x > self.width - len(self.stone[0]):
 
                new_x = self.width - len(self.stone[0])
 
            if not self.check_collision(self.board, self.stone, (new_x, self.stone_y)):
 
                self.stone_x = new_x
 
 
    def drop(self):
 
        if not self.gameover and not self.paused:
 
            self.stone_y += 1
 
            if self.check_collision(self.board, self.stone, (self.stone_x, self.stone_y)):
 
                self.board = self.join_matrixes(self.board, self.stone, (self.stone_x, self.stone_y))
 
                self.new_stone()
 
                while True:
 
                    for i, row in enumerate(self.board[:-1]):
 
                        if 0 not in row:
 
                            self.board = self.remove_row(self.board, i)
 
                            break
 
                    else:
 
                        break
 
 
    def rotate_stone(self):
 
        if not self.gameover and not self.paused:
 
            new_stone = self.rotate_clockwise(self.stone)
 
            if not self.check_collision(self.board, new_stone, (self.stone_x, self.stone_y)):
 
                self.stone = new_stone
 
 
    def toggle_pause(self):
 
        self.paused = not self.paused
 
 
    def __init__(self, config, parent, matrix, controller):
 
        self.logger = logging.getLogger('snake')
 
        self.config = config
 
        self.parent = parent
 
        self.matrix = matrix
 
        self.controller = controller
 
        
 
    def reset(self):
 
        pass
 
        
 
    def splash(self):
 
    
 
        w = matrix.Colors.WHITE.value
 
        r = matrix.Colors.RED.value
 
        g = matrix.Colors.GREEN.value
 
        b = matrix.Colors.BLUE.value
 
        l = matrix.Colors.LIGHT_BLUE.value
 
        m = matrix.Colors.MAGENTA.value
 
        O = matrix.Colors.ORANGE.value
 
        y = matrix.Colors.YELLOW.value
 
        o = matrix.Colors.OFF.value
 
        
 
        splash = [
 
            [o, o, o, o, o, o, y, y],
 
            [o, g, g, g, g, g, o, y],
 
            [o, g, o, g, o, g, o, y],
 
            [o, o, o, g, o, o, l, l],
 
            [o, o, o, g, o, o, l, l],
 
            [r, o, o, g, o, o, b, O],
 
            [r, r, g, g, g, b, b, O],
 
            [r, m, m, m, m, b, O, O],
 
        ]
 
        
 
        for x in range(0, self.matrix.WIDTH):
 
            for y in range(0, self.matrix.HEIGHT):
 
                self.matrix.set_pixel(x, y, splash[y][x])
 
        
 
        self.matrix.update()
 
        
 
    def run(self):
 
    
 
        self.width = 8
 
        self.height = 8
 
        
 
        self.board = self.new_board()
 
        self.new_stone()
 
    
 
        #start timers and counters
 
        self.start_time = time.time()
 
        last_time = time.time()
 
        delay_time = 0.1
 
        
 
        led_iteration_count = 0
 
        frame_count = 0
 
        
 
        self.updateCountMax = 15
 
        self.updateCount = 0
 
        
 
        self.score = 0
 
        
 
        self.gameover = False
 
        self.paused = False
 
        
 
        while not self.gameover:
 
            
 
            for event in self.controller.read_input():
 
                if event.code == 313 and event.value == 1:
 
                    #start button
 
                    self.gameover = True
 
                if event.code == 305 and event.value == 1:
 
                    #A button
 
                    self.toggle_pause()
 
                elif event.code == 16:
 
                    if event.value == 1:
 
                        #dpad right
 
                        self.move(+1)
 
                    if event.value == 0:
 
                        #dpad none
 
                        pass
 
                    if event.value == -1:
 
                        #dpad left
 
                        self.move(-1)
 
                elif event.code == 17:
 
                    if event.value == 1:
 
                        #dpad down
 
                        self.drop()
 
                    if event.value == 0:
 
                        #dpad none
 
                        pass
 
                    if event.value == -1:
 
                        #dpad up
 
                        self.rotate_stone()
 
            
 
            if time.time() > last_time + delay_time:
 
                last_time = time.time()
 
                
 
                self.updateCount = self.updateCount + 1
 
                if self.updateCount >= self.updateCountMax:
 
                    self.drop()
 
                    self.updateCount = 0
 
                
 
                #update display
 
                self.matrix.set_matrix(matrix.Colors.OFF.value)
 
                self.draw(self.matrix, self.board, (0,0))
 
                self.draw(self.matrix, self.stone, (self.stone_x, self.stone_y))
 
                self.matrix.update()
 
                
 
                led_iteration_count = (led_iteration_count + 1) % self.matrix.NUM_LEDS
 
                frame_count = frame_count + 1
 
                
 
            time.sleep(0.01)
 
        
 
        #display score before exiting
 
        self.matrix.set_matrix(matrix.Colors.OFF.value)
 
        if self.score > 750:
 
            for i in range(0, 64):
 
                self.matrix.set_pixel(i % self.matrix.WIDTH, math.floor(i / self.matrix.HEIGHT), matrix.Colors.YELLOW.value)
 
        else:
 
            multiples = math.floor(self.score / 50)
 
            self.score = self.score % 50
 
            for i in range(0, multiples):
 
                self.matrix.set_pixel(i % self.matrix.WIDTH, math.floor(i / self.matrix.HEIGHT), matrix.Colors.YELLOW.value)
 
            for i in range(multiples, self.score):
 
                self.matrix.set_pixel(i % self.matrix.WIDTH, math.floor(i / self.matrix.HEIGHT), matrix.Colors.WHITE.value)
 
        self.matrix.update()
 
        time.sleep(2)
 
\ No newline at end of file
lights.py
Show inline comments
 
#!/usr/bin/python
 
 
### lights.py
 
### Author: Matthew Reed
 
 
import sys
 
import time
 
import signal
 
import logging
 
import threading
 
import configparser
 
from enum import Enum
 
 
import opc
 
import color_utils
 
import math
 
 
import matrix
 
import controller
 
from demos import *
 
 
 
class Lights:
 
 
    def __init__(self, config):
 
        self.logger = logging.getLogger('lights.lights')
 
        self.config = config
 
        
 
        self.matrix = matrix.Matrix(config)
 
        self.controller = controller.Controller(config)
 
        
 
        self.demo_i = 0
 
        self.demos = [
 
                rainbow.Rainbow(self.config, self, self.matrix, self.controller),
 
                paint.Paint(self.config, self, self.matrix, self.controller),
 
                rainbow.Rainbow(self.config, self, self.matrix, self.controller),
 
                snake.Snake(self.config, self, self.matrix, self.controller),
 
                pong.Pong(self.config, self, self.matrix, self.controller),
 
                tetris.Tetris(self.config, self, self.matrix, self.controller),
 
                clouds.Clouds(self.config, self, self.matrix, self.controller),
 
            ]
 
    
 
    def reset(self):
 
    
 
        self.color = matrix.Colors.WHITE.value
 
        self.matrix.set_matrix(matrix.Colors.OFF.value)
 
        
 
    def run(self):
 
        
 
        self.reset()
 
    
 
        #start timers and counters
 
        self.start_time = time.time()
 
        last_time = time.time()
 
        
 
        led_iteration_count = 0
 
        frame_count = 0
 
        
 
        self.demos[self.demo_i].run()
 
        
 
        while True:
 
            
 
            for event in self.controller.read_input():
 
                #print("Event: " + str(event))
 
                if event.code == 312 and event.value == 1:
 
                    self.demo_i = (self.demo_i + 1) % len(self.demos)
 
                    self.reset()
 
                elif event.code == 313 and event.value == 1:
 
                    self.reset()
 
                    self.demos[self.demo_i].run()
 
            
 
            if time.time() > last_time + 0.1:
 
                last_time = time.time()
 
                    
 
                self.demos[self.demo_i].splash()
 
                
 
                led_iteration_count = (led_iteration_count + 1) % self.matrix.NUM_LEDS
 
                frame_count = frame_count + 1
 
                
 
            time.sleep(0.01)
 
        
 
        
 
    def stop(self):
 
        self.matrix.stop()
 
 
 
def main():
 
    logger = logging.getLogger('lights')
 
    logger.setLevel(logging.DEBUG)
 
    # create file handler which logs debug messages
 
    sh1 = logging.StreamHandler(sys.stdout)
 
    sh1.setLevel(logging.DEBUG)
 
    # create formatter and add it to the handlers
 
    formatter = logging.Formatter('[%(asctime)s][%(levelname)s][%(module)s][%(funcName)s] %(message)s')
 
    sh1.setFormatter(formatter)
 
    # add the handlers to the logger
 
    logger.addHandler(sh1)
 
    logger.info('Logger initialized')
 
 
    config = configparser.ConfigParser()
 
    config.read('lights.conf')
 
    
 
    try:
 
        my_lights = Lights(config)
 
        
 
        logger.info('Starting...')
 
        my_lights.run()
 
        
 
    finally:
 
        logger.info('Shutting down')
 
        my_lights.stop()
 
        logger.info('Goodbye')
 
    
 
if __name__ == "__main__":
 
    sys.exit(main())
 
\ No newline at end of file
matrix.py
Show inline comments
 
### matrix.py
 
### Author: Matthew Reed
 
 
import sys
 
import time
 
import signal
 
import logging
 
import threading
 
import configparser
 
from enum import Enum
 
 
import opc
 
import color_utils
 
import math
 
 
 
class Colors(Enum):
 
    OFF = (0, 0, 0)
 
    RED = (255, 0, 0)
 
    GREEN = (0, 255, 0)
 
    BLUE = (0, 0, 255)
 
    LIGHT_BLUE = (0, 220, 220)
 
    PURPLE = (128, 0, 128)
 
    VIOLET = (148, 0, 211)
 
    YELLOW = (255, 255, 0)
 
    ORANGE = (255, 140, 0)
 
    MAGENTA = (255, 0, 255)
 
    WHITE = (255, 255, 255)
 
    WHITE_LOW = (100, 100, 100)
 
 
class Matrix:
 
 
    def __init__(self, config):
 
        self.logger = logging.getLogger('matrix')
 
        self.config = config
 
        
 
        #init leds
 
        self.ADDRESS = 'localhost:7890'
 
        # Create a client object
 
        self.led_client = opc.Client(self.ADDRESS)
 
        
 
        # Test if it can connect (optional)
 
        if self.led_client.can_connect():
 
            self.logger.info('connected to FadeCandy %s' % self.ADDRESS)
 
        else:
 
            # We could exit here, but instead let's just print a warning
 
            # and then keep trying to send pixels in case the server
 
            # appears later
 
            self.logger.error('WARNING: could not connect to %s' % self.ADDRESS)
 
            
 
        self.num_channels = int(self.config.get('leds', 'num_channels'))
 
        self.NUM_LEDS = int(self.config.get('leds', 'num_leds'))
 
        
 
        self.my_pixels = [(0,0,0)] * self.NUM_LEDS
 
        self.led_client.put_pixels(self.my_pixels)
 
        
 
        #map out a matrix that represents the physical layout of the display
 
        self.led_map = [
 
            [63, 48, 47, 32, 31, 16, 15,  0],
 
            [62, 49, 46, 33, 30, 17, 14,  1],
 
            [61, 50, 45, 34, 29, 18, 13,  2],
 
            [60, 51, 44, 35, 28, 19, 12,  3],
 
            [59, 52, 43, 36, 27, 20, 11,  4],
 
            [58, 53, 42, 37, 26, 21, 10,  5],
 
            [57, 54, 41, 38, 25, 22,  9,  6],
 
            [56, 55, 40, 39, 24, 23,  8,  7],
 
        ]
 
        
 
        #x axis
 
        self.WIDTH = 8
 
        #y axis
 
        self.HEIGHT = 8
 
        
 
        #initialize matrix with zeros
 
        self.led_matrix = [[(0,0,0) for x in range(self.WIDTH)] for y in range(self.HEIGHT)]
 
        
 
    def update(self):
 
        
 
        for x in range(self.WIDTH):
 
            for y in range(self.HEIGHT):
 
                self.my_pixels[self.led_map[x][y]] = self.led_matrix[x][y]
 
                
 
        self.led_client.put_pixels(self.my_pixels)
 
        
 
    def set_pixel(self, x, y, color):
 
        self.led_matrix[x][y] = color
 
        
 
    def get_pixel(self, x, y):
 
        return self.led_matrix[x][y]
 
        
 
    def set_matrix(self, color):
 
        for x in range(self.WIDTH):
 
            for y in range(self.HEIGHT):
 
                self.led_matrix[x][y] = color
 
        
 
        
 
    def stop(self):
 
        self.logger.info('Turning off leds')
 
        self.my_pixels = [(0,0,0)] * self.NUM_LEDS
 
        self.led_client.put_pixels(self.my_pixels)
 
\ No newline at end of file
0 comments (0 inline, 0 general)