Files
pilot/scripts/install_pilot.sh
gilles soulier ffabf65b35 feat(yoga14): remote control, app management, install script
- Add keycode module: G7BTS Rii remote control support (evdev, auto-reconnect)
- Add key bindings: single/double press detection with configurable window
  - KEY_HOMEPAGE: single=VacuumTube, double=LiveboxTV
  - KEY_OK: inject Enter keypress via ydotool
  - KEY_PAGEUP/DOWN: LiveboxTV channel navigation
- Add M3U parser and channel selector for LiveboxTV (51 channels)
- Add volume entity (wpctl/PipeWire, 2s polling)
- Add app management: vacuum_tube, livebox_tv (start/stop/state via MQTT)
- Add grace period to prevent app state bounce after stop
- Fix screen ON via GNOME busctl: add SimulateUserActivity
- Fix power commands: trigger on ON, publish OFF immediately (momentary buttons)
- Disable GPU temp/usage entities
- Add install script: build, deploy to ~/pilot, systemd user service
- Fix service startup: WantedBy=graphical-session.target (full GNOME env at launch)

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-03-15 17:16:12 +01:00

253 lines
9.0 KiB
Bash
Executable File

#!/usr/bin/env bash
# Script d'installation de Pilot v2
# Usage:
# bash install_pilot.sh # premiere installation (clone depuis Gitea)
# bash install_pilot.sh --update # mise a jour (git pull + recompile + relance)
# bash install_pilot.sh --local # installe depuis le depot local (dev sur la meme machine)
#
# Le service est installe en tant que service UTILISATEUR (systemctl --user).
# loginctl enable-linger permet le demarrage automatique au boot sans connexion graphique.
#
# Prerequis:
# - rustup / cargo (https://rustup.rs)
# - git
# - sudo (pour loginctl enable-linger et l'ajout au groupe input)
set -euo pipefail
# ---------- Configuration ----------
GITEA_URL="https://gitea.maison43.duckdns.org/gilles/pilot"
INSTALL_DIR="/home/gilles/pilot"
SERVICE_NAME="pilot-v2"
SERVICE_DIR="$HOME/.config/systemd/user"
SERVICE_FILE="$SERVICE_DIR/${SERVICE_NAME}.service"
LOCAL_REPO_DIR="$(cd "$(dirname "$0")/.." && pwd)"
# Couleurs
RED='\033[0;31m'
GREEN='\033[0;32m'
YELLOW='\033[1;33m'
BLUE='\033[0;34m'
NC='\033[0m'
info() { echo -e "${GREEN}[INFO]${NC} $*"; }
warn() { echo -e "${YELLOW}[WARN]${NC} $*"; }
error() { echo -e "${RED}[ERROR]${NC} $*" >&2; exit 1; }
step() { echo -e "\n${BLUE}==> $*${NC}"; }
# ---------- Arguments ----------
MODE="install"
for arg in "$@"; do
case "$arg" in
--update) MODE="update" ;;
--local) MODE="local" ;;
esac
done
# ---------- Prerequis ----------
step "Verification des prerequis"
command -v git &>/dev/null || error "git non trouve. Installez-le: sudo apt install git"
command -v cargo &>/dev/null || error "cargo non trouve. Installez Rust: curl --proto '=https' --tlsv1.2 -sSf https://sh.rustup.rs | sh"
info "git et cargo disponibles"
# ---------- Sources : clone, pull ou copie locale ----------
step "Preparation des sources"
if [ "$MODE" = "local" ]; then
# Copie depuis le depot de developpement local
info "Synchronisation depuis le depot local: $LOCAL_REPO_DIR"
if [ ! -d "$INSTALL_DIR" ]; then
mkdir -p "$INSTALL_DIR"
fi
# Copie en preservant la config existante et en ignorant le dossier target
# On copie tout sauf target/ et le config.yaml de l'install (s'il existe)
(
cd "$LOCAL_REPO_DIR"
find . -mindepth 1 \
! -path './pilot-v2/target*' \
! -path './.git*' \
-print0 | tar --null -T - -cf - | tar -C "$INSTALL_DIR" -xf - \
--exclude='./pilot-v2/config.yaml' 2>/dev/null || true
)
# Copier le config.yaml seulement si absent
if [ ! -f "$INSTALL_DIR/pilot-v2/config.yaml" ] && [ -f "$LOCAL_REPO_DIR/pilot-v2/config.yaml" ]; then
cp "$LOCAL_REPO_DIR/pilot-v2/config.yaml" "$INSTALL_DIR/pilot-v2/config.yaml"
fi
info "Sources synchronisees dans $INSTALL_DIR"
elif [ "$MODE" = "update" ]; then
[ -d "$INSTALL_DIR/.git" ] || error "$INSTALL_DIR n'est pas un depot git. Lancez l'installation complete d'abord."
info "Mise a jour depuis Gitea..."
git -C "$INSTALL_DIR" pull
info "Sources mises a jour"
else
# Installation complete depuis Gitea
if [ -d "$INSTALL_DIR/.git" ]; then
warn "Depot deja present dans $INSTALL_DIR."
warn "Utilisez --update pour mettre a jour, ou --local pour copier depuis le depot dev."
read -rp "Continuer et mettre a jour le depot existant ? [o/N] " confirm
[[ "$confirm" =~ ^[oO]$ ]] || exit 0
git -C "$INSTALL_DIR" pull
else
if [ -d "$INSTALL_DIR" ] && [ "$(ls -A "$INSTALL_DIR" 2>/dev/null)" ]; then
error "$INSTALL_DIR existe et n'est pas vide. Supprimez-le ou utilisez --local / --update."
fi
info "Clonage depuis $GITEA_URL..."
git clone "$GITEA_URL" "$INSTALL_DIR"
fi
fi
# ---------- Compilation ----------
step "Compilation du binaire (release)"
cargo build --release --manifest-path "$INSTALL_DIR/pilot-v2/Cargo.toml"
BINARY="$INSTALL_DIR/pilot-v2/target/release/pilot-v2"
info "Binaire: $BINARY"
# ---------- Configuration ----------
step "Configuration"
CONFIG_FILE="$INSTALL_DIR/pilot-v2/config.yaml"
EXAMPLE_FILE="$INSTALL_DIR/config/config.example.yaml"
if [ ! -f "$CONFIG_FILE" ]; then
if [ -f "$EXAMPLE_FILE" ]; then
cp "$EXAMPLE_FILE" "$CONFIG_FILE"
warn "config.yaml cree depuis l'exemple. A editer avant le demarrage:"
warn " nano $CONFIG_FILE"
warn "Points cles a configurer:"
warn " - mqtt.host / username / password"
warn " - device.name (nom de la machine dans Home Assistant)"
warn " - bluetooth.devices[].mac (voir: bluetoothctl paired-devices)"
else
warn "Aucun exemple de config trouve. Creez $CONFIG_FILE manuellement."
fi
else
info "config.yaml existant conserve"
fi
# Dossier iptv
if [ -d "$INSTALL_DIR/iptv" ]; then
info "Dossier iptv/ present: $INSTALL_DIR/iptv/"
fi
# ---------- Groupe input (pour la telecommande evdev) ----------
step "Permissions groupe input"
if groups "$USER" | grep -qw input; then
info "Utilisateur $USER deja dans le groupe input"
else
warn "Ajout de $USER au groupe input (necessaire pour la telecommande evdev)..."
sudo usermod -aG input "$USER"
warn "IMPORTANT: deconnectez-vous et reconnectez-vous pour que le groupe prenne effet."
warn "Ou relancez le service apres reconnexion: systemctl --user restart $SERVICE_NAME"
fi
# ---------- Service systemd utilisateur ----------
step "Installation du service systemd utilisateur"
mkdir -p "$SERVICE_DIR"
# Detecter l'UID pour XDG_RUNTIME_DIR
USER_ID=$(id -u)
cat > "$SERVICE_FILE" <<EOF
[Unit]
Description=Pilot v2 MQTT Agent
Documentation=https://gitea.maison43.duckdns.org/gilles/pilot
# Demarre apres la session graphique GNOME (env complet: WAYLAND_DISPLAY, XAUTHORITY, XDG_*)
After=graphical-session.target network-online.target
Wants=network-online.target
[Service]
Type=simple
WorkingDirectory=${INSTALL_DIR}/pilot-v2
ExecStart=${BINARY}
# Redemarrage automatique en cas d'erreur (5s entre les tentatives)
Restart=on-failure
RestartSec=5
# Variables d'environnement
Environment=RUST_LOG=info
# Arret propre: pilot publie "offline" sur MQTT avant de quitter
# SIGTERM → pilot capte ctrl_c() et publie LWT offline, 10s max
KillSignal=SIGTERM
TimeoutStopSec=10
[Install]
# graphical-session.target: demarre quand GNOME est pret (env de session complet)
# linger doit etre actif pour que ca fonctionne au boot sans intervention
WantedBy=graphical-session.target
EOF
info "Fichier service cree: $SERVICE_FILE"
# ---------- Linger : demarrage au boot sans connexion ----------
step "Activation du demarrage automatique au boot (linger)"
if loginctl show-user "$USER" 2>/dev/null | grep -q "Linger=yes"; then
info "Linger deja actif pour $USER"
else
if loginctl enable-linger "$USER" 2>/dev/null; then
info "Linger active pour $USER — le service demarrera automatiquement au boot"
elif sudo loginctl enable-linger "$USER" 2>/dev/null; then
info "Linger active (via sudo) pour $USER"
else
warn "Impossible d'activer linger automatiquement."
warn "Activez-le manuellement: loginctl enable-linger $USER"
fi
fi
# ---------- Activation et demarrage ----------
step "Activation du service"
systemctl --user daemon-reload
systemctl --user enable "$SERVICE_NAME"
info "Service active au demarrage"
# Verifier si la config a l'air configuree
CONFIG_READY=true
if [ -f "$CONFIG_FILE" ]; then
if grep -qE 'host:\s+""\s*$|host:\s*$' "$CONFIG_FILE" 2>/dev/null; then
CONFIG_READY=false
fi
fi
if systemctl --user is-active --quiet "$SERVICE_NAME" 2>/dev/null; then
info "Redemarrage du service..."
systemctl --user restart "$SERVICE_NAME"
sleep 2
systemctl --user status "$SERVICE_NAME" --no-pager -l || true
elif $CONFIG_READY; then
info "Demarrage du service..."
systemctl --user start "$SERVICE_NAME" || true
sleep 2
systemctl --user status "$SERVICE_NAME" --no-pager -l || true
else
warn "Config non configuree (mqtt.host vide). Service NON demarre."
warn "Editez $CONFIG_FILE puis lancez:"
warn " systemctl --user start $SERVICE_NAME"
fi
# ---------- Resume ----------
echo ""
echo "══════════════════════════════════════════════════"
info "Installation terminee!"
echo ""
echo " Repertoire : $INSTALL_DIR"
echo " Binaire : $BINARY"
echo " Config : $CONFIG_FILE"
echo " Service : $SERVICE_NAME (utilisateur)"
echo ""
echo " Commandes utiles:"
echo " systemctl --user status $SERVICE_NAME"
echo " systemctl --user start $SERVICE_NAME"
echo " systemctl --user stop $SERVICE_NAME"
echo " systemctl --user restart $SERVICE_NAME"
echo " journalctl --user -u $SERVICE_NAME -f"
echo ""
echo " Mise a jour:"
echo " bash $0 --update # depuis Gitea"
echo " bash $0 --local # depuis le depot dev local"
echo ""
echo " Trouver les MAC Bluetooth:"
echo " bluetoothctl paired-devices"
echo "══════════════════════════════════════════════════"