Skip to content

feat: add dev mode toggle and screen off burn-in protection#385

Open
mrosseel wants to merge 117 commits intobrickbots:mainfrom
mrosseel:screensaver
Open

feat: add dev mode toggle and screen off burn-in protection#385
mrosseel wants to merge 117 commits intobrickbots:mainfrom
mrosseel:screensaver

Conversation

@mrosseel
Copy link
Collaborator

Summary

  • Press square 7 times anywhere to toggle dev mode (shows popup feedback)
  • Dev mode unlocks "Screen Off" option in Status menu and unstable software channel
  • Screen off blanks display and LEDs after configurable timeout (burn-in protection)
  • Hourly LED heartbeat pulse while screen is off
  • Test mode now shows popup "Test Mode ON/OFF" and uses hollow camera icon

Test plan

  • Press square 7x → see "DEV MODE ON" popup
  • Go to Status → "Screen Off" option visible
  • Set sleep_timeout="10s", screen_off_timeout="30s"
  • Wait 10s → screen dims (sleep)
  • Wait 30s more → screen blanks, LEDs off
  • Press any key → full wake
  • Press square 7x → "DEV MODE OFF", Screen Off hidden

🤖 Generated with Claude Code

mrosseel and others added 30 commits February 4, 2026 19:02
- build.yml: single build + Cachix push + unstable channel updates
- release.yml: manual release workflow for stable/beta channels

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
The SD image module provides filesystems, but toplevel builds need
a minimal stub to evaluate successfully.

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
Required for NixOS module system to accept devMode setting.

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
Required when module has both options and config sections.

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
Replaces FIXME placeholders with actual SRI hashes.

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
Uses Pi5 runner when RUNNER_LABELS variable is set, falls back to
ubuntu with QEMU emulation otherwise.

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
- Filter to only Pi 4B device tree (CM4 incompatible with our overlays)
- Use shorthand DTS syntax for PWM overlay

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
Untracked file was excluded from Nix flake source tree, causing
"No module named 'PiFinder.sys_utils_base'" on SD card boot.

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
- Add camera overlay (imx477) to netboot config.txt via flake.nix
- Fix sys_utils import in main.py to use utils.get_sys_utils()
- Add hip_main.dat fetch to pifinder-src.nix for starfield plotting
- Add dma_heap udev rule for libcamera/picamera2 access
- Fix shared memory naming in solver.py (remove leading /)
- Add DNS nameservers for netboot environment
- Document power control scripts in CLAUDE.md

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
- Add runtimeCameraSelection option to hardware.nix (default: true)
- SD image includes config.txt with "include camera.txt" directive
- Users can edit camera.txt and reboot to switch cameras
- Supported cameras: imx296, imx290 (imx462), imx477
- Fix cameraDriver scope in hardware.nix (moved to top-level let)
- Add sudoers rules for systemctl stop/start pifinder.service
- Add DMA heap udev rule for libcamera video group access
- Netboot config sets cameraType = "imx477" for HQ camera dev

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
- Refactor sys_utils modules to use common base class
- Add sys_utils_nixos.py for NixOS-specific implementations
- Add get_sys_utils() detection in utils.py for platform selection
- Add flake.lock for reproducible builds
- Add NetworkManager config to networking.nix
- Add deploy-image-to-nfs.sh for netboot development workflow

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
- Update build.yml CI workflow
- Fix fonts.py import
- Fix marking_menus.py formatting
- Add missing import to preview.py
- Simplify objects_db.py
- Add catalog_imports improvements
- Update pifinder_objects.db

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
- Switch to NFSv4 with caching disabled (noac, actimeo=0)
- Disable auto-optimise-store in devMode (hard links fail on NFS)

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
- Add ServerAliveInterval/CountMax to prevent timeout during transfers
- Use rsync -R (relative) to preserve directory structure correctly

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
Comets.txt is downloaded at runtime and must be in a writable
location, not the read-only Nix store.

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
- Extend eth0 wait to 30 seconds with debug output
- Wait for link carrier before DHCP
- Add DHCP retries (3 attempts)
- Add LIBCAMERA_IPA_MODULE_PATH to pifinder service environment

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
Restore SUBSYSTEM=="pwm" udev rule that was accidentally removed.

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
Turns on keypad LEDs during sysinit for early visual boot feedback.

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
- boot-splash.c: displays welcome image with scanning animation
- Starts at sysinit, stops when pifinder.service starts
- Much faster than Python splash

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
- Remove nixos-hardware module (saves 659MB linux-firmware)
- Fetch nixos-rebuild at runtime (saves ~500MB llvm/nix deps)
- Remove git from systemPackages (nix has built-in git for flakes)

