import hyperion, time, colorsys, math from random import random # Get the parameters rotationTime = float(hyperion.args.get('rotationTime', 20.0)) color = hyperion.args.get('color', (0,0,255)) colorRandom = bool(hyperion.args.get('colorRandom', False)) hueChange = float(hyperion.args.get('hueChange', 60.0)) blobs = int(hyperion.args.get('blobs', 5)) reverse = bool(hyperion.args.get('reverse', False)) baseColorChange = bool(hyperion.args.get('baseChange', False)) baseColorRangeLeft = float(hyperion.args.get('baseColorRangeLeft',0.0)) # Degree baseColorRangeRight = float(hyperion.args.get('baseColorRangeRight',360.0)) # Degree baseColorChangeRate = float(hyperion.args.get('baseColorChangeRate',10.0)) # Seconds for one Degree # switch baseColor change off if left and right are too close together to see a difference in color if (baseColorRangeRight > baseColorRangeLeft and (baseColorRangeRight - baseColorRangeLeft) < 10) or \ (baseColorRangeLeft > baseColorRangeRight and ((baseColorRangeRight + 360) - baseColorRangeLeft) < 10): baseColorChange = False # 360 -> 1 fullColorWheelAvailable = (baseColorRangeRight % 360) == (baseColorRangeLeft % 360) baseColorChangeIncreaseValue = 1.0 / 360.0 # 1 degree hueChange /= 360.0 baseColorRangeLeft = (baseColorRangeLeft / 360.0) baseColorRangeRight = (baseColorRangeRight / 360.0) # Check parameters rotationTime = max(0.1, rotationTime) hueChange = max(0.0, min(abs(hueChange), .5)) blobs = max(1, blobs) baseColorChangeRate = max(0, baseColorChangeRate) # > 0 # Calculate the color data baseHsv = colorsys.rgb_to_hsv(color[0]/255.0, color[1]/255.0, color[2]/255.0) if colorRandom: baseHsv = (random(), baseHsv[1], baseHsv[2]) colorData = bytearray() for i in range(hyperion.ledCount): hue = (baseHsv[0] + hueChange * math.sin(2*math.pi * i / hyperion.ledCount)) % 1.0 rgb = colorsys.hsv_to_rgb(hue, baseHsv[1], baseHsv[2]) colorData += bytearray((int(255*rgb[0]), int(255*rgb[1]), int(255*rgb[2]))) # Calculate the increments sleepTime = 0.1 amplitudePhaseIncrement = blobs * math.pi * sleepTime / rotationTime colorDataIncrement = 3 baseColorChangeRate /= sleepTime # Switch direction if needed if reverse: amplitudePhaseIncrement = -amplitudePhaseIncrement colorDataIncrement = -colorDataIncrement # create a Array for the colors colors = bytearray(hyperion.ledCount * (0,0,0)) # Start the write data loop amplitudePhase = 0.0 rotateColors = False baseColorChangeStepCount = 0 baseHSVValue = baseHsv[0] numberOfRotates = 0 while not hyperion.abort(): # move the basecolor if baseColorChange: # every baseColorChangeRate seconds if baseColorChangeStepCount >= baseColorChangeRate: baseColorChangeStepCount = 0 # cyclic increment when the full colorwheel is available, move up and down otherwise if fullColorWheelAvailable: baseHSVValue = (baseHSVValue + baseColorChangeIncreaseValue) % baseColorRangeRight else: # switch increment direction if baseHSV <= left or baseHSV >= right if baseColorChangeIncreaseValue < 0 and baseHSVValue > baseColorRangeLeft and (baseHSVValue + baseColorChangeIncreaseValue) <= baseColorRangeLeft: baseColorChangeIncreaseValue = abs(baseColorChangeIncreaseValue) elif baseColorChangeIncreaseValue > 0 and baseHSVValue < baseColorRangeRight and (baseHSVValue + baseColorChangeIncreaseValue) >= baseColorRangeRight : baseColorChangeIncreaseValue = -abs(baseColorChangeIncreaseValue) baseHSVValue = (baseHSVValue + baseColorChangeIncreaseValue) % 1.0 # update color values colorData = bytearray() for i in range(hyperion.ledCount): hue = (baseHSVValue + hueChange * math.sin(2*math.pi * i / hyperion.ledCount)) % 1.0 rgb = colorsys.hsv_to_rgb(hue, baseHsv[1], baseHsv[2]) colorData += bytearray((int(255*rgb[0]), int(255*rgb[1]), int(255*rgb[2]))) # set correct rotation after reinitialisation of the array colorData = colorData[-colorDataIncrement*numberOfRotates:] + colorData[:-colorDataIncrement*numberOfRotates] baseColorChangeStepCount += 1 # Calculate new colors for i in range(hyperion.ledCount): amplitude = max(0.0, math.sin(-amplitudePhase + 2*math.pi * blobs * i / hyperion.ledCount)) colors[3*i+0] = int(colorData[3*i+0] * amplitude) colors[3*i+1] = int(colorData[3*i+1] * amplitude) colors[3*i+2] = int(colorData[3*i+2] * amplitude) # set colors hyperion.setColor(colors) # increment the phase amplitudePhase = (amplitudePhase + amplitudePhaseIncrement) % (2*math.pi) if rotateColors: colorData = colorData[-colorDataIncrement:] + colorData[:-colorDataIncrement] numberOfRotates = (numberOfRotates + 1) % hyperion.ledCount rotateColors = not rotateColors # sleep for a while time.sleep(sleepTime)