Tools > Admin: split the Radio tab's single "f,bw,sf,cr" comma-string field (free-text keyboard) into 4 independent, type-appropriate rows -- Frequency (same digit-cursor DigitEditor Settings/Repeater use locally), Bandwidth/Spreading factor/Coding rate (discrete-set LEFT/RIGHT stepping), plus TX power and the 3 Routing numeric fields as number steppers and Repeat as an ON/OFF toggle. Edits happen locally (zero mesh traffic per keystroke); only Enter sends one combined `set`, Cancel sends nothing. Full pre-release audit of all 16 commits since v1.22 (5 parallel focus areas: display/font, keyboard/messages, Nodes/Admin, Bot/channels, UITask+NodePrefs schema) turned up and fixed: - Admin: fetched FK_NUMBER values weren't clamped to the field's range, so a value already out-of-range could get stuck unreachable; fixed commit-time float format noise (%.6f -> %.3f); Cancel/failed-login always returned to the Nodes picker even when Admin was opened directly from a node's Hold-Enter action -- now returns to wherever it was actually opened from (AdminScreen::_from_picker). - Keyboard: one-shot Shift was consumed after the *first* T9 multi-tap, so cycling to the 2nd/3rd candidate always came out lowercase -- fixed by caching the cycle's caps state (t9_caps). - Messages: history is numbered newest-first, so a message arriving while scrolled up to an older one silently relabeled the view onto a different message -- selection now shifts with the insert. - Channels: onChannelRemoved() didn't clear ch_notif_override/ ch_notif_muted/ch_fav_bitmask despite its own contract comment requiring it (now far more reachable via the on-device Delete); an all-zero hex secret silently self-deleted the channel it was just saved into (collides with the empty-slot sentinel) -- rejected. - Room login: isRoomLoggedIn() indexed the login-tracking ring directly instead of via its head offset, silently wrong once the ring wraps (8+ rooms/session) -- the new on-device Logout depends on this being right. - Font/display: removed the now fully-inert Settings > Display > Font toggle and the dead LemonFont.h (retired by the earlier misc-fixed font unification, zero remaining includes); fixed a copy-pasted "5x7" comment (font is 6x9), two meaningless dead ternaries, and an OLED/e-ink inconsistency in the undefined-glyph fallback box offset. - AdminField's `kind`/bounds fields no longer rely on default member initializers inside aggregate-init: this toolchain's actual nRF52 build (unlike env:native) has no explicit -std= override, so it predates C++14's aggregate-with-default-member-initializer rule. Given an explicit constructor instead -- portable regardless of standard, all existing field-table literals unchanged. Docs updated to match: tools_screen.md (Diagnostics as a 3-tab carousel, was documented as one flat screen), message_screen.md (chat bubbles, newest-at-bottom, cursor mode, secret validation), settings_screen.md (dropped the dead Font row), solo_ui_framework.md (header menu_hint signatures, icon priority-drop, KeyboardWidget's T9/alphabets/cursor-mode). release-notes.md gains the v1.23 section covering all of the above plus the other 15 commits since v1.22. Build-verified on WioTrackerL1_companion_solo_dual. Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
Display Screenshot Tool
⚠️ Note: The screenshot feature requires the
ENABLE_SCREENSHOTbuild flag to be enabled. Add-D ENABLE_SCREENSHOTto your PlatformIO build flags, then recompile and flash the firmware.
The firmware supports capturing the current display contents and transmitting it over USB serial. This is useful for debugging, remote monitoring, or creating documentation.
Important: When the device is connected to the companion app, the USB serial port is not available for communication. To use the screenshot tool, ensure the device is not connected to the companion app.
Usage:
- Build and flash firmware with
-D ENABLE_SCREENSHOTbuild flag enabled
Example for the OLED dual firmware:
PLATFORMIO_BUILD_FLAGS="-D ENABLE_SCREENSHOT" pio run -e WioTrackerL1_companion_dual -t upload
-
Connect the device to your computer via USB (ensure no companion app connection)
-
Install dependencies and run the screenshot tool. To manage python and python dependencies, use uv: https://docs.astral.sh/uv/
cd tools uv run tools/screenshot.pyOptions:
--port PORT— Serial port to use (default: auto-detect)--scale SCALE— Upscale factor for the output image (1=no upscale, 2=2x, 3=3x, 4=4x, etc.; default: 1)
-
In the tool's interactive menu, press S to capture a screenshot
-
The tool will save the screenshot as a PNG file in
tools/pngs/with a timestamp-based filename
How it works:
- The tool sends the
CMD_GET_SCREENSHOTcommand (66) to the device - The device responds with
RESP_CODE_SCREENSHOT(29) containing the framebuffer data - The framebuffer is transmitted in chunks (128×64 display = 1024 bytes, split across multiple frames)
- The tool reassembles the chunks and converts them to a PNG image