#!/usr/bin/env bash # homeai-rpi/deploy.sh — Deploy/manage Wyoming Satellite on Raspberry Pi from Mac Mini # # Usage: # ./deploy.sh — full setup (push + install on Pi) # ./deploy.sh --status — check satellite status # ./deploy.sh --restart — restart satellite service # ./deploy.sh --logs — tail satellite logs # ./deploy.sh --test-audio — record 3s from mic, play back through speaker # ./deploy.sh --update — update Python packages only set -euo pipefail SCRIPT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)" # ─── Pi connection ────────────────────────────────────────────────────────── PI_HOST="SELBINA.local" PI_USER="aodhan" PI_SSH="${PI_USER}@${PI_HOST}" # Colors RED='\033[0;31m' GREEN='\033[0;32m' YELLOW='\033[1;33m' BLUE='\033[0;34m' CYAN='\033[0;36m' NC='\033[0m' log_info() { echo -e "${BLUE}[INFO]${NC} $*"; } log_ok() { echo -e "${GREEN}[OK]${NC} $*"; } log_warn() { echo -e "${YELLOW}[WARN]${NC} $*"; } log_error() { echo -e "${RED}[ERROR]${NC} $*"; exit 1; } log_step() { echo -e "${CYAN}[STEP]${NC} $*"; } # ─── SSH helpers ──────────────────────────────────────────────────────────── pi_ssh() { ssh -o ConnectTimeout=5 -o StrictHostKeyChecking=accept-new "${PI_SSH}" "$@" } pi_scp() { scp -o ConnectTimeout=5 -o StrictHostKeyChecking=accept-new "$@" } check_connectivity() { log_step "Checking connectivity to ${PI_HOST}..." if ! ping -c 1 -t 3 "${PI_HOST}" &>/dev/null; then log_error "Cannot reach ${PI_HOST}. Is the Pi on?" fi if ! pi_ssh "echo ok" &>/dev/null; then log_error "SSH to ${PI_SSH} failed. Set up SSH keys: ssh-copy-id ${PI_SSH}" fi log_ok "Connected to ${PI_HOST}" } # ─── Commands ─────────────────────────────────────────────────────────────── cmd_setup() { check_connectivity log_step "Pushing setup script to Pi..." pi_scp "${SCRIPT_DIR}/setup.sh" "${PI_SSH}:~/homeai-satellite-setup.sh" log_step "Running setup on Pi..." pi_ssh "chmod +x ~/homeai-satellite-setup.sh && ~/homeai-satellite-setup.sh" log_ok "Setup complete!" } cmd_status() { check_connectivity log_step "Satellite status:" pi_ssh "systemctl status homeai-satellite.service --no-pager" || true } cmd_restart() { check_connectivity log_step "Restarting satellite..." pi_ssh "sudo systemctl restart homeai-satellite.service" sleep 2 pi_ssh "systemctl is-active homeai-satellite.service" && log_ok "Satellite running" || log_warn "Satellite not active" } cmd_logs() { check_connectivity log_info "Tailing satellite logs (Ctrl+C to stop)..." pi_ssh "journalctl -u homeai-satellite.service -f --no-hostname" } cmd_test_audio() { check_connectivity log_step "Recording 3 seconds from mic..." pi_ssh "arecord -D plughw:2,0 -d 3 -f S16_LE -r 16000 -c 1 /tmp/homeai-test.wav 2>/dev/null" log_step "Playing back through speaker..." pi_ssh "aplay -D plughw:2,0 /tmp/homeai-test.wav 2>/dev/null" log_ok "Audio test complete. Did you hear yourself?" } cmd_update() { check_connectivity log_step "Updating Python packages on Pi..." pi_ssh "source ~/homeai-satellite/venv/bin/activate && pip install --upgrade wyoming-satellite openwakeword -q" log_step "Pushing latest scripts..." pi_scp "${SCRIPT_DIR}/satellite_wrapper.py" "${PI_SSH}:~/homeai-satellite/satellite_wrapper.py" pi_ssh "sudo systemctl restart homeai-satellite.service" log_ok "Updated and restarted" } cmd_push_wrapper() { check_connectivity log_step "Pushing satellite_wrapper.py..." pi_scp "${SCRIPT_DIR}/satellite_wrapper.py" "${PI_SSH}:~/homeai-satellite/satellite_wrapper.py" log_step "Restarting satellite..." pi_ssh "sudo systemctl restart homeai-satellite.service" sleep 2 pi_ssh "systemctl is-active homeai-satellite.service" && log_ok "Satellite running" || log_warn "Satellite not active — check logs" } cmd_test_logs() { check_connectivity log_info "Filtered satellite logs — key events only (Ctrl+C to stop)..." pi_ssh "journalctl -u homeai-satellite.service -f --no-hostname" \ | grep --line-buffered -iE \ 'Waiting for wake|Streaming audio|transcript|synthesize|Speaker active|unmute|_writer|timeout|error|Error|Wake word detected|re-arming|resetting' } # ─── Main ─────────────────────────────────────────────────────────────────── case "${1:-}" in --status) cmd_status ;; --restart) cmd_restart ;; --logs) cmd_logs ;; --test-audio) cmd_test_audio ;; --test-logs) cmd_test_logs ;; --update) cmd_update ;; --push-wrapper) cmd_push_wrapper ;; --help|-h) echo "Usage: $0 [command]" echo "" echo "Commands:" echo " (none) Full setup — push and install satellite on Pi" echo " --status Check satellite service status" echo " --restart Restart satellite service" echo " --logs Tail satellite logs (live, all)" echo " --test-logs Tail filtered logs (key events only)" echo " --test-audio Record 3s from mic, play back on speaker" echo " --push-wrapper Push satellite_wrapper.py and restart (fast iteration)" echo " --update Update packages and restart" echo " --help Show this help" echo "" echo "Pi: ${PI_SSH} (${PI_HOST})" ;; "") cmd_setup ;; *) log_error "Unknown command: $1. Use --help for usage." ;; esac