Refine manage overlay: US/CAN state abbreviations, share-QR caption, and an escalating second menu with named-face labels
Build and push server image / build-and-push (push) Successful in 32s
Build and push server image / build-and-push (push) Successful in 32s
Two rounds of follow-up work on the manage-button overlay:
1. Location formatting: US/Canada now show abbreviated state/province
("CA", "ON") instead of the full name, other countries show the full
country name, and each is its own line (was one line, now wraps to
two) so longer international place names have more room without
threatening to overlap the top-right QR box. The bottom-left share QR
also gets a "SCAN TO DOWNLOAD" caption.
2. Escalating menu: pressing the manage button again while its overlay
is already up adds a second level -- each Immich-identified person's
name labeled next to their face in the photo (using Immich's own
face recognition/People data, no detection/recognition added to this
project). A third press exits immediately instead of waiting out the
30s auto-revert timer. No new Immich API needed -- GET /api/faces
already embeds a nullable person.name per face; new
server/app/face_labels.py maps a named face's box into the final
800x480 frame's pixel space (reusing crop-box math extracted from
image_pipeline.py's face-aware cropping). Capped at 4 named faces,
sized to a real firmware RAM budget: each label is its own malloc'd
overlay region on the device, alongside the 4 fixed corner regions
already in use. New GET /frame/face-labels returns a flattened
fixed-slot JSON shape (not a real array) so firmware's existing
flat-scalar parser can read it without needing an actual array
parser. No persistent state needed for the escalation itself -- it's
all local control flow within one continuous awake session
(frame_client.c's run_management_menu()).
This commit is contained in:
@@ -4,7 +4,15 @@
|
||||
|
||||
#include "esp_err.h"
|
||||
|
||||
#define MANAGE_OVERLAY_MAX_REGIONS 4
|
||||
/* 4 fixed corner regions (manage QR, location, date, share QR) plus up
|
||||
* to MANAGE_FACE_LABELS_MAX arbitrary-position named-face labels (see
|
||||
* manage_face_label_t below). MANAGE_FACE_LABELS_MAX is capped small
|
||||
* deliberately, not arbitrarily -- each label is its own malloc'd
|
||||
* buffer, and the 4 fixed regions alone already use a meaningful chunk
|
||||
* of the ESP32-C6's limited RAM; this keeps worst-case overlay memory
|
||||
* well clear of what the WiFi/HTTP stack needs alongside it. */
|
||||
#define MANAGE_FACE_LABELS_MAX 4
|
||||
#define MANAGE_OVERLAY_MAX_REGIONS (4 + MANAGE_FACE_LABELS_MAX)
|
||||
|
||||
typedef struct {
|
||||
uint8_t *buf; /* malloc'd (w/2)*h bytes, packed 2px/byte; owned by the region */
|
||||
@@ -18,22 +26,33 @@ typedef struct {
|
||||
} manage_overlay_set_t;
|
||||
|
||||
typedef struct {
|
||||
const char *management_url; /* top-right QR + "SCAN TO"/"MANAGE" caption -- always shown */
|
||||
const char *location; /* top-left text; NULL/empty skips this region */
|
||||
const char *taken_at; /* bottom-right text; NULL/empty skips this region */
|
||||
const char *share_url; /* bottom-left QR (no caption); NULL/empty skips this region */
|
||||
char name[16];
|
||||
int x, y; /* anchor point (bottom-center of the face), panel pixel coordinates */
|
||||
} manage_face_label_t;
|
||||
|
||||
typedef struct {
|
||||
const char *management_url; /* top-right QR + "SCAN TO"/"MANAGE" caption -- always shown */
|
||||
const char *location_line1; /* top-left text, line 1 (city); NULL/empty skips this region */
|
||||
const char *location_line2; /* top-left text, line 2 (state/country); NULL/empty is fine if line1 is set */
|
||||
const char *taken_at; /* bottom-right text; NULL/empty skips this region */
|
||||
const char *share_url; /* bottom-left QR + "SCAN TO"/"DOWNLOAD" caption; NULL/empty skips this region */
|
||||
const manage_face_label_t *face_labels; /* named-face labels ("level 2" menu); NULL/empty count skips these */
|
||||
int face_label_count; /* clamped to MANAGE_FACE_LABELS_MAX internally */
|
||||
} manage_overlay_content_t;
|
||||
|
||||
/**
|
||||
* Renders the manage-button overlay: always a "scan to manage" QR in the
|
||||
* top-right corner, plus whichever of location/taken_at/share_url are
|
||||
* non-NULL/non-empty in their own corners (top-left, bottom-right,
|
||||
* bottom-left respectively). Each region is its own separately malloc'd
|
||||
* small buffer (not a full EPD_FRAME_BYTES frame). A failure rendering
|
||||
* the top-right region fails the whole call; a failure rendering one of
|
||||
* the optional regions just skips that region and keeps going. Caller
|
||||
* must call manage_overlay_free() on out regardless of the return value
|
||||
* (out->count reflects however many regions were actually populated).
|
||||
* top-right corner, plus whichever of location_line1/taken_at/share_url
|
||||
* are non-NULL/non-empty in their own corners (top-left, bottom-right,
|
||||
* bottom-left respectively), plus one region per entry in face_labels
|
||||
* (positioned near that face rather than a fixed corner -- see
|
||||
* render_face_label_region() in the .c file for the clamping logic).
|
||||
* Each region is its own separately malloc'd small buffer (not a full
|
||||
* EPD_FRAME_BYTES frame). A failure rendering the top-right region fails
|
||||
* the whole call; a failure rendering any other region just skips that
|
||||
* region and keeps going. Caller must call manage_overlay_free() on out
|
||||
* regardless of the return value (out->count reflects however many
|
||||
* regions were actually populated).
|
||||
*/
|
||||
esp_err_t manage_overlay_render(const manage_overlay_content_t *content, manage_overlay_set_t *out);
|
||||
|
||||
|
||||
Reference in New Issue
Block a user