955bfdfe07
- Onglet Groupes : boutons Modifier et Supprimer fonctionnels via délégation d'événements et data-attributes ; slugify() côté client synchronisé avec le serveur ; classe CSS btn-danger pour Supprimer - Export logs : bouton "Exporter JSON" dans l'onglet Logs (filtre niveau actif) - Export/Import config.yaml : section dédiée dans Configuration avec dialog système (backup automatique .bak avant import) via IPC Electron (config:export / config:import dans main.js + preload.js)
439 lines
14 KiB
Markdown
439 lines
14 KiB
Markdown
# PTT Live - Application Desktop Server
|
||
|
||
Application Electron pour gérer le serveur PTT Live avec interface graphique complète.
|
||
|
||
## 📸 Aperçu
|
||
|
||
L'application desktop intègre :
|
||
- ✅ **Dashboard temps réel** : stats, utilisateurs, QR Code (généré côté Main Process, sans dépendance CDN)
|
||
- ✅ **HTTPS automatique** : certificats locaux mkcert installés au premier lancement
|
||
- ✅ **Configuration audio** : sélection devices, sample rate, bitrate
|
||
- ✅ **Gestion groupes** : CRUD complet avec API
|
||
- ✅ **Monitoring** : VU-mètres temps réel via WebSocket, logs filtrables
|
||
- ✅ **Contrôle serveur** : démarrage manuel/arrêt avec feedback visuel
|
||
|
||
---
|
||
|
||
## 🚀 Démarrage Rapide
|
||
|
||
```bash
|
||
# Depuis la racine du projet
|
||
./start-desktop.sh
|
||
|
||
# OU manuellement
|
||
cd electron
|
||
npm start
|
||
```
|
||
|
||
Au premier lancement, l'app configure automatiquement les certificats HTTPS locaux (mkcert) — voir [HTTPS et certificats](#-https-et-certificats). Le serveur PTT Live **ne démarre pas automatiquement** : cliquez sur "Démarrer" dans le dashboard pour le lancer.
|
||
|
||
---
|
||
|
||
## 📦 Installation
|
||
|
||
Les dépendances sont déjà installées. Si nécessaire :
|
||
|
||
```bash
|
||
cd electron
|
||
npm install
|
||
```
|
||
|
||
---
|
||
|
||
## 🎯 Utilisation
|
||
|
||
### 1. Dashboard
|
||
|
||
**Stats temps réel** :
|
||
- Uptime serveur
|
||
- Nombre d'utilisateurs connectés
|
||
- Groupes actifs
|
||
- Total connexions
|
||
|
||
**QR Code** :
|
||
- Généré côté Main Process (lib `qrcode`, pas de CDN externe — fonctionne sans accès Internet sur le WiFi d'un événement)
|
||
- IP réseau détectée par le Main Process (même logique que pour les certificats mkcert)
|
||
- URL construite à partir du protocole/port réels du serveur (HTTPS par défaut)
|
||
- Scanner depuis smartphone pour connexion rapide
|
||
- Bouton copier URL
|
||
- Placeholder visuel tant que le serveur est arrêté ou qu'aucun QR code n'a été généré
|
||
|
||
**Utilisateurs** :
|
||
- Liste en temps réel
|
||
- Groupe de chaque utilisateur
|
||
- Heure de connexion
|
||
|
||
### 2. Configuration Audio
|
||
|
||
**Périphériques** :
|
||
- Sélection input/output depuis dropdown auto-détecté
|
||
- Support macOS (CoreAudio), Linux (JACK/PipeWire)
|
||
- Appliquer instantanément (bridge audio rechargé)
|
||
|
||
**Paramètres** :
|
||
- Sample Rate : 44.1 / 48 / 96 kHz
|
||
- Bitrate par défaut : 32-320 kbps
|
||
- Jitter Buffer : 20-100 ms
|
||
|
||
### 3. Gestion Groupes
|
||
|
||
- **Créer** : bouton "➕ Nouveau groupe"
|
||
- **Modifier** : depuis la liste (nom, bitrate)
|
||
- **Supprimer** : confirmation requise
|
||
- Sauvegardé automatiquement dans `config.yaml`
|
||
|
||
### 4. Monitoring
|
||
|
||
**VU-Mètres** :
|
||
- Niveaux audio par canal (input/output) et par groupe
|
||
- Temps réel via WebSocket (`/audio-levels`, même port que l'API)
|
||
- Reconnexion automatique si la connexion WebSocket tombe
|
||
|
||
### 5. Logs
|
||
|
||
- Logs serveur en temps réel
|
||
- Filtrage par niveau (error/warn/info/debug)
|
||
- Bouton "Effacer"
|
||
- Format timestamp + niveau + message
|
||
|
||
---
|
||
|
||
## 🏗️ Architecture Technique
|
||
|
||
```
|
||
┌─────────────────────────────────────────────────┐
|
||
│ ELECTRON APP (Desktop) │
|
||
│ │
|
||
│ ┌───────────────────────────────────────────┐ │
|
||
│ │ MAIN PROCESS (Node.js) │ │
|
||
│ │ │ │
|
||
│ │ • spawn server/index.js │ │
|
||
│ │ • IPC handlers (start/stop/status) │ │
|
||
│ │ • Tray icon (macOS/Linux) │ │
|
||
│ │ • Logs forwarding → Renderer │ │
|
||
│ └───────────────────────────────────────────┘ │
|
||
│ ↕ IPC │
|
||
│ ┌───────────────────────────────────────────┐ │
|
||
│ │ RENDERER PROCESS (Frontend) │ │
|
||
│ │ │ │
|
||
│ │ • HTML/CSS/JS (pas de framework) │ │
|
||
│ │ • Fetch API REST :3000/admin/* │ │
|
||
│ │ • WebSocket audio levels (live) │ │
|
||
│ │ • QR Code (data URL via IPC) │ │
|
||
│ └───────────────────────────────────────────┘ │
|
||
└─────────────────────────────────────────────────┘
|
||
↕ HTTPS (127.0.0.1, certs mkcert)
|
||
┌─────────────────────────────────────────────────┐
|
||
│ SERVEUR PTT LIVE (spawned) │
|
||
│ │
|
||
│ • LiveKit Server (binaire Go) :7880 │
|
||
│ • Audio Bridge Manager │
|
||
│ • API REST Express :3000 (HTTPS) │
|
||
│ • Proxy HTTP + WS → LiveKit (/livekit/*) │
|
||
│ • WebSocket Audio Levels (/audio-levels) │
|
||
└─────────────────────────────────────────────────┘
|
||
```
|
||
|
||
Le proxy `/livekit/*` (http-proxy natif) permet aux clients de joindre LiveKit via le même port/certificat HTTPS que l'API, sans exposer le port 7880 séparément. Le serveur Express dispatch lui-même les événements `upgrade` (un seul listener) entre le proxy LiveKit et le WebSocket audio-levels, qui partagent le même port.
|
||
|
||
---
|
||
|
||
## 🔌 API Consommées
|
||
|
||
L'interface desktop utilise toutes les routes admin existantes :
|
||
|
||
| Endpoint | Méthode | Usage |
|
||
|----------|---------|-------|
|
||
| `/admin/stats` | GET | Dashboard metrics |
|
||
| `/admin/users` | GET | Liste utilisateurs |
|
||
| `/admin/groups` | GET | Liste groupes |
|
||
| `/admin/groups` | POST | Créer groupe |
|
||
| `/admin/groups/:id` | PUT | Modifier groupe |
|
||
| `/admin/groups/:id` | DELETE | Supprimer groupe |
|
||
| `/admin/config` | GET | Config complète |
|
||
| `/admin/config/audio` | PUT | Mettre à jour audio |
|
||
| `/admin/audio/devices` | GET | Énumérer devices |
|
||
| `/admin/audio/device` | POST | Sélectionner device |
|
||
| `/admin/devices/list` | GET | Auto-détection (macOS/Linux) |
|
||
| `/admin/logs` | GET | Logs serveur |
|
||
| `/health` | GET | Health check |
|
||
| `/livekit/*` | ALL | Proxy HTTP vers LiveKit Server (port 7880) |
|
||
|
||
WebSocket :
|
||
- `wss://127.0.0.1:3000/audio-levels` → VU-mètres temps réel
|
||
- `wss://127.0.0.1:3000/livekit/*` → Proxy WebSocket signaling LiveKit (clients PWA)
|
||
|
||
---
|
||
|
||
## 🔒 HTTPS et certificats
|
||
|
||
L'app est en HTTPS par défaut (`ENABLE_HTTPS=false` pour revenir en HTTP explicitement).
|
||
|
||
### Setup automatique (premier lancement)
|
||
|
||
Au premier démarrage, si `certs/localhost.pem` et `certs/localhost-key.pem` sont absents, `electron/setup-helper.js` :
|
||
1. Installe `mkcert` automatiquement (Homebrew sur macOS, téléchargement direct sur Linux)
|
||
2. Installe la CA locale (`mkcert -install`) dans le trousseau système
|
||
3. Détecte l'IP réseau et génère les certificats pour `localhost`, `127.0.0.1` et cette IP
|
||
4. Affiche des dialogs de progression/erreur (avec fallback manuel `./setup-certificates.sh`)
|
||
|
||
### Points d'attention
|
||
|
||
- **127.0.0.1, pas localhost** : le serveur écoute en IPv4 (`host: 0.0.0.0`), mais le Node embarqué par Electron peut résoudre `localhost` en IPv6 (`::1`) en priorité. `main.js` et `preload.js` utilisent donc `127.0.0.1` pour tous les appels internes (ping, health check) afin d'éviter des échecs silencieux.
|
||
- **Ping interne et `rejectUnauthorized`** : le module `https` de Node ne lit pas le trousseau système où mkcert installe sa CA (contrairement à Safari/Chrome/Electron renderer) ; `pingServer()` passe donc `rejectUnauthorized: false` pour son propre ping local.
|
||
- **Proxy LiveKit en HTTPS** : LiveKit Server local tourne en HTTP brut (port 7880) ; le proxy Express (`http-proxy`) fait le pont HTTPS ↔ HTTP côté clients.
|
||
|
||
---
|
||
|
||
## 📦 Build pour Distribution
|
||
|
||
### macOS
|
||
|
||
```bash
|
||
cd electron
|
||
npm run build:mac
|
||
```
|
||
|
||
Génère :
|
||
- `dist/mac/PTT Live Server.app`
|
||
- `dist/PTT Live Server-0.3.0.dmg`
|
||
|
||
### Linux
|
||
|
||
```bash
|
||
cd electron
|
||
npm run build:linux
|
||
```
|
||
|
||
Génère :
|
||
- `dist/PTT Live Server-0.3.0.deb`
|
||
- `dist/PTT Live Server-0.3.0.AppImage`
|
||
|
||
### Tester le build
|
||
|
||
```bash
|
||
# macOS
|
||
open dist/mac/PTT\ Live\ Server.app
|
||
|
||
# Linux
|
||
./dist/PTT\ Live\ Server-0.3.0.AppImage
|
||
```
|
||
|
||
---
|
||
|
||
## 🎨 Personnalisation
|
||
|
||
### Icônes
|
||
|
||
Placer les icônes dans `electron/assets/` :
|
||
|
||
```
|
||
electron/assets/
|
||
├── icon.icns # macOS (512x512 minimum)
|
||
├── icon.png # Linux (512x512)
|
||
└── tray-icon.png # Tray 22x22 ou 44x44 (retina)
|
||
```
|
||
|
||
Générer icônes depuis PNG :
|
||
|
||
```bash
|
||
# macOS .icns
|
||
iconutil -c icns assets/icon.iconset
|
||
|
||
# Linux .png
|
||
convert icon.png -resize 512x512 assets/icon.png
|
||
```
|
||
|
||
### Thème
|
||
|
||
Modifier `electron/ui/styles.css` :
|
||
|
||
```css
|
||
:root {
|
||
--bg-primary: #1a1a1a;
|
||
--accent-primary: #4a9eff;
|
||
/* ... */
|
||
}
|
||
```
|
||
|
||
---
|
||
|
||
## 🐛 Debug
|
||
|
||
### DevTools
|
||
|
||
Ouvrir automatiquement en mode dev :
|
||
|
||
```bash
|
||
cd electron
|
||
npm run dev
|
||
```
|
||
|
||
Ou manuellement dans `main.js` :
|
||
|
||
```javascript
|
||
mainWindow.webContents.openDevTools();
|
||
```
|
||
|
||
### Logs Console
|
||
|
||
**Main Process** :
|
||
```javascript
|
||
console.log('[Main]', ...); // Terminal qui a lancé npm start
|
||
```
|
||
|
||
**Renderer Process** :
|
||
```javascript
|
||
console.log('[Renderer]', ...); // DevTools → Console
|
||
```
|
||
|
||
**Serveur PTT Live** :
|
||
```javascript
|
||
// Transmis au Renderer via IPC
|
||
window.electronAPI.server.onLog((log) => {
|
||
console.log('[Serveur]', log);
|
||
});
|
||
```
|
||
|
||
### Erreurs courantes
|
||
|
||
**Port 3000 déjà utilisé** :
|
||
```bash
|
||
# Tuer le process
|
||
lsof -i :3000
|
||
kill -9 <PID>
|
||
|
||
# OU changer de port
|
||
PORT=3001 npm start
|
||
```
|
||
|
||
**Serveur ne démarre pas** :
|
||
- Vérifier que `server/index.js` existe
|
||
- Vérifier permissions LiveKit binaire
|
||
- Voir logs dans DevTools console
|
||
|
||
**Certificats SSL manquants / setup mkcert échoue** :
|
||
- Exécuter manuellement : `./setup-certificates.sh`
|
||
- Ou installer mkcert : https://github.com/FiloSottile/mkcert puis `mkcert -install`
|
||
- Vérifier la présence de `certs/localhost.pem` et `certs/localhost-key.pem`
|
||
|
||
**Statut serveur affiché à tort comme "arrêté"** :
|
||
- Vérifier que le ping utilise bien `127.0.0.1` (pas `localhost`, qui peut résoudre en IPv6 alors que le serveur n'écoute qu'en IPv4)
|
||
- En HTTPS, le ping interne ignore volontairement les erreurs de certificat (`rejectUnauthorized: false`) puisque Node ne lit pas le trousseau système où mkcert installe sa CA
|
||
|
||
**QR Code ne s'affiche pas** :
|
||
- Vérifier que le serveur tourne (le QR code est réinitialisé tant qu'il est arrêté)
|
||
- Le QR code est généré côté Main Process (IPC `qrcode:generate`), pas de dépendance réseau/CDN
|
||
|
||
---
|
||
|
||
## 🚧 TODO / Améliorations
|
||
|
||
### Priorité haute
|
||
- [x] **WebSocket VU-mètres** : implémenter connexion `/audio-levels`
|
||
- [ ] **Vraies icônes** : icns/png pour macOS/Linux
|
||
- [ ] **Tray icon** : avec menu contextuel fonctionnel
|
||
|
||
### Priorité moyenne
|
||
- [ ] **Graphiques monitoring** : Chart.js pour latence/bande passante
|
||
- [x] **Export logs** : bouton télécharger JSON (filtre niveau appliqué)
|
||
- [ ] **Matrice routing** : interface graphique drag & drop
|
||
- [x] **Export & import config** : bouton télécharger YAML et charger config (backup auto .bak)
|
||
|
||
### Priorité basse
|
||
- [ ] **Thème toggle** : dark/light mode
|
||
- [ ] **Auto-update** : electron-updater pour mises à jour
|
||
|
||
### Technique
|
||
- [ ] **Tests** : Spectron ou Playwright pour Electron
|
||
- [ ] **CI/CD** : GitHub Actions pour builds automatiques
|
||
- [ ] **Signature code** : macOS notarization + Linux AppImage signature
|
||
|
||
---
|
||
|
||
## 📝 Notes de Développement
|
||
|
||
### Structure Fichiers
|
||
|
||
```
|
||
electron/
|
||
├── main.js # Main Process
|
||
│ # - Spawn serveur
|
||
│ # - IPC handlers
|
||
│ # - Window management
|
||
│ # - Setup SSL au premier lancement
|
||
│
|
||
├── preload.js # IPC Bridge sécurisé
|
||
│ # - contextBridge
|
||
│ # - Expose electronAPI
|
||
│
|
||
├── setup-helper.js # Installation auto mkcert + génération certificats
|
||
│ # - Détection IP réseau
|
||
│
|
||
├── package.json # Config Electron + electron-builder
|
||
│
|
||
└── ui/ # Renderer Process (Frontend)
|
||
├── index.html # Structure UI
|
||
├── styles.css # Styles (dark theme)
|
||
└── app.js # Logic frontend (QR code reçu via IPC en data URL)
|
||
```
|
||
|
||
### Communication IPC
|
||
|
||
**Renderer → Main** :
|
||
|
||
```javascript
|
||
// Depuis ui/app.js
|
||
const result = await window.electronAPI.server.start();
|
||
```
|
||
|
||
**Main → Renderer** :
|
||
|
||
```javascript
|
||
// Depuis main.js
|
||
mainWindow.webContents.send('server:status', { running: true });
|
||
|
||
// Écouté dans ui/app.js
|
||
window.electronAPI.server.onStatus((data) => {
|
||
console.log('Status:', data);
|
||
});
|
||
```
|
||
|
||
### Sécurité
|
||
|
||
- ✅ **contextIsolation: true** : isole Node.js du renderer
|
||
- ✅ **nodeIntegration: false** : pas d'accès Node direct
|
||
- ✅ **preload.js** : whitelist API exposées via contextBridge
|
||
- ⚠️ **CSP manquant** : ajouter Content-Security-Policy en prod
|
||
|
||
---
|
||
|
||
## 🤝 Contribution
|
||
|
||
L'app desktop est modulaire et extensible :
|
||
|
||
1. **Ajouter une vue** : créer `<div id="view-xxx">` dans `index.html`
|
||
2. **Ajouter un handler IPC** : `ipcMain.handle()` dans `main.js`
|
||
3. **Exposer au renderer** : `contextBridge.exposeInMainWorld()` dans `preload.js`
|
||
4. **Appeler l'API** : fetch dans `ui/app.js`
|
||
|
||
---
|
||
|
||
## 📚 Ressources
|
||
|
||
- **Electron Docs** : https://www.electronjs.org/docs
|
||
- **electron-builder** : https://www.electron.build
|
||
- **LiveKit Server API** : https://docs.livekit.io
|
||
- **QR Code.js** : https://github.com/soldair/node-qrcode
|
||
|
||
---
|
||
|
||
## 📄 Licence
|
||
|
||
Même licence que PTT Live (MIT)
|
||
|
||
---
|
||
|
||
**Version** : 0.3.0
|
||
**Dernière mise à jour** : 2026-06-30
|