diff --git a/FEATURES.md b/FEATURES.md index 92cb64f..18818d6 100644 --- a/FEATURES.md +++ b/FEATURES.md @@ -16,6 +16,23 @@ dedicated PLAN.md phase (or fold it into the relevant existing work) and mark it --- +## Summary + +| ID | Status | Created | Title | Phase | +|----|--------|---------|-------|-------| +| FEAT-01 | `IDEA` | 2026-08-10 | Parallel/concurrent chunked dashcam uploads | Phase 27 | +| FEAT-02 | `IDEA` | 2026-08-10 | QR / claim-code device pairing flow | Phase 27 | +| FEAT-03 | `SHIPPED` | 2026-08-10 | Manual start odometer fallback | Phase 27 | +| FEAT-04 | `IDEA` | 2026-08-11 | Replace SIM868 2G with 4G LTE modem | Phase 27 | +| FEAT-05 | `SHIPPED` | 2026-08-11 | DTC history synced to remote server | Phase 27 | +| FEAT-06 | `SHIPPED` | 2026-08-11 | Trip ID column in history table | Phase 26 | +| FEAT-07 | `SHIPPED` | 2026-08-11 | Phone-hotspot auto-connect docs | Phase 22 | +| FEAT-08 | `SHIPPED` | 2026-08-11 | Predictable IP on phone hotspot | Phase 22 | +| FEAT-09 | `WONTFIX` | 2026-08-11 | mDNS (yaris.local) on phone hotspot | — | +| FEAT-10 | `IDEA` | 2026-08-12 | Home Assistant integration | unassigned | + +--- + ## Feature ideas ### FEAT-01 — Parallel/concurrent chunked dashcam uploads @@ -92,6 +109,21 @@ dedicated PLAN.md phase (or fold it into the relevant existing work) and mark it Upload skips when OBD disconnected (avoids clearing server DTCs on Pi reboot). Snapshot is hash-compared to avoid redundant uploads. +### FEAT-06 — Trip ID column in history table +- **Status**: `SHIPPED` 2026-08-11 +- **Area**: `static/js/history.js`, `templates/history.html`, `server/templates/history.html` +- **Phase**: Phase 26 +- **What**: Narrow `#ID` column on server history (hidden on Pi via `data-show-id`). + Checkbox column and batch-delete restored on server only. + +### FEAT-07 — Phone-hotspot auto-connect documentation +- **Status**: `SHIPPED` 2026-08-11 (already implemented in Phase 22, documented here) +- **Area**: `deploy/yaris_uplink.py`, Settings page, netwatch timer +- **What**: The Pi auto-connects to a saved phone hotspot on wlan1 within ~60s of it + appearing in range, and falls back to home-wifi when it disappears. The wlan0 AP + stays up regardless. Test flow: Settings → save hotspot name + password → "Wait for + hotspot" → enable phone hotspot → verify mode changes to "Phone hotspot". + ### FEAT-08 — Predictable IP on phone hotspot (DHCP client-id) - **Status**: `SHIPPED` 2026-08-11 (Phase 22) - **Area**: `deploy/yaris_uplink.py`, phone-hotspot NM profile @@ -151,24 +183,4 @@ dedicated PLAN.md phase (or fold it into the relevant existing work) and mark it - Keep the integration opt-in and lightweight — don't add MQTT dependencies to the core app.py startup unless the user explicitly configures it. ---- -## Ideas that landed - -(No entries yet — shipped features land here. Keep the original idea text intact and add the -shipped phase/date.) - -### FEAT-07 — Phone-hotspot auto-connect documentation -- **Status**: `SHIPPED` 2026-08-11 (already implemented in Phase 22, documented here) -- **Area**: `deploy/yaris_uplink.py`, Settings page, netwatch timer -- **What**: The Pi auto-connects to a saved phone hotspot on wlan1 within ~60s of it - appearing in range, and falls back to home-wifi when it disappears. The wlan0 AP - stays up regardless. Test flow: Settings → save hotspot name + password → "Wait for - hotspot" → enable phone hotspot → verify mode changes to "Phone hotspot". - -### FEAT-06 — Trip ID column in history table -- **Status**: `SHIPPED` 2026-08-11 -- **Area**: `static/js/history.js`, `templates/history.html`, `server/templates/history.html` -- **Phase**: Phase 26 -- **What**: Narrow `#ID` column on server history (hidden on Pi via `data-show-id`). - Checkbox column and batch-delete restored on server only. diff --git a/android/app/src/main/java/com/yarisobd/app/DownloadWorker.kt b/android/app/src/main/java/com/yarisobd/app/DownloadWorker.kt index 8c9cbc9..b38280f 100644 --- a/android/app/src/main/java/com/yarisobd/app/DownloadWorker.kt +++ b/android/app/src/main/java/com/yarisobd/app/DownloadWorker.kt @@ -24,13 +24,18 @@ import okhttp3.Request import okio.buffer import okio.sink import java.io.File +import java.util.concurrent.TimeUnit class DownloadWorker( context: Context, params: WorkerParameters, ) : CoroutineWorker(context, params) { - private val okHttp = OkHttpClient.Builder().build() + private val okHttp = OkHttpClient.Builder() + .connectTimeout(30, TimeUnit.SECONDS) + .readTimeout(30, TimeUnit.MINUTES) // slow Pi WiFi can take 5min+ per file + .writeTimeout(30, TimeUnit.SECONDS) + .build() private val notificationManager = NotificationManagerCompat.from(context) companion object { @@ -69,13 +74,16 @@ class DownloadWorker( dir.mkdirs() val localFile = File(dir, filename) - // Skip if already downloaded + // Skip if already downloaded with correct size if (localFile.exists() && localFile.length() == totalSize && totalSize > 0) { return@withContext Result.success( workDataOf("filename" to filename, "bytes" to totalSize) ) } + // Delete partial from previous failed attempt + localFile.delete() + setForeground(createForegroundInfo(filename)) try {