#!/usr/bin/env python3 """ Ad-hoc Flask HTTPS Server for LED Controller Webapp Serves the webapp over HTTPS (required for Web Bluetooth API) """ import os import sys from flask import Flask, send_from_directory, send_file from pathlib import Path # Configuration HOST = '0.0.0.0' # Listen on all interfaces PORT = 5000 # HTTPS port DEBUG = True # Get webapp directory (one level up from tools/) SCRIPT_DIR = Path(__file__).parent WEBAPP_DIR = SCRIPT_DIR.parent / 'webapp' # Verify webapp directory exists if not WEBAPP_DIR.exists(): print(f"āŒ ERROR: Webapp directory not found at {WEBAPP_DIR}") print(f" Please run this script from the base repository directory") sys.exit(1) # Create Flask app app = Flask(__name__) @app.route('/') def index(): """Serve index.html""" return send_file(WEBAPP_DIR / 'index.html') @app.route('/app/') def serve_app(filename): """Serve files from app/ directory""" return send_from_directory(WEBAPP_DIR / 'app', filename) @app.route('/css/') def serve_css(filename): """Serve files from css/ directory""" return send_from_directory(WEBAPP_DIR / 'css', filename) @app.route('/data/') def serve_data(filename): """Serve files from data/ directory""" return send_from_directory(WEBAPP_DIR / 'data', filename) @app.route('/favicon.ico') def favicon(): """Serve favicon""" return send_file(WEBAPP_DIR / 'data' / 'favicon.ico') def print_banner(): """Print startup banner with instructions""" print("=" * 70) print(" šŸš€ LED Controller HTTPS Development Server") print("=" * 70) print() print("šŸ“± Web Bluetooth requires HTTPS!") print(" This server provides a self-signed certificate for development.") print() print("🌐 Access the webapp at:") print(f" https://localhost:{PORT}") print(f" https://127.0.0.1:{PORT}") print(f" https://:{PORT}") print() print("āš ļø Browser Security Warning:") print(" You'll see a 'Not Secure' warning - this is normal!") print(" Click 'Advanced' → 'Proceed to localhost' (or similar)") print() print("šŸ”§ To stop the server: Press Ctrl+C") print("=" * 70) print() def get_local_ip(): """Get local IP address for convenience""" import socket try: s = socket.socket(socket.AF_INET, socket.SOCK_DGRAM) s.connect(("8.8.8.8", 80)) ip = s.getsockname()[0] s.close() return ip except: return "unknown" if __name__ == '__main__': print_banner() # Print local IP for convenience local_ip = get_local_ip() if local_ip != "unknown": print(f"šŸ’” Your local IP: {local_ip}") print(f" Access from phone: https://{local_ip}:{PORT}") print() print("šŸ”„ Starting HTTPS server...") print() try: # Run with ad-hoc SSL context (self-signed certificate) # Flask will automatically generate a certificate app.run( host=HOST, port=PORT, debug=DEBUG, ssl_context='adhoc' # Auto-generate self-signed cert ) except OSError as e: if "Address already in use" in str(e): print(f"āŒ ERROR: Port {PORT} is already in use!") print(f" Try a different port or stop the other service.") sys.exit(1) else: raise except KeyboardInterrupt: print("\n\nšŸ‘‹ Server stopped by user") sys.exit(0)