diff --git a/disco.service b/disco.service new file mode 100644 index 0000000..9c6f7ba --- /dev/null +++ b/disco.service @@ -0,0 +1,13 @@ +[Unit] +Description=Discobert as a Service +After=multi-user.target + +[Service] +Type=idle +User=pi +ExecStart=/usr/bin/python3 /home/pi/discobert/discobert.py > /home/pi/discobert.log 2>&1 +Restart=always +RestartSec=3 + +[Install] +WantedBy=multi-user.target diff --git a/discobert.py b/discobert.py index fe87d9e..5d0b4f9 100644 --- a/discobert.py +++ b/discobert.py @@ -3,10 +3,11 @@ import sys, inspect, os import wiringpi import time +from datetime import datetime from time import sleep import lirc - +import random import mpd from pyudmx import pyudmx @@ -17,6 +18,7 @@ import talkey pin_kugel = 2 pin_sun = 4 pin_pir = 0 +pin_door = 11 @@ -28,6 +30,22 @@ dmxScenes = { "black":[0,0,0,0,0,0] } +bye_sayings = [ + "Goodbye!", + "Bye!", + "Bye bye!", + "See you!", + #"Ciao!", + "Have a nice day!", + "Thank's for using!", + #"I'm off!", + "Take it easy!", + "I look forward to our next meeting!", + "Take care!", + "Catch you later!", + "Peace!" +] + dmxUserScenes = [ [255,255,255,255,255,192], [255,0,180,180,0,0], @@ -103,37 +121,17 @@ def stopMusic(): client.stop() def muteMusic(): - global volume - global isMuted - - try: - currentvol = int(client.status()['volume']) - except Exception: - client.connect("localhost", 6600) - currentvol = int(client.status()['volume']) - - if currentvol != 0: - volume = currentvol - - if isMuted: - try: - client.setvol(volume) - except Exception: - client.connect("localhost", 6600) - client.setvol(volume) + global uservolume + if getMpdVolume() != 0: # if not muted + setMpdVolume(0) else: - try: - client.setvol(0) - except Exception: - client.connect("localhost", 6600) - client.setvol(0) - isMuted = not isMuted + setMpdVolume(uservolume) + def changeVolume(change=5): + global uservolume global volume - global isMuted - isMuted = False - newvol = volume + change + newvol = uservolume + change if newvol > 100: newvol = 100 if newvol < 0: @@ -144,11 +142,16 @@ def changeVolume(change=5): except Exception: client.connect("localhost", 6600) client.setvol(newvol) + uservolume = newvol volume = newvol + def setMode(string): global mode + global inUse mode = string + if mode == "off": + inUse = False def setDiscoMode(): setKugel('on') @@ -158,6 +161,30 @@ def setDiscoMode(): setSun('off') setMode('disco') +def getMpdVolume(): + try: + vol = int(client.status()['volume']) + except Exception: + client.connect("localhost", 6600) + vol = int(client.status()['volume']) + if vol != 0: #only if not muted + global uservolume + uservolume = vol + return vol + + +def setMpdVolume(vol): + try: + client.setvol(vol) + except Exception: + client.connect("localhost", 6600) + client.setvol(vol) + if vol != 0: #only if not muted + global uservolume + uservolume = vol + return True + + def getTrackInfo(): try: currentsong = client.currentsong() @@ -166,25 +193,28 @@ def getTrackInfo(): currentsong = client.currentsong() print(currentsong) - global volume - try: - currentvol = int(client.status()['volume']) - except Exception: - client.connect("localhost", 6600) - currentvol = int(client.status()['volume']) + volume = getMpdVolume() - changeVolume(-30) + setMpdVolume(10) try: tts.say(currentsong['artist'] + ', ' + currentsong['title']) except Exception: - tts.say('Willkommen am Discoklo!') - client.setvol(currentvol) - volume = currentvol + tts.say('Willkommen am Discoklo!', 'de') + setMpdVolume(volume) def tour(): - tts.say('Willkommen am Discoklo!', 'de') + tts.say("Welcome! To the world of tomorrow!", "en") + sleep(0.3) + tts.say("Press 1 for nice electronic music", "en") + sleep(0.3) + tts.say("Press 2 for hard electronic music", "en") + sleep(0.3) + tts.say("Press 3 for HGichT", "en") + sleep(0.3) + tts.say("Press 4 for a good laugh", "en") + sleep(0.3) + tts.say("Press 5 for more music", "en") sleep(0.3) - tts.say('Willkommen am Discoklo!') def setWorkingMode(): @@ -203,7 +233,6 @@ def startTimeoutCountdown(): tts.say(str(sec)) sleep(0.5) remotesignal = lirc.nextcode() - print(remotesignal) if wiringpi.digitalRead(pin_pir) == 1 or remotesignal: lastUsed = time.time() tts.say('Timeout cancelled!') @@ -212,10 +241,10 @@ def startTimeoutCountdown(): break if not inUse: - tts.say('Shutting down now. Good bye!', 'en') + tts.say('Shutting down now.', 'en') closeService() -def closeService(): +def closeService(sleepsecs=0): setSun('off') sleep(0.3) setKugel('off') @@ -226,18 +255,33 @@ def closeService(): sleep(0.1) stopMusic() setMode('off') + sleep(sleepsecs) def initService(): startMusic('0', True) # start intro music setDiscoMode() + global volume global defaultvolume + global uservolume try: client.setvol(defaultvolume) except Exception: client.connect("localhost", 6600) client.setvol(defaultvolume) + volume = defaultvolume + uservolume = defaultvolume + + global starttime + starttime = time.time() + +def say(text, lang="en"): + originalvol = getMpdVolume() + setMpdVolume(10) + tts.say(text, lang) + setMpdVolume(originalvol) + def setOnOff(): global mode stopMusic() @@ -246,13 +290,19 @@ def setOnOff(): else: initService() +def doorShutdown(): + tts.say(random.choice(bye_sayings), "en") + closeService(4) # sleep to give pir sensor some time + def bootstrap(): wiringpi.wiringPiSetup() wiringpi.pinMode(pin_kugel, 1) # set Relay Disokugel mode to OUTPUT + wiringpi.pinMode(pin_door, 0) # set Circuit Door mode to INPUT wiringpi.pinMode(pin_sun, 1) # set Relay Sun mode to OUTPUT # TODO: Set pin! wiringpi.pinMode(pin_pir, 0) # set PIR Sensor mode to INPUT - +def timestamp(stamp=time.time()): + return datetime.fromtimestamp(stamp).strftime('%Y-%m-%d %H:%M:%S') @@ -270,20 +320,23 @@ tts = talkey.Talkey( ) -pirstate = wiringpi.digitalRead(6) lirc.init("disco", "~/discobert/lircrc", blocking=False) -lastUsed = time.time() -inUse = True -mode = "none" -inUseBefore = True -timeout = 2 * 60 - 10 -defaultvolume = 90 -volume = 90 -isMuted = False +starttime = time.time() # helper for doorshutdown +lastUsed = time.time() # helper for timeout +inUse = False # is toilet in use? +inUseBefore = False # helper to check statechanges +mode = "off" # can be: disco, work, off +timeout = 2 * 60 - 10 # timeout since last user interaction +defaultvolume = 90 # Volume when user enters the toilet +volume = 90 # Global for actual volume +uservolume = 90 # Global for user volume (ignores mute state) + +setSun('off') + +print(timestamp(), "Ready!") -initService() @@ -291,7 +344,17 @@ initService() while True: sleep(0.25) pirstate = wiringpi.digitalRead(pin_pir) + doorstate = wiringpi.digitalRead(pin_door) #print('pirstate: ', pirstate) + + # 0 => door closed + # 1 => door open + if doorstate == 1: + if (time.time() > (starttime + 15) and inUse == True): + doorShutdown() + inUseBefore = False # Pfusch pfusch! + + if pirstate == 1: lastUsed = time.time() inUse = True @@ -299,6 +362,8 @@ while True: if(time.time() > lastUsed + timeout): inUse = False + + remotesignal = lirc.nextcode() if remotesignal: lastUsed = time.time() # user is active! @@ -337,13 +402,15 @@ while True: changeVolume(-5) if(code == "mode_music_info"): getTrackInfo() + if(code == "mode_record"): + say("I'm sorry, I'm afraid I can't do that!") if(code == "mode_home"): tour() if(inUseBefore != inUse): - print("State change inUse:", inUseBefore, inUse) + print(timestamp(), "State change inUse:", inUseBefore, inUse) if inUse: initService() else: diff --git a/lircrc b/lircrc index 7baeade..8b5112f 100644 --- a/lircrc +++ b/lircrc @@ -47,15 +47,14 @@ end begin button = KEY_VOLUMEUP prog = disco - repeat = 100 + repeat = 2 config = mode_volume_up end begin button = KEY_VOLUMEDOWN prog = disco - repeat = 100 - delay = 1 + repeat = 2 config = mode_volume_down end @@ -107,5 +106,5 @@ end begin button = KEY_RECORD prog = disco - config = mode_dmx_next + config = mode_record end