def __init__(self, verbose, showUpdates):
        # initializations
        self.beVerbose = verbose
        self.dryRun = False
        self.colorCalculator = ColorCalculator()
        self.deviceConnected = False
        self.currentFrameCount = 0
        self.targetTimePerFrame = 0.0
        self.updateFrameTimestamp = datetime.datetime.now()
        self.asyncUpdateRateController = AsyncUpdateRateController(
            self, showUpdates)
        self.pixelMap = [
            42, 43, 44, 45, 46, 47, 48, 41, 20, 21, 22, 23, 24, 25, 40, 19, 18,
            17, 16, 15, 26, 39, 10, 11, 12, 13, 14, 27, 38, 9, 8, 7, 6, 5, 28,
            37, 0, 1, 2, 3, 4, 29, 36, 35, 34, 33, 32, 31, 30
        ]

        # establish connection to device
        try:
            if not self.dryRun:
                self.serialConnection = serial.Serial(DEVICE_FILE,
                                                      DEVICE_BAUDRATE)
            self.deviceConnected = True
        except serial.SerialException:
            print('can not connect to the Arduino; going on as dry run')
            self.dryRun = True

        # build header for buffer
        # unsigned char array, will transfered serially to the device
        self.buffer = array('B')
        # ASCII for 'A'; magic number
        self.buffer.append(65)
        # ASCII for 'd'; magic number
        self.buffer.append(100)
        # ASCII for 'a'; magic number
        self.buffer.append(97)
        # LED count high byte
        self.buffer.append((NUMBER_LEDS - 1) >> 8)
        # LED count low byte
        self.buffer.append((NUMBER_LEDS - 1) & 0xff)
        # checksum
        self.buffer.append((NUMBER_LEDS - 1) >> 8 ^ (NUMBER_LEDS - 1) & 0xff
                           ^ 0x55)
        for _ in range(0, (NUMBER_LEDS * 3)):
            # fill up every channel of every LED with zeros
            self.buffer.append(255)

        # calculate max. useful frame rate which the serial bus can handle
        targetFPS = (DEVICE_BAUDRATE / 8) / sys.getsizeof(self.buffer)
        self.targetTimePerFrame = 1.0 / targetFPS

        # wait for initialization
        if not self.dryRun:
            if self.beVerbose:
                print('wait for Arduino to be initialized')
            sleep(5)

        # start frame rate controller
        self.asyncUpdateRateController.start()
Example #2
0
    def __init__(self, device):
        # initializations
        self.device = device
        self.colors = ColorController
        self.colorCalculator = ColorCalculator()
        self.hueAdditionPerFrame = 0.0

        # animation settings
        self.currentHueAddition = 0.0
        self.speed = 10
Example #3
0
    def __init__(self, device):
        # animation settings
        self.glowingPixelCount = 17
        self.glowingPixelDegreeOfColorDivergence = 35
        self.minimumSpeed = 50

        # initializations
        self.colorCalculator = ColorCalculator()
        self.colors = ColorController
        self.device = device
        self.randomGlowingPixels = {}
        self.sinFactorForHueAddition = 0
    def __init__(self, verbose, showUpdates):
        # initializations
        self.beVerbose = verbose
        self.dryRun = False
        self.colorCalculator = ColorCalculator()
        self.deviceConnected = False
        self.currentFrameCount = 0
        self.targetTimePerFrame = 0.0
        self.updateFrameTimestamp = datetime.datetime.now()
        self.asyncUpdateRateController = AsyncUpdateRateController(
            self, showUpdates)
        self.pixelMap = [
            42, 43, 44, 45, 46, 47, 48, 41, 20, 21, 22, 23, 24, 25, 40, 19, 18, 17,
            16, 15, 26, 39, 10, 11, 12, 13, 14, 27, 38, 9, 8, 7, 6, 5, 28, 37, 0, 1,
            2, 3, 4, 29, 36, 35, 34, 33, 32, 31, 30
        ]

        # establish connection to device
        try:
            if not self.dryRun:
                self.serialConnection = serial.Serial(
                    DEVICE_FILE, DEVICE_BAUDRATE)
            self.deviceConnected = True
        except serial.SerialException:
            print('can not connect to the Arduino; going on as dry run')
            self.dryRun = True

        # build header for buffer
        # unsigned char array, will transfered serially to the device
        self.buffer = array('B')
        # ASCII for 'A'; magic number
        self.buffer.append(65)
        # ASCII for 'd'; magic number
        self.buffer.append(100)
        # ASCII for 'a'; magic number
        self.buffer.append(97)
        # LED count high byte
        self.buffer.append((NUMBER_LEDS - 1) >> 8)
        # LED count low byte
        self.buffer.append((NUMBER_LEDS - 1) & 0xff)
        # checksum
        self.buffer.append((NUMBER_LEDS - 1) >> 8 ^ (NUMBER_LEDS - 1) & 0xff ^ 0x55)
        for _ in range(0, (NUMBER_LEDS * 3)):
            # fill up every channel of every LED with zeros
            self.buffer.append(255)

        # calculate max. useful frame rate which the serial bus can handle
        targetFPS = (DEVICE_BAUDRATE / 8) / sys.getsizeof(self.buffer)
        self.targetTimePerFrame = 1.0 / targetFPS

        # wait for initialization
        if not self.dryRun:
            if self.beVerbose:
                print('wait for Arduino to be initialized')
            sleep(5)

        # start frame rate controller
        self.asyncUpdateRateController.start()
Example #5
0
    def __init__(self, device):
        # initializations
        self.device = device
        self.colors = ColorController
        self.colorCalculator = ColorCalculator()
        self.hueAdditionPerFrame = 0.0

        # animation settings
        self.currentHueAddition = 0.0
        self.speed = 10
Example #6
0
    def __init__(self, device):
        # animation settings
        self.centerPositionX = 1
        self.centerPositionY = 5
        self.degreeOfColorDivergence = 30
        self.distanceToDarkness = 3
        self.speed = 0.01
        self.iterationStep = 0

        # initializations
        self.colorCalculator = ColorCalculator()
        self.colors = ColorController
        self.device = device
        self.degreeFactor = 0

        # construct array of precalculated values
        self.sinSummands = [[
            0.0 for x in range(self.device.getNumberOfLeds())
        ] for x in range(self.device.getNumberOfLeds())]
