refactor(api): complete fastapi migration and related features

Finish native FastAPI controllers, drop vendored microdot, and add
Wi-Fi driver runtime, beat SSE, simulated BPM, sequence playback
improvements, bridge ESP-NOW sources, UI updates, and tests.

Co-authored-by: Cursor <cursoragent@cursor.com>
This commit is contained in:
2026-06-11 22:55:28 +12:00
parent cb9758b97b
commit ace5770b3a
73 changed files with 4540 additions and 4487 deletions

View File

@@ -115,14 +115,36 @@ def parse_args() -> argparse.Namespace:
return parser.parse_args()
def _clamp_detected_bpm(bpm: float | None) -> float | None:
if bpm is None:
return None
try:
from util.bpm_limits import clamp_bpm_optional
return clamp_bpm_optional(bpm)
except ImportError:
v = float(bpm)
if v <= 0:
return None
return max(60.0, min(200.0, v))
def _estimate_bpm(beat_times: Deque[float]) -> float | None:
if len(beat_times) < 3:
return None
try:
from util.bpm_limits import max_beat_interval_s, min_beat_interval_s
ioi_min = min_beat_interval_s()
ioi_max = max_beat_interval_s()
except ImportError:
ioi_min = 0.3
ioi_max = 1.0
intervals = np.diff(np.array(beat_times, dtype=np.float64))
valid = intervals[(intervals > 0.2) & (intervals < 2.0)]
valid = intervals[(intervals >= ioi_min) & (intervals <= ioi_max)]
if valid.size == 0:
return None
return 60.0 / float(np.median(valid))
return _clamp_detected_bpm(60.0 / float(np.median(valid)))
def _is_plausible_ioi(
@@ -131,7 +153,7 @@ def _is_plausible_ioi(
now_s: float,
*,
min_ratio: float = 0.42,
max_ratio: float = 2.5,
max_ratio: float = 3.5,
) -> bool:
"""Reject double-time / half-time false triggers vs recent median interval."""
if last_trigger_s <= 0 or len(beat_times) < 2:
@@ -251,7 +273,7 @@ def _resolve_bpm(
) -> float | None:
estimated = _estimate_bpm(beat_times)
if estimated is None:
return aubio_bpm
return _clamp_detected_bpm(aubio_bpm)
if aubio_bpm is None or aubio_bpm <= 0:
return estimated
ratio = float(aubio_bpm) / estimated
@@ -400,7 +422,7 @@ class BeatDetectRuntime:
if self.tempo is not None:
aubio_hit = bool(self.tempo(f32)[0])
val = float(self.tempo.get_bpm())
aubio_bpm = val if val > 0 else None
aubio_bpm = _clamp_detected_bpm(val if val > 0 else None)
if now_s is None:
now_s = time.time()