63 lines
2.7 KiB
Bash
Executable File

#!/usr/bin/env bash
# p2ctl.sh — run / stop Sanad Package 4 (Guide Tour) in dev mode
# (no Docker), against the vendored engine in ./vendor. Self-contained: no sibling
# Sanad/ checkout needed.
#
# ./p2ctl.sh start | stop | restart | status | logs [N]
#
# The conda env must have google-genai AND (for the LED mask) bleak==0.22.3 + Pillow.
# Override env: SANAD_P4_PY, SANAD_DASHBOARD_PORT (8014), SANAD_AUDIO_PROFILE (builtin),
# SANAD_DDS_INTERFACE (eth0), SANAD_MASK_DIR, SANAD_LICENSE / SANAD_PUBKEY.
set -u
PKG_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)"
PY="${SANAD_P4_PY:-$HOME/miniconda3/envs/gemini_sdk/bin/python}"
PORT="${SANAD_DASHBOARD_PORT:-8014}"
APP="$PKG_DIR/app_p4.py"
LOG="$PKG_DIR/p4.log"
LIC="${SANAD_LICENSE:-$PKG_DIR/license/sanad.lic}"; [ -f "$LIC" ] || LIC="$PKG_DIR/license/sanad.lic.example"
_start() {
if pgrep -f app_p4.py >/dev/null 2>&1; then echo "P4 already running on :$PORT"; return 0; fi
[ -f "$APP" ] || { echo "ERROR: $APP not found (deploy first)"; return 1; }
cd "$PKG_DIR"
export SANAD_APP_DIR="$PKG_DIR/vendor" \
SANAD_LICENSE="$LIC" \
SANAD_PUBKEY="${SANAD_PUBKEY:-$PKG_DIR/license/pubkey.ed25519}" \
SANAD_MASK_DIR="${SANAD_MASK_DIR:-$PKG_DIR/vendor/mask}" \
PYTHONPATH="$PKG_DIR/vendor" \
SANAD_DASHBOARD_PORT="$PORT" SANAD_DASHBOARD_HOST="0.0.0.0" \
SANAD_VOICE_BRAIN="gemini" \
SANAD_AUDIO_PROFILE="${SANAD_AUDIO_PROFILE:-builtin}" \
SANAD_DDS_INTERFACE="${SANAD_DDS_INTERFACE:-eth0}" \
PYTHONUNBUFFERED=1
[ -f /usr/lib/aarch64-linux-gnu/libgomp.so.1 ] && export LD_PRELOAD=/usr/lib/aarch64-linux-gnu/libgomp.so.1
nohup "$PY" "$APP" > "$LOG" 2>&1 &
sleep 3
if pgrep -f app_p4.py >/dev/null 2>&1; then
echo "P4 started -> http://$(hostname -I | awk '{print $1}'):$PORT (log: $LOG)"
else
echo "P4 failed to start. Last log lines:"; tail -20 "$LOG"
fi
}
_stop() {
pgrep -f app_p4.py >/dev/null 2>&1 || { echo "P4 was not running."; return 0; }
pkill -f app_p4.py 2>/dev/null
for _ in $(seq 1 8); do pgrep -f app_p4.py >/dev/null 2>&1 || break; sleep 1; done
pgrep -f app_p4.py >/dev/null 2>&1 && pkill -9 -f app_p4.py 2>/dev/null
sleep 1
pgrep -f app_p4.py >/dev/null 2>&1 && echo "P4 still running (could not kill)." || echo "P4 stopped."
}
_status() { if pgrep -af app_p4.py; then echo -n "health: "; curl -s --max-time 4 "http://127.0.0.1:$PORT/api/health"; echo; else echo "P4 not running."; fi; }
_logs() { tail -n "${1:-40}" "$LOG" 2>/dev/null || echo "no log at $LOG"; }
case "${1:-}" in
start) _start ;;
stop) _stop ;;
restart) _stop; sleep 2; _start ;;
status) _status ;;
logs) shift; _logs "${1:-40}" ;;
*) echo "usage: $0 {start|stop|restart|status|logs [N]}"; exit 2 ;;
esac