Example #7
0
    def __init__(self):
        # initializations
        self.device = None
        self.colorCalculator = ColorCalculator()
        self.basisColor = ORANGE
        self.binaryClockColor = WHITE
        self.basisLightness = 0.50
        self.binaryClockLightness = 1

        # value predefinitions
        self.basisHue = 0
        self.basisSaturation = 1
        self.basisRedChannel = 0
        self.basisGreenChannel = 0
        self.basisBlueChannel = 0
        self.binaryClockColorRedChannel = 0
        self.binaryClockColorGreenChannel = 0
        self.binaryClockColorBlueChannel = 0

        # calculate variations of initial color
        self.calculateVariationsOfBasisValues()
Example #8
0
    def __init__(self, device):
        # animation settings
        self.glowingPixelCount = 17
        self.glowingPixelDegreeOfColorDivergence = 35
        self.minimumSpeed = 50

        # initializations
        self.colorCalculator = ColorCalculator()
        self.colors = ColorController
        self.device = device
        self.randomGlowingPixels = {}
        self.sinFactorForHueAddition = 0
Example #9
0
    def __init__(self, device):
        # animation settings
        self.centerPositionX = 1
        self.centerPositionY = 5
        self.degreeOfColorDivergence = 30
        self.distanceToDarkness = 3
        self.speed = 0.01
        self.iterationStep = 0

        # initializations
        self.colorCalculator = ColorCalculator()
        self.colors = ColorController
        self.device = device
        self.degreeFactor = 0

        # construct array of precalculated values
        self.sinSummands = [
            [0.0 for x in range(self.device.getNumberOfLeds())] for x in range(self.device.getNumberOfLeds())
        ]
Example #10
0
    def __init__(self):
        # initializations
        self.device = None
        self.colorCalculator = ColorCalculator()
        self.basisColor = ORANGE
        self.binaryClockColor = WHITE
        self.basisLightness = 0.50
        self.binaryClockLightness = 1

        # value predefinitions
        self.basisHue = 0
        self.basisSaturation = 1
        self.basisRedChannel = 0
        self.basisGreenChannel = 0
        self.basisBlueChannel = 0
        self.binaryClockColorRedChannel = 0
        self.binaryClockColorGreenChannel = 0
        self.binaryClockColorBlueChannel = 0

        # calculate variations of initial color
        self.calculateVariationsOfBasisValues()
Example #11
0
class ColorChange(IssetHelper):

    def __init__(self, device):
        # initializations
        self.device = device
        self.colors = ColorController
        self.colorCalculator = ColorCalculator()
        self.hueAdditionPerFrame = 0.0

        # animation settings
        self.currentHueAddition = 0.0
        self.speed = 10

    def start(self):
        self.hueAdditionPerFrame = 0.00001 * (self.speed + 1)

    def renderNextFrame(self):
        (currentHue, saturation, lightness) = self.colors.getBasisColorAsHsl()
        targetHue = self.colorCalculator.correctHueValue(
            currentHue + self.hueAdditionPerFrame)

        self.colors.setBasisColorAsHsl(targetHue, saturation, lightness)
        (r, g, b) = self.colors.getBasisColorAsRgb()
        self.device.setRgbToBuffer(r, g, b)

    # ***** getter **********************************

    def getAttributes(self):
        return { 'speed': self.speed }

    # ***** setter **********************************

    def setAttributes(self, attributes):
        if self.isset(attributes, 'speed'):
            speed = self.saveIntConvert(attributes['speed'])
            if speed >= 0:
                self.speed = speed
                self.start()
Example #12
0
class ColorChange(IssetHelper):
    def __init__(self, device):
        # initializations
        self.device = device
        self.colors = ColorController
        self.colorCalculator = ColorCalculator()
        self.hueAdditionPerFrame = 0.0

        # animation settings
        self.currentHueAddition = 0.0
        self.speed = 10

    def start(self):
        self.hueAdditionPerFrame = 0.00001 * (self.speed + 1)

    def renderNextFrame(self):
        (currentHue, saturation, lightness) = self.colors.getBasisColorAsHsl()
        targetHue = self.colorCalculator.correctHueValue(
            currentHue + self.hueAdditionPerFrame)

        self.colors.setBasisColorAsHsl(targetHue, saturation, lightness)
        (r, g, b) = self.colors.getBasisColorAsRgb()
        self.device.setRgbToBuffer(r, g, b)

    # ***** getter **********************************

    def getAttributes(self):
        return {'speed': self.speed}

    # ***** setter **********************************

    def setAttributes(self, attributes):
        if self.isset(attributes, 'speed'):
            speed = self.saveIntConvert(attributes['speed'])
            if speed >= 0:
                self.speed = speed
                self.start()
