/
sandtrails.py
146 lines (119 loc) · 4.75 KB
/
sandtrails.py
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
# Import of standard packages
import logging
import sys
import threading
from datetime import datetime
from subprocess import call # to shut down raspi
# Imports for Flask
from flask import Flask, render_template, request, jsonify
from werkzeug.utils import secure_filename
# Import of own classes
import cfg
from tracks import Tracks
from playlist import Playlist
from hardware import Hardware
from lighting import Lighting, Section
if cfg.val['simulate_led_hw']:
from led_nohw import Leds
else:
from led import Leds
# Initializations
tracks = Tracks("tracks")
playlist = Playlist()
ledHw = Leds(cfg.val['nr_of_leds'])
ledConfig = Lighting(ledHw)
hardware = Hardware(tracks, playlist, ledConfig)
event_start = threading.Event()
event_stop = threading.Event()
event_exit = threading.Event()
# Creating the web server
app = Flask(__name__, template_folder=".", static_folder="assets")
app.config.from_object('config.Config')
log = logging.getLogger('werkzeug')
log.setLevel(logging.ERROR)
# Definition of all the server routings
@app.route('/', methods=['GET', 'POST'])
def index():
return render_template('index.html', **get_dynamic_fields())
@app.route('/status', methods=['GET'])
def status():
# logging.debug('Request for status')
d = dict(status=playlist.get_status_string())
# logging.debug('Status is: ' + str(d))
return jsonify(d)
@app.route('/exit', methods=['POST'])
def exit():
logging.info('Request to exit sandtrails')
event_exit.set()
event_start.clear()
event_stop.clear()
return jsonify(dict(message='Exited sandtrails!'))
@app.route('/shutdown', methods=['POST'])
def shutdown():
logging.info('Request to shut down raspberry pi')
call("sudo shutdown -h now", shell=True)
return jsonify(dict(message='Shutting down rasperry pi...'))
@app.route('/start', methods=['POST'])
def start():
newplaylist = list(filter(None, request.form['newplaylist'].split(';')))
newplaylist_looping = request.form['loop'].lower() == "true"
logging.info('Request to start new playlist: ' + str(newplaylist) + ', looping = ' + str(newplaylist_looping))
playlist.start_new(newplaylist, newplaylist_looping)
event_exit.clear()
event_start.set()
event_stop.clear()
return jsonify(dict(message='Started new playlist: ' + str(newplaylist)))
@app.route('/stop', methods=['POST'])
def stop():
logging.info('Request to stop')
playlist.stop()
event_exit.clear()
event_start.clear()
event_stop.set()
return jsonify(dict(message='Stopping playlist...'))
@app.route('/upload', methods=['POST'])
def upload():
logging.info('Request to upload file')
# check if the post request has the file part
if 'file' not in request.files:
return jsonify(dict(message='Error: No file part!'))
file = request.files['file']
# if user does not select a file, the browser might also submit an empty part without filename
if file.filename == '':
return jsonify(dict(message='Error: No selected file!'))
if file:
tracks.store(file, secure_filename(file.filename))
return jsonify(dict(message='Uploaded file successfully!'))
@app.route('/lighting', methods=['POST'])
def set_lighting():
newcolors = list(filter(None, request.form['newcolors'].split(';')))
logging.info('Request to set lighting: ' + str(newcolors))
sectionList = list()
for color in newcolors:
section = Section.fromHex(color)
sectionList.append(section)
ledConfig.setSectionList(sectionList, True)
return jsonify(dict(message='Lighting set!'))
def get_dynamic_fields():
return dict(tracks=tracks.list(), ledsections=ledConfig.getSectionList())
# Starting the hardware controller loop in a new thread, then run the web server in this thread
if __name__ == '__main__':
msgFormat = "%(asctime)s: %(levelname)s: %(message)s"
dateFormat = "%Y-%m-%d %H:%M:%S"
nameFormat = 'logs/logfile-sandtrails-{:%Y-%m-%d}.log'.format(datetime.now())
logging.basicConfig(filename=nameFormat, level=logging.INFO, format=msgFormat, datefmt=dateFormat)
logging.info("---------------------------------------------------------------")
# logging.basicConfig(level=logging.DEBUG, format=msgFormat, datefmt=dateFormat)
if sys.version_info[0] < 3:
logging.critical("Must use Python 3")
else:
cfg.dump_config_to_log()
ledConfig.init()
mainThread = threading.Thread(name='sandtrailsMain', target=hardware.run,
args=(event_start, event_stop, event_exit))
mainThread.start()
logging.info("Started main sandtrails thread.")
app.run(debug=False, host='0.0.0.0')
# app.run will keep running, never reaching the next two lines:
mainThread.join()
logging.info("Exited cleanly")