153 lines
4.6 KiB
Python
153 lines
4.6 KiB
Python
#!/usr/bin/env python3
|
|
"""
|
|
Local development web server - imports and runs main.py with port 5000
|
|
"""
|
|
|
|
import sys
|
|
import os
|
|
import asyncio
|
|
|
|
# Add src and lib to path
|
|
sys.path.insert(0, os.path.join(os.path.dirname(__file__), 'src'))
|
|
sys.path.insert(0, os.path.join(os.path.dirname(__file__), 'lib'))
|
|
|
|
# Import the main module
|
|
from src import main as main_module
|
|
|
|
# Override the port in the main function
|
|
async def run_local():
|
|
"""Run main with port 5000 for local development."""
|
|
from settings import Settings
|
|
import gc
|
|
|
|
# Mock MicroPython modules for local development
|
|
class MockMachine:
|
|
class WDT:
|
|
def __init__(self, timeout):
|
|
pass
|
|
def feed(self):
|
|
pass
|
|
import sys as sys_module
|
|
sys_module.modules['machine'] = MockMachine()
|
|
|
|
class MockESPNow:
|
|
def __init__(self):
|
|
self.active_value = False
|
|
self.peers = []
|
|
def active(self, value):
|
|
self.active_value = value
|
|
print(f"[MOCK] ESPNow active: {value}")
|
|
def add_peer(self, peer):
|
|
self.peers.append(peer)
|
|
print(f"[MOCK] Added peer: {peer.hex() if hasattr(peer, 'hex') else peer}")
|
|
async def asend(self, peer, data):
|
|
print(f"[MOCK] Would send to {peer.hex() if hasattr(peer, 'hex') else peer}: {data}")
|
|
|
|
class MockAIOESPNow:
|
|
def __init__(self):
|
|
pass
|
|
def active(self, value):
|
|
return MockESPNow()
|
|
def add_peer(self, peer):
|
|
pass
|
|
|
|
class MockNetwork:
|
|
class WLAN:
|
|
def __init__(self, interface):
|
|
self.interface = interface
|
|
def active(self, value):
|
|
print(f"[MOCK] WLAN({self.interface}) active: {value}")
|
|
STA_IF = 0
|
|
|
|
# Replace MicroPython modules with mocks
|
|
sys_module.modules['aioespnow'] = type('module', (), {'AIOESPNow': MockESPNow})()
|
|
sys_module.modules['network'] = MockNetwork()
|
|
|
|
# Mock gc if needed
|
|
if not hasattr(gc, 'collect'):
|
|
class MockGC:
|
|
def collect(self):
|
|
pass
|
|
gc = MockGC()
|
|
|
|
settings = Settings()
|
|
print("Starting LED Controller Web Server (Local Development)")
|
|
print("=" * 60)
|
|
|
|
# Mock network
|
|
import network
|
|
network.WLAN(network.STA_IF).active(True)
|
|
|
|
# Mock ESPNow
|
|
import aioespnow
|
|
e = aioespnow.AIOESPNow()
|
|
e.active(True)
|
|
e.add_peer(b"\xbb\xbb\xbb\xbb\xbb\xbb")
|
|
|
|
from microdot import Microdot, send_file
|
|
from microdot.websocket import with_websocket
|
|
|
|
import controllers.preset as preset
|
|
import controllers.profile as profile
|
|
import controllers.group as group
|
|
import controllers.sequence as sequence
|
|
import controllers.tab as tab
|
|
import controllers.palette as palette
|
|
import controllers.scene as scene
|
|
|
|
app = Microdot()
|
|
|
|
# Mount model controllers as subroutes
|
|
app.mount(preset.controller, '/presets')
|
|
app.mount(profile.controller, '/profiles')
|
|
app.mount(group.controller, '/groups')
|
|
app.mount(sequence.controller, '/sequences')
|
|
app.mount(tab.controller, '/tabs')
|
|
app.mount(palette.controller, '/palettes')
|
|
app.mount(scene.controller, '/scenes')
|
|
|
|
# Serve index.html at root
|
|
@app.route('/')
|
|
def index(request):
|
|
"""Serve the main web UI."""
|
|
return send_file('src/templates/index.html')
|
|
|
|
# Static file route
|
|
@app.route("/static/<path:path>")
|
|
def static_handler(request, path):
|
|
"""Serve static files."""
|
|
if '..' in path:
|
|
return 'Not found', 404
|
|
return send_file('src/static/' + path)
|
|
|
|
@app.route('/ws')
|
|
@with_websocket
|
|
async def ws(request, ws):
|
|
while True:
|
|
data = await ws.receive()
|
|
if data:
|
|
await e.asend(b"\xbb\xbb\xbb\xbb\xbb\xbb", data)
|
|
print(data)
|
|
else:
|
|
break
|
|
|
|
# Use port 5000 for local development
|
|
port = 5000
|
|
print(f"Starting server on http://0.0.0.0:{port}")
|
|
print(f"Open http://localhost:{port} in your browser")
|
|
print("=" * 60)
|
|
|
|
try:
|
|
await app.start_server(host="0.0.0.0", port=port, debug=True)
|
|
except KeyboardInterrupt:
|
|
print("\nShutting down server...")
|
|
|
|
if __name__ == '__main__':
|
|
# Change to project root
|
|
os.chdir(os.path.dirname(os.path.abspath(__file__)))
|
|
# Override settings path for local development
|
|
import settings as settings_module
|
|
settings_module.Settings.SETTINGS_FILE = os.path.join(os.getcwd(), 'settings.json')
|
|
|
|
asyncio.run(run_local())
|