Example #13
0
class RandomGlowAnimation(IssetHelper):
    def __init__(self, device):
        # animation settings
        self.glowingPixelCount = 17
        self.glowingPixelDegreeOfColorDivergence = 35
        self.minimumSpeed = 50

        # initializations
        self.colorCalculator = ColorCalculator()
        self.colors = ColorController
        self.device = device
        self.randomGlowingPixels = {}
        self.sinFactorForHueAddition = 0

    def start(self):
        # precalculate factor needed for every iteration
        self.sinFactorForHueAddition = (
            (self.glowingPixelDegreeOfColorDivergence / 360) / 2)

        # initialize glowing pixels list
        for i in range(0, self.glowingPixelCount):
            self.randomGlowingPixels[i] = self.initializeRandomPixel()

    def renderNextFrame(self):
        for i in range(0, self.glowingPixelCount):
            glowingPixel = self.randomGlowingPixels[i]
            glowingPixel['xAxisPosition'] = glowingPixel['xAxisPosition'] + 1

            if (glowingPixel['xAxisPosition'] /
                    glowingPixel['speedFactor']) > (math.pi * 2):
                self.randomGlowingPixels[i] = self.initializeRandomPixel()
            else:
                # calculate new hue and lightness for current frame
                (hueAddition, lightnessFactor) = self.getColorForIteration(
                    glowingPixel['xAxisPosition'], glowingPixel['speedFactor'])
                targetHue = self.colors.basisHue + hueAddition
                targetLightness = self.colors.basisLightness * lightnessFactor

                # apply new hue and lightness to frame-buffer
                (r, g, b) = self.colorCalculator.convertHslToRgb(
                    targetHue, self.colors.basisSaturation, targetLightness)
                self.device.setRgbColorToBufferForLedWithIndex(
                    r, g, b, glowingPixel['index'])

    def getColorForIteration(self, xAxisPosition, speedFactor):
        sinus = math.sin(xAxisPosition / speedFactor)

        hueAddition = sinus * self.sinFactorForHueAddition
        # probably manipulate this value to make more beautiful light
        lightnessFactor = sinus * 0.5 + 0.5

        return (hueAddition, lightnessFactor)

    def initializeRandomPixel(self):
        randomIndex = random.randint(0, self.device.getNumberOfLeds() - 1)
        if not self.pixelIndexIsUsed(randomIndex):

            # set basis color to pixel
            # self.device.setRgbColorToBufferForLedWithIndex(self.colors.getBasisColorAsRgb(), randomIndex)

            # instantiate new pixel values for iterative color calculation
            speedFactor = random.randint(
                self.minimumSpeed, self.minimumSpeed * SPEED_MULTIPLICATOR)
            return {
                'index': randomIndex,
                'xAxisPosition': 0,
                'speedFactor': speedFactor
            }
        else:
            return self.initializeRandomPixel()

    def pixelIndexIsUsed(self, index):
        if self.randomGlowingPixels == {}:
            return False

        for pixel in self.randomGlowingPixels:
            try:
                if pixel['index'] == index:
                    return True
            except (TypeError):
                return False
        return False

    # ***** getter **********************************

    def getAttributes(self):
        return {
            'pixelCount': self.glowingPixelCount,
            'speed': self.minimumSpeed,
            'oscillation': self.glowingPixelDegreeOfColorDivergence
        }

    # ***** setter **********************************

    def setAttributes(self, attributes):
        recalculationRequired = False

        if self.isset(attributes, 'pixelCount'):
            pixelCount = self.saveIntConvert(attributes['pixelCount'])
            if pixelCount > 0:
                self.glowingPixelCount = pixelCount
                recalculationRequired = True
        if self.isset(attributes, 'speed'):
            speed = self.saveIntConvert(attributes['speed'])
            if speed >= 0:
                self.minimumSpeed = speed
        if self.isset(attributes, 'oscillation'):
            oscillation = self.saveIntConvert(attributes['oscillation'])
            if oscillation >= 0 and oscillation <= 360:
                self.glowingPixelDegreeOfColorDivergence = oscillation
                recalculationRequired = True

        if recalculationRequired:
            self.start()
Example #14
0
class RandomGlowAnimation(IssetHelper):

    def __init__(self, device):
        # animation settings
        self.glowingPixelCount = 17
        self.glowingPixelDegreeOfColorDivergence = 35
        self.minimumSpeed = 50

        # initializations
        self.colorCalculator = ColorCalculator()
        self.colors = ColorController
        self.device = device
        self.randomGlowingPixels = {}
        self.sinFactorForHueAddition = 0

    def start(self):
        # precalculate factor needed for every iteration
        self.sinFactorForHueAddition = (
            (self.glowingPixelDegreeOfColorDivergence / 360) / 2)

        # initialize glowing pixels list
        for i in range(0, self.glowingPixelCount):
            self.randomGlowingPixels[i] = self.initializeRandomPixel()

    def renderNextFrame(self):
        for i in range(0, self.glowingPixelCount):
            glowingPixel = self.randomGlowingPixels[i]
            glowingPixel['xAxisPosition'] = glowingPixel['xAxisPosition'] + 1

            if (glowingPixel['xAxisPosition'] / glowingPixel['speedFactor']) > (math.pi * 2):
                self.randomGlowingPixels[i] = self.initializeRandomPixel()
            else:
                # calculate new hue and lightness for current frame
                (hueAddition, lightnessFactor) = self.getColorForIteration(
                    glowingPixel['xAxisPosition'], glowingPixel['speedFactor'])
                targetHue = self.colors.basisHue + hueAddition
                targetLightness = self.colors.basisLightness * lightnessFactor

                # apply new hue and lightness to frame-buffer
                (r, g, b) = self.colorCalculator.convertHslToRgb(
                    targetHue, self.colors.basisSaturation, targetLightness)
                self.device.setRgbColorToBufferForLedWithIndex(
                    r, g, b, glowingPixel['index'])

    def getColorForIteration(self, xAxisPosition, speedFactor):
        sinus = math.sin(xAxisPosition / speedFactor)

        hueAddition = sinus * self.sinFactorForHueAddition
        # probably manipulate this value to make more beautiful light
        lightnessFactor = sinus * 0.5 + 0.5

        return (hueAddition, lightnessFactor)

    def initializeRandomPixel(self):
        randomIndex = random.randint(0, self.device.getNumberOfLeds() - 1)
        if not self.pixelIndexIsUsed(randomIndex):

            # set basis color to pixel
            # self.device.setRgbColorToBufferForLedWithIndex(self.colors.getBasisColorAsRgb(), randomIndex)

            # instantiate new pixel values for iterative color calculation
            speedFactor = random.randint(
                self.minimumSpeed, self.minimumSpeed * SPEED_MULTIPLICATOR)
            return {
                'index': randomIndex,
                'xAxisPosition': 0,
                'speedFactor': speedFactor
            }
        else:
            return self.initializeRandomPixel()

    def pixelIndexIsUsed(self, index):
        if self.randomGlowingPixels == {}:
            return False

        for pixel in self.randomGlowingPixels:
            try:
                if pixel['index'] == index:
                    return True
            except (TypeError):
                return False
        return False

    # ***** getter **********************************

    def getAttributes(self):
        return {
            'pixelCount': self.glowingPixelCount,
            'speed': self.minimumSpeed,
            'oscillation': self.glowingPixelDegreeOfColorDivergence
        }

    # ***** setter **********************************

    def setAttributes(self, attributes):
        recalculationRequired = False

        if self.isset(attributes, 'pixelCount'):
            pixelCount = self.saveIntConvert(attributes['pixelCount'])
            if pixelCount > 0:
                self.glowingPixelCount = pixelCount
                recalculationRequired = True
        if self.isset(attributes, 'speed'):
            speed = self.saveIntConvert(attributes['speed'])
            if speed >= 0:
                self.minimumSpeed = speed
        if self.isset(attributes, 'oscillation'):
            oscillation = self.saveIntConvert(attributes['oscillation'])
            if oscillation >= 0 and oscillation <= 360:
                self.glowingPixelDegreeOfColorDivergence = oscillation
                recalculationRequired = True

        if recalculationRequired:
            self.start()
