marionette / deploy_wireless.sh
RemiFabre
minor
57e03b6
#!/usr/bin/env bash
# ─────────────────────────────────────────────────────────────────────
# Deploy marionette to Reachy Mini Wireless and start it via the daemon.
#
# This is a development tool: it rsyncs your local source code to the
# robot's site-packages (the same place the dashboard installs to),
# then starts the app through the daemon API (same as clicking "Start"
# on the dashboard). Logs stream live to your terminal.
#
# PREREQUISITES:
# 1. Passwordless SSH access to the robot:
# ssh-copy-id pollen@reachy-mini.local (password: root)
#
# 2. The reachy-mini-daemon must be running on the robot.
# It starts automatically on boot. If stopped:
# ssh pollen@reachy-mini.local 'systemctl restart reachy-mini-daemon.service'
#
# 3. The robot must be powered on and on the same network as your laptop.
# If reachy-mini.local doesn't resolve, pass the IP address instead.
#
# WIRELESS ONLY:
# This script targets the Wireless version's shared venv at
# /venvs/apps_venv/ with Python 3.12. The Lite version uses a
# different venv layout β€” this script will NOT work on Lite as-is.
#
# HOW IT WORKS:
# 1. Checks the daemon is running (systemctl is-active)
# 2. Rsyncs marionette/ into site-packages (~1 second)
# 3. Stops any currently running app (POST /api/apps/stop-current-app)
# 4. Starts marionette via daemon (POST /api/apps/start-app/marionette)
# 5. Tails journalctl for live log output
#
# Ctrl+C detaches from logs β€” the app keeps running on the robot.
# You can also stop it from the dashboard, or with ./stop_app.sh.
#
# USAGE:
# ./deploy_wireless.sh # default: reachy-mini.local
# ./deploy_wireless.sh 192.168.1.42 # custom IP
# ./deploy_wireless.sh --sync-only # sync without starting
# ─────────────────────────────────────────────────────────────────────
set -euo pipefail
SYNC_ONLY=false
HOST="reachy-mini.local"
for arg in "$@"; do
case "$arg" in
--sync-only) SYNC_ONLY=true ;;
*) HOST="$arg" ;;
esac
done
USER="pollen"
SITE_PACKAGES="/venvs/apps_venv/lib/python3.12/site-packages"
REMOTE="${USER}@${HOST}"
TARGET="${REMOTE}:${SITE_PACKAGES}/marionette/"
DAEMON_API="http://127.0.0.1:8000/api/apps"
# Resolve the directory this script lives in (the marionette project root)
SCRIPT_DIR="$(cd "$(dirname "$0")" && pwd)"
SOURCE="${SCRIPT_DIR}/marionette/"
# ── 1. Check daemon is running ───────────────────────────────────────
echo "==> Checking daemon on ${HOST}..."
if ! ssh -o ConnectTimeout=5 "${REMOTE}" \
"systemctl is-active --quiet reachy-mini-daemon" 2>/dev/null; then
echo " ERROR: reachy-mini-daemon is not running on ${HOST}."
echo " Start it with: ssh ${REMOTE} 'sudo systemctl start reachy-mini-daemon'"
exit 1
fi
echo " Daemon is running."
# ── 2. Rsync source to site-packages ─────────────────────────────────
# This overwrites the installed package with your local source.
# The dashboard can still manage the app normally afterwards.
echo "==> Syncing marionette/ to ${HOST}..."
rsync -az --delete \
--exclude '__pycache__' \
--exclude '*.pyc' \
"$SOURCE" "$TARGET"
echo " Sync complete."
if $SYNC_ONLY; then
echo "Done (sync only)."
exit 0
fi
# ── 3. Stop any currently running app ─────────────────────────────────
# Uses the same daemon API as the dashboard's "Stop" button.
# This stops WHATEVER app is running (not just marionette).
echo "==> Stopping current app (if any)..."
ssh "${REMOTE}" "curl -sf -X POST ${DAEMON_API}/stop-current-app >/dev/null 2>&1 || true"
sleep 1
# ── 4. Start marionette via daemon API ────────────────────────────────
# Same as clicking "Start" on the dashboard. The daemon launches
# marionette as a managed subprocess with the correct venv and
# ReachyMini connection context.
echo "==> Starting marionette via daemon..."
RESP=$(ssh "${REMOTE}" "curl -sf -X POST ${DAEMON_API}/start-app/marionette 2>/dev/null")
if [ $? -ne 0 ]; then
echo " ERROR: Failed to start marionette via daemon API."
echo " Response: ${RESP}"
exit 1
fi
echo " Started."
echo ""
echo "Web UI: http://${HOST}:8042"
echo ""
# ── 5. Tail logs live ─────────────────────────────────────────────────
# Streams the daemon's journal output. Marionette's stdout/stderr
# appears here because it runs as a child of the daemon.
# Ctrl+C detaches from logs β€” the app keeps running on the robot.
echo "==> Tailing logs (Ctrl+C to detach β€” app keeps running)..."
echo ""
ssh "${REMOTE}" "journalctl -u reachy-mini-daemon -f --no-hostname -o cat" 2>/dev/null || true