同步移动端工程、设备控制改进与发布资料
This commit is contained in:
+36
-37
@@ -15,6 +15,10 @@ from fastapi.responses import FileResponse, HTMLResponse, JSONResponse, Response
|
||||
from fastapi.staticfiles import StaticFiles
|
||||
from pydantic import BaseModel, ConfigDict, Field, StrictBool, StrictInt, StrictStr, field_validator, model_validator
|
||||
|
||||
from app.control import DeviceControl
|
||||
from app.mobile.control import MobileControl
|
||||
from app.mobile.session import SessionManager
|
||||
from app.mobile.bluez import BluezRuntime
|
||||
from app.config.store import (
|
||||
COLOR_PALETTE_LIMIT,
|
||||
DEFAULT_DISPLAY,
|
||||
@@ -561,6 +565,8 @@ def create_app(
|
||||
staging_root=ota_staging_root,
|
||||
)
|
||||
|
||||
control = DeviceControl(store, display, power_monitor, performance_mode)
|
||||
|
||||
def resolve_content(reference: dict[str, str]) -> dict[str, Any]:
|
||||
checked = normalize_default_display(reference)
|
||||
content_type = checked["type"]
|
||||
@@ -831,8 +837,9 @@ def create_app(
|
||||
},
|
||||
)
|
||||
|
||||
@app.get("/api/status")
|
||||
def get_status() -> dict:
|
||||
mobile_runtime = None
|
||||
|
||||
def read_device_status() -> dict:
|
||||
status = display.get_status()
|
||||
status["service"] = {
|
||||
"app_version": app.state.app_version,
|
||||
@@ -855,8 +862,25 @@ def create_app(
|
||||
store.config["performance_mode_enabled"]
|
||||
),
|
||||
}
|
||||
status["mobile"] = mobile_runtime.status() if mobile_runtime else {"available": False, "connected": False, "reason": "initialization_failed"}
|
||||
return status
|
||||
|
||||
try:
|
||||
mobile = MobileControl(control, network, templates, animations, resolve_content,
|
||||
apply_resolved_content, effective_default_content, set_default_content,
|
||||
read_device_status, storage_monitor.get_status, library_order=library_order)
|
||||
mobile_sessions = SessionManager(mobile.dispatch, mobile.identity)
|
||||
mobile_runtime = BluezRuntime(mobile_sessions, enabled=os.environ.get("MATRIX_BLE_ENABLED") == "1")
|
||||
app.state.mobile_control = mobile
|
||||
app.state.mobile_sessions = mobile_sessions
|
||||
except Exception:
|
||||
logger.exception("Mobile control initialization failed; display remains available")
|
||||
app.state.mobile_runtime = mobile_runtime
|
||||
|
||||
@app.get("/api/status")
|
||||
def get_status() -> dict:
|
||||
return read_device_status()
|
||||
|
||||
@app.get("/api/ota/status")
|
||||
def get_ota_status() -> dict:
|
||||
return {
|
||||
@@ -1123,41 +1147,7 @@ def create_app(
|
||||
def put_config(update: ConfigUpdate) -> dict:
|
||||
values = update.model_dump(exclude_none=True)
|
||||
try:
|
||||
config = validate_config({**store.config, **values})
|
||||
if "low_voltage_protection_enabled" in values:
|
||||
enabled = config["low_voltage_protection_enabled"]
|
||||
store.update({"low_voltage_protection_enabled": enabled})
|
||||
power_monitor.set_protection_enabled(enabled)
|
||||
if enabled:
|
||||
power_monitor.sample_now()
|
||||
if "orientation" in values:
|
||||
display.set_orientation(config["orientation"])
|
||||
if "brightness" in values:
|
||||
display.set_brightness(config["brightness"])
|
||||
if "matrix_refresh_rate_limit_hz" in values:
|
||||
display.set_refresh_rate_limit(
|
||||
config["matrix_refresh_rate_limit_hz"]
|
||||
)
|
||||
if "performance_mode_enabled" in values:
|
||||
performance_mode.transact(
|
||||
config["performance_mode_enabled"],
|
||||
lambda enabled: store.update({"performance_mode_enabled": enabled}),
|
||||
)
|
||||
remaining = {
|
||||
key: config[key]
|
||||
for key in (
|
||||
"default_font",
|
||||
"default_text_size",
|
||||
"preview_refresh_interval_ms",
|
||||
"custom_test_color",
|
||||
"workspace_order",
|
||||
"animation_preview_max_concurrent",
|
||||
)
|
||||
if key in values
|
||||
}
|
||||
if remaining:
|
||||
store.update(remaining)
|
||||
return store.config
|
||||
return control.update_config(values)
|
||||
except (ConfigError, PerformanceModeError, ValueError) as exc:
|
||||
raise HTTPException(status_code=400, detail=str(exc)) from exc
|
||||
except Exception as exc:
|
||||
@@ -2023,6 +2013,8 @@ def create_app(
|
||||
|
||||
@app.on_event("startup")
|
||||
def startup() -> None:
|
||||
if mobile_runtime:
|
||||
mobile_runtime.start()
|
||||
performance_mode.start(store.config["performance_mode_enabled"])
|
||||
media_imports.start()
|
||||
power_monitor.sample_now()
|
||||
@@ -2034,8 +2026,13 @@ def create_app(
|
||||
network.start()
|
||||
except Exception:
|
||||
logger.exception("Failed to restore normal content after OTA completion")
|
||||
try:
|
||||
ota.schedule_kernel_recovery_after_ota()
|
||||
except Exception:
|
||||
logger.exception("Failed to evaluate kernel recovery after OTA completion")
|
||||
|
||||
ota.set_completion_callback(restore_after_ota)
|
||||
ota.finalize_kernel_recovery_after_boot()
|
||||
if ota.resume_or_start_monitor(restore_after_ota):
|
||||
logger.warning("OTA transaction is active; keeping the update indicator visible")
|
||||
elif maintenance_black:
|
||||
@@ -2046,6 +2043,8 @@ def create_app(
|
||||
|
||||
@app.on_event("shutdown")
|
||||
def shutdown() -> None:
|
||||
if mobile_runtime:
|
||||
mobile_runtime.close()
|
||||
logger.info("Shutting down; clearing display")
|
||||
media_imports.stop()
|
||||
power_monitor.close()
|
||||
|
||||
Reference in New Issue
Block a user