Files
LEDMatrix/scripts/utils
ChuckBuildsandClaude Opus 5 c7eb09db1d feat(tools): manage the MQTT bridge and Pixlet editor from the Tools tab
Both shipped in #538 with no interface at all: the bridge could only be
configured by editing integrations/mqtt_bridge/bridge_config.json over SSH, and
the Pixlet editor was a script you had to know existed. Neither appeared
anywhere in the web UI. They are now two sections in the Tools tab.

**MQTT bridge.** Service state (installed / running / stopped), install, start,
stop and restart, and a form for every setting: broker host and port, username,
TLS, command topic, client id, API base, request timeout, on-demand duration
and log level.

The password is write-only. GET returns every other field plus a password_set
flag, never the value -- this interface has no authentication, so anything it
hands back is readable by anyone who can reach the port. Submitting a blank
password keeps whatever is stored; there is an explicit Clear for removing one.
The file is written through a temp file in the same directory and chmod 0600, so
a crash mid-write cannot leave a config the bridge would refuse to load. Values
are range-checked server-side (port, timeouts, log level, http(s) API base).

**Pixlet editor.** Lists the apps on disk and starts a session per app, with a
banner showing which app is open, a link to the editor, a countdown, and Stop.
The banner survives a page reload because status is polled while a session runs,
and Edit is disabled while one is open.

Two changes to the script make that safe to drive from a browser:

- It binds 0.0.0.0 by default (PIXLET_EDITOR_HOST overrides). Loopback-only
  meant the URL shown in a browser was unreachable and needed an SSH tunnel,
  which is the confusing path. The no-auth argument for loopback does not hold
  when web_interface already serves 0.0.0.0:5000 unauthenticated and can
  reconfigure everything.
- The session ends by itself after PIXLET_EDITOR_TIMEOUT (default 30 min),
  enforced by `timeout` inside the script rather than by the caller. The display
  is stopped while editing, so a forgotten session would otherwise leave the
  panel dark and read as broken hardware -- the timeout is the whole reason a
  Start button is defensible.

Two bugs found while testing that lifecycle, both of which would have bitten the
Stop button:

- GNU timeout runs its child in a NEW process group, so signalling the script's
  group killed only bash and orphaned pixlet with the port still bound. Now
  --foreground keeps one group, and the EXIT trap kills the recorded child too.
- The liveness check treated a zombie as running: the script is a child of the
  web process and stays unreaped after exiting, and signal 0 succeeds against a
  zombie, so a finished session would have read as running forever. It now reaps
  non-blockingly and falls back to /proc state for a process that is not ours.

Covered by test/js/dom/test_tools_sections.js (26 assertions, real DOM against
the server-rendered partial): form prefill, the blank-means-unchanged password
contract, the running-session banner and countdown, and that the editor link
uses the host the page was loaded from. Also chmod +x on both scripts, which the
docs tell you to run directly.

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_014RRtqXDCnvnY6EQwhT5CV9
2026-09-09 11:20:18 -04:00
..
2025-12-27 14:15:49 -05:00
2025-12-27 14:15:49 -05:00

Utility Scripts

This directory contains utility scripts for maintenance and system operations.

Scripts

  • clear_cache.py - Clears LEDMatrix cache data (specific keys or all cache)
  • start_web_conditionally.py - Conditionally starts the web interface based on config settings
  • wifi_monitor_daemon.py - Background daemon that monitors WiFi/Ethernet connection and manages access point mode
  • cleanup_venv.sh - Cleans up Python virtual environment files
  • clear_python_cache.sh - Clears Python cache files (pycache, *.pyc, etc.)
  • pixlet_config_editor.sh - Opens Pixlet's own config UI for one installed Starlark app
  • apply_dns_single_request.sh - Adds options single-request to the resolver (run by ledmatrix-dns-fix.service)

Usage

Clear Cache

python3 scripts/utils/clear_cache.py --list          # List cache keys
python3 scripts/utils/clear_cache.py --clear-all      # Clear all cache
python3 scripts/utils/clear_cache.py --clear <key>    # Clear specific key

Start Web Interface Conditionally

This script is typically called by the systemd service (ledmatrix-web.service) and checks the web_display_autostart setting in config/config.json before starting the web interface.

WiFi Monitor Daemon

This daemon is typically run as a systemd service (ledmatrix-wifi-monitor.service) and automatically manages WiFi access point mode based on network connectivity.

Pixlet Config Editor

Run it when you want Pixlet's own config form for a Starlark app -- live render preview, cascading dropdowns -- rather than the LEDMatrix one.

./scripts/utils/pixlet_config_editor.sh                 # list installed apps
./scripts/utils/pixlet_config_editor.sh penndot_signs   # edit, on localhost:8080

Deliberately not a service. It stops the display for the length of the session and pixlet serve listens with no authentication, so it should only be running while you are actually editing. It backs the config up first and restarts the display on exit, however it exits.

It binds loopback only, with no flag to change that: anything that can reach pixlet serve can rewrite the app's config, and a printed warning is not access control. To edit from another machine, forward the port -- SSH does the authenticating and nothing is left listening on the LAN:

ssh -L 8080:localhost:8080 pi@ledpi.local

Apply DNS Single-Request Fix

Installed and run by ledmatrix-dns-fix.service; see systemd/README.md. Safe to run by hand (sudo ./scripts/utils/apply_dns_single_request.sh) and idempotent.