Add DisplayFrame/DisplayPalette screen mirroring and DisplayInfo device metadata - #1054
Draft
jamesarich wants to merge 6 commits into
Draft
Add DisplayFrame/DisplayPalette screen mirroring and DisplayInfo device metadata#1054jamesarich wants to merge 6 commits into
jamesarich wants to merge 6 commits into
Conversation
FromRadio gains display_frame (tag 20) carrying chunked 1bpp framebuffer snapshots, bounded to 384 data bytes per chunk to respect the 512-byte MAX_TO_FROM_RADIO_SIZE cap. AdminMessage gains get_display_frame_request (one-shot) and set_display_mirror (continuous) to arm the stream. Complements the existing send_input_event for full remote display/control. Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
FORMAT_UNSPECIFIED = 0 per the file's sentinel convention (MONO_VLSB moves to 1); document chunk ordering, frame_id reboot/wraparound semantics, mid-frame disable draining, local-only admin verbs and their ack story; bound width/height with int_size:16; correct the options sizing arithmetic. Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
DeviceMetadata.display (tag 15) describes the panel during the handshake — dimensions, frame format, PanelClass (OLED/LCD/TFT/EINK/HUB75) and touch — so clients can gate mirroring UI, expect e-ink refresh behavior, and map taps to touch events; absence means no display. DisplayFrame gains rect_x/y/width/height, reserved so future dirty-rect streaming (LVGL UIs) stays additive; firmware sends full frames only for now. Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
…panels Streams the device's region color table (up to 48 rects with RGB565 on/off pairs plus defaults) as FromRadio.display_palette, chunked by region index and identified by a signature that DisplayFrame.palette_signature references — palettes re-send only when the layout or theme changes, so a color-TFT device mirrors in its true colors at mono bandwidth. Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Restate the options sizing arithmetic for the fields added since it was written (bound still holds at 447 <= 512); make palette override order explicitly global table order across chunk boundaries; allow palette chunks to interleave a frame's chunks; add the stale-partial-palette discard rule; drop the behavior-freezing parenthetical from PanelClass.TFT. Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
|
Important Draft PR not reviewedDraft PRs are not automatically reviewed by default.
To automatically review draft PRs, update your CodeRabbit configuration: reviews:
auto_review:
drafts: trueThanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out. Comment |
This was referenced Aug 31, 2026
Contributor
Author
|
Cross-platform feature spec (client-agnostic wire contract, reassembly rules, input mapping, UX and device requirements): meshtastic/design#142 |
|
The latest Buf updates on your PR. Results from workflow pull-request / build (pull_request).
|
Little-endian RGB565, rows tightly packed, carried in the partial-update rect fields — each rectangle completes independently under its own frame_id. Activates the reservation the rect fields were added for. Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
What does this PR do?
Adds the wire contract for mirroring a device's screen to its locally connected client, with remote control riding the existing
AdminMessage.send_input_event(#702). Prior art: meshtastic/web#224 proposed exactly this and was parked pending a design — cc @mkgin, @todd-herbert (this follows theget_display_frame_requestshape sketched there, plus a continuous mode).DisplayFrame(FromRadio.display_frame, tag 20): the 1bpp framebuffer as chunks of ≤384 bytes, self-describing (width/height/format/frame_id/offset/total_size), withrect_x/y/width/heightreserved so future dirty-rect RGB565 streaming (LVGL UIs) stays additive, andpalette_signaturekeying color.DisplayPalette(FromRadio.display_palette, tag 21): the device's color-region table (color-TFT/HUB75 devices paint the 1bpp UI through per-region on/off colors), signature-keyed and re-sent only when the layout or theme changes — a color-accurate mirror at mono bandwidth.DisplayInfo(DeviceMetadata.display, tag 15): panel geometry, frame format,PanelClass(OLED/LCD/TFT/EINK/HUB75) andhas_touch, sent during the handshake so clients can gate mirroring UI, expect e-ink refresh behavior, and map taps to touch events. Absent on display-less builds.AdminMessage.get_display_frame_request= 50 (one-shot) andset_display_mirror= 51 (continuous). Both documented local-connection-only: frames rideFromRadio, which never crosses the mesh.Size
bin/regen-protos.sh(nanopb 0.4.9):meshtastic_DisplayFrame_size= 419,meshtastic_DisplayPalette_size= 440, andmeshtastic_FromRadio_sizestays 510 ≤ 512 (MAX_TO_FROM_RADIO_SIZE) — MeshPacket remains the largest oneof member. Chunk bounds are budgeted inmesh.optionsalongside the fields.Notes for reviewers
buf breaking --against masteris clean;buf lintpasses;protoc --proto_path=. -o /dev/null meshtastic/*.protopasses.bytes/repeatedfield carries a nanopb bound (data max_size:384,regions max_count:16).frame_idreboot semantics, palette override precedence across chunks, stale-partial discard, mid-frame-disable draining.Firmware follow-up
Not included here — proto change only. Once merged, meshtastic/firmware needs a submodule bump and regenerated
src/mesh/generated/; the implementation is ready in meshtastic/firmware#11681, and the Android client in meshtastic/Meshtastic-Android#6987. Verified end-to-end on real hardware (RAK4631 WisMesh Pocket mono, LILYGO T-Deck in color).Checklist before merging
🤖 Generated with Claude Code