142 lines
4.6 KiB
Bash
142 lines
4.6 KiB
Bash
```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:-<not found>}"
|
||
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:-<not found>}"
|
||
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"
|
||
```
|