Files
mc-webui/app/main.py
MarekWo c376ecff30 fix: Proxy console WebSocket through main app for HTTPS compatibility
Browser blocks mixed content (HTTPS page -> HTTP WebSocket on port 5001).
Solution: Route WebSocket through main Flask app which goes through
existing HTTPS reverse proxy.

- Add Flask-SocketIO to main mc-webui app
- WebSocket handler proxies commands to bridge via HTTP
- Remove port 5001 external exposure (no longer needed)
- Remove duplicate title from console header

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
2026-01-09 13:18:56 +01:00

146 lines
4.4 KiB
Python

"""
mc-webui - Flask application entry point
"""
import logging
import requests
from flask import Flask
from flask_socketio import SocketIO, emit
from app.config import config
from app.routes.views import views_bp
from app.routes.api import api_bp
from app.archiver.manager import schedule_daily_archiving
# Configure logging
logging.basicConfig(
level=logging.DEBUG if config.FLASK_DEBUG else logging.INFO,
format='%(asctime)s - %(name)s - %(levelname)s - %(message)s'
)
logger = logging.getLogger(__name__)
# Initialize SocketIO globally
socketio = SocketIO()
def create_app():
"""Create and configure Flask application"""
app = Flask(__name__)
# Load configuration
app.config['DEBUG'] = config.FLASK_DEBUG
app.config['SECRET_KEY'] = 'mc-webui-secret-key-change-in-production'
# Register blueprints
app.register_blueprint(views_bp)
app.register_blueprint(api_bp)
# Initialize SocketIO with the app
socketio.init_app(app, cors_allowed_origins="*", async_mode='gevent')
# Initialize archive scheduler if enabled
if config.MC_ARCHIVE_ENABLED:
schedule_daily_archiving()
logger.info(f"Archive scheduler enabled - directory: {config.MC_ARCHIVE_DIR}")
else:
logger.info("Archive scheduler disabled")
logger.info(f"mc-webui started - device: {config.MC_DEVICE_NAME}")
logger.info(f"Messages file: {config.msgs_file_path}")
logger.info(f"Serial port: {config.MC_SERIAL_PORT}")
return app
# ============================================================
# WebSocket handlers for Console
# ============================================================
@socketio.on('connect', namespace='/console')
def handle_console_connect():
"""Handle console WebSocket connection"""
logger.info("Console WebSocket client connected")
emit('console_status', {'message': 'Connected to mc-webui console proxy'})
@socketio.on('disconnect', namespace='/console')
def handle_console_disconnect():
"""Handle console WebSocket disconnection"""
logger.info("Console WebSocket client disconnected")
@socketio.on('send_command', namespace='/console')
def handle_send_command(data):
"""Handle command from console client - proxy to bridge via HTTP"""
command = data.get('command', '').strip()
if not command:
emit('command_response', {
'success': False,
'error': 'Empty command'
})
return
logger.info(f"Console command received: {command}")
# Execute command via bridge HTTP API
def execute_and_respond():
try:
bridge_url = f"http://{config.MC_BRIDGE_HOST}:{config.MC_BRIDGE_PORT}/cli"
response = requests.post(
bridge_url,
json={'command': command},
timeout=30
)
if response.status_code == 200:
result = response.json()
output = result.get('output', '')
# Handle list output (join with newlines)
if isinstance(output, list):
output = '\n'.join(output)
emit('command_response', {
'success': True,
'command': command,
'output': output
})
else:
emit('command_response', {
'success': False,
'command': command,
'error': f'Bridge returned status {response.status_code}'
})
except requests.exceptions.Timeout:
emit('command_response', {
'success': False,
'command': command,
'error': 'Command timed out'
})
except requests.exceptions.ConnectionError:
emit('command_response', {
'success': False,
'command': command,
'error': 'Cannot connect to meshcore-bridge'
})
except Exception as e:
logger.error(f"Console command error: {e}")
emit('command_response', {
'success': False,
'command': command,
'error': str(e)
})
# Run in background to not block
socketio.start_background_task(execute_and_respond)
if __name__ == '__main__':
app = create_app()
socketio.run(
app,
host=config.FLASK_HOST,
port=config.FLASK_PORT,
debug=config.FLASK_DEBUG
)