pumpkin/pumpkin.py

185 lines
4.1 KiB
Python

#!/usr/bin/env python3
import _thread
import atexit
import RPi.GPIO as GPIO
import os
from waveloader import WaveLoader
from rgb import RGBMatrix
from rgb import RGB
from subprocess import call
from time import time
from random import randint
class Pumpkin:
def __init__(self, soundpath, GPIOS_RED = [11], GPIOS_GREEN = [12], GPIOS_BLUE = [13], GPIO_TRIGGER = 15, PWM_FREQUENCY = 60):
self.soundfiles = []
self.loadWaveFolder(soundpath)
if len(self.soundfiles) == 0:
raise IOError('No audio files found in ' + soundpath + '!')
GPIO.setmode(GPIO.BOARD)
self.GPIOS_RED = GPIOS_RED
self.GPIOS_GREEN = GPIOS_GREEN
self.GPIOS_BLUE = GPIOS_BLUE
self.GPIO_TRIGGER = GPIO_TRIGGER
self.GPIO_EVAPORATOR = 0
self.GPIO_PUMP = 0
self.GPIO_POWEROFF = 0
self.fogRuntimeMax = 3
GPIO.setup(self.GPIO_TRIGGER, GPIO.IN)
self.rgbControl = RGBMatrix(PWM_FREQUENCY)
for r in self.GPIOS_RED:
self.rgbControl.addRed(r)
for g in self.GPIOS_GREEN:
self.rgbControl.addGreen(g)
for b in self.GPIOS_BLUE:
self.rgbControl.addBlue(b)
self.color = RGB(255, 255, 255)
self.colorBackground = RGB(0, 0, 0)
self.colorFire = RGB(255, 55, 0)
atexit.register(self.cleanup)
def __del__(self):
self.cleanup()
def cleanup(self):
GPIO.cleanup()
def enableFog(self, GPIO_EVAPORATOR, GPIO_PUMP, runtimeSecondsMax = 3):
self.GPIO_EVAPORATOR = GPIO_EVAPORATOR
self.GPIO_PUMP = GPIO_PUMP
self.fogRuntimeMax = runtimeSecondsMax
if self.GPIO_EVAPORATOR != 0:
GPIO.setup(self.GPIO_EVAPORATOR, GPIO.OUT)
if self.GPIO_PUMP != 0:
GPIO.setup(self.GPIO_PUMP, GPIO.OUT)
self.stopFog()
def enablePowerOff(self, GPIO_POWEROFF):
self.GPIO_POWEROFF = GPIO_POWEROFF
if self.GPIO_POWEROFF != 0:
self.powerSwitch = GPIO.setup(self.GPIO_POWEROFF, GPIO.IN)
def loadWaveFolder(self, path):
if not path.endswith('/'):
path += '/'
files = os.listdir(path)
for f in files:
if f.endswith('.wav'):
self.soundfiles.append(path + f)
def lurk(self):
if self.isTurnedOff():
self.poweroff()
self.rgbControl.candle(self.colorFire.r, self.colorFire.g, self.colorFire.b, 0.5)
def speak(self):
self.startFog()
soundfile = self.soundfiles[randint(0, len(self.soundfiles) - 1)]
sound = WaveLoader(soundfile)
duration = sound.frameCount / sound.frameRate
t_now = 0
player = _thread.start_new_thread(call, (['aplay', soundfile],))
t_start = time()
while t_now < duration:
t_now = time() - t_start
amplitude = sound.getCurrentLevelRealtime(t_now)
if amplitude < 0.1:
red = self.colorBackground.r
green = self.colorBackground.g
blue = self.colorBackground.b
else:
amplitude = 1
red = self.color.r * amplitude
green = self.color.g * amplitude
blue = self.color.b * amplitude
self.rgbControl.setColor(red, green, blue)
if t_now > self.fogRuntimeMax:
self.stopFog()
self.stopFog()
def startFog(self):
if self.GPIO_EVAPORATOR != 0:
GPIO.output(self.GPIO_EVAPORATOR, True)
if self.GPIO_PUMP != 0:
GPIO.output(self.GPIO_PUMP, True)
def stopFog(self):
if self.GPIO_EVAPORATOR != 0:
GPIO.output(self.GPIO_EVAPORATOR, False)
if self.GPIO_PUMP != 0:
GPIO.output(self.GPIO_PUMP, False)
def isTriggered(self):
return bool(GPIO.input(self.GPIO_TRIGGER))
def isTurnedOff(self):
if self.GPIO_POWEROFF == 0:
return False
return bool(GPIO.input(self.GPIO_POWEROFF))
def poweroff(self):
call(['poweroff'])
def setAudioColor(self, red, green, blue):
self.color = RGB(red, green, blue)
def setBackgroundColor(self, red, green, blue):
self.colorBackground = RGB(red, green, blue)
def setFireColor(self, red, green, blue):
self.colorFire = RGB(red, green, blue)
def loadAudioFolder(self, path):
if os.path.isdir(path):
if not path.endswith('/'):
path += '/'
for file in os.listdir(path):
if file.endswith('.wav'):
audioFiles.append(audioPath + file)
@staticmethod
def findAudioFiles():
audioFiles = []
for home in os.listdir('/home'):
audioPath = '/home/' + home + '/.config/pumpkin/audio/'
if os.path.isdir(audioPath):
for file in os.listdir(audioPath):
audioFiles.append(audioPath + file)
return audioFiles