|
123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447 |
- import subprocess
- 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
-
- import talkey
-
- # HTTP Server
- from twisted.web import server, resource
- from twisted.internet import reactor
-
- class Simple(resource.Resource):
- isLeaf = True
- def render_GET(self, request):
- statustext = ""
- if inUse:
- statustext = "Disco in use!"
- else:
- statustext = "Ready to Disco!"
- html = '<html><body style="min-height:100vh;display:flex;flex-grow:1;align-items:center;justify-content:center;"><div style="display:flex;font-size:10vw">%s</div></body></html>' % statustext
- return html.encode('utf-8')
-
-
- # GPIO
- pin_kugel = 2
- pin_sun = 4
- pin_pir = 0
- pin_door = 11
-
-
-
- dmxScenes = {
- "fadecolors":[255,255,255,255,255,192],
- "plain-red":[255,255,0,0,0,0],
- "strobe":[190,255,255,255,0,0],
- "nini":[120,0,255,255,0,224],
- "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!",
- "See you later!",
- "This was nice. See you!",
- "Peace!"
- ]
-
- dmxUserScenes = [
- [255,255,255,255,255,192],
- [255,0,180,180,0,0],
- [255,255,0,0,0,0],
- [255,0,255,0,0,0],
- [255,0,0,255,0,0],
- [190,255,255,255,0,0],
- [120,0,255,255,0,224]
- ]
-
- def setDmxScene(scene):
- cv = [0 for v in range(0, 512)]
- errorcode = [240,255,0,0,0,0]
- for index, val in enumerate(dmxScenes.get(scene,errorcode)):
- cv[index] = val
- dev.send_multi_value(1, cv)
-
-
- def setUserDmxScene():
- global dmxScene
- if dmxScene < len(dmxUserScenes)-1:
- dmxScene += 1
- else:
- dmxScene = 0
- cv = [0 for v in range(0, 512)]
- for index, val in enumerate(dmxUserScenes[dmxScene]):
- cv[index] = val
- dev.send_multi_value(1, cv)
-
-
-
- def setKugel(state):
- if state == 'on':
- wiringpi.digitalWrite(pin_kugel, 0)
- if state == 'off':
- wiringpi.digitalWrite(pin_kugel, 1)
-
- def setSun(state):
- if state == 'off':
- wiringpi.digitalWrite(pin_sun, 0)
- if state == 'on':
- wiringpi.digitalWrite(pin_sun, 1)
-
-
-
- def startMusic(playlist, single=False, shuffle=True, repeat=True):
- try:
- client.clear() # clear playlist
- except Exception:
- client.connect("localhost", 6600)
- client.clear() # clear playlist
-
- client.add(playlist) # add file/directory to playlist
- if shuffle:
- client.shuffle() # shuffle playlist
- if repeat:
- client.repeat(1) # set playback mode repeat
- else:
- client.repeat(0) # set playback mode repeat
- if single:
- client.repeat(0) # set playback mode repeat
- client.single(1) # set playback mode single
- else:
- client.single(0) # set playback mode single
- client.setvol(80)# set volume
- client.play() # play
-
- def stopMusic():
- try:
- client.stop()
- except Exception:
- client.connect("localhost", 6600)
- client.stop()
-
- def muteMusic():
- global uservolume
- if getMpdVolume() != 0: # if not muted
- setMpdVolume(0)
- else:
- setMpdVolume(uservolume)
-
-
- def changeVolume(change=5):
- global uservolume
- global volume
- newvol = uservolume + change
- if newvol > 100:
- newvol = 100
- if newvol < 0:
- newvol = 0
-
- try:
- client.setvol(newvol)
- 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')
- setDmxScene('fadecolors')
- setUserDmxScene()
- sleep(0.3)
- 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()
- except Exception:
- client.connect("localhost", 6600)
- currentsong = client.currentsong()
- print(currentsong)
-
- volume = getMpdVolume()
-
- setMpdVolume(10)
- try:
- tts.say(currentsong['artist'] + ', ' + currentsong['title'])
- except Exception:
- tts.say('Willkommen am Discoklo!', 'de')
- setMpdVolume(volume)
-
- def tour():
- tts.say("Hello, I'm Discobert!", "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)
-
-
- def setWorkingMode():
- setSun('on')
- sleep(0.3)
- setKugel('off')
- setDmxScene('black')
- setMode('work')
-
- def startTimeoutCountdown():
- global lastUsed
- global inUse
- tts.say('Timeout in')
- countdown = [5,4,3,2,1] #10,9,8,7,6,
- for sec in countdown:
- tts.say(str(sec))
- sleep(0.5)
- remotesignal = lirc.nextcode()
- if wiringpi.digitalRead(pin_pir) == 1 or remotesignal:
- lastUsed = time.time()
- tts.say('Timeout cancelled!')
- inUse = True
- toilet = lirc.nextcode()
- break
-
- if not inUse:
- tts.say('Shutting down now.', 'en')
- closeService()
-
- def closeService(sleepsecs=0):
- setSun('off')
- sleep(0.3)
- setKugel('off')
- setDmxScene('black')
-
- for x in range(0, 20):
- changeVolume(-5)
- 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()
- if mode is not 'work':
- setWorkingMode()
- else:
- initService()
-
- def doorShutdown():
- tts.say(random.choice(bye_sayings), "en")
- # sleep to give user some time to close the door
- # (pir sensor also stays up for 2 sec)
- closeService(5)
-
- 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')
-
-
-
- dmxScene = 0
- bootstrap()
- dev = pyudmx.uDMXDevice()
- dev.open()
-
- client = mpd.MPDClient()
- client.connect("localhost", 6600)
-
- tts = talkey.Talkey(
- preferred_languages=['en'],
- engine_preference=['pico'],
- )
-
-
- site = server.Site(Simple())
- reactor.listenTCP(8080, site)
- reactor.startRunning(False)
-
-
- lirc.init("disco", "~/discobert/lircrc", blocking=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!")
-
-
- # Main event loop ...
- 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
- else:
- if(time.time() > lastUsed + timeout):
- inUse = False
-
-
-
- remotesignal = lirc.nextcode()
- if remotesignal:
- lastUsed = time.time() # user is active!
- inUse = True
- for code in remotesignal:
- print('received code:', code)
- if(code == "mode_disco"):
- setDiscoMode()
- if(code == "mode_work"):
- setWorkingMode()
- if(code == "mode_power"):
- setOnOff()
- #if(code == "mode_dmx_next"):
-
- if(code == "mode_music_play_1"):
- startMusic('1')
- if(code == "mode_music_play_2"):
- startMusic('2')
- if(code == "mode_music_play_3"):
- startMusic('3')
- if(code == "mode_music_play_4"):
- startMusic('4')
- if(code == "mode_music_play_5"):
- startMusic('5')
- if(code == "mode_play_fm4"):
- startMusic('http://185.85.29.141:8000')
- if(code == "mode_play_oe1"):
- startMusic('http://185.85.29.142:8000')
- if(code == "mode_music_stop"):
- stopMusic()
- if(code == "mode_music_mute"):
- muteMusic()
- if(code == "mode_volume_up"):
- changeVolume(5)
- if(code == "mode_volume_down"):
- 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(timestamp(), "State change inUse:", inUseBefore, inUse)
- if inUse:
- initService()
- else:
- startTimeoutCountdown()
- inUseBefore = inUse
-
- # Webserver
- reactor.iterate()
-
-
- lirc.deinit() # Clean up lirc
-
- dev.close()
|