# Remote Testing on Reachy Mini Run hardware tests directly on the robot via SSH + rsync. This avoids network-latency artefacts and ensures audio playback uses the robot's local speakers (WAV files are silently dropped over WebRTC). ## Robot Models | Model | Default hostname | User | Notes | |-------|-----------------|------|-------| | **Wireless** | `reachy-mini.local` | `pollen` | Wi-Fi, mDNS discovery | | **Lite** | `reachy-mini.local` | `pollen` | Same procedure, may differ in hostname/IP | Both models use the same venv on-robot: ``` /venvs/apps_venv/bin/python ``` ## One-Time SSH Key Setup Identical across Linux, macOS, and Windows (WSL2/Git Bash): ```bash # Generate a key if you don't already have one ssh-keygen -t ed25519 -f ~/.ssh/id_ed25519 # Copy it to the robot (password: pollen) ssh-copy-id pollen@reachy-mini.local # Verify passwordless access ssh pollen@reachy-mini.local echo OK ``` ## Network Discovery The robot advertises itself via mDNS as `reachy-mini.local`. | Platform | mDNS support | Notes | |----------|-------------|-------| | **Linux (Ubuntu)** | Requires `avahi-daemon` | Usually pre-installed; `sudo apt install avahi-daemon` if not | | **macOS** | Built-in (Bonjour) | Works out of the box | | **Windows** | Not native | Use WSL2 or Git Bash; fall back to `--host ` | If mDNS doesn't resolve, find the robot's IP from your router or use: ```bash python tests/run_on_robot.py --host 192.168.1.42 ``` ## What Gets Synced The `run_on_robot.py` script uses `rsync -avz --delete` to sync three items to `/tmp/marionette_test/` on the robot: | Local path | Remote path | Contents | |-----------|------------|----------| | `marionette/` | `/tmp/marionette_test/marionette/` | Python package | | `tests/` | `/tmp/marionette_test/tests/` | Test files | | `pyproject.toml` | `/tmp/marionette_test/pyproject.toml` | Package metadata | ### Excluded from sync - `__pycache__/` — bytecode cache - `*.egg-info/` — build artefacts - `build/` — build output - `local_dataset/` — user data - `.pytest_cache/` — pytest cache - `dataset_registry.json` — local state - `temp_uploads/` — uploaded audio files - `tests/e2e/` — browser tests (no browser on robot) - `tests/test_results.json` — local results log - `.git/` — version control ## Commands ### Run hardware tests on the robot ```bash cd marionette python tests/run_on_robot.py ``` This will: 1. Create `/tmp/marionette_test/` on the robot 2. rsync the code (excluding E2E tests, caches, user data) 3. Install missing dev deps (`pytest`, `httpx`, `pytest-json-report`, `scipy`) 4. Run `pytest -m hardware -v` on the robot, streaming output 5. Fetch the JSON report and print a summary **Options:** ```bash python tests/run_on_robot.py --dry-run # show what would be synced python tests/run_on_robot.py --host 192.168.1.42 # custom host/IP python tests/run_on_robot.py --user pollen # custom SSH user python tests/run_on_robot.py -k test_playback # extra pytest args ``` ### Run smoke test on the robot A quick check that the robot moves and audio plays: ```bash cd marionette python tests/run_smoke_on_robot.py ``` ### Via the main test runner ```bash cd marionette python tests/run_tests.py --on-robot python tests/run_tests.py --on-robot --host 192.168.1.42 ``` ## Platform Notes ### Ubuntu (Linux) - Ensure `avahi-daemon` is running for `.local` resolution - If the default system mic is the robot's mic, audio recording tests may hang — use an external mic or skip audio tests with `-k "not Audio"` - Tested with Python 3.10+ ### macOS - Bonjour handles `.local` resolution automatically - No known issues with SSH/rsync workflow ### Windows - Use WSL2 or Git Bash for SSH/rsync - mDNS (`.local`) doesn't work natively — use `--host ` instead - Or install Bonjour Print Services for mDNS support ## For AI Agents ### Prerequisites - **Sandbox must be disabled** — the robot SDK uses Zenoh on `tcp/localhost:7447` which requires real network access. Use `/sandbox` → disable in Claude Code. - **Bash permissions** — must be allowed for running SSH commands ### Detecting the robot ```bash # Quick connectivity check (exits 0 if robot is reachable) cd marionette python tests/check_robot.py ``` This imports `ReachyMini()` and checks for a response. Times out after 15 seconds if the robot is unreachable. ### What's pre-installed on the robot The robot runs Ubuntu with Python 3.12 in `/venvs/apps_venv/`. The following are already available: - `reachy_mini` SDK - `numpy`, `scipy` - `soundfile` (for audio) - Standard system tools: `rsync`, `ssh`, `python3` Dev dependencies (`pytest`, `httpx`, `pytest-json-report`) are installed automatically by `run_on_robot.py` if missing. ### Running tests programmatically ```python import subprocess result = subprocess.run( ["python", "tests/run_on_robot.py", "--host", "reachy-mini.local"], cwd="/path/to/marionette", capture_output=True, text=True, ) print(result.stdout) ``` ## Deploying the app (not tests) To deploy and run marionette on a Wireless robot for manual testing (not automated tests), use `deploy_wireless.sh` from the project root. See `TESTING.md` for details. ## Troubleshooting | Problem | Solution | |---------|----------| | `ssh: Could not resolve hostname reachy-mini.local` | Install avahi-daemon (Linux) or use `--host ` | | `Permission denied (publickey)` | Run `ssh-copy-id pollen@reachy-mini.local` | | `rsync: connection unexpectedly closed` | Check robot is powered on and on the same network | | `ReachyMini() connection timed out` | Robot may be starting up — wait 30s and retry | | Audio tests hang | System mic may be the robot's mic; use external mic or skip with `-k "not Audio"` | | `ModuleNotFoundError: No module named 'marionette'` | Ensure `PYTHONPATH` includes the sync dir (handled by `run_on_robot.py`) |