class DeviceController:

    def __init__(self, verbose, showUpdates):
        # initializations
        self.beVerbose = verbose
        self.dryRun = False
        self.colorCalculator = ColorCalculator()
        self.deviceConnected = False
        self.currentFrameCount = 0
        self.targetTimePerFrame = 0.0
        self.updateFrameTimestamp = datetime.datetime.now()
        self.asyncUpdateRateController = AsyncUpdateRateController(
            self, showUpdates)
        self.pixelMap = [
            42, 43, 44, 45, 46, 47, 48, 41, 20, 21, 22, 23, 24, 25, 40, 19, 18, 17,
            16, 15, 26, 39, 10, 11, 12, 13, 14, 27, 38, 9, 8, 7, 6, 5, 28, 37, 0, 1,
            2, 3, 4, 29, 36, 35, 34, 33, 32, 31, 30
        ]

        # establish connection to device
        try:
            if not self.dryRun:
                self.serialConnection = serial.Serial(
                    DEVICE_FILE, DEVICE_BAUDRATE)
            self.deviceConnected = True
        except serial.SerialException:
            print('can not connect to the Arduino; going on as dry run')
            self.dryRun = True

        # build header for buffer
        # unsigned char array, will transfered serially to the device
        self.buffer = array('B')
        # ASCII for 'A'; magic number
        self.buffer.append(65)
        # ASCII for 'd'; magic number
        self.buffer.append(100)
        # ASCII for 'a'; magic number
        self.buffer.append(97)
        # LED count high byte
        self.buffer.append((NUMBER_LEDS - 1) >> 8)
        # LED count low byte
        self.buffer.append((NUMBER_LEDS - 1) & 0xff)
        # checksum
        self.buffer.append((NUMBER_LEDS - 1) >> 8 ^ (NUMBER_LEDS - 1) & 0xff ^ 0x55)
        for _ in range(0, (NUMBER_LEDS * 3)):
            # fill up every channel of every LED with zeros
            self.buffer.append(255)

        # calculate max. useful frame rate which the serial bus can handle
        targetFPS = (DEVICE_BAUDRATE / 8) / sys.getsizeof(self.buffer)
        self.targetTimePerFrame = 1.0 / targetFPS

        # wait for initialization
        if not self.dryRun:
            if self.beVerbose:
                print('wait for Arduino to be initialized')
            sleep(5)

        # start frame rate controller
        self.asyncUpdateRateController.start()

    # ***** controller handling **********************************
    def writeBuffer(self):
        if self.deviceConnected:
            # write to serial port
            if not self.dryRun:
                try:
                    self.serialConnection.flushOutput()
                    self.serialConnection.write(bytearray(self.buffer))
                except serial.SerialException:
                    exc_type, _, exc_tb = sys.exc_info()
                    fname = os.path.split(exc_tb.tb_frame.f_code.co_filename)[1]
                    print('\n', exc_type, fname, exc_tb.tb_lineno,
                          '\nerror sending data to device! closing connection')
                    self.closeConnection()
                    exit()

        # increment counter for FPS calculation
        self.currentFrameCount = self.currentFrameCount + 1

        # limit the frame rate to what the serial connection is capable of
        self.frameRateLimiter()

    def frameRateLimiter(self):
        # measure current time
        currentTimestamp = datetime.datetime.now()
        updateFrameTimeDelta = currentTimestamp - self.updateFrameTimestamp
        self.updateFrameTimestamp = datetime.datetime.now()
        frameCalculationTime = updateFrameTimeDelta.microseconds / 1000000

        if frameCalculationTime > self.targetTimePerFrame:
            return

        compensateTime = self.targetTimePerFrame - frameCalculationTime
        sleep(compensateTime)

    def closeConnection(self):
        self.deviceConnected = False
        if not self.dryRun:
            self.serialConnection.close()
        if self.beVerbose:
            print('serial connection closed')

    def clearBuffer(self):
        for i in range(6, 6 + (NUMBER_LEDS * 3)):
            self.buffer[i] = 0

    # ***** getters **********************************
    def getNumberOfLeds(self):
        return NUMBER_LEDS

    def getCurrentFps(self):
        return self.asyncUpdateRateController.currentFPS

    def getRgbFromBufferWithIndex(self, index):
        bufferIndex = 6 + (index * 3)

        redChannel = self.buffer[bufferIndex]
        greenChannel = self.buffer[bufferIndex + 1]
        blueChannel = self.buffer[bufferIndex + 2]

        return (redChannel, greenChannel, blueChannel)

    def getRgbFromBufferWithCoordinates(self, xIndex, yIndex):
        return self.getRgbFromBufferWithIndex(xIndex + (yIndex * NUMBER_LED_ROWS))

    # ***** setters **********************************
    def setRgbColorToBufferForLedWithIndex(self, redChannel, greenChannel, blueChannel, ledIndex):
        ledAddress = 6 + (ledIndex * 3)
        self.buffer[ledAddress] = self.colorCalculator.frameRgbValue(
            redChannel)
        self.buffer[
            ledAddress + 1] = self.colorCalculator.frameRgbValue(greenChannel)
        self.buffer[
            ledAddress + 2] = self.colorCalculator.frameRgbValue(blueChannel)

    def setRgbColorToBufferForLedWithCoordinates(self, redChannel, greenChannel, blueChannel, xIndex, yIndex):
        alignedIndex = xIndex + (yIndex * NUMBER_LED_ROWS)
        self.setRgbColorToBufferForLedWithIndex(
            redChannel, greenChannel, blueChannel, self.pixelMap[alignedIndex]
        )

    def setRgbToBuffer(self, redChannel, greenChannel, blueChannel):
        for i in range(6, (NUMBER_LEDS * 3 + 6), 3):
            self.buffer[i] = self.colorCalculator.frameRgbValue(redChannel)
            self.buffer[
                i + 1] = self.colorCalculator.frameRgbValue(greenChannel)
            self.buffer[
                i + 2] = self.colorCalculator.frameRgbValue(blueChannel)
