```bash #!/usr/bin/env bash set -euo pipefail # ========================= # Go2 Voice Starter Script # ========================= BASE_DIR="/home/unitree/GoVoice" PY_FILE="$BASE_DIR/Go2Voice.py" WIFI_DEV="wlan0" AUDIO_KEYWORDS_REGEX='anker|powerconf' # auto-detect USB audio by name (case-insensitive) ts() { date "+[%b %d %H:%M:%S]"; } echo "$(ts) πŸ“ Base dir: $BASE_DIR" cd "$BASE_DIR" # ------------------------------------------------------------------- # 0) Improve chances pactl works under systemd by setting runtime dir # ------------------------------------------------------------------- if [[ -z "${XDG_RUNTIME_DIR:-}" ]]; then UID_NOW="$(id -u)" if [[ -d "/run/user/$UID_NOW" ]]; then export XDG_RUNTIME_DIR="/run/user/$UID_NOW" fi fi # ============================================================ # 1) Ensure default route via Wi-Fi (non-interactive sudo safe) # ============================================================ echo "$(ts) 🌐 Ensuring default route via $WIFI_DEV ..." # Detect gateway from wlan0 route table (best) GW="$(ip -4 route show dev "$WIFI_DEV" 2>/dev/null | awk '/default via/ {print $3; exit}' || true)" # Fallback: infer gateway as x.x.x.1 from wlan0 IP if [[ -z "${GW:-}" ]]; then WIFI_IP="$(ip -4 addr show dev "$WIFI_DEV" 2>/dev/null | awk '/inet /{print $2}' | cut -d/ -f1 | head -n1 || true)" if [[ -n "${WIFI_IP:-}" ]]; then GW="$(awk -F. '{print $1"."$2"."$3".1"}' <<<"$WIFI_IP")" fi fi if [[ -z "${GW:-}" ]]; then echo "$(ts) ⚠️ Could not detect Wi-Fi gateway (no IP on $WIFI_DEV?). Skipping route fix." else echo "$(ts) βœ… Using gateway: $GW" # systemd service has no TTY β†’ only do route changes if sudo is non-interactive (NOPASSWD) if sudo -n true 2>/dev/null; then # Keep eth0 default route as a higher metric fallback; ensure wlan0 exists with a better metric sudo ip -4 route del default dev "$WIFI_DEV" 2>/dev/null || true sudo ip -4 route add default via "$GW" dev "$WIFI_DEV" metric 600 2>/dev/null || true else echo "$(ts) ⚠️ sudo needs password (systemd has no TTY). Skipping route fix." fi echo "$(ts) πŸ“‘ Current default routes:" ip -4 route show default 2>/dev/null || true fi # ============================================================ # 2) Audio (PulseAudio / PipeWire-Pulse) # ============================================================ echo "$(ts) πŸ”Š Checking PulseAudio (pactl)..." if ! command -v pactl >/dev/null 2>&1; then echo "$(ts) ❌ pactl not found. Install:" echo " sudo apt-get install -y pulseaudio-utils" exit 1 fi # Wait a bit for pulse server to come up echo "$(ts) ⏳ Waiting for audio server..." READY=0 for i in {1..25}; do if timeout 0.3s pactl info >/dev/null 2>&1; then READY=1 break fi sleep 0.25 done # If not ready, try to start pulseaudio (best-effort; safe if PipeWire is used too) if [[ "$READY" -ne 1 ]] && command -v pulseaudio >/dev/null 2>&1; then echo "$(ts) ⚠️ Audio server not ready, trying: pulseaudio --start" pulseaudio --start >/dev/null 2>&1 || true for i in {1..15}; do if timeout 0.3s pactl info >/dev/null 2>&1; then READY=1 break fi sleep 0.25 done fi if [[ "$READY" -ne 1 ]]; then echo "$(ts) ❌ PulseAudio/PipeWire not ready (pactl info failed)" exit 1 fi echo "$(ts) βœ… Audio server ready" # Auto-detect PowerConf/Anker sink+source (don’t hardcode names that may differ) SINK="$(pactl list short sinks 2>/dev/null | awk -v IGNORECASE=1 -v re="$AUDIO_KEYWORDS_REGEX" '$0 ~ re {print $2; exit}')" SOURCE="$(pactl list short sources 2>/dev/null | awk -v IGNORECASE=1 -v re="$AUDIO_KEYWORDS_REGEX" '$0 ~ re {print $2; exit}')" echo "$(ts) 🎧 Setting default speaker β†’ ${SINK:-}" if [[ -n "${SINK:-}" ]]; then pactl set-default-sink "$SINK" >/dev/null 2>&1 || echo "$(ts) ⚠️ Could not set default sink" else echo "$(ts) ⚠️ PowerConf/Anker sink not found; keeping current default" fi echo "$(ts) 🎀 Setting default microphone β†’ ${SOURCE:-}" if [[ -n "${SOURCE:-}" ]]; then pactl set-default-source "$SOURCE" >/dev/null 2>&1 || echo "$(ts) ⚠️ Could not set default source" else echo "$(ts) ⚠️ PowerConf/Anker source not found; keeping current default" fi echo echo "$(ts) πŸ“‹ Current PulseAudio defaults:" pactl info | grep -E "Default Sink|Default Source" || true echo # ============================================================ # 3) Run python # ============================================================ if [[ ! -f "$PY_FILE" ]]; then echo "$(ts) ❌ Python file not found: $PY_FILE" exit 1 fi echo "$(ts) πŸš€ Starting Gemini Sanad" echo "$(ts) 🐍 Running: $PY_FILE" exec python3 "$PY_FILE" ```