Replies: 8 comments 3 replies
|
This fits, and the part you've identified as most reusable is the right part. Answers in order, plus three things worth pulling forward. 1. Neither a special Deck nor a parallel copy: factor the frame-collection layer out and give it two producers. The manifest, per-device frame digests, byte accounting, version digest, and orphan cleanup aren't deck-specific; the link graph and home-relative navigation are. So the sync layer becomes a shared primitive, a deck is one producer of a frame collection, and an album is another, sourced from a Gallery folder with its own authoring and lifecycle. Same move as This is compatible with #167 rather than competing with it. #167 is about when and what to show; the cache layer is about how frames reach the card. Different axis, so factoring it doesn't need to wait. 2. Yes to device-owned interval and shuffle, with two conditions. The interval should reuse the page wake cadence shape I've had in the backlog (a page proposes a sleep interval, the device clamps it to its own bounds) rather than inventing an album-specific timer. Same concept, and albums are a better first customer for it than pages were. The shuffle bag is genuinely new device state and I'm fine with it, but it breaks an assumption we just agreed in #147: once the device is advancing locally, the server no longer knows which frame is on the glass, so 3. Inherit 32 for the first slice, but shape the manifest so paging isn't a breaking change. Two notes from the server side: Bytes are not the binding constraint. At 800x480 a 4bpp frame is around 187 KiB and a 1-bit frame around 47 KiB, so a 64 MiB budget holds roughly 350 or 1,400 frames. The firmware page count is what limits an album, not the card, and for a photo frame the gap between 32 and 350 is the gap between a demo and the feature. Worth pricing paging early even if slice one ships without it. The existing capacity trim won't transfer as-is. It prioritises by ring distance from the deck's home page, which is meaningless for a shuffled album. Albums want a different fill order (play order, or simply until the budget is spent), so that heuristic needs to be a property of the producer rather than baked into the shared layer. 4. Yes, Web plus firmware first. Gallery already has the folders and multi-upload, so the server UI can prove the workflow end to end without any client work. Companion album management and sync progress are a good follow-up capability, not a blocker. 5. Yes, version on the heartbeat. The deck manifest already carries a version digest that One thing in this idea's favour that you undersold: albums are dramatically cheaper to warm than decks. Deck warming needs the browser pool per page, while photos only need Sequencing. Natural split is the usual one: I take the server side (factor the frame-collection layer, the album object, the Gallery action, per-device pre-render and sync), you take firmware playback (interval wake, shuffle bag, and paging if we go past 32). Worth agreeing the manifest shape between us before either side starts, since it's the contract both halves depend on. |
|
Since I will add SD-buffering anyhow (to support low-memory systems), I thought about adding this offline feature too. It would fit naturally into the minimal display program. There is one caveat: currently there is only one "push" slot. So anybody sending multiple photos to the offline slideshow system, only one of them will succeed. Basically this is what Frameo is doing. My parents have one of these displays backed by Frameo. Children and grandchildren can send images and they are automatically downloaded to the device and then it is all offline. Management of images is offline, i.e. if you run out of SD space, you have to delete images manually. |
|
Thanks — this split works for me. I’ll take the firmware playback side, and I agree we should pin the shared manifest before either implementation starts. From the firmware boundary, I think the contract needs to settle these points first:
Because the server refactor determines the endpoint and shared document envelope, it probably makes sense for you to sketch the first JSON shape. I can review it against the current fixed-memory parser/cache constraints and then immediately turn the accepted shape into host-side parser, shuffle-state and wake-policy tests before wiring the ESP-IDF path. I’ll hold off on coding against an invented schema in the meantime, but I’m ready to start as soon as that shape is pinned. |
|
I compared the existing v1 deck manifest and the planned v2 state-bundle shape against the firmware memory/runtime constraints. Here is a concrete candidate we can edit rather than continuing at the noun level. Capability (additive, with v1 compatibility): {
"frame_cache": {
"schema": 1,
"capacity_bytes": 67108864,
"max_frames": 32
},
"deck_cache": {
"schema": 1,
"capacity_bytes": 67108864
}
}Slice one can advertise both. Old servers keep using Heartbeat version signal: {
"collection": {
"id": "album:kitchen",
"kind": "album",
"version": "a1b2c3d4e5f60718"
}
}Absent means no collection is active. This can later carry a Deck collection too, but it need not replace the existing Paged manifest candidate: {
"schema": 1,
"collection_id": "album:kitchen",
"kind": "album",
"version": "a1b2c3d4e5f60718",
"total_frames": 127,
"cursor": null,
"next_cursor": "opaque-version-bound-cursor",
"frames": [
{
"frame_id": "photo:7f8c",
"position": 0,
"digest": "0f1e2d3c4b5a6978",
"bytes": 960000,
"ttl_s": 0,
"cache": true,
"url": "/api/v1/device/frame01/collection/frame/0f1e2d3c4b5a6978"
}
],
"producer": {
"album": {
"playback": {
"mode": "shuffle",
"interval_s": 1800,
"repeat": "reshuffle"
}
}
}
}My intent behind these fields:
Device report (never an exact live photo): {
"collection_state": {
"id": "album:kitchen",
"kind": "album",
"version": "a1b2c3d4e5f60718",
"state": "playing",
"cached_frames": 32,
"total_frames": 127
}
}One runtime detail the manifest should not accidentally conflate: playback cadence and network sync cadence are two deadlines. Firmware should wake at the earlier one; a frame-only deadline paints from SD and returns to sleep with the radio off, while the normal server cadence still performs the heartbeat/version check. A downloaded direct frame push pauses Album playback before paint, so it cannot be overwritten at the next local timer. If this is close to what you had in mind, the remaining choices I need pinned before coding are the endpoint names, whether |
|
The server side of slice one is built and pushed (edge v0.237.0), to the shape we pinned in
Endpoints: @bablokb, on the single push slot: this path sidesteps it. Album frames are pre-rendered per device into a content-addressed cache and served from That leaves firmware playback (your half), the report-ingest/Devices surface, real paging past 32, and the quiet-hours window. Want to settle 6 and 7 before you start on the parser? |
|
Accepted for slice 1: I will implement and validate firmware with album folders of 32 images or fewer, matching the advertised Recording one non-blocking follow-up for paging: the current server manifest emits every folder frame in one page and marks overflow entries This does not block the agreed first slice or its <=32-image test matrix. Before large-album support, we should either page/cap the returned frame entries or move the firmware collection path to a bounded/streaming parser. I will keep this explicit in the firmware test boundary. |
|
Thanks — confirmed from the firmware side:
No server-side changes are needed for these decisions. The large single-page manifest / 32 KiB receive ceiling noted below remains a non-blocking paging follow-up. |
|
Both decisions are recorded and the pinned doc already says what you confirmed, so nothing moved there: interruption stays "push interrupts, auto-resume at next interval; reassign or unbind stops", and quiet hours stay out of slice 1. Two server-side changes since, both on edge v0.239.0: The 32 KiB ceiling is closed rather than just noted. The playback report is now consumed. A
|
Uh oh!
There was an error while loading. Please reload this page.
Hi! After looking at the current Gallery, Rotations, Decks, and the new SD-backed deck cache, I wanted to ask about a common digital-photo-frame use case:
Why this seems close to what Tesserae already has
The current pieces cover much of the plumbing:
deck_cacheis runtime-advertised only when local storage is mounted, reports a capacity budget, and already provides content-addressed incremental frame sync plus orphan cleanup.Possible user-facing model
Rather than exposing generated photo Pages, a Gallery folder could gain an action such as Use as offline album:
The original JPEG/HEIC/WebP files could stay on the server. The card would hold only the device-native, already-fitted/dithered frame artifacts, preserving Tesserae as the rendering source of truth and avoiding image decoding on the ESP32.
Architecture questions
Before trying to prototype this, I would appreciate your view on where it belongs:
album_cache/frame-collection manifest?This is mainly a product/protocol question, not a request to force Gallery into Decks. The part that feels especially valuable to reuse is the proven
deck_cachemachinery; the user-facing object would still be an album sourced from Gallery.Does this fit the direction you have in mind for local storage, or are Decks intentionally the only abstraction that should place rendered frames on the card?
All reactions