Example #16
0
class _ColorController:
    def __call__(self):
        return self

    def __init__(self):
        # initializations
        self.device = None
        self.colorCalculator = ColorCalculator()
        self.basisColor = ORANGE
        self.binaryClockColor = WHITE
        self.basisLightness = 0.50
        self.binaryClockLightness = 1

        # value predefinitions
        self.basisHue = 0
        self.basisSaturation = 1
        self.basisRedChannel = 0
        self.basisGreenChannel = 0
        self.basisBlueChannel = 0
        self.binaryClockColorRedChannel = 0
        self.binaryClockColorGreenChannel = 0
        self.binaryClockColorBlueChannel = 0

        # calculate variations of initial color
        self.calculateVariationsOfBasisValues()

    def setDeviceReference(self, device):
        self.device = device

    # ***** value calculation **********************************
    def calculateVariationsOfBasisValues(self):
        self.calculateBasisColorValuesFomHex()
        self.calculateBinaryClockColorValuesFromHex()

    def calculateBasisColorValuesFomHex(self):
        (bHue, bSaturation,
         bLightness) = self.colorCalculator.convertHexColorToHSL(
             self.basisColor)
        (bR, bG,
         bB) = self.colorCalculator.convertHexColorToRgb(self.basisColor)
        self.basisHue = bHue
        self.basisSaturation = bSaturation
        self.basisLightness = bLightness
        self.basisRedChannel = bR
        self.basisGreenChannel = bG
        self.basisBlueChannel = bB

    def calculateBasisColorValuesFomRgb(self):
        self.basisColor = self.colorCalculator.convertRgbToHexColor(
            self.basisRedChannel, self.basisGreenChannel,
            self.basisBlueChannel)
        (bHue, bSaturation, bLightness) = self.colorCalculator.convertRgbToHsl(
            self.basisRedChannel, self.basisGreenChannel,
            self.basisBlueChannel)
        self.basisHue = bHue
        self.basisSaturation = bSaturation
        self.basisLightness = bLightness

    def calculateBasisColorValuesFomHsl(self):
        (bR, bG,
         bB) = self.colorCalculator.convertHslToRgb(self.basisHue,
                                                    self.basisSaturation,
                                                    self.basisLightness)
        self.basisColor = self.colorCalculator.convertRgbToHexColor(bR, bG, bB)
        self.basisRedChannel = bR
        self.basisGreenChannel = bG
        self.basisBlueChannel = bB

    def calculateBinaryClockColorValuesFromHex(self):
        (r, g,
         b) = self.colorCalculator.convertHexColorToRgb(self.binaryClockColor)
        self.binaryClockColorRedChannel = r
        self.binaryClockColorGreenChannel = g
        self.binaryClockColorBlueChannel = b

    def calculateBinaryClockColorValuesFomRgb(self):
        self.binaryClockColor = self.colorCalculator.convertRgbToHexColor(
            self.binaryClockColorRedChannel, self.binaryClockColorGreenChannel,
            self.binaryClockColorBlueChannel)

    # ***** getter **********************************
    def getBasisColorAsHex(self):
        return self.colorCalculator.getHtmlHexStringFromRgbColor(
            self.basisRedChannel, self.basisGreenChannel,
            self.basisBlueChannel)

    def getBasisColorAsRgb(self):
        return (self.basisRedChannel, self.basisGreenChannel,
                self.basisBlueChannel)

    def getBasisColorAsHsl(self):
        return (self.basisHue, self.basisSaturation, self.basisLightness)

    def getBasisLightness(self):
        return self.basisLightness

    def getTotalLightness(self):
        numberOfLeds = self.device.getNumberOfLeds()
        totalLightness = 0

        for i in range(0, numberOfLeds):
            r, g, b = self.device.getRgbFromBufferWithIndex(i)
            totalLightness += self.colorCalculator.convertRgbToLightness(
                r, g, b)

        return totalLightness / numberOfLeds

    # ***** setter **********************************
    def setBasisColorAsHex(self, hexColor):
        self.basisColor = hexColor
        self.calculateBasisColorValuesFomHex()

    def setBasisColorAsRgb(self, redChannel, greenChannel, blueChannel):
        self.basisRedChannel = redChannel
        self.basisGreenChannel = greenChannel
        self.basisBlueChannel = blueChannel
        self.calculateBasisColorValuesFomRgb()

    def setBasisColorAsHsl(self, hue, saturation, lightness):
        self.basisHue = hue
        self.basisSaturation = saturation
        self.basisLightness = lightness
        self.calculateBasisColorValuesFomHsl()

    def setBinaryClockColorAsHex(self, hexColor):
        self.binaryClockColor = hexColor
        self.calculateBinaryClockColorValuesFromHex()

    def setBinaryClockColorAsRgb(self, redChannel, greenChannel, blueChannel):
        self.binaryClockColorRedChannel = redChannel
        self.binaryClockColorGreenChannel = greenChannel
        self.binaryClockColorBlueChannel = blueChannel
        self.calculateBinaryClockColorValuesFomRgb()

    def setBasisLightness(self, lightness):
        if lightness > 1:
            lightness = 1
        elif lightness < 0:
            lightness = 0

        self.basisLightness = lightness
        self.setBasisColorAsHsl(self.basisHue, self.basisSaturation, lightness)

    def setBinaryClockLightness(self, lightness):
        if lightness > 1:
            lightness = 1
        elif lightness < 0:
            lightness = 0

        self.binaryClockLightness = lightness
        self.setBinaryClockColorAsHex(
            self.colorCalculator.setBrightnessToHexColor(
                self.binaryClockColor, lightness))
