Skip to content

Instantly share code, notes, and snippets.

@haveyouwantto
Created May 25, 2023 07:59
Show Gist options
  • Save haveyouwantto/7022e089b049826c3fd08e0e5bba9085 to your computer and use it in GitHub Desktop.
Save haveyouwantto/7022e089b049826c3fd08e0e5bba9085 to your computer and use it in GitHub Desktop.
PicoJMBox for ESP32
import network
import uos
import usocket as socket
import ujson as json
import _thread
from time import sleep_ms
ap = network.WLAN(network.AP_IF)
ap.active(True)
ap.config(essid="PicoJMBox")
print(ap.config('txpower'))
server_info = json.dumps({"capabilities":{"play":False,"midi":True},"themeColor":"#288cd1","serverName":"PicoJMBox (ESP32)"})
def url_decode(s) :
r = str(s).split('%')
try :
b = r[0].encode()
for i in range(1, len(r)) :
try :
b += bytes([int(r[i][:2], 16)]) + r[i][2:].encode()
except :
b += b'%' + r[i].encode()
return b.decode('UTF-8')
except :
return str(s)
# Start the server
def start_server():
server_socket = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
server_socket.bind(('', 80))
server_socket.listen(5)
print("Server started, listening on port 80...")
try:
while True:
try:
client_socket, client_address = server_socket.accept()
_thread.start_new_thread(handle_request, (client_socket,))
sleep_ms(500)
except OSError:
pass
except KeyboardInterrupt:
server_socket.close()
# Handle the HTTP request
def handle_request(client):
request = client.recv(1024)
request_lines = request.decode().split('\r\n')
http = request_lines[0].split(' ')
method, path = http[0], http[1]
path = url_decode(path)
file = 'midi/'+'/'.join(path.split('/')[3:])
print(path)
if method == 'GET':
if path.startswith('/api/info'):
serve_info(client)
elif path.startswith('/api/list'):
serve_list(file, client)
elif path.startswith('/api/midi'):
serve_midi(file, client)
elif path == '/':
serve_file('/index.html', client)
else:
serve_file(path, client)
client.close()
# Serve a file from the webui directory
def serve_file(filename, client):
try:
with open('ui' + filename, 'rb') as file:
client.send(b"HTTP/1.1 200 OK\r\nServer: PicoJMBox\r\nCache-Control: public, max-age=3600\r\n\r\n")
while True:
chunk = file.read(1024)
if not chunk:
break
client.send(chunk)
except OSError:
not_found(client)
# Serve server info
def serve_info(client):
client.send(b"HTTP/1.1 200 OK\r\nServer: PicoJMBox\r\nContent-Type: application/json\r\n\r\n")
client.send(server_info)
def list_files(directory):
files = uos.listdir(directory)
file_list = []
for file in files:
file_path = directory + '/' + file
stat = uos.stat(file_path)
file_info = {
"date": stat[8]*1000,
"size": stat[6],
'name': file,
'isDir': stat[0] & 0x4000 == 0x4000 # Check if directory flag is set
}
file_list.append(file_info)
return file_list
# Serve the list of MIDI files and directories
def serve_list(directory,client):
try:
client.send(b"HTTP/1.1 200 OK\r\nServer: PicoJMBox\r\nContent-Type: application/json\r\n\r\n")
client.send(json.dumps(list_files(directory)))
except OSError:
not_found(client) # Return an empty list if the path does not exist or an error occurs
# Serve the original MIDI file
def serve_midi(filename,client):
try:
with open(filename, 'rb') as file:
client.send(b"HTTP/1.1 200 OK\r\nServer: PicoJMBox\r\nContent-Type: audio/midi\r\nCache-Control: public, max-age=3600\r\n\r\n")
while True:
chunk = file.read(1024)
if not chunk:
break
client.send(chunk)
except OSError:
not_found(client)
# Serve a "404 Not Found" response
def not_found(client):
client.send(b"HTTP/1.1 404 Not Found\r\nServer: PicoJMBox\r\nContent-Type: text/plain\r\n\r\n404 Not Found")
# Start the server
start_server()
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment