Initial commit: Javis project
This commit is contained in:
commit
435c645f36
164 files changed
+35279
No files matched your search
@@ -0,0 +1,122 @@
|
||||
#!/usr/bin/env bash
|
||||
# One-shot Raspberry Pi installer for javis-slave (headless or with touch display).
|
||||
#
|
||||
# sudo ./setup-pi.sh # headless satellite (mic + speaker)
|
||||
# sudo ./setup-pi.sh --gui # Pi with official touch display
|
||||
# sudo ./setup-pi.sh --with-vad # also install silero-vad (+PyTorch, ~200 MB)
|
||||
#
|
||||
# Idempotent: re-running upgrades the venv and rewrites the service unit.
|
||||
set -euo pipefail
|
||||
|
||||
INSTALL_DIR="${INSTALL_DIR:-/opt/javis-slave}"
|
||||
SERVICE_USER="${SERVICE_USER:-${SUDO_USER:-pi}}"
|
||||
WITH_GUI=0
|
||||
WITH_VAD=0
|
||||
for arg in "$@"; do
|
||||
case "$arg" in
|
||||
--gui) WITH_GUI=1 ;;
|
||||
--with-vad) WITH_VAD=1 ;;
|
||||
-h|--help) sed -n '2,9p' "$0"; exit 0 ;;
|
||||
*) echo "unknown option: $arg" >&2; exit 2 ;;
|
||||
esac
|
||||
done
|
||||
|
||||
if [[ $EUID -ne 0 ]]; then
|
||||
echo "Run with sudo (installs apt packages and a systemd unit)." >&2
|
||||
exit 1
|
||||
fi
|
||||
|
||||
SRC_DIR="$(cd -- "$(dirname -- "${BASH_SOURCE[0]}")" && pwd)"
|
||||
|
||||
echo "==> apt packages"
|
||||
apt-get update -qq
|
||||
# portaudio: sounddevice; libsndfile: soundfile; alsa-utils: amixer/aplay/arecord;
|
||||
# libatomic1 + libopenblas: onnxruntime/numpy wheels on aarch64.
|
||||
apt-get install -y -qq python3 python3-venv python3-dev libportaudio2 libsndfile1 \
|
||||
alsa-utils libatomic1 libopenblas0 rsync
|
||||
if [[ $WITH_GUI -eq 1 ]]; then
|
||||
# Qt platform plugin deps for PySide6 wheels on Raspberry Pi OS + colour emoji
|
||||
# glyphs used by the orb/buttons (🎤 🔊 ⚙).
|
||||
apt-get install -y -qq libxcb-cursor0 libxkbcommon-x11-0 libegl1 libgl1 libglib2.0-0 \
|
||||
libfontconfig1 libdbus-1-3 fonts-noto-color-emoji
|
||||
fi
|
||||
|
||||
echo "==> copying to ${INSTALL_DIR}"
|
||||
mkdir -p "$INSTALL_DIR"
|
||||
if [[ "$SRC_DIR" != "$INSTALL_DIR" ]]; then
|
||||
rsync -a --delete --exclude .venv --exclude config --exclude '__pycache__' \
|
||||
"$SRC_DIR"/ "$INSTALL_DIR"/
|
||||
fi
|
||||
mkdir -p "$INSTALL_DIR/config"
|
||||
chown -R "$SERVICE_USER":"$SERVICE_USER" "$INSTALL_DIR"
|
||||
|
||||
echo "==> python venv"
|
||||
extras=""
|
||||
[[ $WITH_GUI -eq 1 ]] && extras="gui"
|
||||
[[ $WITH_VAD -eq 1 ]] && extras="${extras:+$extras,}vad"
|
||||
sudo -u "$SERVICE_USER" bash -c "
|
||||
set -e
|
||||
cd '$INSTALL_DIR'
|
||||
[[ -x .venv/bin/python ]] || python3 -m venv .venv
|
||||
.venv/bin/python -m pip install --upgrade pip wheel
|
||||
if [[ -n '$extras' ]]; then .venv/bin/python -m pip install -e '.[$extras]'; else .venv/bin/python -m pip install -e .; fi
|
||||
# Pre-download openWakeWord ONNX models so the service works offline later.
|
||||
.venv/bin/python -c 'from openwakeword.utils import download_models; download_models()' || true
|
||||
"
|
||||
|
||||
echo "==> permissions (audio, backlight)"
|
||||
usermod -aG audio,video "$SERVICE_USER"
|
||||
cat > /etc/udev/rules.d/90-javis-backlight.rules <<'EOF'
|
||||
# Let members of 'video' set the display brightness (javis-slave /mcp/v1/brightness).
|
||||
SUBSYSTEM=="backlight", ACTION=="add", RUN+="/bin/chgrp video /sys/class/backlight/%k/brightness", RUN+="/bin/chmod g+w /sys/class/backlight/%k/brightness"
|
||||
EOF
|
||||
udevadm control --reload-rules || true
|
||||
# Passwordless power control for the service user (only the exact commands used).
|
||||
cat > /etc/sudoers.d/javis-slave <<EOF
|
||||
$SERVICE_USER ALL=(root) NOPASSWD: /usr/bin/systemctl suspend, /usr/sbin/shutdown
|
||||
EOF
|
||||
chmod 0440 /etc/sudoers.d/javis-slave
|
||||
|
||||
echo "==> systemd unit"
|
||||
sed -e "s|^User=.*|User=$SERVICE_USER|" \
|
||||
-e "s|/opt/javis-slave|$INSTALL_DIR|g" \
|
||||
"$INSTALL_DIR/javis-slave.service" > /etc/systemd/system/javis-slave.service
|
||||
systemctl daemon-reload
|
||||
if [[ $WITH_GUI -eq 1 ]]; then
|
||||
# With a display the touch UI runs in the user's desktop session (kiosk),
|
||||
# not as a system service — both would fight over the microphone.
|
||||
systemctl disable javis-slave.service >/dev/null 2>&1 || true
|
||||
AUTOSTART_DIR="$(getent passwd "$SERVICE_USER" | cut -d: -f6)/.config/autostart"
|
||||
sudo -u "$SERVICE_USER" mkdir -p "$AUTOSTART_DIR"
|
||||
cat > "$AUTOSTART_DIR/javis-slave.desktop" <<EOF
|
||||
[Desktop Entry]
|
||||
Type=Application
|
||||
Name=Javis Slave
|
||||
Exec=env JAVIS_SLAVE_CONFIG_DIR=$INSTALL_DIR/config $INSTALL_DIR/.venv/bin/python -m javis_slave --kiosk
|
||||
X-GNOME-Autostart-enabled=true
|
||||
EOF
|
||||
chown "$SERVICE_USER":"$SERVICE_USER" "$AUTOSTART_DIR/javis-slave.desktop"
|
||||
else
|
||||
systemctl enable javis-slave.service
|
||||
fi
|
||||
|
||||
cat <<EOF
|
||||
|
||||
Done. Next steps:
|
||||
|
||||
1. Find your audio devices:
|
||||
sudo -u $SERVICE_USER JAVIS_SLAVE_CONFIG_DIR=$INSTALL_DIR/config \\
|
||||
$INSTALL_DIR/.venv/bin/python -m javis_slave --list-devices
|
||||
2. Pair with the master (generate a code in its Devices tab), e.g.:
|
||||
sudo -u $SERVICE_USER JAVIS_SLAVE_CONFIG_DIR=$INSTALL_DIR/config \\
|
||||
$INSTALL_DIR/.venv/bin/python -m javis_slave --headless \\
|
||||
--input-device 1 --output-device 0 --pair 192.168.1.10:8765 123456 --name Kueche
|
||||
Press Ctrl+C once you hear the wake chime working, then:
|
||||
EOF
|
||||
if [[ $WITH_GUI -eq 1 ]]; then
|
||||
echo " 3. Reboot (or log out/in): the touch UI autostarts in kiosk mode."
|
||||
echo " Manual start: $INSTALL_DIR/.venv/bin/python -m javis_slave --kiosk"
|
||||
else
|
||||
echo " 3. sudo systemctl start javis-slave"
|
||||
echo " journalctl -u javis-slave -f"
|
||||
fi
|
||||
Reference in new issue
Block a user