class DeviceController:
    def __init__(self, verbose, showUpdates):
        # initializations
        self.beVerbose = verbose
        self.dryRun = False
        self.colorCalculator = ColorCalculator()
        self.deviceConnected = False
        self.currentFrameCount = 0
        self.targetTimePerFrame = 0.0
        self.updateFrameTimestamp = datetime.datetime.now()
        self.asyncUpdateRateController = AsyncUpdateRateController(
            self, showUpdates)
        self.pixelMap = [
            42, 43, 44, 45, 46, 47, 48, 41, 20, 21, 22, 23, 24, 25, 40, 19, 18,
            17, 16, 15, 26, 39, 10, 11, 12, 13, 14, 27, 38, 9, 8, 7, 6, 5, 28,
            37, 0, 1, 2, 3, 4, 29, 36, 35, 34, 33, 32, 31, 30
        ]

        # establish connection to device
        try:
            if not self.dryRun:
                self.serialConnection = serial.Serial(DEVICE_FILE,
                                                      DEVICE_BAUDRATE)
            self.deviceConnected = True
        except serial.SerialException:
            print('can not connect to the Arduino; going on as dry run')
            self.dryRun = True

        # build header for buffer
        # unsigned char array, will transfered serially to the device
        self.buffer = array('B')
        # ASCII for 'A'; magic number
        self.buffer.append(65)
        # ASCII for 'd'; magic number
        self.buffer.append(100)
        # ASCII for 'a'; magic number
        self.buffer.append(97)
        # LED count high byte
        self.buffer.append((NUMBER_LEDS - 1) >> 8)
        # LED count low byte
        self.buffer.append((NUMBER_LEDS - 1) & 0xff)
        # checksum
        self.buffer.append((NUMBER_LEDS - 1) >> 8 ^ (NUMBER_LEDS - 1) & 0xff
                           ^ 0x55)
        for _ in range(0, (NUMBER_LEDS * 3)):
            # fill up every channel of every LED with zeros
            self.buffer.append(255)

        # calculate max. useful frame rate which the serial bus can handle
        targetFPS = (DEVICE_BAUDRATE / 8) / sys.getsizeof(self.buffer)
        self.targetTimePerFrame = 1.0 / targetFPS

        # wait for initialization
        if not self.dryRun:
            if self.beVerbose:
                print('wait for Arduino to be initialized')
            sleep(5)

        # start frame rate controller
        self.asyncUpdateRateController.start()

    # ***** controller handling **********************************
    def writeBuffer(self):
        if self.deviceConnected:
            # write to serial port
            if not self.dryRun:
                try:
                    self.serialConnection.flushOutput()
                    self.serialConnection.write(bytearray(self.buffer))
                except serial.SerialException:
                    exc_type, _, exc_tb = sys.exc_info()
                    fname = os.path.split(
                        exc_tb.tb_frame.f_code.co_filename)[1]
                    print(
                        '\n', exc_type, fname, exc_tb.tb_lineno,
                        '\nerror sending data to device! closing connection')
                    self.closeConnection()
                    exit()

        # increment counter for FPS calculation
        self.currentFrameCount = self.currentFrameCount + 1

        # limit the frame rate to what the serial connection is capable of
        self.frameRateLimiter()

    def frameRateLimiter(self):
        # measure current time
        currentTimestamp = datetime.datetime.now()
        updateFrameTimeDelta = currentTimestamp - self.updateFrameTimestamp
        self.updateFrameTimestamp = datetime.datetime.now()
        frameCalculationTime = updateFrameTimeDelta.microseconds / 1000000

        if frameCalculationTime > self.targetTimePerFrame:
            return

        compensateTime = self.targetTimePerFrame - frameCalculationTime
        sleep(compensateTime)

    def closeConnection(self):
        self.deviceConnected = False
        if not self.dryRun:
            self.serialConnection.close()
        if self.beVerbose:
            print('serial connection closed')

    def clearBuffer(self):
        for i in range(6, 6 + (NUMBER_LEDS * 3)):
            self.buffer[i] = 0

    # ***** getters **********************************
    def getNumberOfLeds(self):
        return NUMBER_LEDS

    def getCurrentFps(self):
        return self.asyncUpdateRateController.currentFPS

    def getRgbFromBufferWithIndex(self, index):
        bufferIndex = 6 + (index * 3)

        redChannel = self.buffer[bufferIndex]
        greenChannel = self.buffer[bufferIndex + 1]
        blueChannel = self.buffer[bufferIndex + 2]

        return (redChannel, greenChannel, blueChannel)

    def getRgbFromBufferWithCoordinates(self, xIndex, yIndex):
        return self.getRgbFromBufferWithIndex(xIndex +
                                              (yIndex * NUMBER_LED_ROWS))

    # ***** setters **********************************
    def setRgbColorToBufferForLedWithIndex(self, redChannel, greenChannel,
                                           blueChannel, ledIndex):
        ledAddress = 6 + (ledIndex * 3)
        self.buffer[ledAddress] = self.colorCalculator.frameRgbValue(
            redChannel)
        self.buffer[ledAddress +
                    1] = self.colorCalculator.frameRgbValue(greenChannel)
        self.buffer[ledAddress +
                    2] = self.colorCalculator.frameRgbValue(blueChannel)

    def setRgbColorToBufferForLedWithCoordinates(self, redChannel,
                                                 greenChannel, blueChannel,
                                                 xIndex, yIndex):
        alignedIndex = xIndex + (yIndex * NUMBER_LED_ROWS)
        self.setRgbColorToBufferForLedWithIndex(redChannel, greenChannel,
                                                blueChannel,
                                                self.pixelMap[alignedIndex])

    def setRgbToBuffer(self, redChannel, greenChannel, blueChannel):
        for i in range(6, (NUMBER_LEDS * 3 + 6), 3):
            self.buffer[i] = self.colorCalculator.frameRgbValue(redChannel)
            self.buffer[i +
                        1] = self.colorCalculator.frameRgbValue(greenChannel)
            self.buffer[i +
                        2] = self.colorCalculator.frameRgbValue(blueChannel)
