mirror of
https://github.com/ChuckBuilds/LEDMatrix.git
synced 2026-05-14 09:33:32 +00:00
* fix: pixlet install false-failure, force render in web service, web UI perf Fixes three user-reported issues: 1. Pixlet install reported failure even on success — `set -e` in download_pixlet.sh caused the script to exit non-zero when `((success_count++))` evaluated the post-increment old value (0), which bash treats as a failed command. Fixed with shell arithmetic assignment instead. 2. Force render returned 503 "plugin not loaded in web service" — the web service runs its own PluginManager with display_manager=None, so the starlark-apps plugin can never be loaded there. Added a standalone render path (_standalone_render_starlark_app) that calls pixlet directly from the web service, writing to cached_render.webp. The main-service plugin path is preserved and tried first. 3. Web UI sluggishness — the SSE /stream/stats generator was blocking a Flask thread for 1s per tick via psutil.cpu_percent(interval=1). Switched to non-blocking interval=None (primed at startup). Also cached the per-client ledmatrix systemctl check (15s TTL), raised the AP mode check TTL from 5s to 30s, and halved the display preview poll rate from 0.5s to 1s. Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com> * refactor(starlark): surface config errors, deduplicate pixlet lookup, uniform response shape - _standalone_render_starlark_app: split silent except into separate json.JSONDecodeError and OSError handlers that return (False, message) with the file path and parse error, so callers know when config.json is unreadable rather than silently rendering with empty config - get_starlark_status: replace 14-line inline platform/shutil pixlet lookup with _find_pixlet_binary(), which also checks the user- configured starlark-apps.pixlet_path — the old code never consulted that setting so the status endpoint could wrongly report pixlet unavailable even when a custom path was configured - render_starlark_app standalone branch: add frame_count: 0 to success and error responses so both branches return the same payload shape; 0 is accurate since standalone render writes cached_render.webp but does not extract frames into memory Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com> * fix(starlark): safe chmod fallback in pixlet lookup, semantic HTTP codes in standalone render _find_pixlet_binary: bundled.chmod(0o755) could raise OSError (e.g. file owned by root) and abort the entire resolution chain, skipping the PATH fallback. Now checks os.access first; if chmod is needed, wraps it in try/except OSError, logs a warning, and falls through to shutil.which so PATH is always tried. _standalone_render_starlark_app: expanded return type from (bool, str) to (bool, int, str) so each failure mode carries a semantic HTTP status code: app/star file missing → 404 invalid/unreadable config.json → 400 pixlet binary missing → 503 pixlet non-zero exit → 502 subprocess timeout → 504 unexpected exception → 500 success → 200 Call site updated to unpack (success, status_code, error) and forward status_code directly in both success and error responses. Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com> * fix(starlark): validate config.json is a dict before iterating items json.load succeeds on valid JSON that isn't an object (e.g. an array or bare string), leaving app_config as a non-dict and causing an AttributeError on the subsequent .items() call. Added isinstance check immediately after json.load; non-dict values return (False, 400, ...) with the actual type name in the message. Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com> * fix(starlark): harden pixlet binary check and manifest shape validation _find_pixlet_binary: switched bundled.exists() to bundled.is_file() so a directory named pixlet-linux-arm64 (traversable, hence X_OK) is no longer returned as a binary; re-check os.access after chmod succeeds so we only return the path when executability is confirmed, with a separate warning if it still isn't executable after chmod. _standalone_render_starlark_app: added isinstance guards on the manifest and apps values returned by _read_starlark_manifest(); a manifest.json containing valid non-object JSON (e.g. an array) would previously raise AttributeError on .get(); invalid shape now returns (False, 400, ...) instead. Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com> --------- Co-authored-by: Chuck <chuck@example.com> Co-authored-by: Claude Sonnet 4.6 <noreply@anthropic.com>
140 lines
3.8 KiB
Bash
Executable File
140 lines
3.8 KiB
Bash
Executable File
#!/bin/bash
|
|
#
|
|
# Download Pixlet binaries for bundled distribution
|
|
#
|
|
# This script downloads Pixlet binaries from the Tronbyte fork
|
|
# for multiple architectures to support various platforms.
|
|
|
|
set -e
|
|
|
|
SCRIPT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)"
|
|
PROJECT_ROOT="$(dirname "$SCRIPT_DIR")"
|
|
BIN_DIR="$PROJECT_ROOT/bin/pixlet"
|
|
|
|
# Pixlet version to download (use 'latest' to auto-detect)
|
|
PIXLET_VERSION="${PIXLET_VERSION:-latest}"
|
|
|
|
# GitHub repository (Tronbyte fork)
|
|
REPO="tronbyt/pixlet"
|
|
|
|
echo "========================================"
|
|
echo "Pixlet Binary Download Script"
|
|
echo "========================================"
|
|
|
|
# Auto-detect latest version if needed
|
|
if [ "$PIXLET_VERSION" = "latest" ]; then
|
|
echo "Detecting latest version..."
|
|
PIXLET_VERSION=$(curl -s "https://api.github.com/repos/${REPO}/releases/latest" | grep '"tag_name"' | sed -E 's/.*"([^"]+)".*/\1/')
|
|
if [ -z "$PIXLET_VERSION" ]; then
|
|
echo "Failed to detect latest version, using fallback"
|
|
PIXLET_VERSION="v0.50.2"
|
|
fi
|
|
fi
|
|
|
|
echo "Version: $PIXLET_VERSION"
|
|
echo "Target directory: $BIN_DIR"
|
|
echo ""
|
|
|
|
# Create bin directory if it doesn't exist
|
|
mkdir -p "$BIN_DIR"
|
|
|
|
# New naming convention: pixlet_v0.50.2_linux-arm64.tar.gz
|
|
# Only download ARM64 Linux binary for Raspberry Pi
|
|
declare -A ARCHITECTURES=(
|
|
["linux-arm64"]="pixlet_${PIXLET_VERSION}_linux-arm64.tar.gz"
|
|
)
|
|
|
|
download_binary() {
|
|
local arch="$1"
|
|
local archive_name="$2"
|
|
local binary_name="pixlet-${arch}"
|
|
|
|
local output_path="$BIN_DIR/$binary_name"
|
|
|
|
# Skip if already exists
|
|
if [ -f "$output_path" ]; then
|
|
echo "✓ $binary_name already exists, skipping..."
|
|
return 0
|
|
fi
|
|
|
|
echo "→ Downloading $arch..."
|
|
|
|
# Construct download URL
|
|
local url="https://github.com/${REPO}/releases/download/${PIXLET_VERSION}/${archive_name}"
|
|
|
|
# Download to temp directory (use project-local temp to avoid /tmp permission issues)
|
|
local temp_dir
|
|
temp_dir=$(mktemp -d -p "$PROJECT_ROOT" -t pixlet_download.XXXXXXXXXX)
|
|
local temp_file="$temp_dir/$archive_name"
|
|
|
|
if ! curl -L -o "$temp_file" "$url" 2>/dev/null; then
|
|
echo "✗ Failed to download $arch"
|
|
rm -rf "$temp_dir"
|
|
return 1
|
|
fi
|
|
|
|
# Extract binary
|
|
echo " Extracting..."
|
|
if ! tar -xzf "$temp_file" -C "$temp_dir"; then
|
|
echo "✗ Failed to extract archive: $temp_file"
|
|
rm -rf "$temp_dir"
|
|
return 1
|
|
fi
|
|
|
|
# Find the pixlet binary in extracted files
|
|
local extracted_binary
|
|
extracted_binary=$(find "$temp_dir" -name "pixlet" | head -n 1)
|
|
|
|
if [ -z "$extracted_binary" ]; then
|
|
echo "✗ Binary not found in archive"
|
|
rm -rf "$temp_dir"
|
|
return 1
|
|
fi
|
|
|
|
# Move to final location
|
|
mv "$extracted_binary" "$output_path"
|
|
|
|
# Make executable
|
|
chmod +x "$output_path"
|
|
|
|
# Clean up
|
|
rm -rf "$temp_dir"
|
|
|
|
# Verify
|
|
local size
|
|
size=$(stat -f%z "$output_path" 2>/dev/null || stat -c%s "$output_path" 2>/dev/null || echo "unknown")
|
|
if [ "$size" = "unknown" ]; then
|
|
echo "✓ Downloaded $binary_name"
|
|
else
|
|
echo "✓ Downloaded $binary_name ($(numfmt --to=iec-i --suffix=B $size 2>/dev/null || echo "${size} bytes"))"
|
|
fi
|
|
|
|
return 0
|
|
}
|
|
|
|
# Download binaries for each architecture
|
|
success_count=0
|
|
total_count=${#ARCHITECTURES[@]}
|
|
|
|
for arch in "${!ARCHITECTURES[@]}"; do
|
|
if download_binary "$arch" "${ARCHITECTURES[$arch]}"; then
|
|
success_count=$((success_count + 1))
|
|
fi
|
|
done
|
|
|
|
echo ""
|
|
echo "========================================"
|
|
echo "Download complete: $success_count/$total_count succeeded"
|
|
echo "========================================"
|
|
|
|
# List downloaded binaries
|
|
echo ""
|
|
echo "Installed binaries:"
|
|
if compgen -G "$BIN_DIR/*" > /dev/null 2>&1; then
|
|
ls -lh "$BIN_DIR"/*
|
|
else
|
|
echo "No binaries found"
|
|
fi
|
|
|
|
exit 0
|