Page MenuHomec4science

webcontrol.py
No OneTemporary

File Metadata

Created
Thu, Mar 13, 05:22

webcontrol.py

import time
import threading
import subprocess
import bottle
from bottle import route, request, run, template, static_file, redirect
# home page name
SITE_NAME = '/sleepy'
#######################################################################################################
# GLOBALS
DEFAULT_VOLUME = 40
VOLUME_STEP = 5
DEFAULT_HRS = 2
DEFAULT_MINS = 30
# available sound files
AUDIO_DIR = 'audio/'
AUDIO_TYPES = ['wav', 'ogg', 'mp3', ]
sounds = [
{'name': 'space travel', 'file': AUDIO_DIR + 'space_travel.wav'},
{'name': 'brown noise', 'file': AUDIO_DIR + 'brown_noise.wav'},
]
# global status
global_status = {
'home': SITE_NAME,
'title': 'Sleepy Sounds',
'is_playing': False,
'volume': DEFAULT_VOLUME,
'sound': sounds[0]['name'],
'sound_file': sounds[0]['file'],
'hours': DEFAULT_HRS,
'mins': DEFAULT_MINS,
}
# sound process
sound_process = None
# shell scripts
SCRIPT_DIR = 'scripts/'
scripts = {
'PLAY_SOUND': SCRIPT_DIR + 'play_sound.sh',
'STOP_SOUND': SCRIPT_DIR + 'stop_sound.sh',
'SET_VOLUME': SCRIPT_DIR + 'set_volume.sh',
'FADE_OUT': SCRIPT_DIR + 'fade_out.sh',
}
#######################################################################################################
# shutoff timer
def timer_thread_worker():
global global_status
while True:
time.sleep(60)
print global_status
if (global_status['is_playing']):
global_status['mins'] -= 1
if global_status['mins'] < 0:
global_status['hours'] -= 1
if global_status['hours'] < 0:
global_status['mins'] = global_status['hours'] = 0
# stop audio here
audio_toggle(force_off=True)
# timer back to default
global_status['hours'] = DEFAULT_HRS
global_status['mins'] = DEFAULT_MINS
else:
global_status['mins'] = 59
#######################################################################################################
# init: load sounds from files and start timer thread
import glob, os
for ext in AUDIO_TYPES:
files = glob.glob(AUDIO_DIR + '*.' + ext)
for f in files:
name = os.path.basename(f)[:-(len(ext)+1)].replace('_', ' ')
if name not in [i['name'] for i in sounds]:
sounds.append({
'name': name,
'file': f,
})
timer_thread = threading.Thread(target=timer_thread_worker)
timer_thread.start()
#######################################################################################################
# CSS, JS etc
@route(SITE_NAME + '/static/<filepath:path>')
def server_static(filepath):
return static_file(filepath, root='./static')
# main page: start, stop and volume control
@route(SITE_NAME)
@route(SITE_NAME + '/')
def home():
global global_status
return template('home', ctx=global_status)
# set timer
@route(SITE_NAME + '/timer')
def set_timer():
global global_status
return template('timer', ctx=global_status, active='timer')
@route(SITE_NAME + '/set_timer', method='POST')
def set_timer():
global global_status
t = request.forms.get('timer')
if t is not None:
global_status['hours'] = int(t[:2])
global_status['mins'] = int(t[-2:])
return redirect(SITE_NAME)
# select sound
@route(SITE_NAME + '/sound')
def select_sound():
global global_status, sounds
return template('sound', ctx=global_status, sounds=sounds)
@route(SITE_NAME + '/set_sound', method='POST')
def set_sound():
global global_status, sounds
s = request.forms.get('sound')
for item in sounds:
if s == item['name']:
if (global_status['sound'] != s):
# changing sound
global_status['sound'] = s
global_status['sound_file'] = item['file']
# stop audio and reload file
if (global_status['is_playing']):
audio_toggle(force_off=True)
audio_toggle()
return redirect(SITE_NAME)
# turn audio on and off
@route(SITE_NAME + '/onoff')
def audio_toggle(force_off=False):
global global_status, sound_process, scripts
if global_status['is_playing'] or force_off:
# stop
subprocess.call([scripts['STOP_SOUND'], str(sound_process.pid)])
global_status['is_playing'] = False
#volume_change(80)
elif global_status['mins'] + global_status['hours'] > 0:
global_status['is_playing'] = True
if global_status['volume'] > DEFAULT_VOLUME:
volume_change(DEFAULT_VOLUME)
# start audio
kwargs = {'stdin': subprocess.PIPE, 'stdout': subprocess.PIPE, 'stderr': subprocess.PIPE}
sound_process = subprocess.Popen([scripts['PLAY_SOUND'], global_status['sound_file']], **kwargs)
return '1' if global_status['is_playing'] else '0'
# volume changes
@route(SITE_NAME + '/vol/<chg>')
def volume_change(chg):
global global_status
v = global_status['volume']
if chg == 'inc':
v += VOLUME_STEP
if v > 100:
v = 100
elif chg == 'dec':
v -= VOLUME_STEP
if v < 0:
v = 0
elif chg == 'mute':
v = 0
elif chg == 'max':
v = 100
elif chg == 'poll':
return str(v)
else:
v = int(chg)
v = VOLUME_STEP * (v // VOLUME_STEP)
try:
subprocess.Popen(['./scripts/set_volume.sh', str(v)])
except:
pass
try:
v = int(subprocess.check_output(['./scripts/get_volume.sh']))
global_status['volume'] = v
except: #IndexError, AttributeError:
pass
return str(global_status['volume'])
#######################################################################################################
# server
run(host='0.0.0.0', port=8080)
# VM
# run(reloader=True, host='192.168.56.101', port=8000)
#run(host='localhost', port=8000)
# Run bottle internal test server when invoked directly ie: non-uxsgi mode
#if __name__ == '__main__':
# print "running internal server"
#bottle.run(host='0.0.0.0', port=80)
# Run bottle in application mode. Required in order to get the application working with uWSGI!
#else:
# app = application = bottle.default_app()

Event Timeline