Example #18
0
class PulsingCircleAnimation(IssetHelper):
    def __init__(self, device):
        # animation settings
        self.centerPositionX = 1
        self.centerPositionY = 5
        self.degreeOfColorDivergence = 30
        self.distanceToDarkness = 3
        self.speed = 0.01
        self.iterationStep = 0

        # initializations
        self.colorCalculator = ColorCalculator()
        self.colors = ColorController
        self.device = device
        self.degreeFactor = 0

        # construct array of precalculated values
        self.sinSummands = [
            [0.0 for x in range(self.device.getNumberOfLeds())] for x in range(self.device.getNumberOfLeds())
        ]

    def start(self):
        # precalculated values
        self.degreeFactor = (self.degreeOfColorDivergence / 360) / 2

        # calculate values for each pixel position
        for i in range(0, self.device.getNumberOfLeds()):
            for j in range(0, self.device.getNumberOfLeds()):
                x = i - self.centerPositionX
                y = j - self.centerPositionY
                self.sinSummands[i][j] = (math.sqrt((x * x) + (y * y)) * math.pi) / self.distanceToDarkness

    def renderNextFrame(self):
        # handle iteration counting and limit it to maxint
        if self.iterationStep < MAX_INT:
            self.iterationStep = self.iterationStep + 1
        else:
            self.iterationStep = 0

        for x in range(0, 7):
            for y in range(0, 7):
                # calculate new hue and lightness for current frame
                (hueAddition, lightnessFactor) = self.getColorForCoordinates(x, y)
                targetHue = self.colors.basisHue + hueAddition
                targetLightness = self.colors.basisLightness * lightnessFactor

                # apply new hue and lightness to frame-buffer
                (r, g, b) = self.colorCalculator.convertHslToRgb(
                    targetHue, self.colors.basisSaturation, targetLightness
                )
                self.device.setRgbColorToBufferForLedWithCoordinates(r, g, b, x, y)

    # ***** getter **********************************

    def getColorForCoordinates(self, x, y):
        intensity = math.sin(self.sinSummands[x][y] - (self.iterationStep * self.speed))

        newHue = intensity * self.degreeFactor
        newLightness = (intensity * 0.5) + 0.5
        return (newHue, newLightness)

    def getAttributes(self):
        return {
            "size": self.distanceToDarkness,
            "speed": self.speed,
            "oscillation": self.degreeOfColorDivergence,
            "posX": self.centerPositionX,
            "posY": self.centerPositionY,
        }

    # ***** setter **********************************

    def setAttributes(self, attributes):
        recalculationRequired = False

        if self.isset(attributes, "size"):
            size = self.saveFloatConvert(attributes["size"])
            if size > 0:
                self.distanceToDarkness = size
                recalculationRequired = True
        if self.isset(attributes, "speed"):
            speed = self.saveFloatConvert(attributes["speed"])
            if speed >= 0:
                self.speed = speed
        if self.isset(attributes, "oscillation"):
            oscillation = self.saveIntConvert(attributes["oscillation"])
            if oscillation >= 0 and oscillation <= 360:
                self.degreeOfColorDivergence = oscillation
                recalculationRequired = True
        if self.isset(attributes, "posX"):
            posX = self.saveFloatConvert(attributes["posX"])
            if posX >= 0 and posX <= 6:
                self.centerPositionX = posX
                recalculationRequired = True
        if self.isset(attributes, "posY"):
            posY = self.saveFloatConvert(attributes["posY"])
            if posY >= 0 and posY <= 6:
                self.centerPositionY = posY
                recalculationRequired = True

        if recalculationRequired:
            self.start()
Example #19
0
class _ColorController:
    def __call__(self):
        return self

    def __init__(self):
        # initializations
        self.device = None
        self.colorCalculator = ColorCalculator()
        self.basisColor = ORANGE
        self.binaryClockColor = WHITE
        self.basisLightness = 0.50
        self.binaryClockLightness = 1

        # value predefinitions
        self.basisHue = 0
        self.basisSaturation = 1
        self.basisRedChannel = 0
        self.basisGreenChannel = 0
        self.basisBlueChannel = 0
        self.binaryClockColorRedChannel = 0
        self.binaryClockColorGreenChannel = 0
        self.binaryClockColorBlueChannel = 0

        # calculate variations of initial color
        self.calculateVariationsOfBasisValues()

    def setDeviceReference(self, device):
        self.device = device

    # ***** value calculation **********************************
    def calculateVariationsOfBasisValues(self):
        self.calculateBasisColorValuesFomHex()
        self.calculateBinaryClockColorValuesFromHex()

    def calculateBasisColorValuesFomHex(self):
        (bHue, bSaturation, bLightness) = self.colorCalculator.convertHexColorToHSL(self.basisColor)
        (bR, bG, bB) = self.colorCalculator.convertHexColorToRgb(self.basisColor)
        self.basisHue = bHue
        self.basisSaturation = bSaturation
        self.basisLightness = bLightness
        self.basisRedChannel = bR
        self.basisGreenChannel = bG
        self.basisBlueChannel = bB

    def calculateBasisColorValuesFomRgb(self):
        self.basisColor = self.colorCalculator.convertRgbToHexColor(self.basisRedChannel, self.basisGreenChannel, self.basisBlueChannel)
        (bHue, bSaturation, bLightness) = self.colorCalculator.convertRgbToHsl(self.basisRedChannel, self.basisGreenChannel, self.basisBlueChannel)
        self.basisHue = bHue
        self.basisSaturation = bSaturation
        self.basisLightness = bLightness

    def calculateBasisColorValuesFomHsl(self):
        (bR, bG, bB) = self.colorCalculator.convertHslToRgb(self.basisHue, self.basisSaturation, self.basisLightness)
        self.basisColor = self.colorCalculator.convertRgbToHexColor(bR, bG, bB)
        self.basisRedChannel = bR
        self.basisGreenChannel = bG
        self.basisBlueChannel = bB

    def calculateBinaryClockColorValuesFromHex(self):
        (r, g, b) = self.colorCalculator.convertHexColorToRgb(self.binaryClockColor)
        self.binaryClockColorRedChannel = r
        self.binaryClockColorGreenChannel = g
        self.binaryClockColorBlueChannel = b

    def calculateBinaryClockColorValuesFomRgb(self):
        self.binaryClockColor = self.colorCalculator.convertRgbToHexColor(self.binaryClockColorRedChannel, self.binaryClockColorGreenChannel, self.binaryClockColorBlueChannel)

    # ***** getter **********************************
    def getBasisColorAsHex(self):
        return self.colorCalculator.getHtmlHexStringFromRgbColor(self.basisRedChannel, self.basisGreenChannel, self.basisBlueChannel)

    def getBasisColorAsRgb(self):
        return (self.basisRedChannel, self.basisGreenChannel, self.basisBlueChannel)

    def getBasisColorAsHsl(self):
        return (self.basisHue, self.basisSaturation, self.basisLightness)

    def getBasisLightness(self):
        return self.basisLightness

    def getTotalLightness(self):
        numberOfLeds = self.device.getNumberOfLeds()
        totalLightness = 0

        for i in range(0, numberOfLeds):
            r, g, b = self.device.getRgbFromBufferWithIndex(i)
            totalLightness += self.colorCalculator.convertRgbToLightness(r, g, b)

        return totalLightness / numberOfLeds

    # ***** setter **********************************
    def setBasisColorAsHex(self, hexColor):
        self.basisColor = hexColor
        self.calculateBasisColorValuesFomHex()

    def setBasisColorAsRgb(self, redChannel, greenChannel, blueChannel):
        self.basisRedChannel = redChannel
        self.basisGreenChannel = greenChannel
        self.basisBlueChannel = blueChannel
        self.calculateBasisColorValuesFomRgb()

    def setBasisColorAsHsl(self, hue, saturation, lightness):
        self.basisHue = hue
        self.basisSaturation = saturation
        self.basisLightness = lightness
        self.calculateBasisColorValuesFomHsl()

    def setBinaryClockColorAsHex(self, hexColor):
        self.binaryClockColor = hexColor
        self.calculateBinaryClockColorValuesFromHex()

    def setBinaryClockColorAsRgb(self, redChannel, greenChannel, blueChannel):
        self.binaryClockColorRedChannel = redChannel
        self.binaryClockColorGreenChannel = greenChannel
        self.binaryClockColorBlueChannel = blueChannel
        self.calculateBinaryClockColorValuesFomRgb()

    def setBasisLightness(self, lightness):
        if lightness > 1:
            lightness = 1
        elif lightness < 0:
            lightness = 0

        self.basisLightness = lightness
        self.setBasisColorAsHsl(self.basisHue, self.basisSaturation, lightness)

    def setBinaryClockLightness(self, lightness):
        if lightness > 1:
            lightness = 1
        elif lightness < 0:
            lightness = 0

        self.binaryClockLightness = lightness
        self.setBinaryClockColorAsHex(self.colorCalculator.setBrightnessToHexColor(self.binaryClockColor, lightness))
