Add non-regression test states and Bluetooth diagnostic script

- Introduced a new JSON file containing non-regression test states with detailed unit information, including positions, ages, and movement directions across multiple frames.
- Added a shell script for Bluetooth diagnostics that checks system information, Bluetooth binaries, running processes, D-Bus status, Bluetooth controller details, and audio stack status, providing a comprehensive overview for troubleshooting.
This commit is contained in:
2026-05-17 23:36:24 +02:00
parent dd82ccc087
commit 486cd6b7c5
31 changed files with 2244 additions and 698 deletions
+182
View File
@@ -0,0 +1,182 @@
#!/usr/bin/env bash
# Deploy Mice! to a Koriki CFW device over SSH.
#
# Requirements on host:
# sshpass, tar, ssh
#
# Target: koriki@<IP> (default 10.0.0.199)
# - ARMv7l Linux, glibc 2.28
# - Python 3.11 archive already present at /mnt/SDCARD/python_armv7.tar.gz
# - SDL2 libs in /mnt/SDCARD/Koriki/lib/
# - Internet access via WiFi
#
# Usage:
# ./packaging/deploy_koriki.sh [TARGET_IP]
set -euo pipefail
TARGET_IP="${1:-10.0.0.199}"
TARGET_USER="${TARGET_USER:-koriki}"
TARGET_PASS="${TARGET_PASS:-koriki}"
SDCARD="/mnt/SDCARD"
PYTHON_ARCHIVE="${SDCARD}/python_armv7.tar.gz"
PYTHON_DIR="${SDCARD}/python"
GAME_DIR="${SDCARD}/Ports/mice"
KORIKI_LIB="${SDCARD}/Koriki/lib"
VENDOR_DIR="${GAME_DIR}/vendor"
ROOT_DIR=$(CDPATH= cd -- "$(dirname -- "${BASH_SOURCE[0]}")/.." && pwd)
ssh_cmd() {
sshpass -p "$TARGET_PASS" ssh \
-o StrictHostKeyChecking=no \
-o ConnectTimeout=10 \
-o PreferredAuthentications=password \
-o PubkeyAuthentication=no \
"${TARGET_USER}@${TARGET_IP}" "$@"
}
log() { printf '==> %s\n' "$*"; }
# ── 1. Estrai Python 3.11 ──────────────────────────────────────────────────────
log "Step 1: Extracting Python 3.11 on device"
ssh_cmd "
if [ ! -f '${PYTHON_DIR}/bin/python3.11' ]; then
echo 'Extracting Python archive...'
tar -xzf '${PYTHON_ARCHIVE}' -C '${SDCARD}'
echo 'Done'
else
echo 'Python 3.11 already extracted, skipping'
fi
"
# ── 1b. Fix FAT32: i symlink non possono essere creati su vfat; li sostituiamo
# con copie reali dei file critici
log "Step 1b: Fixing missing symlinks on FAT32 (copying critical binaries)"
ssh_cmd "
PYBIN='${PYTHON_DIR}/bin'
PYLIB='${PYTHON_DIR}/lib'
# Copie necessarie all'interprete
[ ! -f \"\${PYBIN}/python3\" ] && cp \"\${PYBIN}/python3.11\" \"\${PYBIN}/python3\"
[ ! -f \"\${PYBIN}/python\" ] && cp \"\${PYBIN}/python3.11\" \"\${PYBIN}/python\"
[ ! -f \"\${PYBIN}/pip3\" ] && [ -f \"\${PYBIN}/pip3.11\" ] && cp \"\${PYBIN}/pip3.11\" \"\${PYBIN}/pip3\"
# Libreria condivisa
[ ! -f \"\${PYLIB}/libpython3.11.so\" ] && cp \"\${PYLIB}/libpython3.11.so.1.0\" \"\${PYLIB}/libpython3.11.so\"
echo 'Symlink workaround done'
"
# ── 2. Installa dipendenze Python ──────────────────────────────────────────────
log "Step 2: Installing Python dependencies (wheel download + extract)"
ssh_cmd "
PYTHON='${PYTHON_DIR}/bin/python3.11'
export TMPDIR='${GAME_DIR}/tmp'
export LD_LIBRARY_PATH='${PYTHON_DIR}/lib:${KORIKI_LIB}'
# pip --target su FAT32 puo fallire (rename di file temporanei).
# Workaround: scarichiamo wheel in /tmp e li estraiamo manualmente in vendor.
mkdir -p '${VENDOR_DIR}' '${GAME_DIR}/tmp' '${GAME_DIR}/tmp/mice_wheels'
rm -f '${GAME_DIR}/tmp/mice_wheels'/*.whl
\"\$PYTHON\" -m pip download --no-cache-dir \
--extra-index-url https://www.piwheels.org/simple/ \
--dest '${GAME_DIR}/tmp/mice_wheels' \
pysdl2 \
'Pillow>=10.0' \
'numpy>=1.26' \
pyaml \
requests
\"\$PYTHON\" - << 'PY'
import glob
import os
import zipfile
vendor = '${VENDOR_DIR}'
wheels = sorted(glob.glob('${GAME_DIR}/tmp/mice_wheels/*.whl'))
if not wheels:
raise SystemExit('No wheels downloaded')
for whl in wheels:
print('Extracting', os.path.basename(whl))
with zipfile.ZipFile(whl) as zf:
zf.extractall(vendor)
print('Dependencies extracted to', vendor)
PY
echo 'Dependencies installed (wheel extraction)'
"
# ── 3. Crea directory di gioco ─────────────────────────────────────────────────
log "Step 3: Creating game directory ${GAME_DIR}"
ssh_cmd "mkdir -p '${GAME_DIR}'"
# ── 4. Trasferisci il gioco ────────────────────────────────────────────────────
# Pipe diretta tar → tar: evita di scrivere file intermedi in /tmp (tmpfs 49MB)
log "Step 4: Transferring game files via direct pipe (no tmp file)"
tar czf - \
-C "$ROOT_DIR" \
--exclude='.git' \
--exclude='.venv' \
--exclude='venv' \
--exclude='__pycache__' \
--exclude='*.pyc' \
--exclude='dist' \
--exclude='logs' \
--exclude='packaging' \
--exclude='tools' \
--exclude='server' \
--exclude='*.tar.gz' \
. \
| sshpass -p "$TARGET_PASS" ssh \
-o StrictHostKeyChecking=no \
"${TARGET_USER}@${TARGET_IP}" \
"mkdir -p '${GAME_DIR}' && tar -xzf - -C '${GAME_DIR}' && echo 'Game extracted'"
# ── 5. Crea il launcher ────────────────────────────────────────────────────────
log "Step 5: Creating launcher script"
LAUNCHER_CONTENT="#!/bin/sh
# Mice! launcher for Koriki CFW
export PYTHON_DIR=\"${PYTHON_DIR}\"
export PATH=\"\${PYTHON_DIR}/bin:\$PATH\"
export PYTHONPATH=\"${VENDOR_DIR}:\${PYTHON_DIR}/lib/python3.11/site-packages\"
# Puntiamo PySDL2 alle librerie SDL2 di Koriki
export PYSDL2_DLL_PATH=\"${KORIKI_LIB}\"
export LD_LIBRARY_PATH=\"${KORIKI_LIB}:\${LD_LIBRARY_PATH:-}\"
# Root del progetto e dati persistenti
export MICE_PROJECT_ROOT=\"${GAME_DIR}\"
export MICE_DATA_DIR=\"\${SDCARD}/.mice_data\"
mkdir -p \"\${MICE_DATA_DIR}\"
cd \"\${MICE_PROJECT_ROOT}\"
exec \"\${PYTHON_DIR}/bin/python3\" rats.py \"\$@\"
"
ssh_cmd "cat > '${SDCARD}/Ports/mice.sh'" <<< "$LAUNCHER_CONTENT"
ssh_cmd "chmod +x '${SDCARD}/Ports/mice.sh'"
log "Launcher written to ${SDCARD}/Ports/mice.sh"
# ── 6. Test rapido ─────────────────────────────────────────────────────────────
log "Step 6: Quick smoke test"
ssh_cmd "
export PATH='${PYTHON_DIR}/bin:\$PATH'
export PYSDL2_DLL_PATH='${KORIKI_LIB}'
export LD_LIBRARY_PATH='${PYTHON_DIR}/lib:${KORIKI_LIB}'
export PYTHONPATH='${VENDOR_DIR}:${PYTHON_DIR}/lib/python3.11/site-packages'
python3 -c \"
import sys
print('Python', sys.version)
import sdl2; print('PySDL2 OK:', sdl2.__version__)
import numpy; print('NumPy OK:', numpy.__version__)
import PIL; print('Pillow OK:', PIL.__version__)
import yaml; print('pyaml OK')
import requests; print('requests OK')
print('All dependencies OK')
\"
"
log "Deployment complete!"
log "Run the game from Ports > mice on Koriki, or manually:"
log " ssh ${TARGET_USER}@${TARGET_IP} '${SDCARD}/Ports/mice.sh'"