Here’s a small Python program that uses the SecretAPI to send a stream of randomly coloured lights scrolling down your Holiday.
Usage: python nye.py ip-address-of-holiday optional-frame-rate
And here’s the code. Copy and paste it in and have fun!
#!/usr/bin/python # """ Holiday class implementation for the Secret API for Holiday by Moorescloud Homepage and documentation: http://mooresclouddev.markpesce.com/ Copyright (c) 2013, Mark Pesce. License: MIT (see LICENSE for details) """ __author__ = 'Mark Pesce' __version__ = '1.0b4' __license__ = 'MIT' import sys, array, socket class HolidaySecretAPI: NUM_GLOBES = 50 # Storage for all 50 globe values # globes = [ [ 0x00, 0x00, 0x00], [ 0x00, 0x00, 0x00], [ 0x00, 0x00, 0x00], [ 0x00, 0x00, 0x00], [ 0x00, 0x00, 0x00], [ 0x00, 0x00, 0x00], [ 0x00, 0x00, 0x00], [ 0x00, 0x00, 0x00], [ 0x00, 0x00, 0x00], [ 0x00, 0x00, 0x00], [ 0x00, 0x00, 0x00], [ 0x00, 0x00, 0x00], [ 0x00, 0x00, 0x00], [ 0x00, 0x00, 0x00], [ 0x00, 0x00, 0x00], [ 0x00, 0x00, 0x00], [ 0x00, 0x00, 0x00], [ 0x00, 0x00, 0x00], [ 0x00, 0x00, 0x00], [ 0x00, 0x00, 0x00], [ 0x00, 0x00, 0x00], [ 0x00, 0x00, 0x00], [ 0x00, 0x00, 0x00], [ 0x00, 0x00, 0x00], [ 0x00, 0x00, 0x00], [ 0x00, 0x00, 0x00], [ 0x00, 0x00, 0x00], [ 0x00, 0x00, 0x00], [ 0x00, 0x00, 0x00], [ 0x00, 0x00, 0x00], [ 0x00, 0x00, 0x00], [ 0x00, 0x00, 0x00], [ 0x00, 0x00, 0x00], [ 0x00, 0x00, 0x00], [ 0x00, 0x00, 0x00], [ 0x00, 0x00, 0x00], [ 0x00, 0x00, 0x00], [ 0x00, 0x00, 0x00], [ 0x00, 0x00, 0x00], [ 0x00, 0x00, 0x00], [ 0x00, 0x00, 0x00], [ 0x00, 0x00, 0x00], [ 0x00, 0x00, 0x00], [ 0x00, 0x00, 0x00], [ 0x00, 0x00, 0x00], [ 0x00, 0x00, 0x00], [ 0x00, 0x00, 0x00], [ 0x00, 0x00, 0x00], [ 0x00, 0x00, 0x00], [ 0x00, 0x00, 0x00] ] def __init__(self, addr=''): """If remote, you better supply a valid address. We'll throw an exception when you don't do this.""" self.addr = addr # IP address we're chatting with. self.port = 9988 # Secret API port self.sock = socket.socket(socket.AF_INET, socket.SOCK_DGRAM) # UDP def setglobe(self, globenum, r, g, b): """Set a globe""" if (globenum < 0) or (globenum >= self.NUM_GLOBES): return self.globes[globenum][0] = r self.globes[globenum][1] = g self.globes[globenum][2] = b def fill(self, r, g, b): """Sets the whole string to a particular colour""" for e in self.globes: e[0] = int(r) e[1] = int(g) e[2] = int(b) def getglobe(self, globenum): """Return a tuple representing a globe's RGB color value""" if (globenum < 0) or (globenum >= self.NUM_GLOBES): return False return (self.globes[globenum][0], self.globes[globenum][1], self.globes[globenum][2]) def chase(self, direction="True"): """Rotate all of the globes around - up if TRUE, down if FALSE""" return def rotate(self, newr, newg, newb, direction="True"): if direction == "True": for i in range(1, self.NUM_GLOBES): self.globes[self.NUM_GLOBES - i][0] = self.globes[self.NUM_GLOBES - (i+1)][0] self.globes[self.NUM_GLOBES - i][1] = self.globes[self.NUM_GLOBES - (i+1)][1] self.globes[self.NUM_GLOBES - i][2] = self.globes[self.NUM_GLOBES - (i+1)][2] self.setglobe(0, newr, newg, newb) return else: return """Rotate all of the globes up if TRUE, down if FALSE Set the new start of the string to the color values""" return def render(self): """The render routine sends out a UDP packet using the SecretAPI""" # Create the 160-byte array of data packet = array.array('B', [ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0]) # initialize basic packet, ignore first 10 bytes for g in self.globes: packet.append(g[0]) packet.append(g[1]) packet.append(g[2]) # Send the packet to the Holiday self.sock.sendto(packet, (self.addr, self.port)) return # Just some basic testerating from the command linery # if __name__ == '__main__': if len(sys.argv) > 1: hol = HolidaySecretAPI(addr=sys.argv[1]) else: sys.exit(1) if len(sys.argv) > 2: fps = float(sys.argv[2]) else: fps = 10.0 rate = 1.0/fps import random, time clr = [0, 1, 2] while True: clr[0] = random.randint(0, 255) clr[1] = random.randint(0, 255) clr[2] = random.randint(0, 255) clr[random.randint(0,2)] = 0 # knock out one colour component for richness hol.rotate(clr[0], clr[1], clr[2]) hol.render() time.sleep(rate)
Update: Had a little think about it, and added some interpolation code. Now the string generates a random colour and moves from that to another random colour in a smooth transition. Essentially it means the globes become a series of rainbow washes moving down the string.
Usage: python nyebow.py ip-of-holiday frames-per-second frames-per-transition (last two are optional and both default to 10)
#!/usr/bin/python # """ Holiday class implementation for the Secret API for Holiday by Moorescloud Homepage and documentation: http://mooresclouddev.markpesce.com/ Copyright (c) 2013, Mark Pesce. License: MIT (see LICENSE for details) """ __author__ = 'Mark Pesce' __version__ = '1.0b4' __license__ = 'MIT' import sys, array, socket class HolidaySecretAPI: NUM_GLOBES = 50 # Storage for all 50 globe values # globes = [ [ 0x00, 0x00, 0x00], [ 0x00, 0x00, 0x00], [ 0x00, 0x00, 0x00], [ 0x00, 0x00, 0x00], [ 0x00, 0x00, 0x00], [ 0x00, 0x00, 0x00], [ 0x00, 0x00, 0x00], [ 0x00, 0x00, 0x00], [ 0x00, 0x00, 0x00], [ 0x00, 0x00, 0x00], [ 0x00, 0x00, 0x00], [ 0x00, 0x00, 0x00], [ 0x00, 0x00, 0x00], [ 0x00, 0x00, 0x00], [ 0x00, 0x00, 0x00], [ 0x00, 0x00, 0x00], [ 0x00, 0x00, 0x00], [ 0x00, 0x00, 0x00], [ 0x00, 0x00, 0x00], [ 0x00, 0x00, 0x00], [ 0x00, 0x00, 0x00], [ 0x00, 0x00, 0x00], [ 0x00, 0x00, 0x00], [ 0x00, 0x00, 0x00], [ 0x00, 0x00, 0x00], [ 0x00, 0x00, 0x00], [ 0x00, 0x00, 0x00], [ 0x00, 0x00, 0x00], [ 0x00, 0x00, 0x00], [ 0x00, 0x00, 0x00], [ 0x00, 0x00, 0x00], [ 0x00, 0x00, 0x00], [ 0x00, 0x00, 0x00], [ 0x00, 0x00, 0x00], [ 0x00, 0x00, 0x00], [ 0x00, 0x00, 0x00], [ 0x00, 0x00, 0x00], [ 0x00, 0x00, 0x00], [ 0x00, 0x00, 0x00], [ 0x00, 0x00, 0x00], [ 0x00, 0x00, 0x00], [ 0x00, 0x00, 0x00], [ 0x00, 0x00, 0x00], [ 0x00, 0x00, 0x00], [ 0x00, 0x00, 0x00], [ 0x00, 0x00, 0x00], [ 0x00, 0x00, 0x00], [ 0x00, 0x00, 0x00], [ 0x00, 0x00, 0x00], [ 0x00, 0x00, 0x00] ] def __init__(self, addr=''): """If remote, you better supply a valid address. We'll throw an exception when you don't do this.""" self.addr = addr # IP address we're chatting with. self.port = 9988 # Secret API port self.sock = socket.socket(socket.AF_INET, socket.SOCK_DGRAM) # UDP def setglobe(self, globenum, r, g, b): """Set a globe""" if (globenum < 0) or (globenum >= self.NUM_GLOBES): return self.globes[globenum][0] = r self.globes[globenum][1] = g self.globes[globenum][2] = b def fill(self, r, g, b): """Sets the whole string to a particular colour""" for e in self.globes: e[0] = int(r) e[1] = int(g) e[2] = int(b) def getglobe(self, globenum): """Return a tuple representing a globe's RGB color value""" if (globenum < 0) or (globenum >= self.NUM_GLOBES): return False return (self.globes[globenum][0], self.globes[globenum][1], self.globes[globenum][2]) def chase(self, direction="True"): """Rotate all of the globes around - up if TRUE, down if FALSE""" return def rotate(self, newr, newg, newb, direction="True"): if direction == "True": for i in range(1, self.NUM_GLOBES): self.globes[self.NUM_GLOBES - i][0] = self.globes[self.NUM_GLOBES - (i+1)][0] self.globes[self.NUM_GLOBES - i][1] = self.globes[self.NUM_GLOBES - (i+1)][1] self.globes[self.NUM_GLOBES - i][2] = self.globes[self.NUM_GLOBES - (i+1)][2] self.setglobe(0, newr, newg, newb) return else: return """Rotate all of the globes up if TRUE, down if FALSE Set the new start of the string to the color values""" return def render(self): """The render routine sends out a UDP packet using the SecretAPI""" # Create the 160-byte array of data packet = array.array('B', [ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0]) # initialize basic packet, ignore first 10 bytes for g in self.globes: packet.append(g[0]) packet.append(g[1]) packet.append(g[2]) # Send the packet to the Holiday self.sock.sendto(packet, (self.addr, self.port)) return # Just some basic testerating from the command linery # if __name__ == '__main__': if len(sys.argv) > 1: hol = HolidaySecretAPI(addr=sys.argv[1]) else: sys.exit(1) if len(sys.argv) > 2: fps = float(sys.argv[2]) else: fps = 10.0 rate = 1.0/fps if len(sys.argv) > 3: steps = int(sys.argv[3]) else: steps = 10 import random, time sclr = [ 0, 0, 0 ] eclr = [ 0, 0, 0 ] diff = [ 0.0, 0.0, 0.0 ] clr = [0, 1, 2] while True: # Copy the end colour to the start colour sclr[0] = eclr[0] sclr[1] = eclr[1] sclr[2] = eclr[2] # Generate a random colour end colour eclr[0] = random.randint(0, 255) eclr[1] = random.randint(0, 255) eclr[2] = random.randint(0, 255) eclr[random.randint(0,2)] = 0 # knock out one colour component for richness # Calculate the difference per frame diff[0] = float((eclr[0] - sclr[0]) / steps) diff[1] = float((eclr[1] - sclr[1]) / steps) diff[2] = float((eclr[2] - sclr[2]) / steps) for i in range(steps): r = int(sclr[0] + (diff[0] * i)) if (r < 0): r = 0 elif (r > 255): r = 255 clr[0] = r g = int(sclr[1] + (diff[1] * i)) if (g < 0): g = 0 elif (g > 255): g = 255 clr[1] = g b = int(sclr[2] + (diff[2] * i)) if (b < 0): b = 0 elif (b > 255): b = 255 clr[2] = b hol.rotate(clr[0], clr[1], clr[2]) hol.render() time.sleep(rate)
Have fun!