from rpi_ws281x import PixelStrip import atexit from tkinter import Tk, Canvas from threading import Thread class _LedData(object): _led: [] def __init__(self, channel, size): self.size = size self.channel = channel def __getitem__(self, pos): """Return the 24-bit RGB color value at the provided position or slice of positions. """ # Handle if a slice of positions are passed in by grabbing all the values # and returning them in a list. if isinstance(pos, slice): return [self._led[n] for n in range(*pos.indices(self.size))] # Else assume the passed in value is a number to the position. else: return self._led[pos] def __setitem__(self, pos, value): """Set the 24-bit RGB color value at the provided position or slice of positions. """ # Handle if a slice of positions are passed in by setting the appropriate # LED data values to the provided values. if isinstance(pos, slice): index = 0 for n in range(*pos.indices(self.size)): self._led[n] = value[index] index += 1 # Else assume the passed in value is a number to the position. # else: self._led[pos] = value class FakeStrip(PixelStrip): _brightness: int def __init__(self, num, pin, freq_hz=800000, dma=10, invert=False, brightness=255, channel=0, strip_type=None, gamma=None): if gamma is None: # Support gamma in place of strip_type for back-compat with # previous version of forked library if type(strip_type) is list and len(strip_type) == 256: gamma = strip_type # strip_type = None else: gamma = list(range(256)) # Initialize the channel in use self._channel = None self._gamma = gamma self._brightness = brightness # Grab the led data array. self._led_data = _LedData(self._channel, num) # Substitute for __del__, traps an exit condition and cleans up properly atexit.register(self._cleanup) self.viz = Tk() self.x = 1000 self.y = 500 self.viz.geometry(f'{self.x}x{self.y}') self.canv = Canvas(self.viz) self.canv.pack(expand=1) self.th.start() self.th = Thread(target=self.viz.mainloop) def _cleanup(self): # Clean up memory used by the library when not needed anymore. if self._channel is not None: self._channel = None def setGamma(self, gamma): if type(gamma) is list and len(gamma) == 256: self._gamma = gamma def begin(self): """Initialize library, must be called once before other functions are called.""" return def show(self): """Update the display with the data from the LED buffer.""" self.canv.delete("all") size = 10.5 bp = [47, 97, 191, 242, 289] for s in range(self.numPixels()): x1 = 0 y1 = 0 x2 = 0 y2 = 0 if s < bp[0]: x1 = (self.x / 2) + s * size y1 = 0 x2 = x1 + size y2 = size elif s < bp[1]: x1 = self.x - size y1 = -(bp[0] - s) * size x2 = x1 + size y2 = y1 + size elif s < bp[2]: x1 = self.x + (bp[1] - s) * size y1 = self.y x2 = x1 - size y2 = y1 - size elif s < bp[3]: x1 = 0 y1 = self.y + (bp[2] - s) * size x2 = x1 + size y2 = y1 - size elif s < bp[4]: x1 = size * - (bp[3] - s) y1 = 0 x2 = x1 + size y2 = y1 + size rgb = self.getPixelColorRGB(s) self.canv.create_rectangle(x1, y1, x2, y2, fill="#%02x%02x%02x" % (rgb.r, rgb.g, rgb.b)) def getBrightness(self) -> int: return self._brightness def setBrightness(self, brightness: int): """Scale each LED in the buffer by the provided brightness. A brightness of 0 is the darkest and 255 is the brightest. """ self._brightness = brightness def numPixels(self): """Return the number of pixels in the display.""" return self._led_data.size