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>
This commit is contained in:
252
scripts/install_pilot.sh
Executable file
252
scripts/install_pilot.sh
Executable file
@@ -0,0 +1,252 @@
|
||||
#!/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 "══════════════════════════════════════════════════"
|
||||
Reference in New Issue
Block a user