Example #20
0
class PulsingCircleAnimation(IssetHelper):
    def __init__(self, device):
        # animation settings
        self.centerPositionX = 1
        self.centerPositionY = 5
        self.degreeOfColorDivergence = 30
        self.distanceToDarkness = 3
        self.speed = 0.01
        self.iterationStep = 0

        # initializations
        self.colorCalculator = ColorCalculator()
        self.colors = ColorController
        self.device = device
        self.degreeFactor = 0

        # construct array of precalculated values
        self.sinSummands = [[
            0.0 for x in range(self.device.getNumberOfLeds())
        ] for x in range(self.device.getNumberOfLeds())]

    def start(self):
        # precalculated values
        self.degreeFactor = ((self.degreeOfColorDivergence / 360) / 2)

        # calculate values for each pixel position
        for i in range(0, self.device.getNumberOfLeds()):
            for j in range(0, self.device.getNumberOfLeds()):
                x = i - self.centerPositionX
                y = j - self.centerPositionY
                self.sinSummands[i][j] = (math.sqrt((x * x) + (y * y)) *
                                          math.pi) / self.distanceToDarkness

    def renderNextFrame(self):
        # handle iteration counting and limit it to maxint
        if self.iterationStep < MAX_INT:
            self.iterationStep = self.iterationStep + 1
        else:
            self.iterationStep = 0

        for x in range(0, 7):
            for y in range(0, 7):
                # calculate new hue and lightness for current frame
                (hueAddition,
                 lightnessFactor) = self.getColorForCoordinates(x, y)
                targetHue = self.colors.basisHue + hueAddition
                targetLightness = self.colors.basisLightness * lightnessFactor

                # apply new hue and lightness to frame-buffer
                (r, g, b) = self.colorCalculator.convertHslToRgb(
                    targetHue, self.colors.basisSaturation, targetLightness)
                self.device.setRgbColorToBufferForLedWithCoordinates(
                    r, g, b, x, y)

    # ***** getter **********************************

    def getColorForCoordinates(self, x, y):
        intensity = math.sin(self.sinSummands[x][y] -
                             (self.iterationStep * self.speed))

        newHue = intensity * self.degreeFactor
        newLightness = (intensity * 0.5) + 0.5
        return (newHue, newLightness)

    def getAttributes(self):
        return {
            'size': self.distanceToDarkness,
            'speed': self.speed,
            'oscillation': self.degreeOfColorDivergence,
            'posX': self.centerPositionX,
            'posY': self.centerPositionY
        }

    # ***** setter **********************************

    def setAttributes(self, attributes):
        recalculationRequired = False

        if self.isset(attributes, 'size'):
            size = self.saveFloatConvert(attributes['size'])
            if size > 0:
                self.distanceToDarkness = size
                recalculationRequired = True
        if self.isset(attributes, 'speed'):
            speed = self.saveFloatConvert(attributes['speed'])
            if speed >= 0:
                self.speed = speed
        if self.isset(attributes, 'oscillation'):
            oscillation = self.saveIntConvert(attributes['oscillation'])
            if oscillation >= 0 and oscillation <= 360:
                self.degreeOfColorDivergence = oscillation
                recalculationRequired = True
        if self.isset(attributes, 'posX'):
            posX = self.saveFloatConvert(attributes['posX'])
            if posX >= 0 and posX <= 6:
                self.centerPositionX = posX
                recalculationRequired = True
        if self.isset(attributes, 'posY'):
            posY = self.saveFloatConvert(attributes['posY'])
            if posY >= 0 and posY <= 6:
                self.centerPositionY = posY
                recalculationRequired = True

        if recalculationRequired:
            self.start()