mirror of
https://github.com/maziggy/bambuddy.git
synced 2026-10-04 13:11:35 +02:00
Bambu's end-gcode lowers the bed at gcode_state=FINISH. Bambuddy's live-camera grab captured the bed already dropped, ruining the photo framing. Source the photo from a brief Bambu timelapse instead — firmware stops timelapse recording AFTER toolhead parks but BEFORE bed-drop runs, so the last frame frames the finished print correctly. When capture_finish_photo is on AND the user did not opt in to timelapse for this print, force timelapse=True at dispatch + mark the new PrintArchive.bambuddy_forced_timelapse column. After extraction (success or failure), cleanup deletes the locally-attached file, clears archive.timelapse_path, and walks the four scanner directories (/timelapse, /timelapse/video, /record, /recording) trying FTP DELE against the original filename. User-opted-in timelapses pass through unchanged. Resolver lives at services/background_dispatch.py::resolve_effective_timelapse (module-level so the print queue can reuse it). Both dispatch paths wired: background_dispatch.py (Print Now / Reprint) AND print_scheduler.py:_start_print (the queue). Field testing caught the scheduler gap on the first round — AST regression test now asserts start_print(timelapse=...) references effective_timelapse, not the raw item.timelapse, so a future refactor can't silently drop it. Extractor: ffmpeg -i input.mp4 -update 1 -q:v 2 out.jpg. Decoded frames overwrite the same output file, so the file left on disk is the literal last frame regardless of duration. Bambu records one frame per layer-change, so a 16-layer cube produces a 0.6 s timelapse — the original -sseof -1.0 approach seeked before the start of the file and returned frame 0 (empty bed). Decoding every frame is fine; Bambu timelapses are short by construction even on hours-long prints. Migration adds bambuddy_forced_timelapse branched on is_sqlite() (DEFAULT 0 / DEFAULT FALSE — PG rejects DEFAULT 0 for BOOLEAN). Verified live on postgres:16-alpine. Photo-task wait_for budget extends 45s -> 75s when timelapse_was_active so the notification carries the bed-up photo instead of falling back to the live-cam grab on slow links. Scope limit, documented in the camera wiki: prints started directly on the printer touchscreen / Bambu Handy / Bambu Studio Send bypass both dispatch paths, so the override doesn't fire there. Future option: mid-print M981 S1 P20000 MQTT toggle in on_print_start. Setting description rewritten in all 11 locales to drop the "only works when timelapse enabled" caveat (Bambuddy now forces it) and explain the kept-or-deleted behaviour.
41 lines
1.8 KiB
HTML
41 lines
1.8 KiB
HTML
<!doctype html>
|
|
<html lang="en">
|
|
<head>
|
|
<meta charset="UTF-8" />
|
|
<meta name="viewport" content="width=device-width, initial-scale=1.0, maximum-scale=1.0, user-scalable=no" />
|
|
<!-- L-4: Restrict Referer header to origin-only on cross-origin navigation so
|
|
sensitive tokens in query parameters are not leaked to third-party servers. -->
|
|
<meta name="referrer" content="strict-origin-when-cross-origin" />
|
|
<title>Bambuddy</title>
|
|
|
|
<!-- PWA Meta Tags -->
|
|
<meta name="description" content="Monitor and manage your Bambu Lab 3D printers" />
|
|
<meta name="theme-color" content="#00ae42" />
|
|
<meta name="mobile-web-app-capable" content="yes" />
|
|
<meta name="apple-mobile-web-app-capable" content="yes" />
|
|
<meta name="apple-mobile-web-app-status-bar-style" content="black-translucent" />
|
|
<meta name="apple-mobile-web-app-title" content="Bambuddy" />
|
|
|
|
<!-- Manifest -->
|
|
<link rel="manifest" href="/manifest.json" />
|
|
|
|
<!-- Favicons -->
|
|
<link rel="icon" type="image/png" sizes="32x32" href="/img/favicon-32x32.png" />
|
|
<link rel="icon" type="image/png" sizes="16x16" href="/img/favicon-16x16.png" />
|
|
<link rel="apple-touch-icon" sizes="180x180" href="/img/apple-touch-icon.png" />
|
|
|
|
<!-- Splash screens for iOS -->
|
|
<link rel="apple-touch-startup-image" href="/img/android-chrome-512x512.png" />
|
|
<script type="module" crossorigin src="/assets/index-14DWwfbR.js"></script>
|
|
<link rel="stylesheet" crossorigin href="/assets/index-Df3XYvpK.css">
|
|
</head>
|
|
<body>
|
|
<div id="root"></div>
|
|
|
|
<!-- Service Worker Registration (skip on SpoolBuddy kiosk).
|
|
Kept as an external file so the CSP `script-src 'self'` covers it
|
|
without needing 'unsafe-inline' or per-build hashes. -->
|
|
<script src="/sw-register.js"></script>
|
|
</body>
|
|
</html>
|