Phase 12: remove phone-relay dashcam upload feature
Removes the phone-relay feature entirely per the Phase 11 finding that it hit a fundamental phone-OS limitation (a browser page can't route WiFi and cellular traffic simultaneously, no code fix possible) - see PLAN.md for the full test writeup. - app.py: dropped /api/dash/pending, /api/dash/file/<path>, /api/dash/relay/config, /api/dash/relay/heartbeat, /api/dash/relay/stop, /api/dash/relay/mark_uploaded routes and their now-unused imports (os, send_file, abort, safe_join). - modules/app_upload.py: dropped list_pending_dashcam_files(), relay_heartbeat()/relay_stop()/is_relay_active(), RELAY_LEASE_SECONDS/_relay_lease_until, and the relay-lease check inside _upload_dashcam_files()/get_status(). Kept the chunked upload protocol, dashcam_hash_cache/_hash_dashcam_file() (still used by the Pi's own background uploader), and DASHCAM_CHUNK_SIZE - none of that was relay-specific. - templates/dash.html: removed the 'Relay via phone' card. - static/js/dash.js: removed all relay JS (relayOneFile, fetchChunkWithRetry, uploadChunkWithRetry, heartbeat timers, pending-file list rendering). - server/app.py: removed the CORS after_request hook, added solely for the phone's cross-origin browser calls (the Pi's own Python requests-based client was never subject to CORS). - readme.md: dropped the phone-relay feature bullet, updated the project-status blurb to explain the removal + point at the planned native Android app as the real fix for that use case. - PLAN.md: marked Phase 12 done with a verification writeup. Verified: py_compile on all touched Python files, node --check on dash.js, grepped all touched files for any leftover relay/RELAY reference (none), and smoke-tested by importing app.py + hitting it with Flask's test client - app starts cleanly, every relay route is gone from url_map, and both / and /dash still render HTTP 200 with zero 'relay' occurrences in /dash's HTML. Co-authored-by: Copilot <[email protected]>
This commit is contained in:
+8
-55
@@ -67,17 +67,10 @@ DASHCAM_CHUNK_SIZE = 40 * 1024 * 1024
|
||||
|
||||
DASHCAM_UPLOAD_SETTING_KEY = "dashcam_upload_enabled"
|
||||
|
||||
# How long a phone-relay "lease" stays valid without a fresh heartbeat before
|
||||
# the Pi's own background uploader assumes the phone gave up/closed its tab
|
||||
# and resumes uploading dashcam files itself. The phone page is expected to
|
||||
# heartbeat well under this (every ~15-20s) - see /api/dash/relay/heartbeat.
|
||||
RELAY_LEASE_SECONDS = 45
|
||||
|
||||
_upload_thread = None
|
||||
_last_error = None
|
||||
_last_success_at = None
|
||||
_last_network_path = None # "wifi" or "cellular" - last path a batch actually went out on
|
||||
_relay_lease_until = None # monotonic time.time() the phone-relay lease expires, or None
|
||||
|
||||
|
||||
def _headers():
|
||||
@@ -107,30 +100,9 @@ def get_status():
|
||||
"last_success_at": _last_success_at,
|
||||
"last_network_path": _last_network_path,
|
||||
"cellular_fallback_configured": app_cellular.is_configured(),
|
||||
"relay_active": is_relay_active(),
|
||||
}
|
||||
|
||||
|
||||
# --- Phone-relay lease (pauses the Pi's own background dashcam uploader
|
||||
# while a phone is manually relaying files, so they don't fight over the
|
||||
# Pi's single, often WiFi-congested, radio) -------------------------------
|
||||
|
||||
def relay_heartbeat():
|
||||
"""Called by the phone-relay page every ~15-20s while active."""
|
||||
global _relay_lease_until
|
||||
_relay_lease_until = time.time() + RELAY_LEASE_SECONDS
|
||||
|
||||
|
||||
def relay_stop():
|
||||
"""Called when the phone-relay page is done/closed cleanly."""
|
||||
global _relay_lease_until
|
||||
_relay_lease_until = None
|
||||
|
||||
|
||||
def is_relay_active():
|
||||
return _relay_lease_until is not None and time.time() < _relay_lease_until
|
||||
|
||||
|
||||
def _sha256_file(path):
|
||||
hasher = hashlib.sha256()
|
||||
with open(path, "rb") as f:
|
||||
@@ -145,9 +117,8 @@ def _sha256_file(path):
|
||||
def _hash_dashcam_file(abs_path, rel_path):
|
||||
"""sha256 of a dashcam file, cached by (path, size, mtime) so unchanged
|
||||
files already copied from the dashcam never get rehashed - real backlogs
|
||||
here run 20GB+, and both the background loop and the phone-relay pending
|
||||
list would otherwise rehash everything, including already-uploaded files,
|
||||
on every single call."""
|
||||
here run 20GB+, and the background upload loop would otherwise rehash
|
||||
everything, including already-uploaded files, on every single call."""
|
||||
stat = os.stat(abs_path)
|
||||
cached = app_sql.get_cached_dashcam_hash(rel_path, stat.st_size, stat.st_mtime)
|
||||
if cached is not None:
|
||||
@@ -157,22 +128,6 @@ def _hash_dashcam_file(abs_path, rel_path):
|
||||
return sha256
|
||||
|
||||
|
||||
def list_pending_dashcam_files():
|
||||
"""Return [{relative_path, sha256, size}, ...] for dashcam files not yet
|
||||
confirmed uploaded - used by the phone-relay page to pick what to fetch."""
|
||||
pending = []
|
||||
for abs_path, rel_path in app_dash.find_video_files(app_dash.DEFAULT_DESTINATION):
|
||||
sha256 = _hash_dashcam_file(abs_path, rel_path)
|
||||
if app_sql.dashcam_file_marked_uploaded(rel_path, sha256):
|
||||
continue
|
||||
pending.append({
|
||||
"relative_path": rel_path,
|
||||
"sha256": sha256,
|
||||
"size": os.path.getsize(abs_path),
|
||||
})
|
||||
return pending
|
||||
|
||||
|
||||
def _upload_tracking_batch():
|
||||
"""Send up to TRACKING_BATCH_SIZE not-yet-uploaded rows. Returns count sent.
|
||||
|
||||
@@ -290,11 +245,10 @@ def _upload_video_chunked(abs_path, rel_path, sha256):
|
||||
def _upload_dashcam_files():
|
||||
"""Upload any not-yet-uploaded dashcam files, one at a time. Returns count sent.
|
||||
|
||||
Skipped entirely (returns 0) while the dashcam-upload toggle is off, or
|
||||
while a phone-relay session is actively leased - tracking-log uploads are
|
||||
unaffected by either of these.
|
||||
Skipped entirely (returns 0) while the dashcam-upload toggle is off -
|
||||
tracking-log uploads are unaffected.
|
||||
"""
|
||||
if not is_dashcam_upload_enabled() or is_relay_active():
|
||||
if not is_dashcam_upload_enabled():
|
||||
return 0
|
||||
|
||||
uploaded_count = 0
|
||||
@@ -307,10 +261,9 @@ def _upload_dashcam_files():
|
||||
app_sql.mark_dashcam_file_uploaded(rel_path, sha256)
|
||||
uploaded_count += 1
|
||||
|
||||
# Re-check between files so flipping the toggle off, or a phone
|
||||
# relay starting, mid-run stops further uploads promptly without
|
||||
# waiting for the next cycle.
|
||||
if not is_dashcam_upload_enabled() or is_relay_active():
|
||||
# Re-check between files so flipping the toggle off mid-run stops
|
||||
# further uploads promptly without waiting for the next cycle.
|
||||
if not is_dashcam_upload_enabled():
|
||||
break
|
||||
|
||||
return uploaded_count
|
||||
|
||||
Reference in New Issue
Block a user