Target: ~150MB vs current 1.7GB
- Remove default packages (vim, nano, etc)
- Disable polkit, udisks2, speechd
- Should reduce closure significantly
NetworkManager-vpnc alone has 1.1GB closure (webkitgtk, llvm, etc).
Disable all NM plugins for bootstrap - we just need WiFi.
mrosseel and others added 22 commits February 13, 2026 13:25
switch-to-configuration stops changed services, which kills the
pifinder-upgrade service mid-switch. Move activation (test, health
check, bootloader persist, cleanup) into a systemd-run scope that
survives the service being stopped.

Poll /run/pifinder/upgrade-status file instead of relying solely on
systemctl is-active, which falsely reported failure.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
The systemd-run --scope approach failed — switch-to-configuration
deactivated the transient scope during daemon-reload. Instead, set
restartIfChanged=false and stopIfChanged=false on pifinder-upgrade
so it survives switch-to-configuration without being killed.

Also add granular upgrade phases (downloading, activating, verifying,
persisting) to the status file for future progress display.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Compares top-level keys in default_config.json between base and head
on pull requests. Emits ::warning:: annotations for any removed keys
to catch accidental breakage of user preferences across releases.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
version.txt was manually maintained and redundant. Now:
- CI stamps branch-sha as version for non-release builds
- Release workflow already sets version from input
- Python reads version from pifinder-build.json via utils.get_version()

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
This function was never called in production code.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Multiple queued runs for the same branch compete for the single
self-hosted runner and can stall the GitHub Actions dispatcher.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Save the unlock state to config so users don't have to tap
square 7 times after every reboot.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
- Upgrade service reports "downloading X/Y" progress
- UI shows progress bar with percentage and path count
- Non-blocking upgrade flow with polling
- Reboot-based upgrade instead of live switch
- Add subtitle support for PR titles/release names
- Scrolling text for long labels

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
Strict reverse path filtering blocks WiFi traffic when ethernet is also
connected on the same subnet, as return packets route via ethernet.
This breaks both direct connections and DHCP renewal on WiFi.

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
Document that nix build/eval must never run on Pi 4 targets due to
resource constraints. Include the correct upgrade workflow:
build on pi5 → push to cachix → trigger upgrade service on target.

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
- Add global dev_mode config option (replaces software_unstable_unlocked)
- Toggle dev mode by pressing square 7 times anywhere in UI
- Wire up screen_off_timeout: after sleep timeout, additional timeout
  blanks screen completely with hourly LED heartbeat
- Gate "Screen Off" status option and unstable software channel on dev_mode
- Add power_state=-1 for screen off mode with IMU wake detection

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
- Add test_mode state to SharedStateObj for tracking
- Toggle test mode on/off via menu (was activate-only)
- Show popup "Test Mode ON/OFF" when toggling
- Use hollow camera icon in title bar when test_mode is active
- Provides visual indicator that fake GPS data is in use

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
- Add global dev_mode config option (replaces software_unstable_unlocked)
- Toggle dev mode by pressing square 7 times anywhere in UI
- Wire up screen_off_timeout: after sleep timeout, additional timeout
  blanks screen completely with hourly LED heartbeat
- Gate "Screen Off" status option and unstable software channel on dev_mode
- Add power_state=-1 for screen off mode with IMU wake detection

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
- Add test_mode state to SharedStateObj for tracking
- Toggle test mode on/off via menu (was activate-only)
- Show popup "Test Mode ON/OFF" when toggling
- Use hollow camera icon in title bar when test_mode is active
- Provides visual indicator that fake GPS data is in use

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
@mrosseel mrosseel added the testable Ready for testing via PiFinder software update label Feb 20, 2026
mrosseel and others added 4 commits February 20, 2026 01:34
- Test Mode menu shows ON/OFF suffix dynamically
- Inverted camera icon (light bg, dark icon) when test mode active
- Debug camera only sends images to solver when test_mode ON
- Initialize test_mode in shared_state from config at startup
- Move Screen Off option to Experimental menu, gated by dev_mode

Co-Authored-By: Claude Sonnet 4.5 <noreply@anthropic.com>
Extract dev mode toggle into DevModeToggle class that runs before
register_activity(). When counting towards the 7-press toggle,
square presses are consumed and not forwarded to menu_manager,
fixing double-processing on physical hardware.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
mrosseel and others added 2 commits February 21, 2026 12:35
Derives version string from flake's self.shortRev so local nix builds
show "nix-<sha>" instead of stale CI-committed values.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
# Conflicts:
#	pifinder-build.json
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

testable Ready for testing via PiFinder software update

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant