Skip to content

feat(r1.1/esp32): show last capture (speed + photo) on config portal#21

Open
daniel-frenkel wants to merge 2 commits into
feat/api-events-endpointfrom
feat/portal-last-capture
Open

feat(r1.1/esp32): show last capture (speed + photo) on config portal#21
daniel-frenkel wants to merge 2 commits into
feat/api-events-endpointfrom
feat/portal-last-capture

Conversation

@daniel-frenkel

Copy link
Copy Markdown
Member

Summary

Adds a Last capture card at the top of the config portal showing the most recent pass's speed, direction, age, and photo.

  • last_photo.h — retains one JPEG copy of the latest capture in PSRAM (a UXGA/q20 frame is a few hundred KB of the board's 8 MB OPI PSRAM; internal SRAM is untouched — the build shows +56 B SRAM). The camera driver already keeps its framebuffers in that PSRAM, so one retained frame is a small, bounded cost.
  • Concurrency — the radar task (Core 1) stages a new photo at run-end while the single port-80 httpd task serves it. A portMUX guards the pointer swap; the slow WiFi send holds no lock; and a borrow/release protocol hands any buffer retired mid-send to the reader to free on completion, so a fast car during a slow page load can't cause a use-after-free.
  • GET /api/last.jpg — chunked JPEG (no second contiguous buffer), Host-allowlisted like /api/state (it can disclose road/vehicle imagery), cached per-seq so the frame is only refetched when it changes — not on every 4 s /api/state poll.
  • /api/state gains lastSeq/lastSpeed/lastKph/lastDir/lastAgeSec + photoSeq; eventsRecord() now returns the pass seq so the retained photo ties to its /api/events event. The card shows speed-only passes too, noting when the newest pass had no photo.

Stacked on the api-events-endpoint chain (which now contains the merged speed-correction work from #20); retarget to main as the chain lands.

Test plan

  • pio run builds clean (Flash 46.3%, SRAM 19.0%)
  • On-device (COM4): trigger a pass, confirm the card shows speed + photo, image refetches only on a new pass, and a speed-only pass shows the note

🤖 Generated with Claude Code

daniel-frenkel and others added 2 commits July 11, 2026 08:02
Retain the most recent capture's JPEG in PSRAM (last_photo.h) and add a
top-of-page 'Last capture' card to the config portal showing the newest
pass's speed, direction, age, and photo.

- last_photo.h: one retained JPEG copy in PSRAM (~hundreds of KB of the
  board's 8 MB; internal SRAM untouched). Writer (radar task, Core 1) vs.
  single httpd reader is guarded by a portMUX pointer-swap plus a
  borrow/release protocol, so a fresh capture mid-send never frees the
  buffer the web server is still streaming.
- GET /api/last.jpg: chunked JPEG, Host-allowlisted like /api/state,
  cached per-seq so the frame is refetched only when it changes.
- /api/state gains lastSeq/lastSpeed/lastKph/lastDir/lastAgeSec + photoSeq;
  eventsRecord() now returns the pass seq so the photo ties to its event.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
…e photo

The image now always corresponds to the newest pass: shown only when that
pass has its own photo (photoSeq === lastSeq), otherwise a same-size
'No photo — speed-only pass' placeholder box. Drops the previous behavior
of displaying an older pass's photo with an explanatory note.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant