Initial commit — Serveur Lucas SmartEye
API réception alertes chute (SmartEye/YOLO), analyse IA (Gemini 2.5 Flash), gestion alertes avec escalade (watchdog), notifications Firebase, dashboard web, documentation MkDocs. Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
3
mkdocs-smarteye/docs/api/endpoints.md
Normal file
@@ -0,0 +1,3 @@
|
||||
# Endpoints API
|
||||
|
||||
Section en cours de rédaction. Cette page décrira les endpoints de l'API REST, leurs paramètres et leurs réponses.
|
||||
3
mkdocs-smarteye/docs/api/fcm-payload.md
Normal file
@@ -0,0 +1,3 @@
|
||||
# Payload FCM
|
||||
|
||||
Section en cours de rédaction. Cette page décrira la structure des payloads Firebase Cloud Messaging utilisés pour les notifications push.
|
||||
3
mkdocs-smarteye/docs/architecture/data-flow.md
Normal file
@@ -0,0 +1,3 @@
|
||||
# Flux de données
|
||||
|
||||
Section en cours de rédaction. Cette page décrira le flux de données entre les différents composants du système SmartEye (Jetson, serveur, application mobile).
|
||||
84
mkdocs-smarteye/docs/architecture/overview.md
Normal file
@@ -0,0 +1,84 @@
|
||||
# Architecture du système
|
||||
|
||||
## Vue d'ensemble
|
||||
|
||||
```mermaid
|
||||
graph TB
|
||||
subgraph Domicile["🏠 Domicile du bénéficiaire"]
|
||||
CAM1[Caméra 1 - Salon]
|
||||
CAM2[Caméra 2 - Chambre]
|
||||
CAM3[Caméra 3 - Cuisine]
|
||||
JETSON[Jetson Orin Nano<br/>SmartEye v30]
|
||||
CAM1 -->|RTSP local| JETSON
|
||||
CAM2 -->|RTSP local| JETSON
|
||||
CAM3 -->|RTSP local| JETSON
|
||||
end
|
||||
|
||||
subgraph OVH["☁️ Serveur OVH (57.128.74.87)"]
|
||||
API[api.php<br/>Réception images]
|
||||
ANALYZE[analyze.py<br/>Gemini 2.5 Flash]
|
||||
ALERT[alert_manager.py<br/>Cycle de vie alertes]
|
||||
WATCHDOG[alert_watchdog.py<br/>Escalade cron]
|
||||
DB[(database.json)]
|
||||
API --> ANALYZE
|
||||
ANALYZE --> ALERT
|
||||
ANALYZE --> DB
|
||||
WATCHDOG --> ALERT
|
||||
end
|
||||
|
||||
subgraph Mobile["📱 Téléphones aidants"]
|
||||
APP1[LucasApp - Fille]
|
||||
APP2[LucasApp - Fils]
|
||||
end
|
||||
|
||||
JETSON ==>|SSH Tunnel<br/>Image POST| API
|
||||
ANALYZE ==>|Firebase Push| APP1
|
||||
ANALYZE ==>|Firebase Push| APP2
|
||||
JETSON -.->|RTSP Tunnel| APP1
|
||||
JETSON -.->|Audio WebSocket| APP1
|
||||
```
|
||||
|
||||
## Composants
|
||||
|
||||
### SmartEye (Jetson Orin Nano)
|
||||
|
||||
| Caractéristique | Détail |
|
||||
|----------------|--------|
|
||||
| **Modèle IA** | YOLOv8 (détection) + pose estimation |
|
||||
| **Caméras max** | 6 par site |
|
||||
| **Flux** | HD (/11) pour détection, SD (/12) pour streaming |
|
||||
| **Communication** | SSH tunnels inversés vers OVH |
|
||||
|
||||
### Lucas (Serveur OVH)
|
||||
|
||||
| Caractéristique | Détail |
|
||||
|----------------|--------|
|
||||
| **Analyse IA** | Google Gemini 2.5 Flash (vision) |
|
||||
| **Notifications** | Firebase Cloud Messaging |
|
||||
| **SMS backup** | OVH SMS API |
|
||||
| **Dashboard** | PHP + Tailwind CSS |
|
||||
|
||||
### LucasApp (Flutter)
|
||||
|
||||
| Caractéristique | Détail |
|
||||
|----------------|--------|
|
||||
| **Plateforme** | Android (Flutter) |
|
||||
| **Flux vidéo** | RTSP via tunnels SSH |
|
||||
| **Interphone** | WebSocket audio bidirectionnel (PCM A-law) |
|
||||
| **Acquittement** | POST vers alert_ack.php |
|
||||
|
||||
## Convention de ports
|
||||
|
||||
Chaque site client utilise une plage de 10 ports :
|
||||
|
||||
```
|
||||
Site N → base_port = 8550 + (N-1) × 10
|
||||
|
||||
Offset 0-5 : RTSP caméras (max 6)
|
||||
Offset 6 : Audio WebSocket relay
|
||||
Offset 7 : WebUI locale SmartEye
|
||||
Offset 8-9 : Réservés
|
||||
```
|
||||
|
||||
!!! note "Site pilote (Aléria)"
|
||||
Le site pilote conserve ses ports historiques : 8554/8555/8556 (RTSP) + 8800 (audio).
|
||||
|
After Width: | Height: | Size: 454 KiB |
|
After Width: | Height: | Size: 532 KiB |
|
After Width: | Height: | Size: 70 KiB |
BIN
mkdocs-smarteye/docs/assets/images/deploiement/mes-cameras.png
Normal file
|
After Width: | Height: | Size: 578 KiB |
|
After Width: | Height: | Size: 364 KiB |
|
After Width: | Height: | Size: 422 KiB |
|
After Width: | Height: | Size: 260 KiB |
330
mkdocs-smarteye/docs/deploiement/carte-gold.md
Normal file
@@ -0,0 +1,330 @@
|
||||
# Preparation de la carte Gold (image maitre)
|
||||
|
||||
<div style="background: linear-gradient(135deg, #f57f17 0%, #e65100 100%); color: white; padding: 24px; border-radius: 12px; margin-bottom: 24px;">
|
||||
<h2 style="margin:0; color: white;">Document reserve au responsable technique</h2>
|
||||
<p style="margin: 8px 0 0 0; opacity: 0.9;">Cette procedure ne se fait qu'une seule fois. Elle produit l'image maitre qui sera clonee pour chaque nouveau client.</p>
|
||||
</div>
|
||||
|
||||
---
|
||||
|
||||
## Qu'est-ce que la carte Gold ?
|
||||
|
||||
La carte Gold est une carte SD **de reference** contenant :
|
||||
|
||||
- Le systeme d'exploitation (JetPack / Linux)
|
||||
- Les drivers GPU (CUDA, cuDNN, TensorRT)
|
||||
- SmartEye complet (YOLO, modeles IA, services)
|
||||
- **Aucune configuration client** (pas de cameras, pas de compte, pas de logs)
|
||||
|
||||
C'est l'equivalent de l'image usine d'une box Free ou Orange. Le Jetson qui demarre avec cette carte arrive directement en **mode installation**, pret a etre configure depuis un smartphone.
|
||||
|
||||
---
|
||||
|
||||
## Principe : on ne touche JAMAIS a la carte de dev
|
||||
|
||||
```
|
||||
Carte actuelle (DEV/Aleria) Carte neuve n°1 Carte neuve n°2, 3, 4...
|
||||
┌─────────────────────┐ ┌─────────────┐ ┌─────────────┐
|
||||
│ SmartEye + Demo_01 │──── clone ──→│ Copie brute │ │ │
|
||||
│ Cameras configurees │ │ (tout dedans)│ │ │
|
||||
│ Logs, images, etc. │ └──────┬──────┘ │ Client X │
|
||||
│ │ │ │ │
|
||||
│ ON N'Y TOUCHE PAS │ nettoyage config │ │
|
||||
│ │ suppression logs └─────────────┘
|
||||
└─────────────────────┘ suppression images ▲
|
||||
│ │
|
||||
▼ │
|
||||
┌──────────────┐ clone a l'infini
|
||||
│ CARTE GOLD │────────────────┘
|
||||
│ (mode usine)│
|
||||
└──────────────┘
|
||||
```
|
||||
|
||||
!!! warning "Regle d'or"
|
||||
La carte du Jetson de developpement (Aleria/Demo_01) **reste en place, intacte**. On la clone d'abord, puis on nettoie le clone. Comme ca, si quelque chose se passe mal, le Jetson de dev est toujours operationnel.
|
||||
|
||||
---
|
||||
|
||||
## Pre-requis
|
||||
|
||||
| Element | Detail |
|
||||
|---------|--------|
|
||||
| **Jetson de dev** | Le Jetson actuel (Aleria) qui fonctionne |
|
||||
| **Carte SD neuve** | 64 Go minimum, classe A2/U3 |
|
||||
| **PC Linux ou Mac** | Pour cloner et nettoyer |
|
||||
| **Lecteur de carte SD** | USB ou integre |
|
||||
| **Espace disque** | ~64 Go libres sur le PC |
|
||||
| **Balena Etcher** | [balena.io/etcher](https://www.balena.io/etcher/) (gratuit) |
|
||||
|
||||
---
|
||||
|
||||
!!! danger "Carte SD de reference"
|
||||
La carte originale du Jetson de dev est une **Samsung EVO 128 Go**.
|
||||
Les cartes clones doivent etre de capacite **egale ou superieure** et idealement de la meme marque.
|
||||
Deux cartes "128 Go" de marques differentes n'ont pas exactement la meme taille en octets.
|
||||
Si la carte clone est plus petite (meme de quelques Mo), le clone sera corrompu et ne bootera pas.
|
||||
|
||||
## Etape 1 — Cloner la carte actuelle (telle quelle)
|
||||
|
||||
Eteindre le Jetson de dev proprement :
|
||||
|
||||
```bash
|
||||
# Sur le Jetson
|
||||
sudo shutdown -h now
|
||||
# Attendre extinction complete (LED eteintes)
|
||||
```
|
||||
|
||||
Retirer la carte SD et l'inserer dans le lecteur du PC.
|
||||
|
||||
=== "Linux"
|
||||
|
||||
```bash
|
||||
# Identifier la carte SD
|
||||
lsblk
|
||||
|
||||
# Cloner la carte entiere (NE RIEN MODIFIER)
|
||||
sudo dd if=/dev/sdb of=$HOME/smarteye-dev-backup.img bs=4M status=progress
|
||||
|
||||
# Compresser le backup
|
||||
gzip $HOME/smarteye-dev-backup.img
|
||||
```
|
||||
|
||||
=== "Mac"
|
||||
|
||||
```bash
|
||||
# Identifier la carte SD
|
||||
diskutil list
|
||||
|
||||
# Demonter sans ejecter
|
||||
diskutil unmountDisk /dev/disk4
|
||||
|
||||
# Cloner (~ 1h pour une carte 128 Go)
|
||||
sudo dd if=/dev/rdisk4 of=/Users/$(whoami)/smarteye-dev-backup.img bs=4m status=progress
|
||||
|
||||
# Compresser
|
||||
gzip /Users/$(whoami)/smarteye-dev-backup.img
|
||||
```
|
||||
|
||||
!!! tip "Pourquoi `/Users/$(whoami)/` et pas `~/` ?"
|
||||
Avec `sudo`, le `~` pointe vers `/var/root/` au lieu de votre dossier utilisateur. `$(whoami)` resout ce probleme en inserant automatiquement votre nom d'utilisateur.
|
||||
|
||||
!!! tip "Conserver ce backup"
|
||||
Le fichier `smarteye-dev-backup.img.gz` est votre **sauvegarde de securite** du Jetson de dev. Gardez-le precieusement. En cas de probleme, vous pouvez toujours reflasher la carte d'origine.
|
||||
|
||||
**Remettre immediatement la carte dans le Jetson de dev** et le redemarrer. Il reprend son fonctionnement normal.
|
||||
|
||||
---
|
||||
|
||||
## Etape 2 — Flasher le clone sur une carte neuve
|
||||
|
||||
Inserer une **carte SD neuve** (128 Go) dans le lecteur.
|
||||
|
||||
=== "Balena Etcher (recommande)"
|
||||
|
||||
1. Ouvrir Balena Etcher
|
||||
2. **Flash from file** → selectionner `smarteye-dev-backup.img.gz`
|
||||
3. **Select target** → selectionner la carte SD neuve
|
||||
4. **Flash!** → attendre ~10 minutes
|
||||
|
||||
=== "Linux"
|
||||
|
||||
```bash
|
||||
# 1. Verifier que la carte neuve est detectee
|
||||
lsblk
|
||||
# Reperer la carte neuve par sa taille (ex: /dev/sdb, 128 Go)
|
||||
|
||||
# 2. Flasher
|
||||
gunzip -c $HOME/smarteye-dev-backup.img.gz | sudo dd of=/dev/sdb bs=4M status=progress
|
||||
sync
|
||||
```
|
||||
|
||||
=== "Mac"
|
||||
|
||||
```bash
|
||||
# 1. Verifier que la carte neuve est detectee
|
||||
diskutil list
|
||||
# Reperer la carte par sa taille (ex: /dev/disk4, 134.2 GB = 128 Go)
|
||||
|
||||
# 2. Demonter la carte sans l'ejecter
|
||||
diskutil unmountDisk /dev/disk4
|
||||
|
||||
# 3. Flasher (~ 1h pour 128 Go, adapter /dev/rdisk4 si necessaire)
|
||||
gunzip -c /Users/$(whoami)/smarteye-dev-backup.img.gz | sudo dd of=/dev/rdisk4 bs=4m status=progress
|
||||
```
|
||||
|
||||
!!! info "Pourquoi 3 commandes separees ?"
|
||||
- `diskutil list` → **verifier** qu'on cible la bonne carte (pas le disque du Mac !)
|
||||
- `diskutil unmountDisk` → **liberer** la carte pour que `dd` puisse y ecrire
|
||||
- `gunzip -c ... | dd` → **decompresser et flasher** en une seule passe
|
||||
|
||||
A ce stade, la carte neuve est une **copie exacte** de la carte de dev (avec Demo_01, les cameras, les logs — tout).
|
||||
|
||||
---
|
||||
|
||||
## Etape 3 — Nettoyer le clone (le transformer en Gold)
|
||||
|
||||
Inserer la carte neuve (le clone) dans le Jetson **ou** la monter sur le PC pour nettoyer.
|
||||
|
||||
### Option A : Nettoyer depuis le Jetson
|
||||
|
||||
Inserer la carte clone dans un Jetson, le demarrer, puis :
|
||||
|
||||
```bash
|
||||
# 1. Arreter SmartEye
|
||||
sudo systemctl stop smarteye
|
||||
|
||||
# 2. Supprimer la configuration client (Demo_01)
|
||||
rm -f /w/smarteye_config.yaml
|
||||
|
||||
# 3. Supprimer toutes les images capturees
|
||||
rm -rf /w/runs/*
|
||||
|
||||
# 4. Supprimer les logs
|
||||
rm -rf /w/logs/*
|
||||
rm -f /w/*.log
|
||||
|
||||
# 5. Nettoyer les known_hosts SSH (specifiques au site)
|
||||
rm -f ~/.ssh/known_hosts
|
||||
|
||||
# 6. Vider l'historique bash
|
||||
history -c
|
||||
> ~/.bash_history
|
||||
```
|
||||
|
||||
### Option B : Nettoyer depuis le PC (sans Jetson)
|
||||
|
||||
Si vous n'avez qu'un seul Jetson, monter la carte sur le PC :
|
||||
|
||||
```bash
|
||||
# Monter la partition principale de la carte SD
|
||||
sudo mount /dev/sdb1 /mnt
|
||||
|
||||
# Nettoyer (adapter les chemins selon la structure)
|
||||
sudo rm -f /mnt/home/*/w/smarteye_config.yaml
|
||||
sudo rm -rf /mnt/home/*/w/runs/*
|
||||
sudo rm -rf /mnt/home/*/w/logs/*
|
||||
sudo rm -f /mnt/home/*/.ssh/known_hosts
|
||||
sudo rm -f /mnt/home/*/.bash_history
|
||||
|
||||
# Demonter
|
||||
sudo umount /mnt
|
||||
```
|
||||
|
||||
### Verification du nettoyage
|
||||
|
||||
```
|
||||
=== Verification ===
|
||||
Config client : ABSENT ✓
|
||||
Images : 0 fichiers ✓
|
||||
Logs : 0 fichiers ✓
|
||||
known_hosts : ABSENT ✓
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
## Etape 4 — Verifier le mode setup
|
||||
|
||||
Si vous avez nettoye depuis le Jetson (Option A), verifier que SmartEye demarre en mode installation :
|
||||
|
||||
```bash
|
||||
sudo systemctl start smarteye
|
||||
curl http://localhost:8080/api/identity
|
||||
```
|
||||
|
||||
Reponse attendue :
|
||||
|
||||
```json
|
||||
{
|
||||
"type": "smarteye",
|
||||
"version": "v30",
|
||||
"status": "setup",
|
||||
"message": "En attente de configuration"
|
||||
}
|
||||
```
|
||||
|
||||
Puis eteindre :
|
||||
|
||||
```bash
|
||||
sudo shutdown -h now
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
## Etape 5 — Creer l'image Gold definitive
|
||||
|
||||
Retirer la carte nettoyee du Jetson et la recloner en tant que **Gold** :
|
||||
|
||||
=== "Linux"
|
||||
|
||||
```bash
|
||||
# La carte nettoyee est dans le lecteur
|
||||
lsblk
|
||||
sudo dd if=/dev/sdb of=$HOME/smarteye-gold-v30.img bs=4M status=progress
|
||||
gzip $HOME/smarteye-gold-v30.img
|
||||
|
||||
# Resultat final
|
||||
ls -lh $HOME/smarteye-gold-v30.img.gz
|
||||
```
|
||||
|
||||
=== "Mac"
|
||||
|
||||
```bash
|
||||
# La carte nettoyee est dans le lecteur
|
||||
diskutil list
|
||||
diskutil unmountDisk /dev/disk4
|
||||
|
||||
sudo dd if=/dev/rdisk4 of=/Users/$(whoami)/smarteye-gold-v30.img bs=4m status=progress
|
||||
gzip /Users/$(whoami)/smarteye-gold-v30.img
|
||||
|
||||
# Resultat final
|
||||
ls -lh /Users/$(whoami)/smarteye-gold-v30.img.gz
|
||||
```
|
||||
|
||||
!!! success "Votre image Gold est prete"
|
||||
Le fichier `smarteye-gold-v30.img.gz` est votre image maitre. C'est a partir de ce fichier que vous [clonerez chaque nouveau Jetson](clonage.md).
|
||||
|
||||
---
|
||||
|
||||
## Resume des cartes
|
||||
|
||||
| Carte | Contenu | Usage |
|
||||
|-------|---------|-------|
|
||||
| **Carte de dev** | SmartEye + Demo_01 + cameras | Reste dans le Jetson de dev, **jamais modifiee** |
|
||||
| **Backup dev** | `smarteye-dev-backup.img.gz` | Sauvegarde de securite, au cas ou |
|
||||
| **Image Gold** | `smarteye-gold-v30.img.gz` | Image vierge, **source de tous les clones** |
|
||||
| **Carte client** | Flashee depuis la Gold | Une par client, configuree sur site |
|
||||
|
||||
---
|
||||
|
||||
## Checklist finale
|
||||
|
||||
- [ ] Carte de dev clonee → `smarteye-dev-backup.img.gz`
|
||||
- [ ] Carte de dev remise dans le Jetson, fonctionnement verifie
|
||||
- [ ] Clone flashe sur carte neuve
|
||||
- [ ] Clone nettoye (pas de config, pas d'images, pas de logs)
|
||||
- [ ] Mode setup verifie (JSON "status: setup")
|
||||
- [ ] Clone nettoye reclone → `smarteye-gold-v30.img.gz`
|
||||
- [ ] Image Gold stockee en lieu sur
|
||||
|
||||
---
|
||||
|
||||
## Ou stocker les images ?
|
||||
|
||||
| Fichier | Taille estimee | Ou le garder |
|
||||
|---------|:--------------:|--------------|
|
||||
| `smarteye-dev-backup.img.gz` | ~8-15 Go | PC + disque externe |
|
||||
| `smarteye-gold-v30.img.gz` | ~8-15 Go | PC + disque externe + serveur OVH |
|
||||
|
||||
!!! info "Versionnement"
|
||||
A chaque mise a jour de SmartEye, creer une nouvelle image Gold :
|
||||
|
||||
```
|
||||
smarteye-gold-v30-2026-02-21.img.gz ← actuelle
|
||||
smarteye-gold-v31-2026-03-15.img.gz ← apres mise a jour
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
## Etape suivante
|
||||
|
||||
→ [Cloner et deployer un nouveau Jetson](clonage.md)
|
||||
239
mkdocs-smarteye/docs/deploiement/clonage.md
Normal file
@@ -0,0 +1,239 @@
|
||||
# Clonage des cartes SD (au bureau)
|
||||
|
||||
<div style="background: linear-gradient(135deg, #00695c 0%, #004d40 100%); color: white; padding: 24px; border-radius: 12px; margin-bottom: 24px;">
|
||||
<h2 style="margin:0; color: white;">Operations internes — production en serie</h2>
|
||||
<p style="margin: 8px 0 0 0; opacity: 0.9;">Cloner, flasher, verifier et reparer les cartes SD avant expedition. Tout en ligne de commande depuis un Mac.</p>
|
||||
</div>
|
||||
|
||||
---
|
||||
|
||||
## Image de reference
|
||||
|
||||
| Fichier | Taille | Statut |
|
||||
|---------|:------:|--------|
|
||||
| `smarteye-dev-backup.img` | ~54 Go | **Fonctionnelle** — validee le 22/02/2026 |
|
||||
|
||||
Localisation Mac : `/Users/rachid/jetson_backup/smarteye-dev-backup.img`
|
||||
|
||||
!!! warning "Sauvegarde obligatoire"
|
||||
Cette image doit exister en **au moins 2 exemplaires** :
|
||||
|
||||
- Sur le Mac (disque local ou externe)
|
||||
- Sur le serveur OVH : `scp smarteye-dev-backup.img debian@lucas.unigest.fr:/home/debian/backups/`
|
||||
|
||||
---
|
||||
|
||||
## 1 — Flasher une carte SD (production)
|
||||
|
||||
C'est l'operation principale. Pour chaque nouveau client, on flashe une carte SD neuve depuis l'image de reference.
|
||||
|
||||
### Materiel
|
||||
|
||||
- Carte SD neuve **SanDisk Extreme Pro** 64 Go minimum
|
||||
- Lecteur de carte SD (integre ou USB)
|
||||
|
||||
### Procedure
|
||||
|
||||
```bash
|
||||
# Identifier la carte SD
|
||||
diskutil list
|
||||
# Reperer la carte par sa taille et ses partitions
|
||||
# Le lecteur integre du Mac peut apparaitre comme "internal, physical", c'est normal
|
||||
|
||||
# Demonter sans ejecter
|
||||
diskutil unmountDisk /dev/diskN
|
||||
|
||||
# Flasher (remplacer N par le bon numero)
|
||||
sudo dd if=/Users/rachid/jetson_backup/smarteye-dev-backup.img of=/dev/rdiskN bs=4m status=progress
|
||||
|
||||
# Ejecter proprement
|
||||
diskutil eject /dev/diskN
|
||||
```
|
||||
|
||||
!!! danger "Verifier le numero de disque"
|
||||
Toujours verifier **deux fois** le `/dev/diskN` avant de lancer `dd`. Se tromper de disque = ecraser le disque du Mac.
|
||||
|
||||
Le `r` devant `diskN` (→ `rdiskN`) utilise le mode raw, **5x plus rapide**.
|
||||
|
||||
Duree : ~20-25 min pour 54 Go a ~39 MB/s.
|
||||
|
||||
### Verification rapide
|
||||
|
||||
Apres le flash, avant d'ejecter :
|
||||
|
||||
```bash
|
||||
diskutil list /dev/diskN
|
||||
```
|
||||
|
||||
Resultat attendu : une **GUID_partition_scheme** avec ~14 partitions Linux + 1 partition EFI. C'est la structure standard du Jetson Nano.
|
||||
|
||||
### Production en serie
|
||||
|
||||
Pour flasher plusieurs cartes a la suite :
|
||||
|
||||
1. Flasher la carte → ejecter
|
||||
2. Etiqueter la carte (numero de serie / nom client)
|
||||
3. Inserer la carte dans un Jetson
|
||||
4. Inserer la carte suivante dans le lecteur → recommencer
|
||||
|
||||
La box part chez le client **carte SD deja inseree, prete a brancher**.
|
||||
|
||||
---
|
||||
|
||||
## 2 — Creer une nouvelle image de reference (backup)
|
||||
|
||||
Quand SmartEye evolue (nouvelle version YOLO, corrections, etc.), il faut creer une nouvelle image de reference depuis le Jetson de dev.
|
||||
|
||||
### Procedure
|
||||
|
||||
Eteindre le Jetson proprement, retirer la carte SD, l'inserer dans le lecteur du Mac.
|
||||
|
||||
```bash
|
||||
# Identifier la carte SD
|
||||
diskutil list
|
||||
|
||||
# Demonter
|
||||
diskutil unmountDisk /dev/diskN
|
||||
|
||||
# Cloner bit-a-bit
|
||||
sudo dd if=/dev/rdiskN of=/Users/rachid/jetson_backup/smarteye-dev-backup.img bs=4m status=progress
|
||||
|
||||
# Ejecter
|
||||
diskutil eject /dev/diskN
|
||||
```
|
||||
|
||||
Duree : ~20-25 min pour une carte 64 Go.
|
||||
|
||||
### Nommage et archivage
|
||||
|
||||
```
|
||||
smarteye-dev-backup-2026-02-22.img ← actuelle (validee)
|
||||
smarteye-dev-backup-2026-03-XX.img ← future
|
||||
```
|
||||
|
||||
Conserver les anciennes images. Copier sur OVH :
|
||||
|
||||
```bash
|
||||
scp smarteye-dev-backup.img debian@lucas.unigest.fr:/home/debian/backups/
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
## 3 — Verifier une image (sans carte SD)
|
||||
|
||||
Pour inspecter une image `.img` sans la flasher :
|
||||
|
||||
```bash
|
||||
hdiutil attach -nomount -readonly /Users/rachid/jetson_backup/smarteye-dev-backup.img
|
||||
```
|
||||
|
||||
Resultat attendu :
|
||||
|
||||
```
|
||||
/dev/disk6 GUID_partition_scheme
|
||||
/dev/disk6s1 EFI
|
||||
/dev/disk6s2 - s15 Linux Filesystem (multiple)
|
||||
```
|
||||
|
||||
Detacher apres verification :
|
||||
|
||||
```bash
|
||||
hdiutil detach /dev/disk6
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
## 4 — Reparer une image corrompue
|
||||
|
||||
Si une carte SD ne boot plus (erreur `mmcblk0p1 not found` sur le Jetson), la table de partitions est corrompue. Les donnees sont generalement encore intactes.
|
||||
|
||||
### Diagnostic sur le Jetson
|
||||
|
||||
Si le Jetson tombe dans un shell d'urgence (`bash-5.1#`) :
|
||||
|
||||
```bash
|
||||
ls /dev/mmcblk0*
|
||||
```
|
||||
|
||||
- `mmcblk0` present mais pas `mmcblk0p1` → table de partitions corrompue → reparable
|
||||
- `mmcblk0` absent → probleme hardware (carte morte ou mauvais contact)
|
||||
|
||||
### Etape 1 : testdisk (retrouver les partitions)
|
||||
|
||||
```bash
|
||||
brew install testdisk
|
||||
testdisk /Users/rachid/jetson_backup/smarteye-dev-backup.img
|
||||
```
|
||||
|
||||
1. **Create** → nouveau log
|
||||
2. Selectionner l'image → **Proceed**
|
||||
3. Type de table → **Intel**
|
||||
4. **Analyse** → **Quick Search**
|
||||
5. testdisk retrouve les partitions (FAT32 + Linux)
|
||||
6. **Entree** pour continuer → **Write** → **Y**
|
||||
|
||||
!!! warning "testdisk ne suffit pas"
|
||||
testdisk ecrit une table MBR. Le Jetson Nano utilise une table **GPT** avec ~14 partitions. Il faut enchainer avec gdisk.
|
||||
|
||||
### Etape 2 : gdisk (restaurer la GPT)
|
||||
|
||||
```bash
|
||||
brew install gptfdisk
|
||||
gdisk /Users/rachid/jetson_backup/smarteye-dev-backup.img
|
||||
```
|
||||
|
||||
gdisk detecte le conflit :
|
||||
|
||||
```
|
||||
Found valid MBR and corrupt GPT. Which do you want to use?
|
||||
1 - MBR
|
||||
2 - GPT
|
||||
3 - Create blank GPT
|
||||
```
|
||||
|
||||
1. Taper **`2`** (GPT — le header principal est souvent intact)
|
||||
2. Taper **`x`** (menu expert)
|
||||
3. Taper **`e`** (relocate backup structures to end of disk)
|
||||
4. Taper **`m`** (retour menu principal)
|
||||
5. Taper **`w`** → **Y**
|
||||
|
||||
Si gdisk refuse avec "Secondary partition table overlaps the last partition by N blocks" :
|
||||
|
||||
```bash
|
||||
# Dans un AUTRE terminal, agrandir l'image
|
||||
dd if=/dev/zero bs=512 count=200 >> /Users/rachid/jetson_backup/smarteye-dev-backup.img
|
||||
```
|
||||
|
||||
Puis **quitter** gdisk (`q`) et le **relancer** (il doit recharger la nouvelle taille). Recommencer : 2 → x → e → m → w → Y.
|
||||
|
||||
### Verification finale
|
||||
|
||||
```bash
|
||||
hdiutil attach -nomount -readonly /Users/rachid/jetson_backup/smarteye-dev-backup.img
|
||||
```
|
||||
|
||||
GUID_partition_scheme avec ~14 partitions = image reparee. Flasher sur une carte SD et tester le boot.
|
||||
|
||||
---
|
||||
|
||||
## Fiabilite en production
|
||||
|
||||
!!! danger "Cartes SD : prototypage seulement"
|
||||
Les cartes SD ont une duree de vie limitee en ecriture. Docker + YOLO = beaucoup d'ecritures. Pour une production a plusieurs centaines de clients :
|
||||
|
||||
- **SSD SATA via USB 3.0** pour le systeme (fiabilite industrielle)
|
||||
- **Carte SD uniquement pour le boot initial** (lecture seule)
|
||||
- **Backup automatique** des configs vers le serveur OVH
|
||||
|
||||
| Composant | Cout unitaire |
|
||||
|-----------|:------------:|
|
||||
| SD 32 Go (boot) | ~10 EUR |
|
||||
| SSD 120 Go SATA | ~15 EUR |
|
||||
| Adaptateur USB 3.0 → SATA | ~8 EUR |
|
||||
| **Total par box** | **~33 EUR** |
|
||||
|
||||
---
|
||||
|
||||
## Etape suivante
|
||||
|
||||
→ [Installation chez le client](installation-client.md)
|
||||
110
mkdocs-smarteye/docs/deploiement/config-video-camera.md
Normal file
@@ -0,0 +1,110 @@
|
||||
# Configuration video des cameras
|
||||
|
||||
<div style="background: linear-gradient(135deg, #b71c1c 0%, #1565c0 100%); color: white; padding: 24px; border-radius: 12px; margin-bottom: 24px;">
|
||||
<h2 style="margin:0; color: #ffcdd2;">Les 2 flux RTSP — Detection & Preuve HD</h2>
|
||||
<p style="margin: 8px 0 0 0; opacity: 0.9;">Chaque camera diffuse 2 flux simultanes utilises pour des besoins differents par SmartEye.</p>
|
||||
</div>
|
||||
|
||||
---
|
||||
|
||||
## Comprendre les 2 flux
|
||||
|
||||
Chaque camera IP diffuse **2 flux video RTSP** en parallele :
|
||||
|
||||
| | Flux 2 (SD) | Flux 1 (HD) |
|
||||
|---|---|---|
|
||||
| **Subtype** | `subtype=1` | `subtype=0` |
|
||||
| **Resolution** | 800 x 448 | 2880 x 1620 |
|
||||
| **Usage** | Detection YOLO 24/7 | Capture preuve en cas de chute |
|
||||
| **Debit** | 300 kbps | 6144 kbps |
|
||||
| **Quand** | En permanence | Uniquement lors d'une detection |
|
||||
|
||||
```mermaid
|
||||
graph LR
|
||||
CAM[Camera IP] -->|Flux 2 - SD| YOLO[Jetson YOLO]
|
||||
YOLO -->|Chute detectee| CAPTURE[Capture HD]
|
||||
CAM -->|Flux 1 - HD| CAPTURE
|
||||
CAPTURE -->|POST image| LUCAS[Lucas api.php]
|
||||
LUCAS -->|Gemini analyse| AVA[Push AVA]
|
||||
```
|
||||
|
||||
!!! question "Pourquoi 2 flux ?"
|
||||
**YOLO n'a pas besoin de HD** pour detecter une personne. Un flux leger (800x448) permet d'analyser plus de FPS avec moins de charge GPU. Par contre, **l'image de preuve doit etre nette** pour que Gemini puisse analyser finement et pour que la famille voie clairement la situation.
|
||||
|
||||
---
|
||||
|
||||
## Parametres recommandes
|
||||
|
||||
### Parametres generaux
|
||||
|
||||
| Parametre | Valeur |
|
||||
|-----------|--------|
|
||||
| Format video | **50Hz** |
|
||||
| Codage video | **H.264 Main Profile** |
|
||||
|
||||
!!! warning "H.264 obligatoire"
|
||||
Le H.265 n'est pas supporte par tous les lecteurs RTSP. Toujours utiliser H.264 Main Profile.
|
||||
|
||||
### Flux 1 — Preuve HD (subtype=0)
|
||||
|
||||
| Parametre | Valeur | Explication |
|
||||
|-----------|--------|-------------|
|
||||
| Resolution | **2880 x 1620** | Resolution max. Image nette pour Gemini et la famille |
|
||||
| Debit binaire | **6144 kbps** | Debit max. Qualite optimale pour la capture |
|
||||
| Frequence | **20 fps** | Suffisant pour un screenshot net |
|
||||
| Intervalle image cle | **20** | 1 keyframe/seconde. Capture plus rapide |
|
||||
| Controle debit | **CBR** | Debit constant. Qualite stable en mouvement |
|
||||
| Qualite image | **1** (meilleure) | Valeur basse = qualite max |
|
||||
|
||||
### Flux 2 — Detection YOLO (subtype=1)
|
||||
|
||||
| Parametre | Valeur | Explication |
|
||||
|-----------|--------|-------------|
|
||||
| Resolution | **800 x 448** | YOLO detecte bien en SD. Economise le GPU |
|
||||
| Debit binaire | **300 kbps** | 20x moins que le flux HD |
|
||||
| Frequence | **15 fps** | Suffisant pour detecter un mouvement |
|
||||
| Intervalle image cle | **30** | 1 keyframe toutes les 2 secondes |
|
||||
| Controle debit | **VBR** | Debit variable. Economise la bande passante au repos |
|
||||
| Qualite image | **1** (meilleure) | Meilleure qualite meme en SD |
|
||||
|
||||
---
|
||||
|
||||
## URLs RTSP
|
||||
|
||||
Format pour cameras Dahua :
|
||||
|
||||
=== "Flux 1 — HD (preuve)"
|
||||
|
||||
```
|
||||
rtsp://admin:password@192.168.1.196/cam/realmonitor?channel=1&subtype=0
|
||||
```
|
||||
|
||||
=== "Flux 2 — SD (detection)"
|
||||
|
||||
```
|
||||
rtsp://admin:password@192.168.1.196/cam/realmonitor?channel=1&subtype=1
|
||||
```
|
||||
|
||||
!!! info "Parametres URL"
|
||||
- `channel` : numero de canal (1 pour camera mono-objectif)
|
||||
- `subtype` : **0** = flux principal (HD), **1** = flux secondaire (SD)
|
||||
|
||||
---
|
||||
|
||||
## Procedure de configuration
|
||||
|
||||
1. Acceder a l'interface web de la camera (`http://IP_CAMERA`)
|
||||
2. Aller dans **Parametres > Camera > Video**
|
||||
3. Configurer le **Premier flux** (HD) selon le tableau ci-dessus
|
||||
4. Configurer le **Deuxieme flux** (SD) selon le tableau ci-dessus
|
||||
5. Cliquer **Appliquer**
|
||||
6. Tester les 2 flux avec VLC : `vlc rtsp://admin:password@IP/cam/realmonitor?channel=1&subtype=1`
|
||||
7. Verifier que SmartEye recoit le flux 2 et detecte correctement
|
||||
|
||||
---
|
||||
|
||||
## Voir aussi
|
||||
|
||||
- [Installation camera IP](installation-camera.md) — Ajouter une camera au reseau
|
||||
- [Checklist installation](https://lucas.unigest.fr/checklist.php) — Suivi complet d'une installation
|
||||
- [Configuration video interactive](https://lucas.unigest.fr/doc_camera.php) — Version web avec tableaux detailles
|
||||
154
mkdocs-smarteye/docs/deploiement/installation-camera.md
Normal file
@@ -0,0 +1,154 @@
|
||||
# Installation d'une camera IP
|
||||
|
||||
<div style="background: linear-gradient(135deg, #1a237e 0%, #283593 100%); color: white; padding: 24px; border-radius: 12px; margin-bottom: 24px;">
|
||||
<h2 style="margin:0; color: #82b1ff;">Guide technicien — Ajout d'une camera</h2>
|
||||
<p style="margin: 8px 0 0 0; opacity: 0.9;">Configuration d'une camera IP via l'application mobile. Temps estime : 5 minutes par camera.</p>
|
||||
</div>
|
||||
|
||||
---
|
||||
|
||||
## Pre-requis
|
||||
|
||||
- [ ] Smartphone avec l'application **CamHi** (ou equivalent) installee
|
||||
- [ ] Camera IP allumee et en mode appairage (LED clignotante)
|
||||
- [ ] Acces au reseau WiFi du client (SSID + mot de passe)
|
||||
- [ ] Bluetooth active sur le smartphone
|
||||
|
||||
---
|
||||
|
||||
## Etape 1 — Trouver la camera
|
||||
|
||||
Ouvrir l'application et lancer la recherche. La camera est detectee automatiquement via **Bluetooth**.
|
||||
|
||||
{ width="280" }
|
||||
|
||||
1. Verifier que la camera est **allumee** et en mode appairage
|
||||
2. La camera apparait avec son identifiant (ex: `SSAT-326256-ECCFB`)
|
||||
3. Appuyer sur **Ajouter a**
|
||||
|
||||
!!! tip "La camera n'apparait pas ?"
|
||||
- Verifier que le Bluetooth est active sur le smartphone
|
||||
- Rapprocher le telephone de la camera (< 3 metres)
|
||||
- Redemarrer la camera (debrancher/rebrancher)
|
||||
|
||||
---
|
||||
|
||||
## Etape 2 — Configurer le WiFi
|
||||
|
||||
La camera doit se connecter au **reseau WiFi du client** pour etre accessible par le Jetson.
|
||||
|
||||
{ width="280" }
|
||||
|
||||
1. Le **nom du WiFi** (SSID) est pre-rempli avec le reseau actuel du smartphone
|
||||
2. Saisir le **mot de passe WiFi** du client
|
||||
3. Appuyer sur **Configurer le sans fil et ajouter**
|
||||
|
||||
!!! warning "Important"
|
||||
La camera et le Jetson doivent etre sur le **meme reseau**. Utiliser le WiFi principal du client, pas un reseau invite.
|
||||
|
||||
---
|
||||
|
||||
## Etape 3 — Nommer la camera
|
||||
|
||||
Donner un nom explicite a la camera pour l'identifier facilement.
|
||||
|
||||
{ width="280" }
|
||||
|
||||
1. Saisir le **nom de la piece** ou la camera est installee
|
||||
2. Utiliser les suggestions rapides si disponibles : `Salon`, `Chambre`, `Corridor`, `Hall`, etc.
|
||||
3. Valider avec **OK**
|
||||
|
||||
!!! info "Convention de nommage"
|
||||
Utiliser des noms simples et coherents : **Salon cuisine**, **Chambre**, **Terrasse**, **Camera fenetre**. Ces noms apparaitront dans LucasApp.
|
||||
|
||||
---
|
||||
|
||||
## Etape 4 — Changer le mot de passe
|
||||
|
||||
A la premiere connexion, l'application demande de **changer le mot de passe par defaut** de la camera.
|
||||
|
||||
{ width="280" }
|
||||
|
||||
1. Appuyer sur **Ok** pour accepter
|
||||
2. Definir un **mot de passe securise** (minimum 8 caracteres)
|
||||
3. **Noter le mot de passe** — il sera necessaire pour configurer le flux RTSP sur le Jetson
|
||||
|
||||
!!! danger "Ne pas ignorer cette etape"
|
||||
Une camera avec le mot de passe par defaut est un risque de securite. Toujours changer le mot de passe.
|
||||
|
||||
---
|
||||
|
||||
## Etape 5 — Verifier l'installation
|
||||
|
||||
La camera apparait maintenant dans la liste des appareils.
|
||||
|
||||
{ width="280" }
|
||||
|
||||
Verifier que :
|
||||
|
||||
- [ ] La camera est **en ligne** (apercu video visible)
|
||||
- [ ] Le **nom** est correct
|
||||
- [ ] L'**icone cloud** indique la connectivite
|
||||
|
||||
---
|
||||
|
||||
## Etape 6 — Parametrer la camera
|
||||
|
||||
Acceder aux reglages de la camera pour ajuster les parametres.
|
||||
|
||||
{ width="280" }
|
||||
|
||||
Parametres recommandes :
|
||||
|
||||
| Parametre | Reglage |
|
||||
|-----------|---------|
|
||||
| **Parametres video** | Resolution maximale, 15-20 FPS |
|
||||
| **Parametres audio** | Activer le micro et le haut-parleur |
|
||||
| **Gestion des alarmes** | Desactiver (c'est SmartEye qui gere la detection) |
|
||||
| **Enregistrement carte TF** | Optionnel — activer si une carte SD est inseree |
|
||||
| **Reglage de l'heure** | Verifier le fuseau horaire (Europe/Paris) |
|
||||
|
||||
---
|
||||
|
||||
## Etape 7 — Recuperer l'adresse IP
|
||||
|
||||
Aller dans **Information sur l'appareil** pour noter l'adresse IP de la camera.
|
||||
|
||||
{ width="280" }
|
||||
|
||||
| Information | Usage |
|
||||
|-------------|-------|
|
||||
| **Adresse IP** | Necessaire pour configurer le Jetson (ex: `192.168.1.196`) |
|
||||
| **Type de reseau** | Verifier que c'est bien `WIFI` (ou Ethernet) |
|
||||
| **Version du logiciel** | Utile pour le support technique |
|
||||
|
||||
!!! success "Camera prete"
|
||||
L'adresse IP est la derniere information necessaire. Elle sera utilisee pour configurer le flux RTSP dans SmartEye.
|
||||
|
||||
---
|
||||
|
||||
## Recapitulatif
|
||||
|
||||
| Etape | Action | Duree |
|
||||
|:-----:|--------|:-----:|
|
||||
| 1 | Trouver la camera (Bluetooth) | 30s |
|
||||
| 2 | Configurer le WiFi | 30s |
|
||||
| 3 | Nommer la camera | 15s |
|
||||
| 4 | Changer le mot de passe | 30s |
|
||||
| 5 | Verifier la connexion | 15s |
|
||||
| 6 | Parametrer (video, audio) | 1 min |
|
||||
| 7 | Recuperer l'adresse IP | 15s |
|
||||
|
||||
---
|
||||
|
||||
## Prochaine etape
|
||||
|
||||
Une fois toutes les cameras installees et leurs IPs notees, passer a l'[installation du Jetson SmartEye](jetson.md) pour configurer la detection IA.
|
||||
|
||||
!!! info "Flux RTSP"
|
||||
Le Jetson utilise les flux RTSP des cameras. L'URL standard est :
|
||||
```
|
||||
rtsp://<login>:<password>@<IP>:554/11 (flux HD)
|
||||
rtsp://<login>:<password>@<IP>:554/12 (flux SD)
|
||||
```
|
||||
SmartEye utilise le flux SD (`/12`) pour la detection afin d'optimiser les performances.
|
||||
262
mkdocs-smarteye/docs/deploiement/installation-client.md
Normal file
@@ -0,0 +1,262 @@
|
||||
# Installation chez le client
|
||||
|
||||
<div style="background: linear-gradient(135deg, #1a1a2e 0%, #16213e 50%, #0f3460 100%); color: white; padding: 32px; border-radius: 12px; margin-bottom: 24px; border: 1px solid rgba(0, 188, 212, 0.3); box-shadow: 0 0 30px rgba(0, 188, 212, 0.1);">
|
||||
<div style="display: flex; align-items: center; gap: 12px; margin-bottom: 8px;">
|
||||
<span style="font-size: 1.8em;">:material-shield-home:</span>
|
||||
<h2 style="margin:0; color: #00e5ff; font-weight: 300; letter-spacing: 2px;">GUIDE TECHNICIEN TERRAIN</h2>
|
||||
</div>
|
||||
<p style="margin: 4px 0 0 0; opacity: 0.85; font-size: 0.95em;">Deploiement du systeme de surveillance intelligent Lucas. Duree estimee sur site : ~30 minutes.</p>
|
||||
<div style="margin-top: 16px; padding-top: 12px; border-top: 1px solid rgba(255,255,255,0.15); display: flex; gap: 24px; font-size: 0.85em; opacity: 0.7;">
|
||||
<span>:material-cctv: Surveillance</span>
|
||||
<span>:material-brain: IA embarquee</span>
|
||||
<span>:material-shield-check: Protection 24/7</span>
|
||||
<span>:material-phone-alert: Alerte instantanee</span>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
---
|
||||
|
||||
## Pre-requis
|
||||
|
||||
!!! info "Le compte client est deja cree"
|
||||
Le compte est cree automatiquement lors de la souscription. Le technicien recoit par email :
|
||||
|
||||
- **Identifiant client** (`client_id`)
|
||||
- **Mot de passe** (token d'authentification)
|
||||
- **Numero de site** attribue
|
||||
|
||||
**Chez le client :**
|
||||
|
||||
- [ ] Acces Internet (fibre ou ADSL stable)
|
||||
- [ ] Reseau WiFi pour les cameras (SSID + mot de passe)
|
||||
- [ ] Prise Ethernet pour le Jetson (cable recommande)
|
||||
- [ ] Prises electriques a proximite des emplacements cameras
|
||||
|
||||
---
|
||||
|
||||
## Le kit materiel
|
||||
|
||||
Voici ce que le technicien deballera chez le client :
|
||||
|
||||
### Jetson Orin Nano — Le cerveau SmartEye
|
||||
|
||||
{ width="500" }
|
||||
|
||||
*NVIDIA Jetson Orin Nano — Le boitier d'intelligence artificielle embarquee.*
|
||||
|
||||
| Caracteristique | Valeur |
|
||||
|----------------|--------|
|
||||
| **Processeur** | 6-core Arm Cortex-A78AE |
|
||||
| **GPU** | 1024-core NVIDIA Ampere |
|
||||
| **Performance IA** | Jusqu'a 67 TOPS |
|
||||
| **RAM** | 8 Go LPDDR5 |
|
||||
| **Stockage** | Carte SD pre-flashee (image Gold) |
|
||||
| **Alimentation** | USB-C (adaptateur fourni) |
|
||||
|
||||
### Cameras Ctronics PTZ — Les yeux du systeme
|
||||
|
||||
<!-- Ajouter les images dans docs/assets/images/ :
|
||||
ctronics-camera-1.jpg (vue de face)
|
||||
ctronics-camera-2.jpg (vue d'angle / exterieur)
|
||||
Source : https://ctronics.com/collections/all ou Amazon -->
|
||||
|
||||
*Cameras Ctronics PTZ avec vision nocturne et audio bidirectionnel.*
|
||||
|
||||
| Caracteristique | Valeur |
|
||||
|----------------|--------|
|
||||
| **Resolution** | 2K / 4MP minimum |
|
||||
| **PTZ** | 355 pan, 90 tilt |
|
||||
| **Vision nocturne** | 30m couleur |
|
||||
| **Audio** | Bidirectionnel (micro + haut-parleur) |
|
||||
| **Protocole** | ONVIF, RTSP |
|
||||
| **Connexion** | WiFi 2.4/5GHz ou Ethernet |
|
||||
| **Flux RTSP** | HD = `/11`, SD = `/12` |
|
||||
|
||||
### Checklist depart
|
||||
|
||||
- [ ] Boitier Jetson SmartEye (carte SD deja inseree, clonee depuis la Gold)
|
||||
- [ ] Alimentation USB-C
|
||||
- [ ] Cable Ethernet (RJ45) — 2 metres minimum
|
||||
- [ ] Cameras IP (Ctronics) — autant que prevu pour ce client
|
||||
- [ ] Alimentations cameras (12V)
|
||||
- [ ] **Fiche credentials** (ID + Token + N site — recus par email)
|
||||
- [ ] Smartphone avec **LucasApp** installe
|
||||
|
||||
!!! tip "Carte SD"
|
||||
La carte SD doit etre flashee depuis l'image Gold **avant** le deplacement.
|
||||
Voir [Clonage des cartes SD](clonage.md) pour la procedure.
|
||||
|
||||
---
|
||||
|
||||
## Sur site (chez le client)
|
||||
|
||||
### Etape 1 — Installer les cameras
|
||||
|
||||
**Avant de toucher au Jetson**, positionner et brancher toutes les cameras.
|
||||
|
||||
**Regles de positionnement** :
|
||||
|
||||
| Regle | Detail |
|
||||
|-------|--------|
|
||||
| Hauteur | 2 a 2,5 metres du sol (au-dessus des portes) |
|
||||
| Angle | Plongee a ~30, couvrir le maximum de sol |
|
||||
| Zones cibles | Salon, chambre, couloir — la ou le senior passe le plus de temps |
|
||||
| Eviter | Contre-jour (fenetre dans le champ), reflets de miroirs |
|
||||
| Branchement | Chaque camera a son alimentation + connectee au **reseau du client** (WiFi ou Ethernet) |
|
||||
|
||||
!!! info "Combien de cameras ?"
|
||||
Le systeme supporte jusqu'a **6 cameras par site**. Minimum recommande : 2 (salon + chambre).
|
||||
|
||||
**Verifier** que chaque camera est allumee et connectee au reseau du client avant de continuer.
|
||||
|
||||
---
|
||||
|
||||
### Etape 2 — Brancher et configurer le Jetson
|
||||
|
||||
#### Branchement physique
|
||||
|
||||
```
|
||||
Box Internet du client
|
||||
[ ::: ]
|
||||
|
|
||||
Cable Ethernet
|
||||
|
|
||||
[ Jetson SmartEye ] ← USB-C (alimentation)
|
||||
```
|
||||
|
||||
1. Brancher le **cable Ethernet** entre le Jetson et la box internet
|
||||
2. Brancher le **cable USB-C** (alimentation)
|
||||
3. Attendre **1 minute** — la LED passe au vert fixe
|
||||
|
||||
#### Configuration depuis le smartphone
|
||||
|
||||
Se connecter au **meme WiFi** que le boitier, puis ouvrir dans le navigateur :
|
||||
|
||||
<div style="background: #263238; color: #80cbc4; padding: 16px; border-radius: 8px; font-size: 1.3em; text-align: center; font-family: monospace;">
|
||||
http://smarteye.local:8080
|
||||
</div>
|
||||
|
||||
<br/>
|
||||
|
||||
!!! tip "Ca ne marche pas ?"
|
||||
**Solution 1** — Ouvrir LucasApp > Parametres > **Installer un SmartEye**
|
||||
|
||||
**Solution 2** — Scanner le **QR code** colle sous le boitier
|
||||
|
||||
#### Ecran 1/4 : Identification
|
||||
|
||||
Saisir les informations recues par email :
|
||||
|
||||
| Champ | Quoi mettre |
|
||||
|-------|-------------|
|
||||
| **ID Client** | L'identifiant recu par email |
|
||||
| **Token** | Le mot de passe recu par email |
|
||||
| **Nom du site** | Nom libre (ex: `Mme Dupont - Aleria`) |
|
||||
|
||||
#### Ecran 2/4 : Cameras
|
||||
|
||||
Le Jetson detecte les cameras automatiquement sur le reseau.
|
||||
|
||||
Pour chaque camera trouvee :
|
||||
|
||||
1. **Nommer la piece** (Salon, Chambre, Cuisine...)
|
||||
2. Saisir les **identifiants** si demande (login/mot de passe de la camera)
|
||||
3. Appuyer sur **Tester** — verifier que l'image s'affiche
|
||||
|
||||
!!! warning "Aucune camera detectee ?"
|
||||
- Les cameras sont-elles allumees ?
|
||||
- Sont-elles sur le **meme reseau** que le Jetson ?
|
||||
- Essayer de redemarrer la camera
|
||||
|
||||
#### Ecran 3/4 : Connexion serveur
|
||||
|
||||
Les valeurs sont **pre-remplies**. Ne rien modifier sauf indication contraire.
|
||||
|
||||
| Parametre | Valeur par defaut |
|
||||
|-----------|-------------------|
|
||||
| Serveur | `57.128.74.87` |
|
||||
| Utilisateur | `debian` |
|
||||
| N de site | Automatique |
|
||||
|
||||
Appuyer sur **Tester la connexion** — doit afficher un resultat vert.
|
||||
|
||||
#### Ecran 4/4 : Test final
|
||||
|
||||
Le systeme verifie toute la chaine automatiquement :
|
||||
|
||||
| Etape | Verification | Resultat |
|
||||
|:-----:|-------------|:--------:|
|
||||
| 1 | Connexion aux cameras | :material-check: |
|
||||
| 2 | Detection IA (YOLO) | :material-check: |
|
||||
| 3 | Tunnel vers le serveur | :material-check: |
|
||||
| 4 | Envoi d'une image test | :material-check: |
|
||||
| 5 | Notification recue sur le telephone | :material-check: |
|
||||
|
||||
Si tout est vert : appuyer sur **Terminer**.
|
||||
|
||||
Le Jetson passe en mode surveillance active.
|
||||
|
||||
---
|
||||
|
||||
## Avant de partir
|
||||
|
||||
### Etape 3 — Test de bout en bout
|
||||
|
||||
**Test obligatoire** — ne pas quitter le domicile sans l'avoir fait.
|
||||
|
||||
1. **Simuler une chute** : se coucher au sol devant une camera, rester immobile 30 secondes
|
||||
2. **Verifier** la notification sur le telephone du technicien (LucasApp)
|
||||
3. **Verifier** que l'image recue est nette et bien cadree
|
||||
4. **Verifier** le flux video en direct dans LucasApp (toutes les cameras)
|
||||
5. **Tester l'interphone** : parler dans l'app, verifier que le son sort de la camera
|
||||
|
||||
---
|
||||
|
||||
### Etape 4 — Configurer les telephones des aidants
|
||||
|
||||
Sur le telephone de **chaque aidant** (fils, fille, aide-soignant...) :
|
||||
|
||||
1. **Installer LucasApp** (Play Store / APK)
|
||||
2. **Ouvrir l'app** — elle s'enregistre automatiquement aupres du serveur
|
||||
3. **Verifier les notifications** : elles doivent etre autorisees dans les reglages du telephone
|
||||
4. **Montrer le fonctionnement** :
|
||||
- Comment repondre a une alerte
|
||||
- Comment voir les cameras en direct
|
||||
- Comment utiliser l'interphone
|
||||
- Expliquer que le numero d'urgence (15 par defaut) est accessible depuis l'alerte
|
||||
|
||||
!!! success "Installation terminee"
|
||||
Le systeme est operationnel. Le Jetson fonctionne 24h/24, redemarre seul en cas de coupure de courant.
|
||||
Aucune intervention de l'aidant n'est necessaire au quotidien.
|
||||
|
||||
---
|
||||
|
||||
## Checklist de depart
|
||||
|
||||
Avant de quitter le domicile, cocher chaque point :
|
||||
|
||||
- [ ] Toutes les cameras sont fixees et alimentees
|
||||
- [ ] Le Jetson est branche (Ethernet + USB-C)
|
||||
- [ ] La LED du Jetson clignote rapidement (surveillance active)
|
||||
- [ ] Le test de chute simulee a fonctionne
|
||||
- [ ] Le flux video est visible dans LucasApp
|
||||
- [ ] L'interphone fonctionne dans les deux sens
|
||||
- [ ] **Chaque aidant** a LucasApp installe et les notifications activees
|
||||
- [ ] Le boitier est place dans un endroit discret et ventile
|
||||
|
||||
---
|
||||
|
||||
## Depannage rapide
|
||||
|
||||
| Symptome | Cause probable | Solution |
|
||||
|----------|---------------|----------|
|
||||
| LED eteinte | Pas d'alimentation | Verifier le cable USB-C et l'adaptateur |
|
||||
| `smarteye.local` ne repond pas | mDNS non supporte | Utiliser le scan LucasApp ou le QR code |
|
||||
| Camera non detectee | Reseau different | Verifier que la camera est sur le meme reseau |
|
||||
| Test serveur echoue | Pas d'internet | Verifier la connexion internet de la box client |
|
||||
| Pas de notification | Notifications desactivees | Verifier les reglages du telephone de l'aidant |
|
||||
| Image floue ou sombre | Mauvais positionnement | Repositionner la camera (hauteur, angle, eclairage) |
|
||||
| Intercom muet | Camera sans audio | Verifier que la camera supporte l'audio bidirectionnel |
|
||||
|
||||
!!! info "Probleme non resolu ?"
|
||||
Consulter le [Guide expert](jetson-expert.md) pour un diagnostic technique approfondi.
|
||||
380
mkdocs-smarteye/docs/deploiement/jetson-expert.md
Normal file
@@ -0,0 +1,380 @@
|
||||
# Installation du Jetson SmartEye
|
||||
|
||||
## Philosophie : le Jetson est une Box
|
||||
|
||||
Le Jetson SmartEye se deploie comme une box internet (Free, Orange). L'installateur arrive chez le beneficiaire avec le boitier pre-configure, le branche sur le reseau local, et **tout se passe depuis son smartphone**. Aucun ecran, aucun clavier, aucun cable HDMI.
|
||||
|
||||
```mermaid
|
||||
graph LR
|
||||
subgraph Domicile["Domicile du beneficiaire"]
|
||||
BOX["Jetson SmartEye"]
|
||||
CAM1["Camera 1"]
|
||||
CAM2["Camera 2"]
|
||||
CAM3["Camera 3"]
|
||||
ROUTER["Box Internet"]
|
||||
BOX ---|Ethernet| ROUTER
|
||||
CAM1 ---|WiFi/Ethernet| ROUTER
|
||||
CAM2 ---|WiFi/Ethernet| ROUTER
|
||||
CAM3 ---|WiFi/Ethernet| ROUTER
|
||||
end
|
||||
|
||||
subgraph Install["Smartphone installateur"]
|
||||
APP["LucasApp / Navigateur"]
|
||||
end
|
||||
|
||||
ROUTER ---|WiFi| APP
|
||||
APP -.->|"http://smarteye.local:8080"| BOX
|
||||
```
|
||||
|
||||
## Materiel necessaire
|
||||
|
||||
| Element | Detail |
|
||||
|---------|--------|
|
||||
| **Jetson Orin Nano** | Avec SmartEye pre-installe sur carte SD |
|
||||
| **Alimentation** | USB-C 5V/3A (fournie) |
|
||||
| **Cable Ethernet** | RJ45, branchement sur la box internet du client |
|
||||
| **Cameras IP** | CTronic ou compatible ONVIF, deja installees |
|
||||
| **Smartphone** | Android ou iOS, connecte au meme reseau WiFi |
|
||||
|
||||
---
|
||||
|
||||
## Etape 1 : Branchement physique
|
||||
|
||||
1. **Brancher le cable Ethernet** du Jetson a la box internet du client
|
||||
2. **Brancher l'alimentation USB-C** du Jetson
|
||||
3. **Attendre 60 secondes** — le Jetson demarre et se connecte au reseau local
|
||||
|
||||
!!! info "LED de statut"
|
||||
Le Jetson n'a pas d'ecran mais dispose d'une LED verte :
|
||||
|
||||
- **Clignotement lent** : demarrage en cours
|
||||
- **Fixe** : connecte au reseau, pret pour la configuration
|
||||
- **Clignotement rapide** : surveillance active, tout fonctionne
|
||||
|
||||
---
|
||||
|
||||
## Etape 2 : Decouverte sur le reseau local
|
||||
|
||||
Le Jetson annonce automatiquement sa presence sur le reseau local via **mDNS (Avahi/Bonjour)**. Depuis le smartphone connecte au meme WiFi :
|
||||
|
||||
### Option A : Acces direct (recommande)
|
||||
|
||||
Ouvrir un navigateur et aller a :
|
||||
|
||||
```
|
||||
http://smarteye.local:8080
|
||||
```
|
||||
|
||||
!!! tip "Si smarteye.local ne repond pas"
|
||||
Certaines box internet bloquent le mDNS. Dans ce cas, utiliser l'option B.
|
||||
|
||||
### Option B : Scan reseau depuis LucasApp
|
||||
|
||||
1. Ouvrir **LucasApp** sur le smartphone
|
||||
2. Aller dans **Parametres > Installer un SmartEye**
|
||||
3. L'application scanne le reseau local (plage 192.168.x.x)
|
||||
4. Le Jetson apparait dans la liste des appareils detectes
|
||||
5. Appuyer dessus pour ouvrir l'interface de configuration
|
||||
|
||||
```mermaid
|
||||
sequenceDiagram
|
||||
participant Phone as Smartphone
|
||||
participant Jetson as Jetson SmartEye
|
||||
participant Router as Box Internet
|
||||
|
||||
Phone->>Router: Scan reseau local (UDP broadcast)
|
||||
Router-->>Phone: Liste des appareils
|
||||
Phone->>Jetson: GET /api/identity (port 8080)
|
||||
Jetson-->>Phone: {"type": "smarteye", "version": "v30", "status": "setup"}
|
||||
Phone->>Phone: Affiche "SmartEye detecte"
|
||||
```
|
||||
|
||||
### Option C : QR Code sur le boitier
|
||||
|
||||
Un QR code colle sur le Jetson contient son adresse MAC. LucasApp peut scanner ce QR code pour identifier le bon appareil sur le reseau.
|
||||
|
||||
---
|
||||
|
||||
## Etape 3 : Interface de configuration (WebUI)
|
||||
|
||||
L'interface web du Jetson s'affiche sur le smartphone. L'installation se fait en **4 sous-etapes** guidees.
|
||||
|
||||
### 3.1 — Identification du site
|
||||
|
||||
| Champ | Description | Exemple |
|
||||
|-------|-------------|---------|
|
||||
| **ID Client** | Identifiant du beneficiaire (fourni par Lucas) | `dupont_marie` |
|
||||
| **Token** | Jeton d'authentification (fourni par Lucas) | `b5ce5015` |
|
||||
| **Nom du site** | Nom lisible | `Residence Dupont` |
|
||||
|
||||
!!! warning "Ou trouver l'ID et le Token ?"
|
||||
L'ID client et le token sont generes lors de la creation du dossier dans l'interface d'administration Lucas ([admin.php](https://lucas.unigest.fr/admin.php)). Voir le [Guide nouveau client](../guide/nouveau-client.md).
|
||||
|
||||
### 3.2 — Detection automatique des cameras (ONVIF)
|
||||
|
||||
Le Jetson scanne le reseau local a la recherche de cameras compatibles ONVIF.
|
||||
|
||||
```
|
||||
Scan en cours...
|
||||
|
||||
Camera detectee : 192.168.1.143 (CTronic - Salon)
|
||||
Camera detectee : 192.168.1.148 (CTronic - Chambre)
|
||||
Camera detectee : 192.168.1.152 (CTronic - Cuisine)
|
||||
|
||||
3 cameras trouvees.
|
||||
```
|
||||
|
||||
Pour chaque camera detectee :
|
||||
|
||||
| Champ | Auto-detecte | Modifiable |
|
||||
|-------|:------------:|:----------:|
|
||||
| **Adresse IP** | Oui | Oui |
|
||||
| **Nom** (piece) | Non | Oui |
|
||||
| **Login RTSP** | Non | Oui |
|
||||
| **Mot de passe RTSP** | Non | Oui |
|
||||
| **Flux HD** (/11) | Oui | Oui |
|
||||
| **Flux SD** (/12) | Oui | Oui |
|
||||
| **Active** | Oui | Oui |
|
||||
|
||||
!!! tip "Verifier le flux en direct"
|
||||
Appuyer sur **Tester** a cote de chaque camera pour afficher un apercu en direct sur le smartphone. Cela confirme que les identifiants RTSP sont corrects.
|
||||
|
||||
### 3.3 — Connexion au serveur Lucas
|
||||
|
||||
Le Jetson doit etablir une connexion securisee (tunnel SSH) vers le serveur OVH.
|
||||
|
||||
| Parametre | Valeur par defaut | Modifiable |
|
||||
|-----------|-------------------|:----------:|
|
||||
| **Serveur** | `57.128.74.87` | Oui |
|
||||
| **Utilisateur SSH** | `debian` | Oui |
|
||||
| **Domaine** | `lucas.unigest.fr` | Oui |
|
||||
| **Numero de site** | Auto (prochain disponible) | Oui |
|
||||
|
||||
```mermaid
|
||||
sequenceDiagram
|
||||
participant Jetson
|
||||
participant OVH as Serveur OVH
|
||||
|
||||
Jetson->>OVH: Test connexion SSH
|
||||
OVH-->>Jetson: OK - Cle autorisee
|
||||
Jetson->>OVH: Ouverture tunnels RTSP (ports 8560-8565)
|
||||
Jetson->>OVH: Ouverture tunnel Audio (port 8566)
|
||||
Jetson->>OVH: POST api.php (test image)
|
||||
OVH-->>Jetson: 200 OK - Client reconnu
|
||||
Jetson-->>Jetson: Connexion validee
|
||||
```
|
||||
|
||||
!!! note "Attribution automatique des ports"
|
||||
Le Jetson calcule automatiquement sa plage de ports selon la convention :
|
||||
|
||||
```
|
||||
Site N → base_port = 8550 + (N-1) x 10
|
||||
|
||||
Ports attribues :
|
||||
base+0 a base+5 : RTSP cameras (max 6)
|
||||
base+6 : Audio WebSocket
|
||||
base+7 : WebUI locale
|
||||
base+8 a base+9 : Reserves
|
||||
```
|
||||
|
||||
Exemple pour le site n°2 : ports 8560 a 8569.
|
||||
|
||||
### 3.4 — Test de bout en bout
|
||||
|
||||
Le Jetson effectue un test complet de la chaine :
|
||||
|
||||
```
|
||||
[1/5] Connexion cameras RTSP............ OK
|
||||
[2/5] Detection IA (YOLO)............... OK (personne detectee)
|
||||
[3/5] Tunnel SSH vers OVH............... OK
|
||||
[4/5] Envoi image test a api.php........ OK (Gemini: "RAS")
|
||||
[5/5] Notification push Firebase........ OK (recue sur LucasApp)
|
||||
|
||||
=== INSTALLATION TERMINEE ===
|
||||
SmartEye est operationnel.
|
||||
La surveillance demarre automatiquement.
|
||||
```
|
||||
|
||||
!!! success "Installation terminee"
|
||||
Une fois le test valide, le Jetson passe en mode **surveillance active**. Il demarre automatiquement a chaque mise sous tension, sans aucune intervention.
|
||||
|
||||
---
|
||||
|
||||
## Etape 4 : Verification depuis LucasApp
|
||||
|
||||
Sur le smartphone de chaque aidant :
|
||||
|
||||
1. Ouvrir **LucasApp**
|
||||
2. Verifier que le flux video en direct est accessible
|
||||
3. Verifier que l'interphone fonctionne (audio bidirectionnel)
|
||||
4. Effectuer un **test de chute simule** :
|
||||
- Se coucher au sol dans le champ d'une camera
|
||||
- Attendre ~30 secondes
|
||||
- Verifier la reception de la notification push
|
||||
- Verifier l'image et le message Gemini dans l'alerte
|
||||
|
||||
---
|
||||
|
||||
## Architecture reseau complete
|
||||
|
||||
```mermaid
|
||||
graph TB
|
||||
subgraph Domicile["Domicile du beneficiaire"]
|
||||
CAM1["Camera 1<br/>192.168.1.143"]
|
||||
CAM2["Camera 2<br/>192.168.1.148"]
|
||||
CAM3["Camera 3<br/>192.168.1.152"]
|
||||
JETSON["Jetson SmartEye<br/>192.168.1.xxx"]
|
||||
ROUTER["Box Internet<br/>192.168.1.1"]
|
||||
|
||||
CAM1 -->|RTSP local| JETSON
|
||||
CAM2 -->|RTSP local| JETSON
|
||||
CAM3 -->|RTSP local| JETSON
|
||||
JETSON ---|Ethernet| ROUTER
|
||||
end
|
||||
|
||||
subgraph OVH["Serveur OVH (57.128.74.87)"]
|
||||
SSH["SSH Gateway"]
|
||||
RTSP_RELAY["Relay RTSP<br/>ports 8560-8565"]
|
||||
AUDIO["Audio WebSocket<br/>port 8566"]
|
||||
API["api.php"]
|
||||
GEMINI["Gemini 2.5 Flash"]
|
||||
FCM["Firebase Cloud Messaging"]
|
||||
end
|
||||
|
||||
JETSON ==>|"SSH Tunnel (autossh)<br/>Persistant, auto-reconnect"| SSH
|
||||
SSH --> RTSP_RELAY
|
||||
SSH --> AUDIO
|
||||
JETSON ==>|"POST image<br/>si chute detectee"| API
|
||||
API --> GEMINI
|
||||
GEMINI --> FCM
|
||||
|
||||
subgraph Aidants["Smartphones aidants"]
|
||||
APP1["LucasApp - Fille"]
|
||||
APP2["LucasApp - Fils"]
|
||||
end
|
||||
|
||||
FCM ==>|Push notification| APP1
|
||||
FCM ==>|Push notification| APP2
|
||||
RTSP_RELAY -.->|"Flux video live"| APP1
|
||||
AUDIO -.->|"Interphone"| APP1
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
## Fichier de configuration genere
|
||||
|
||||
A la fin de l'installation, le Jetson cree automatiquement le fichier `smarteye_config.yaml` :
|
||||
|
||||
```yaml
|
||||
# Genere automatiquement par l'assistant d'installation
|
||||
# Ne pas modifier manuellement sauf si necessaire
|
||||
|
||||
site:
|
||||
id: "dupont_marie"
|
||||
name: "Residence Dupont"
|
||||
client_token: "b5ce5015"
|
||||
|
||||
server:
|
||||
api_url: "https://lucas.unigest.fr/api.php"
|
||||
ovh_ip: "57.128.74.87"
|
||||
ssh_user: "debian"
|
||||
|
||||
ports:
|
||||
site_number: 2
|
||||
base_port: 8560
|
||||
|
||||
cameras:
|
||||
- id: "Cam1"
|
||||
name: "Salon"
|
||||
ip: "192.168.1.143"
|
||||
username: "admin"
|
||||
password: "********"
|
||||
stream_hd: "/11"
|
||||
stream_sd: "/12"
|
||||
tunnel_port: 8560
|
||||
enabled: true
|
||||
|
||||
- id: "Cam2"
|
||||
name: "Chambre"
|
||||
ip: "192.168.1.148"
|
||||
username: "admin"
|
||||
password: "********"
|
||||
stream_hd: "/11"
|
||||
stream_sd: "/12"
|
||||
tunnel_port: 8561
|
||||
enabled: true
|
||||
|
||||
- id: "Cam3"
|
||||
name: "Cuisine"
|
||||
ip: "192.168.1.152"
|
||||
username: "admin"
|
||||
password: "********"
|
||||
stream_hd: "/11"
|
||||
stream_sd: "/12"
|
||||
tunnel_port: 8562
|
||||
enabled: true
|
||||
|
||||
audio:
|
||||
local_port: 8800
|
||||
tunnel_port: 8566
|
||||
|
||||
detection:
|
||||
yolo:
|
||||
std_confidence: 0.15
|
||||
pose_confidence: 0.25
|
||||
alert_interval: 120
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
## Maintenance et acces distant
|
||||
|
||||
Une fois installe, le Jetson est accessible a distance depuis le serveur OVH via le tunnel SSH inverse :
|
||||
|
||||
```bash
|
||||
# Depuis le serveur OVH, acceder au WebUI du Jetson
|
||||
# (tunnel inverse sur le port base+7)
|
||||
curl http://localhost:8567/api/status
|
||||
```
|
||||
|
||||
### Commandes utiles (pour le support technique)
|
||||
|
||||
| Action | Commande |
|
||||
|--------|----------|
|
||||
| **Statut du Jetson** | `curl http://localhost:<base+7>/api/status` |
|
||||
| **Redemarrer SmartEye** | `ssh -p <tunnel> jetson "sudo systemctl restart smarteye"` |
|
||||
| **Voir les logs** | `ssh -p <tunnel> jetson "journalctl -u smarteye -f"` |
|
||||
| **Mettre a jour** | `ssh -p <tunnel> jetson "cd /w && git pull && sudo systemctl restart smarteye"` |
|
||||
|
||||
!!! warning "Resilience reseau"
|
||||
Le service `autossh` maintient les tunnels SSH en permanence. En cas de coupure internet :
|
||||
|
||||
- Les tunnels se retablissent automatiquement a la reconnexion
|
||||
- SmartEye continue la detection localement meme sans internet
|
||||
- Les alertes en attente sont envoyees des que la connexion revient
|
||||
|
||||
---
|
||||
|
||||
## Resume du flux d'installation
|
||||
|
||||
```mermaid
|
||||
graph TD
|
||||
A["Branchement Ethernet + USB-C"] --> B["Demarrage automatique (60s)"]
|
||||
B --> C["Annonce mDNS sur le reseau local"]
|
||||
C --> D{"Smartphone detecte le Jetson"}
|
||||
D -->|"smarteye.local:8080"| E["WebUI de configuration"]
|
||||
D -->|"LucasApp scan"| E
|
||||
D -->|"QR Code"| E
|
||||
E --> F["Saisie ID client + Token"]
|
||||
F --> G["Scan ONVIF des cameras"]
|
||||
G --> H["Configuration des cameras"]
|
||||
H --> I["Connexion SSH vers OVH"]
|
||||
I --> J["Test de bout en bout"]
|
||||
J -->|"Tout OK"| K["Surveillance active"]
|
||||
J -->|"Echec"| L["Diagnostic et correction"]
|
||||
L --> J
|
||||
|
||||
style A fill:#455a64,color:#fff
|
||||
style K fill:#00695c,color:#fff
|
||||
style L fill:#bf360c,color:#fff
|
||||
```
|
||||
165
mkdocs-smarteye/docs/deploiement/jetson.md
Normal file
@@ -0,0 +1,165 @@
|
||||
# Installation SmartEye - Guide simplifie
|
||||
|
||||
<div style="background: linear-gradient(135deg, #00695c 0%, #004d40 100%); color: white; padding: 24px; border-radius: 12px; margin-bottom: 24px;">
|
||||
<h2 style="margin:0; color: white;">Guide d'installation rapide</h2>
|
||||
<p style="margin: 8px 0 0 0; opacity: 0.9;">Tout se fait depuis votre smartphone. Temps estime : 10 minutes.</p>
|
||||
</div>
|
||||
|
||||
---
|
||||
|
||||
## Ce dont vous avez besoin
|
||||
|
||||
| | Element | Fourni |
|
||||
|:-:|---------|:------:|
|
||||
| 1 | **Boitier Jetson SmartEye** (avec carte SD) | Oui |
|
||||
| 2 | **Alimentation USB-C** | Oui |
|
||||
| 3 | **Cable Ethernet (RJ45)** | Oui |
|
||||
| 4 | **Cameras** deja installees chez le client | - |
|
||||
| 5 | **Votre smartphone** connecte au WiFi du client | - |
|
||||
| 6 | **Fiche client** (ID + Token, fournis par l'admin) | Oui |
|
||||
|
||||
---
|
||||
|
||||
## Etape 1 — Brancher le boitier
|
||||
|
||||
```
|
||||
Box Internet du client
|
||||
[ ::: ]
|
||||
|
|
||||
Cable Ethernet
|
||||
|
|
||||
[ Jetson SmartEye ] ← USB-C (alimentation)
|
||||
```
|
||||
|
||||
1. Brancher le **cable Ethernet** entre le Jetson et la box internet
|
||||
2. Brancher le **cable USB-C** (alimentation)
|
||||
3. Attendre **1 minute** que la LED passe au vert fixe
|
||||
|
||||
| LED | Signification |
|
||||
|:---:|---------------|
|
||||
| Clignotement lent | Demarrage en cours — patientez |
|
||||
| **Vert fixe** | Pret — passez a l'etape 2 |
|
||||
| Clignotement rapide | Surveillance active (tout roule) |
|
||||
|
||||
---
|
||||
|
||||
## Etape 2 — Se connecter au Jetson
|
||||
|
||||
Assurez-vous que votre smartphone est connecte **au meme WiFi** que le boitier.
|
||||
|
||||
Ouvrez votre navigateur et tapez :
|
||||
|
||||
<div style="background: #263238; color: #80cbc4; padding: 16px; border-radius: 8px; font-size: 1.3em; text-align: center; font-family: monospace;">
|
||||
http://smarteye.local:8080
|
||||
</div>
|
||||
|
||||
<br/>
|
||||
|
||||
!!! tip "Ca ne marche pas ?"
|
||||
**Solution 1** — Ouvrir LucasApp > Parametres > **Installer un SmartEye** (scan automatique)
|
||||
|
||||
**Solution 2** — Scanner le **QR code** colle sous le boitier avec LucasApp
|
||||
|
||||
---
|
||||
|
||||
## Etape 3 — Configurer (4 ecrans)
|
||||
|
||||
### Ecran 1/4 : Identification
|
||||
|
||||
Saisir les informations de la **fiche client** :
|
||||
|
||||
| Champ | Quoi mettre | Exemple |
|
||||
|-------|-------------|---------|
|
||||
| **ID Client** | Sur la fiche | `dupont_marie` |
|
||||
| **Token** | Sur la fiche | `b5ce5015` |
|
||||
| **Nom du site** | Nom libre | `Mme Dupont - Aleria` |
|
||||
|
||||
Appuyer sur **Suivant →**
|
||||
|
||||
---
|
||||
|
||||
### Ecran 2/4 : Cameras
|
||||
|
||||
Le Jetson scanne et trouve les cameras automatiquement.
|
||||
|
||||
```
|
||||
✓ Camera 1 — 192.168.1.143
|
||||
✓ Camera 2 — 192.168.1.148
|
||||
✓ Camera 3 — 192.168.1.152
|
||||
```
|
||||
|
||||
Pour chaque camera :
|
||||
|
||||
1. **Nommer la piece** (Salon, Chambre, Cuisine...)
|
||||
2. Saisir les **identifiants RTSP** si demande (login/mot de passe camera)
|
||||
3. Appuyer sur **Tester** pour verifier l'image en direct
|
||||
|
||||
!!! warning "Aucune camera detectee ?"
|
||||
Verifier que les cameras sont allumees et connectees au meme reseau (WiFi ou Ethernet).
|
||||
|
||||
Appuyer sur **Suivant →**
|
||||
|
||||
---
|
||||
|
||||
### Ecran 3/4 : Connexion serveur
|
||||
|
||||
Les valeurs par defaut sont pre-remplies. **Ne rien modifier** sauf indication contraire.
|
||||
|
||||
| Parametre | Valeur par defaut |
|
||||
|-----------|-------------------|
|
||||
| Serveur | `57.128.74.87` |
|
||||
| Utilisateur | `debian` |
|
||||
| Domaine | `lucas.unigest.fr` |
|
||||
| N° de site | Automatique |
|
||||
|
||||
Appuyer sur **Tester la connexion**, puis **Suivant →**
|
||||
|
||||
---
|
||||
|
||||
### Ecran 4/4 : Test final
|
||||
|
||||
Le Jetson verifie toute la chaine automatiquement :
|
||||
|
||||
| Etape | Quoi | Resultat attendu |
|
||||
|:-----:|------|:-----------------:|
|
||||
| 1 | Connexion cameras | ✓ |
|
||||
| 2 | Detection IA | ✓ |
|
||||
| 3 | Tunnel vers serveur | ✓ |
|
||||
| 4 | Envoi image test | ✓ |
|
||||
| 5 | Notification sur telephone | ✓ |
|
||||
|
||||
Si tout est vert : appuyer sur **Terminer**.
|
||||
|
||||
!!! success "C'est fini"
|
||||
Le Jetson passe en surveillance. Il redemarre seul en cas de coupure de courant. Rien d'autre a faire.
|
||||
|
||||
---
|
||||
|
||||
## Etape 4 — Verifier sur LucasApp
|
||||
|
||||
Sur le telephone de **chaque aidant** :
|
||||
|
||||
- [ ] Ouvrir LucasApp → verifier le flux video en direct
|
||||
- [ ] Tester l'interphone (parler / ecouter)
|
||||
- [ ] **Simuler une chute** : se coucher au sol devant une camera, attendre 30 secondes, verifier que la notification arrive
|
||||
|
||||
---
|
||||
|
||||
## En cas de probleme
|
||||
|
||||
| Symptome | Solution |
|
||||
|----------|----------|
|
||||
| LED ne s'allume pas | Verifier l'alimentation USB-C |
|
||||
| `smarteye.local` ne repond pas | Utiliser le scan LucasApp ou le QR code |
|
||||
| Camera non detectee | Verifier qu'elle est sur le meme reseau |
|
||||
| Test serveur echoue | Verifier la connexion internet du client |
|
||||
| Pas de notification | Verifier que LucasApp est installe et les notifications activees |
|
||||
|
||||
!!! info "Besoin d'aide ?"
|
||||
Contacter le support technique ou consulter le [Guide expert](jetson-expert.md) pour un diagnostic approfondi.
|
||||
|
||||
---
|
||||
|
||||
<div style="background: #e8f5e9; padding: 16px; border-radius: 8px; border-left: 4px solid #2e7d32; color: #1b5e20;">
|
||||
<strong>Recapitulatif</strong> : Brancher → Se connecter → 4 ecrans de config → Verifier sur LucasApp. C'est tout.
|
||||
</div>
|
||||
3
mkdocs-smarteye/docs/guide/alertes.md
Normal file
@@ -0,0 +1,3 @@
|
||||
# Gestion des alertes
|
||||
|
||||
Section en cours de rédaction. Cette page décrira le cycle de vie des alertes, de leur déclenchement à leur résolution.
|
||||
3
mkdocs-smarteye/docs/guide/dashboard.md
Normal file
@@ -0,0 +1,3 @@
|
||||
# Dashboard de surveillance
|
||||
|
||||
Section en cours de rédaction. Cette page décrira le tableau de bord de surveillance en temps réel et ses différentes fonctionnalités.
|
||||
66
mkdocs-smarteye/docs/guide/nouveau-client.md
Normal file
@@ -0,0 +1,66 @@
|
||||
# Ajouter un nouveau client
|
||||
|
||||
## 1. Accéder à l'administration
|
||||
|
||||
Rendez-vous sur **[lucas.unigest.fr/admin.php](https://lucas.unigest.fr/admin.php)** et entrez le code d'accès.
|
||||
|
||||
{ width="400" }
|
||||
|
||||
## 2. Créer le dossier
|
||||
|
||||
Cliquez sur **+ Nouveau Dossier** en haut à droite.
|
||||
|
||||
### Fiche bénéficiaire
|
||||
|
||||
Remplissez les informations de la personne surveillée :
|
||||
|
||||
| Champ | Description | Obligatoire | Exemple |
|
||||
|-------|-------------|:-----------:|---------|
|
||||
| **ID Système** | Identifiant unique (minuscules, sans espaces) | :material-check: | `dupont_marie` |
|
||||
| **Nom & Prénom** | Nom complet du bénéficiaire | :material-check: | `Marie Dupont` |
|
||||
| **Age** | Age du bénéficiaire | | `87` |
|
||||
| **Sexe** | F ou H | | `F` |
|
||||
| **Adresse** | Adresse d'installation des caméras | | `12 rue des Roses` |
|
||||
| **Ville** | Ville / Code postal | | `20270 Aléria` |
|
||||
| **Mobile** | Numéro principal (format international) | :material-check: | `+33612345678` |
|
||||
| **Fixe** | Numéro fixe du domicile | | `+33495123456` |
|
||||
|
||||
!!! tip "Convention de nommage"
|
||||
L'ID système sera utilisé partout : dossier images, configuration SmartEye, base de données.
|
||||
Choisissez un ID court et descriptif : `nom_prenom` ou `nom_ville`.
|
||||
|
||||
## 3. Ajouter les contacts d'urgence
|
||||
|
||||
Cliquez sur **+ Ajouter Contact** pour chaque personne à prévenir en cas de chute.
|
||||
|
||||
| Champ | Description | Exemple |
|
||||
|-------|-------------|---------|
|
||||
| **Nom** | Prénom du contact | Jean |
|
||||
| **Rôle** | Lien avec le bénéficiaire | Fils |
|
||||
| **Téléphone** | Numéro mobile (format international) | +33698765432 |
|
||||
| **Email** | Email (optionnel) | jean@email.fr |
|
||||
|
||||
!!! warning "Ordre des contacts"
|
||||
Les contacts sont alertés **dans l'ordre de la liste**. Placez le contact principal en premier.
|
||||
|
||||
### Exemple de réseau de contacts typique
|
||||
|
||||
```
|
||||
1. Fille (proche géographiquement) → Premier appel
|
||||
2. Fils (disponible en journée) → Deuxième appel
|
||||
3. Voisin (à côté, peut intervenir) → Troisième appel
|
||||
4. Médecin traitant → Notification email
|
||||
```
|
||||
|
||||
## 4. Enregistrer
|
||||
|
||||
Cliquez sur **:material-content-save: Enregistrer la Fiche**. Le client apparaît dans le tableau principal avec le statut **Surveillance Active**.
|
||||
|
||||
## 5. Étapes suivantes
|
||||
|
||||
Après la création du client dans Lucas, il faut :
|
||||
|
||||
- [ ] **Installer les caméras** chez le bénéficiaire → [Guide déploiement](../deploiement/jetson.md)
|
||||
- [ ] **Configurer SmartEye** avec l'ID client → [Installation client](../deploiement/installation-client.md)
|
||||
- [ ] **Installer LucasApp** sur le téléphone des contacts → [Guide LucasApp](dashboard.md)
|
||||
- [ ] **Tester une chute simulée** pour valider la chaîne complète
|
||||
60
mkdocs-smarteye/docs/index.md
Normal file
@@ -0,0 +1,60 @@
|
||||
# Lucas — Système Intelligent de Protection à Domicile
|
||||
|
||||
**Surveillance IA · Détection de chutes · Alerte instantanée · Protection 24/7**
|
||||
|
||||
---
|
||||
|
||||
## Comment ça marche ?
|
||||
|
||||
```mermaid
|
||||
graph LR
|
||||
A[Caméras IP] -->|RTSP| B[Jetson Orin Nano]
|
||||
B -->|Détection YOLO| C{Chute ?}
|
||||
C -->|Image| D[Serveur Lucas]
|
||||
D -->|Gemini AI| E{Confirmée ?}
|
||||
E -->|Oui| F[Alerte Firebase]
|
||||
F -->|Push| G[LucasApp Mobile]
|
||||
E -->|Non| H[Fausse alerte filtrée]
|
||||
```
|
||||
|
||||
## Les 3 composants
|
||||
|
||||
| Composant | Rôle | Technologie |
|
||||
|-----------|------|-------------|
|
||||
| :material-cctv: **SmartEye** | Détection de chutes en temps réel | YOLO + Jetson Orin Nano |
|
||||
| :material-server: **Lucas** | Backend IA, alertes, gestion clients | PHP + Python + Gemini |
|
||||
| :material-cellphone: **LucasApp** | Réception alertes, flux live, interphone | Flutter (Android) |
|
||||
|
||||
## Démarrage rapide
|
||||
|
||||
<div class="grid cards" markdown>
|
||||
|
||||
- :material-account-plus:{ .lg .middle } **Ajouter un client**
|
||||
|
||||
---
|
||||
|
||||
Créer une fiche bénéficiaire et ses contacts d'urgence
|
||||
|
||||
[:octicons-arrow-right-24: Guide nouveau client](guide/nouveau-client.md)
|
||||
|
||||
- :material-server-network:{ .lg .middle } **Déployer un site**
|
||||
|
||||
---
|
||||
|
||||
Installer les caméras, le Jetson et configurer le réseau
|
||||
|
||||
[:octicons-arrow-right-24: Guide déploiement](deploiement/jetson.md)
|
||||
|
||||
- :material-api:{ .lg .middle } **API & Intégration**
|
||||
|
||||
---
|
||||
|
||||
Endpoints, payloads FCM et contrats entre composants
|
||||
|
||||
[:octicons-arrow-right-24: Documentation API](api/endpoints.md)
|
||||
|
||||
</div>
|
||||
|
||||
!!! warning "Philosophie de sécurité"
|
||||
**Mieux vaut 10 fausses alertes filtrées par Gemini qu'une seule chute ignorée.**
|
||||
YOLO ratisse large, Gemini confirme. En cas de doute, l'alerte part toujours.
|
||||
57
mkdocs-smarteye/docs/outils/checklist.md
Normal file
@@ -0,0 +1,57 @@
|
||||
# Checklist Installation
|
||||
|
||||
<div style="background: linear-gradient(135deg, #1b5e20 0%, #2e7d32 100%); color: white; padding: 24px; border-radius: 12px; margin-bottom: 24px;">
|
||||
<h2 style="margin:0; color: #a5d6a7;">Suivi d'installation client</h2>
|
||||
<p style="margin: 8px 0 0 0; opacity: 0.9;">Outil interactif pour suivre chaque etape du deploiement chez un client — du bureau jusqu'a la mise en production.</p>
|
||||
</div>
|
||||
|
||||
---
|
||||
|
||||
## Acceder a la checklist
|
||||
|
||||
:material-open-in-new: **[Ouvrir la checklist interactive](https://lucas.unigest.fr/checklist.php)**
|
||||
|
||||
---
|
||||
|
||||
## Les 6 phases d'installation
|
||||
|
||||
La checklist couvre le parcours complet du technicien :
|
||||
|
||||
| Phase | Description | Responsable principal |
|
||||
|:-----:|-------------|:---------------------:|
|
||||
| 1 | **Au bureau** — Creer le dossier client, preparer le Jetson et les cameras | :material-server: Lucas + :material-eye: SmartEye |
|
||||
| 2 | **Sur place : Materiel** — Brancher, connecter, positionner | :material-eye: SmartEye |
|
||||
| 3 | **Configuration AVA** — Enregistrer le compte, scanner les cameras | :material-cellphone: AVA |
|
||||
| 4 | **Tunnels SSH** — Cle SSH, autossh, verification ports | :material-eye: SmartEye + :material-server: Lucas |
|
||||
| 5 | **Tests complets** — Camera live, simulation chute, notifications | :material-check-all: Tous |
|
||||
| 6 | **Mise en production** — Activation, formation famille, PV recette | :material-check-all: Tous |
|
||||
|
||||
---
|
||||
|
||||
## Fonctionnalites
|
||||
|
||||
- **2 cases par tache** : Fait + Teste
|
||||
- **Selecteur client** : gerer plusieurs installations en parallele
|
||||
- **Barre de progression** : vue d'ensemble de l'avancement
|
||||
- **Notes libres** : documenter les particularites de chaque installation
|
||||
- **Sauvegarde locale** : les donnees persistent dans le navigateur (localStorage)
|
||||
- **Lien vers les guides** : chaque etape technique renvoie vers la documentation detaillee
|
||||
|
||||
---
|
||||
|
||||
## 3 systemes, 3 couleurs
|
||||
|
||||
| Couleur | Systeme | Role |
|
||||
|---------|---------|------|
|
||||
| :material-circle:{ style="color: #f59e0b" } Orange | **SmartEye** | Jetson + cameras + detection YOLO |
|
||||
| :material-circle:{ style="color: #10b981" } Vert | **Lucas** | Serveur OVH + admin + API + Gemini |
|
||||
| :material-circle:{ style="color: #6366f1" } Violet | **AVA** | Application mobile famille |
|
||||
|
||||
---
|
||||
|
||||
## Voir aussi
|
||||
|
||||
- [Configuration video camera](../deploiement/config-video-camera.md)
|
||||
- [Installation camera IP](../deploiement/installation-camera.md)
|
||||
- [Installation Jetson](../deploiement/jetson.md)
|
||||
- [Guide nouveau client](../guide/nouveau-client.md)
|
||||
72
mkdocs-smarteye/mkdocs.yml
Normal file
@@ -0,0 +1,72 @@
|
||||
site_name: Lucas Documentation
|
||||
site_description: Système intelligent de protection à domicile — Détection de chutes par IA
|
||||
site_url: https://lucas.unigest.fr/docs
|
||||
|
||||
theme:
|
||||
name: material
|
||||
language: fr
|
||||
palette:
|
||||
- scheme: slate
|
||||
primary: deep purple
|
||||
accent: cyan
|
||||
toggle:
|
||||
icon: material/brightness-4
|
||||
name: Mode clair
|
||||
- scheme: default
|
||||
primary: deep purple
|
||||
accent: cyan
|
||||
toggle:
|
||||
icon: material/brightness-7
|
||||
name: Mode sombre
|
||||
font:
|
||||
text: Inter
|
||||
code: JetBrains Mono
|
||||
icon:
|
||||
logo: material/shield-home
|
||||
features:
|
||||
- navigation.tabs
|
||||
- navigation.sections
|
||||
- navigation.expand
|
||||
- navigation.top
|
||||
- search.highlight
|
||||
- content.code.copy
|
||||
- content.tabs.link
|
||||
|
||||
markdown_extensions:
|
||||
- admonition
|
||||
- pymdownx.details
|
||||
- pymdownx.superfences:
|
||||
custom_fences:
|
||||
- name: mermaid
|
||||
class: mermaid
|
||||
format: !!python/name:pymdownx.superfences.fence_code_format
|
||||
- pymdownx.tabbed:
|
||||
alternate_style: true
|
||||
- pymdownx.emoji:
|
||||
emoji_index: !!python/name:material.extensions.emoji.twemoji
|
||||
emoji_generator: !!python/name:material.extensions.emoji.to_svg
|
||||
- tables
|
||||
- attr_list
|
||||
|
||||
nav:
|
||||
- Accueil: index.md
|
||||
- Architecture:
|
||||
- Vue d'ensemble: architecture/overview.md
|
||||
- Flux de données: architecture/data-flow.md
|
||||
- Guide Utilisateur:
|
||||
- Nouveau client: guide/nouveau-client.md
|
||||
- Dashboard: guide/dashboard.md
|
||||
- Gestion des alertes: guide/alertes.md
|
||||
- Déploiement:
|
||||
- Installation caméra IP: deploiement/installation-camera.md
|
||||
- Configuration vidéo caméra: deploiement/config-video-camera.md
|
||||
- Installation simplifiée: deploiement/jetson.md
|
||||
- Installation expert: deploiement/jetson-expert.md
|
||||
- Préparer la carte Gold: deploiement/carte-gold.md
|
||||
- Clonage des cartes SD: deploiement/clonage.md
|
||||
- Installation client: deploiement/installation-client.md
|
||||
- Outils:
|
||||
- Checklist installation: outils/checklist.md
|
||||
- API:
|
||||
- Endpoints: api/endpoints.md
|
||||
- Payload FCM: api/fcm-payload.md
|
||||
415
mkdocs-smarteye/upload.php
Normal file
@@ -0,0 +1,415 @@
|
||||
<?php
|
||||
/**
|
||||
* Upload d'images pour la documentation MkDocs SmartEye
|
||||
* Supporte : drag & drop, sélection de fichier, collage (Cmd+V / Ctrl+V)
|
||||
*
|
||||
* Accès : https://lucas.unigest.fr/docs-upload/upload.php
|
||||
*/
|
||||
|
||||
// Sécurité basique — à adapter si besoin
|
||||
$UPLOAD_DIR = __DIR__ . '/docs/assets/images/';
|
||||
$ALLOWED_EXTENSIONS = ['jpg', 'jpeg', 'png', 'gif', 'webp', 'svg'];
|
||||
$MAX_SIZE = 10 * 1024 * 1024; // 10 MB
|
||||
|
||||
// Sous-dossiers disponibles
|
||||
$SUBDIRS = ['general', 'architecture', 'guide', 'deploiement', 'api', 'app'];
|
||||
|
||||
// Traitement de l'upload
|
||||
if ($_SERVER['REQUEST_METHOD'] === 'POST' && isset($_FILES['image'])) {
|
||||
header('Content-Type: application/json');
|
||||
|
||||
$file = $_FILES['image'];
|
||||
$subdir = isset($_POST['subdir']) && in_array($_POST['subdir'], $SUBDIRS) ? $_POST['subdir'] : 'general';
|
||||
$targetDir = $UPLOAD_DIR . $subdir . '/';
|
||||
|
||||
// Vérifications
|
||||
if ($file['error'] !== UPLOAD_ERR_OK) {
|
||||
echo json_encode(['success' => false, 'error' => 'Erreur upload: ' . $file['error']]);
|
||||
exit;
|
||||
}
|
||||
|
||||
if ($file['size'] > $MAX_SIZE) {
|
||||
echo json_encode(['success' => false, 'error' => 'Fichier trop volumineux (max 10 MB)']);
|
||||
exit;
|
||||
}
|
||||
|
||||
// Déterminer l'extension
|
||||
$originalName = $file['name'];
|
||||
$ext = strtolower(pathinfo($originalName, PATHINFO_EXTENSION));
|
||||
|
||||
// Si c'est un collage (blob), détecter le type MIME
|
||||
if (empty($ext) || $ext === 'blob') {
|
||||
$mime = mime_content_type($file['tmp_name']);
|
||||
$mimeMap = [
|
||||
'image/png' => 'png',
|
||||
'image/jpeg' => 'jpg',
|
||||
'image/gif' => 'gif',
|
||||
'image/webp' => 'webp',
|
||||
'image/svg+xml' => 'svg',
|
||||
];
|
||||
$ext = $mimeMap[$mime] ?? '';
|
||||
}
|
||||
|
||||
if (!in_array($ext, $ALLOWED_EXTENSIONS)) {
|
||||
echo json_encode(['success' => false, 'error' => "Extension non autorisée: $ext"]);
|
||||
exit;
|
||||
}
|
||||
|
||||
// Nom du fichier : soit le nom custom, soit le nom original, soit un timestamp
|
||||
$customName = isset($_POST['filename']) ? trim($_POST['filename']) : '';
|
||||
if ($customName) {
|
||||
// Nettoyer le nom
|
||||
$customName = preg_replace('/[^a-zA-Z0-9_\-]/', '-', $customName);
|
||||
$filename = $customName . '.' . $ext;
|
||||
} elseif ($originalName && $originalName !== 'blob' && $originalName !== 'image.png') {
|
||||
$filename = preg_replace('/[^a-zA-Z0-9_\-\.]/', '-', $originalName);
|
||||
} else {
|
||||
$filename = date('Y-m-d_H-i-s') . '.' . $ext;
|
||||
}
|
||||
|
||||
$targetPath = $targetDir . $filename;
|
||||
|
||||
// Éviter l'écrasement
|
||||
if (file_exists($targetPath)) {
|
||||
$base = pathinfo($filename, PATHINFO_FILENAME);
|
||||
$filename = $base . '_' . time() . '.' . $ext;
|
||||
$targetPath = $targetDir . $filename;
|
||||
}
|
||||
|
||||
if (move_uploaded_file($file['tmp_name'], $targetPath)) {
|
||||
$mdPath = "assets/images/$subdir/$filename";
|
||||
echo json_encode([
|
||||
'success' => true,
|
||||
'filename' => $filename,
|
||||
'subdir' => $subdir,
|
||||
'markdown' => "",
|
||||
'path' => $mdPath,
|
||||
]);
|
||||
} else {
|
||||
echo json_encode(['success' => false, 'error' => 'Impossible de déplacer le fichier']);
|
||||
}
|
||||
exit;
|
||||
}
|
||||
|
||||
// Lister les images existantes
|
||||
$existingImages = [];
|
||||
foreach ($SUBDIRS as $sd) {
|
||||
$dir = $UPLOAD_DIR . $sd . '/';
|
||||
if (is_dir($dir)) {
|
||||
$files = scandir($dir);
|
||||
foreach ($files as $f) {
|
||||
if ($f === '.' || $f === '..') continue;
|
||||
$ext = strtolower(pathinfo($f, PATHINFO_EXTENSION));
|
||||
if (in_array($ext, $ALLOWED_EXTENSIONS)) {
|
||||
$existingImages[] = [
|
||||
'name' => $f,
|
||||
'subdir' => $sd,
|
||||
'path' => "assets/images/$sd/$f",
|
||||
'url' => "docs/assets/images/$sd/$f",
|
||||
'size' => filesize($dir . $f),
|
||||
];
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
// Image à la racine de images/
|
||||
$rootDir = $UPLOAD_DIR;
|
||||
if (is_dir($rootDir)) {
|
||||
$files = scandir($rootDir);
|
||||
foreach ($files as $f) {
|
||||
if ($f === '.' || $f === '..' || is_dir($rootDir . $f)) continue;
|
||||
$ext = strtolower(pathinfo($f, PATHINFO_EXTENSION));
|
||||
if (in_array($ext, $ALLOWED_EXTENSIONS)) {
|
||||
$existingImages[] = [
|
||||
'name' => $f,
|
||||
'subdir' => '(racine)',
|
||||
'path' => "assets/images/$f",
|
||||
'url' => "docs/assets/images/$f",
|
||||
'size' => filesize($rootDir . $f),
|
||||
];
|
||||
}
|
||||
}
|
||||
}
|
||||
?>
|
||||
<!DOCTYPE html>
|
||||
<html lang="fr">
|
||||
<head>
|
||||
<meta charset="UTF-8">
|
||||
<meta name="viewport" content="width=device-width, initial-scale=1.0">
|
||||
<title>Upload Images — Documentation SmartEye</title>
|
||||
<style>
|
||||
* { margin: 0; padding: 0; box-sizing: border-box; }
|
||||
body {
|
||||
font-family: 'Inter', -apple-system, sans-serif;
|
||||
background: #1a1a2e;
|
||||
color: #e0e0e0;
|
||||
min-height: 100vh;
|
||||
padding: 2rem;
|
||||
}
|
||||
h1 { color: #bb86fc; margin-bottom: 0.5rem; }
|
||||
.subtitle { color: #888; margin-bottom: 2rem; }
|
||||
|
||||
.upload-zone {
|
||||
border: 3px dashed #bb86fc44;
|
||||
border-radius: 16px;
|
||||
padding: 3rem 2rem;
|
||||
text-align: center;
|
||||
transition: all 0.3s;
|
||||
cursor: pointer;
|
||||
margin-bottom: 2rem;
|
||||
background: #16213e;
|
||||
}
|
||||
.upload-zone:hover, .upload-zone.dragover {
|
||||
border-color: #bb86fc;
|
||||
background: #1a1a3e;
|
||||
transform: scale(1.01);
|
||||
}
|
||||
.upload-zone .icon { font-size: 3rem; margin-bottom: 1rem; }
|
||||
.upload-zone p { color: #aaa; }
|
||||
.upload-zone .hint { font-size: 0.85rem; color: #666; margin-top: 0.5rem; }
|
||||
|
||||
.controls {
|
||||
display: flex;
|
||||
gap: 1rem;
|
||||
margin-bottom: 2rem;
|
||||
flex-wrap: wrap;
|
||||
align-items: center;
|
||||
}
|
||||
select, input[type="text"] {
|
||||
padding: 0.6rem 1rem;
|
||||
border-radius: 8px;
|
||||
border: 1px solid #333;
|
||||
background: #16213e;
|
||||
color: #e0e0e0;
|
||||
font-size: 0.95rem;
|
||||
}
|
||||
select:focus, input:focus { outline: none; border-color: #bb86fc; }
|
||||
input[type="text"] { flex: 1; min-width: 200px; }
|
||||
|
||||
.result {
|
||||
display: none;
|
||||
background: #0f3460;
|
||||
border-radius: 12px;
|
||||
padding: 1.5rem;
|
||||
margin-bottom: 2rem;
|
||||
}
|
||||
.result.show { display: block; }
|
||||
.result.error { background: #3d0000; }
|
||||
.result .md-code {
|
||||
background: #1a1a2e;
|
||||
padding: 0.8rem 1rem;
|
||||
border-radius: 8px;
|
||||
font-family: 'JetBrains Mono', monospace;
|
||||
font-size: 0.9rem;
|
||||
cursor: pointer;
|
||||
display: flex;
|
||||
justify-content: space-between;
|
||||
align-items: center;
|
||||
margin-top: 0.5rem;
|
||||
}
|
||||
.result .md-code:hover { background: #222244; }
|
||||
.result .md-code .copy-btn {
|
||||
background: #bb86fc;
|
||||
color: #000;
|
||||
border: none;
|
||||
padding: 0.3rem 0.8rem;
|
||||
border-radius: 6px;
|
||||
cursor: pointer;
|
||||
font-size: 0.8rem;
|
||||
}
|
||||
|
||||
.preview-img {
|
||||
max-width: 300px;
|
||||
max-height: 200px;
|
||||
border-radius: 8px;
|
||||
margin-top: 1rem;
|
||||
}
|
||||
|
||||
h2 { color: #bb86fc; margin: 2rem 0 1rem; }
|
||||
|
||||
.gallery {
|
||||
display: grid;
|
||||
grid-template-columns: repeat(auto-fill, minmax(200px, 1fr));
|
||||
gap: 1rem;
|
||||
}
|
||||
.gallery-item {
|
||||
background: #16213e;
|
||||
border-radius: 12px;
|
||||
padding: 0.8rem;
|
||||
text-align: center;
|
||||
}
|
||||
.gallery-item img {
|
||||
max-width: 100%;
|
||||
max-height: 150px;
|
||||
border-radius: 8px;
|
||||
object-fit: contain;
|
||||
}
|
||||
.gallery-item .name {
|
||||
font-size: 0.8rem;
|
||||
color: #aaa;
|
||||
margin-top: 0.5rem;
|
||||
word-break: break-all;
|
||||
}
|
||||
.gallery-item .badge {
|
||||
display: inline-block;
|
||||
background: #bb86fc22;
|
||||
color: #bb86fc;
|
||||
padding: 0.15rem 0.5rem;
|
||||
border-radius: 4px;
|
||||
font-size: 0.7rem;
|
||||
margin-top: 0.3rem;
|
||||
}
|
||||
.gallery-item .md-snippet {
|
||||
font-size: 0.7rem;
|
||||
color: #666;
|
||||
cursor: pointer;
|
||||
margin-top: 0.3rem;
|
||||
}
|
||||
.gallery-item .md-snippet:hover { color: #bb86fc; }
|
||||
|
||||
.empty { color: #555; text-align: center; padding: 2rem; }
|
||||
|
||||
.toast {
|
||||
position: fixed;
|
||||
bottom: 2rem;
|
||||
right: 2rem;
|
||||
background: #bb86fc;
|
||||
color: #000;
|
||||
padding: 0.8rem 1.5rem;
|
||||
border-radius: 8px;
|
||||
font-weight: 600;
|
||||
transform: translateY(100px);
|
||||
opacity: 0;
|
||||
transition: all 0.3s;
|
||||
}
|
||||
.toast.show { transform: translateY(0); opacity: 1; }
|
||||
</style>
|
||||
</head>
|
||||
<body>
|
||||
<h1>Upload Images</h1>
|
||||
<p class="subtitle">Documentation SmartEye — Glissez, cliquez ou collez (Cmd+V) une image</p>
|
||||
|
||||
<div class="controls">
|
||||
<select id="subdir">
|
||||
<?php foreach ($SUBDIRS as $sd): ?>
|
||||
<option value="<?= $sd ?>"><?= ucfirst($sd) ?></option>
|
||||
<?php endforeach; ?>
|
||||
</select>
|
||||
<input type="text" id="filename" placeholder="Nom du fichier (optionnel, sans extension)">
|
||||
</div>
|
||||
|
||||
<div class="upload-zone" id="dropzone">
|
||||
<div class="icon">📸</div>
|
||||
<p><strong>Glissez une image ici</strong> ou cliquez pour sélectionner</p>
|
||||
<p class="hint">Cmd+V pour coller depuis le presse-papiers • JPG, PNG, GIF, WebP, SVG • Max 10 MB</p>
|
||||
<input type="file" id="fileInput" accept="image/*" style="display:none">
|
||||
</div>
|
||||
|
||||
<div class="result" id="result"></div>
|
||||
|
||||
<h2>Images existantes (<?= count($existingImages) ?>)</h2>
|
||||
<?php if (empty($existingImages)): ?>
|
||||
<p class="empty">Aucune image pour l'instant.</p>
|
||||
<?php else: ?>
|
||||
<div class="gallery">
|
||||
<?php foreach ($existingImages as $img): ?>
|
||||
<div class="gallery-item">
|
||||
<?php if (in_array(pathinfo($img['name'], PATHINFO_EXTENSION), ['svg'])): ?>
|
||||
<img src="<?= htmlspecialchars($img['url']) ?>" alt="<?= htmlspecialchars($img['name']) ?>">
|
||||
<?php else: ?>
|
||||
<img src="<?= htmlspecialchars($img['url']) ?>" alt="<?= htmlspecialchars($img['name']) ?>" loading="lazy">
|
||||
<?php endif; ?>
|
||||
<div class="name"><?= htmlspecialchars($img['name']) ?></div>
|
||||
<span class="badge"><?= htmlspecialchars($img['subdir']) ?></span>
|
||||
<div class="md-snippet" onclick="copyText(' ?>)')">
|
||||
Copier le markdown
|
||||
</div>
|
||||
</div>
|
||||
<?php endforeach; ?>
|
||||
</div>
|
||||
<?php endif; ?>
|
||||
|
||||
<div class="toast" id="toast">Copié !</div>
|
||||
|
||||
<script>
|
||||
const dropzone = document.getElementById('dropzone');
|
||||
const fileInput = document.getElementById('fileInput');
|
||||
const resultDiv = document.getElementById('result');
|
||||
|
||||
// Click to select
|
||||
dropzone.addEventListener('click', () => fileInput.click());
|
||||
fileInput.addEventListener('change', () => {
|
||||
if (fileInput.files[0]) uploadFile(fileInput.files[0]);
|
||||
});
|
||||
|
||||
// Drag & drop
|
||||
dropzone.addEventListener('dragover', (e) => {
|
||||
e.preventDefault();
|
||||
dropzone.classList.add('dragover');
|
||||
});
|
||||
dropzone.addEventListener('dragleave', () => dropzone.classList.remove('dragover'));
|
||||
dropzone.addEventListener('drop', (e) => {
|
||||
e.preventDefault();
|
||||
dropzone.classList.remove('dragover');
|
||||
const file = e.dataTransfer.files[0];
|
||||
if (file) uploadFile(file);
|
||||
});
|
||||
|
||||
// Paste (Cmd+V)
|
||||
document.addEventListener('paste', (e) => {
|
||||
const items = e.clipboardData.items;
|
||||
for (let item of items) {
|
||||
if (item.type.startsWith('image/')) {
|
||||
const file = item.getAsFile();
|
||||
if (file) uploadFile(file);
|
||||
return;
|
||||
}
|
||||
}
|
||||
});
|
||||
|
||||
function uploadFile(file) {
|
||||
const formData = new FormData();
|
||||
formData.append('image', file);
|
||||
formData.append('subdir', document.getElementById('subdir').value);
|
||||
const customName = document.getElementById('filename').value.trim();
|
||||
if (customName) formData.append('filename', customName);
|
||||
|
||||
resultDiv.className = 'result show';
|
||||
resultDiv.innerHTML = '<p>Upload en cours...</p>';
|
||||
|
||||
fetch('upload.php', { method: 'POST', body: formData })
|
||||
.then(r => r.json())
|
||||
.then(data => {
|
||||
if (data.success) {
|
||||
resultDiv.className = 'result show';
|
||||
resultDiv.innerHTML = `
|
||||
<p><strong>Upload réussi !</strong> — ${data.filename} dans <em>${data.subdir}/</em></p>
|
||||
<div class="md-code">
|
||||
<code>${data.markdown}</code>
|
||||
<button class="copy-btn" onclick="copyText('${data.markdown}')">Copier</button>
|
||||
</div>
|
||||
<img src="docs/assets/images/${data.subdir}/${data.filename}" class="preview-img" alt="Preview">
|
||||
`;
|
||||
// Reset le nom custom
|
||||
document.getElementById('filename').value = '';
|
||||
} else {
|
||||
resultDiv.className = 'result show error';
|
||||
resultDiv.innerHTML = `<p><strong>Erreur :</strong> ${data.error}</p>`;
|
||||
}
|
||||
})
|
||||
.catch(err => {
|
||||
resultDiv.className = 'result show error';
|
||||
resultDiv.innerHTML = `<p><strong>Erreur réseau :</strong> ${err.message}</p>`;
|
||||
});
|
||||
}
|
||||
|
||||
function copyText(text) {
|
||||
navigator.clipboard.writeText(text).then(() => {
|
||||
const toast = document.getElementById('toast');
|
||||
toast.classList.add('show');
|
||||
setTimeout(() => toast.classList.remove('show'), 1500);
|
||||
});
|
||||
}
|
||||
</script>
|
||||
</body>
|
||||
</html>
|
||||