# Dashboard Observatoire Allsky GEVEX — Documentation complète

**Auteur :** Frédéric Tapissier — Gîte AVEX / GEVEX, Vimoutiers, Normandie  
**Site :** https://avex-asso.org/ftapissier/  
**Dashboard live :** http://86.241.95.110:8888/  
**Version :** Mai 2026  

---

## Table des matières

1. [Présentation du projet](#1-présentation-du-projet)
2. [Matériel et logiciels utilisés](#2-matériel-et-logiciels-utilisés)
3. [Architecture générale](#3-architecture-générale)
4. [Le dashboard HTML](#4-le-dashboard-html)
5. [L'analyseur Python allsky_analyzer.py](#5-lanalyseur-python-allsky_analyzerpy)
6. [Analyse de la couverture nuageuse](#6-analyse-de-la-couverture-nuageuse)
7. [Comptage des étoiles et calibration](#7-comptage-des-étoiles-et-calibration)
8. [Intégration OpenWeatherMap](#8-intégration-openweathermap)
9. [Correction de la Lune](#9-correction-de-la-lune)
10. [Intégration NINA via ninaAPI](#10-intégration-nina-via-ninaapi)
11. [Publication sur serveur web Infomaniak](#11-publication-sur-serveur-web-infomaniak)
12. [Historique multi-nuits](#12-historique-multi-nuits)
13. [Démarrage automatique Windows](#13-démarrage-automatique-windows)
14. [Structure des fichiers](#14-structure-des-fichiers)
15. [Dépannage](#15-dépannage)
16. [Évolutions possibles](#16-évolutions-possibles)

---

## 1. Présentation du projet

### Objectif

Le GEVEX est un gîte astronomique situé à Vimoutiers en Normandie, équipé d'une caméra allsky ASI178 pilotée par le logiciel AllSkEye. L'objectif de ce projet est de construire un **dashboard d'observatoire complet**, accessible depuis n'importe quel appareil (PC, téléphone, tablette), affichant en temps réel :

- L'image allsky en direct
- L'analyse automatique du ciel (couverture nuageuse, comptage d'étoiles)
- L'état du séquenceur astronomique NINA
- Les données météo (OWM + Météo-France + carte interactive)
- Les flux des caméras de surveillance
- L'historique des nuits d'observation

### Point de départ

AllSkEye génère une page HTML de statut (`allskeyestatus.html`) servie sur le réseau local (port 8888). Cette page existait mais était basique. Le projet consiste à l'enrichir considérablement tout en restant compatible avec le mécanisme de mise à jour d'AllSkEye.

> 📸 *[Capture : page AllSkEye originale]*

### Résultat final

> 📸 *[Capture : dashboard complet GEVEX]*

---

## 2. Matériel et logiciels utilisés

### Matériel

| Élément | Détail |
|---|---|
| Caméra allsky | ZWO ASI178 couleur, objectif fisheye |
| PC observatoire | Windows 11, héberge AllSkEye |
| PC télescope | Windows, héberge NINA (réseau local séparé) |
| Réseau | IP publique fixe `86.241.95.110` |
| Hébergement web | Infomaniak (`avex-asso.org`) |

### Logiciels

| Logiciel | Rôle |
|---|---|
| **AllSkEye** | Pilotage caméra allsky, génération JPG, serveur web port 8888 |
| **NINA** | Séquenceur d'acquisition astronomique |
| **ninaAPI** (plugin) | API REST pour NINA (v2) |
| **Python 3.14** | Analyseur d'images, proxy, serveur HTTP |
| **FileZilla** | Client FTP pour uploads Infomaniak |

### Bibliothèques Python

```bash
pip install opencv-python numpy matplotlib watchdog ephem pillow
```

| Bibliothèque | Usage |
|---|---|
| `opencv-python` | Analyse d'images allsky |
| `numpy` | Calculs matriciels sur les pixels |
| `matplotlib` | Génération des graphiques PNG |
| `watchdog` | Surveillance du dossier images en temps réel |
| `ephem` | Calcul position Soleil, Lune, crépuscules |
| `pillow` | Lecture du masque PNG |

---

## 3. Architecture générale

```
┌─────────────────────────────────────────────────────┐
│  PC OBSERVATOIRE (86.241.95.110)                    │
│                                                     │
│  AllSkEye ──► D:\AllSkEye\ImageConversions\*.jpg   │
│                    │                                │
│                    ▼                                │
│  allsky_analyzer.py (Python, tâche planifiée admin) │
│    ├── Analyse image (OpenCV)                       │
│    ├── Appel OWM (météo référence)                  │
│    ├── Calcul Soleil/Lune (ephem)                   │
│    ├── Génère sky_status.json + PNG graphiques      │
│    ├── Poll NINA API ──► nina_status.json           │
│    ├── Upload FTP ──► Infomaniak                    │
│    └── Serveur HTTP :8890 (proxy NINA + données)    │
│                                                     │
│  AllSkEye web server :8888                          │
│    └── allskeyestatus.html (dashboard)              │
└─────────────────────────────────────────────────────┘
         │ FTP TLS                    │ navigateur
         ▼                            ▼
┌──────────────────┐    ┌─────────────────────────────┐
│  Infomaniak      │    │  Navigateur (local/internet) │
│  avex-asso.org   │    │                             │
│  /ftapissier/    │    │  http://86.241.95.110:8888/ │
│  gevex/          │    │  ├── allskeyestatus.html    │
│  ├── sky_status  │◄───│  └── iframes Infomaniak :   │
│  ├── nina_status │    │      ├── sky_status_iframe  │
│  ├── history     │    │      ├── nina_iframe        │
│  └── graphiques  │    │      └── history_iframe     │
└──────────────────┘    └─────────────────────────────┘
```

### Pourquoi cette architecture ?

La contrainte principale est que le navigateur impose des restrictions **CORS** (Cross-Origin Resource Sharing) : une page chargée depuis `86.241.95.110:8888` ne peut pas faire de requêtes `fetch()` vers d'autres domaines/ports. Les solutions retenues :

- Les **données textuelles** (JSON) sont lues depuis des **iframes** hébergées sur Infomaniak — même domaine = pas de CORS
- Les **images PNG** (graphiques) passent directement car les balises `<img>` ne sont pas soumises au CORS
- **NINA** (sur un autre PC du réseau local) est proxyfié par le programme Python via un serveur HTTP sur le port 8890

---

## 4. Le dashboard HTML

### Fichier : `allskeyestatus.html`

Ce fichier est le fichier de statut standard d'AllSkEye, enrichi. Il doit rester dans `C:\Program Files\AllSkEye_0.9.29.2\` et conserve les **placeholders AllSkEye** :

- `{ImagesPlaceholderDoNotChange}` — image allsky injectée par AllSkEye
- `{StatusPlaceholderDoNotChange}` — statut système AllSkEye
- `{RefreshTimePlaceholderDoNotChange}` — timer de refresh AllSkEye

### Layout du dashboard (grille 3 colonnes)

```
┌─────────────┬─────────────┬─────────────┐  Ligne 1
│ Caméra      │ Analyse     │ Vue         │
│ Allsky      │ Ciel GEVEX  │ observatoire│
│ + Statut    │ (iframe +   │ gevex2.jpg  │
│             │ graphiques) │             │
├─────────────┴─────────────┼─────────────┤  Ligne 2
│ NINA — Séquenceur         │ Caméra      │
│ (iframe Infomaniak)       │ télescope   │
├─────────────┬─────────────┴─────────────┤  Ligne 3
│ Satellite   │ Carte météo  │ Caméra     │
│ animé       │ interactive  │ observ. 2  │
├─────────────┴──────────────┴────────────┤  Ligne 4
│ Historique des nuits (pleine largeur)   │
└─────────────────────────────────────────┘
```

### Design

- Thème **dark** scientifique/industriel
- Police `Rajdhani` (titres) + `Share Tech Mono` (données)
- Effet scanlines subtil
- Accents colorés : bleu cyan, rose, vert, orange selon les panneaux
- Widget horloge externe (zeitverschiebung.net) — heure locale + date
- Widget phase lunaire (moonphase.guide)

### Rafraîchissement

- **Toutes les 30 secondes** : cache-bust sur les images statiques (allsky, satellite, gevex2.jpg, graphiques PNG) via `?t=timestamp`
- **Toutes les 2 minutes** : rechargement complet de la page via `location.href` avec paramètre `?nocache=timestamp`
- **Iframes Infomaniak** : se rechargent indépendamment via `<meta http-equiv="refresh">`

> 📸 *[Capture : dashboard complet annoté]*

---

## 5. L'analyseur Python allsky_analyzer.py

### Rôle

Programme Python tournant en permanence sur le PC observatoire. Il surveille le dossier images d'AllSkEye et traite chaque nouvelle image dès qu'elle apparaît.

### Configuration (début du fichier)

```python
CONFIG = {
    'images_dir':  r'D:\AllSkEye\ImageConversions',
    'mask_path':   r'D:\AllSkEye\masque_etoile_pour_Claude.png',
    'output_dir':  r'D:\AllSkEye',
    'lat':         '48.873',
    'lon':         '0.219',
    'elevation':   100,
    'owm_key':     'VOTRE_CLE_API_OWM',
    'owm_lat':     48.7167,   # Fresnay-les-Samon
    'owm_lon':     0.3833,
    'ftp_host':    'dzcd.ftp.infomaniak.com',
    'ftp_user':    'dzcd_XXXXX',
    'ftp_pass':    'VOTRE_MOT_DE_PASSE',
    'ftp_dir':     '/web/ftapissier/gevex',
    'ftp_tls':     True,
    'ftp_enabled': True,
}
```

### Pipeline de traitement par image

```
Nouvelle image JPG détectée (watchdog)
    │
    ├── Attente 1.5s (écriture complète du fichier)
    ├── Lecture image OpenCV
    ├── Extraction horodatage depuis nom de fichier
    │     └── Format AllSkEye : -YYYY-MM-DDTHH-MM-SS-mmm.jpg
    │         (heure LOCALE France → conversion UTC pour ephem)
    ├── Calcul contexte astronomique (ephem)
    │     ├── Altitude Soleil → mode JOUR/CRÉPUSCULE/NUIT
    │     ├── Position Lune → masque dynamique
    │     └── Phase lunaire → facteur de correction étoiles
    ├── Application masque paysage + masque Lune dynamique
    ├── Analyse couverture nuageuse (selon mode)
    ├── Si NUIT : comptage étoiles + correction OWM/Lune
    ├── Enregistrement point historique nuit
    ├── Génération sky_status.json
    ├── Génération graphiques PNG (2h glissantes)
    └── Upload FTP vers Infomaniak (thread séparé)
```

### Nommage des fichiers AllSkEye

AllSkEye nomme ses JPG en heure **locale France** :
```
-2026-05-04T22-30-15-123.jpg
 └── 4 mai 2026, 22h30m15s heure locale
```

Le programme convertit automatiquement en UTC pour les calculs astronomiques (ephem travaille toujours en UTC). La conversion tient compte du changement d'heure été/hiver (CEST UTC+2 / CET UTC+1).

---

## 6. Analyse de la couverture nuageuse

### Problématique

La détection de nuages sur une caméra allsky couleur est plus complexe qu'il n'y paraît, pour deux raisons :
1. La méthode varie selon que c'est le jour ou la nuit
2. La présence de la Lune (surtout pleine) peut faire briller les nuages exactement comme un ciel dégagé

### Mode jour : saturation HSV

De jour, les nuages sont **blancs ou gris** (faible saturation), tandis que le ciel dégagé est **bleu** (forte saturation et teinte dans la plage 85°-135° en HSV).

```python
# Ciel bleu dégagé : teinte bleue + saturation > 50
blue_frac  = pixels avec H∈[85-135] et S>50

# Nuages : saturation faible (blanc/gris)  
cloud_frac = pixels avec S < 60

# Résultat combiné
cloud_pct = 0.5 * cloud_frac * 100 + 0.5 * (1 - blue_frac) * 100
```

**Fusion avec OWM :** La caméra ASI178 produit des images avec une saturation naturellement faible, ce qui peut sous-estimer les nuages. On fusionne donc la détection image (40%) avec la donnée OWM (60%) pour le mode jour :
```python
cloud_pct = 0.4 * cloud_image + 0.6 * owm_clouds
```

### Mode nuit : variance locale + comptage étoiles

La nuit, le ratio B/R et la saturation HSV ne fonctionnent plus (tout est sombre). On utilise deux indicateurs :

**Variance locale par blocs 32×32 pixels :**
- Un ciel dégagé avec des étoiles → variance résiduelle **élevée** (sources ponctuelles brillantes)
- Un ciel couvert homogène → variance résiduelle **faible**

**Ratio étoiles observées / étoiles attendues (méthode principale) :**
```python
cloud_pct = 0.75 * (1 - étoiles_observées/étoiles_attendues) * 100
          + 0.25 * cloud_variance
```

> 📸 *[Capture : graphique couverture nuageuse 2h]*

---

## 7. Comptage des étoiles et calibration

### Méthode de détection

```
Image nuit → Niveaux de gris
    │
    ├── Soustraction du fond lent (GaussianBlur 51×51)
    │     └── Élimine le gradient de luminosité (Lune, pollution lumineuse)
    ├── Seuillage strict (moyenne + 3.5 σ, minimum 12)
    ├── Détection de contours
    └── Filtres de validation :
          ├── Aire entre 3 et 120 pixels²  (élimine bruit et satellites)
          └── Circularité > 0.4            (élimine artefacts allongés)
```

### Auto-calibration de star_max_ref

Le programme maintient une référence `star_max_ref` (nombre d'étoiles pour un ciel parfait). Cette valeur s'auto-calibre automatiquement :

- **Conditions requises** : OWM < 10% nuages, visibilité > 8 km, Lune < 20% ou couchée
- **Mécanisme** : si le nombre d'étoiles observées dépasse la référence actuelle (corrigé de la gêne lunaire), la référence est mise à jour et sauvegardée dans `star_max_ref.json`

```python
# Sauvegardé dans D:\AllSkEye\star_max_ref.json
{"star_max_ref": 450, "updated": "2026-05-10T03:15:00"}
```

> 📸 *[Capture : graphique étoiles détectées 2h]*

---

## 8. Intégration OpenWeatherMap

### Pourquoi OWM ?

OWM fournit des données météo en temps réel (toutes les 10 minutes dans le programme) qui servent à **deux usages distincts** :

1. **Calibration de jour** : référence de vérité terrain pour la couverture nuageuse
2. **Calcul d'étoiles attendues la nuit** : transparence atmosphérique théorique

### Clé API

Inscription gratuite sur [openweathermap.org](https://openweathermap.org). Le plan gratuit suffit (60 appels/minute, largement suffisant).

### Calcul de transparence atmosphérique

```python
transp = (1 - nuages_OWM/100)     # couverture nuageuse
       × (visibilité/10000)        # brume/brouillard  
       × (1 - 0.25 × humidité/100) # vapeur d'eau
       × facteur_code_météo        # 0.0 si pluie, 0.3 si brume, 1.0 si clair
```

### Localisation

La station météo OWM est choisie proche de l'observatoire mais pas exactement au même endroit (Fresnay-les-Samon est plus représentatif météorologiquement que Vimoutiers pour ce site).

---

## 9. Correction de la Lune

### Problème

La Lune, surtout en phase gibbeuse ou pleine, éclaire les nuages et fausse tous les algorithmes de détection. Une pleine Lune à 45° de hauteur rend un ciel couvert indiscernable d'un ciel dégagé par simple analyse de luminosité.

### Masque dynamique

La position de la Lune est calculée à chaque image avec `ephem`. Un masque circulaire est appliqué autour de sa position projetée sur l'image fisheye :

```python
# Projection fisheye équidistante
r = r_max × (1 - altitude_lune / 90°)
moon_x = cx + r × sin(azimut)
moon_y = cy - r × cos(azimut)

# Rayon du masque proportionnel à la phase et l'altitude
rayon = 80 × (0.5 + phase) × (altitude/90°)
```

### Étoiles attendues corrigées

```python
# Facteur lunaire : réduit les étoiles visibles selon phase et altitude
moon_factor = 1 - (phase × altitude/90° × 0.75)

étoiles_attendues = star_max_ref × transparence_OWM × moon_factor
```

---

## 10. Intégration NINA via ninaAPI

### Prérequis

- Plugin **ninaAPI** installé dans NINA (disponible sur le gestionnaire de plugins NINA)
- API activée dans les paramètres du plugin (port 1888 par défaut)
- Les deux PC (observatoire et télescope) sur le même réseau local

### Endpoints utilisés (API v2)

| Endpoint | Données récupérées |
|---|---|
| `GET /v2/api/equipment/camera/info` | Température capteur, gain, setpoint |
| `GET /v2/api/equipment/mount/info` | RA, DEC, Alt, Az, statut parking |
| `GET /v2/api/equipment/guider/info` | RMS guidage RA et DEC |
| `GET /v2/api/equipment/focuser/info` | Position, température |
| `GET /v2/api/sequence/json` | Nom séquence, statut, progression |

### Contournement CORS

NINA tourne sur `192.168.1.21:1888`, le dashboard sur `86.241.95.110:8888`. Le navigateur bloque les requêtes cross-origin entre ces deux origines. Solution : le programme Python **proxyfie** les appels NINA via son serveur HTTP interne (port 8890) qui ajoute les headers CORS appropriés.

```
Navigateur → GET http://86.241.95.110:8890/nina/camera
                        │
                Python :8890 → GET http://192.168.1.21:1888/v2/api/equipment/camera/info
                        │
                        └── Réponse + header Access-Control-Allow-Origin: *
```

**Depuis internet** : le port 8890 n'est pas exposé sur internet (sécurité). Les données NINA sont uploadées toutes les 30 secondes sur Infomaniak via FTP, et affichées via une iframe `nina_iframe.html` hébergée sur le même domaine.

### Affichage

> 📸 *[Capture : panneau NINA avec équipements connectés]*

---

## 11. Publication sur serveur web Infomaniak

### Pourquoi Infomaniak ?

Le serveur web d'AllSkEye (port 8888) ne sert pas les fichiers statiques librement — il génère dynamiquement sa page HTML. Les fichiers JSON et PNG générés par le programme ne peuvent donc pas être servis directement. Infomaniak (hébergeur du site `avex-asso.org`) sert de relais public accessible depuis internet.

### Structure des fichiers sur Infomaniak

```
/web/ftapissier/gevex/
├── .htaccess              ← Headers CORS (uploadé au démarrage)
├── sky_status.json        ← Données ciel temps réel
├── sky_cloud_chart.png    ← Graphique nuages 2h
├── sky_star_chart.png     ← Graphique étoiles 2h
├── sky_status_iframe.html ← Page HTML affichant sky_status.json
├── nina_status.json       ← État NINA temps réel
├── nina_iframe.html       ← Page HTML affichant nina_status.json
├── history_status.json    ← Historique 30 dernières nuits
├── sky_history_chart.png  ← Graphique historique
└── history_iframe.html    ← Page HTML affichant l'historique
```

### Upload automatique FTP TLS

Le programme uploade automatiquement après chaque analyse (~1 min) :
- Upload principal : 6 fichiers (status JSON + PNG)
- Upload NINA : `nina_status.json` toutes les 30 secondes
- Upload historique : à chaque clôture de nuit (aube)
- Upload `.htaccess` : une seule fois au démarrage

### .htaccess CORS

```apache
Header always set Access-Control-Allow-Origin "*"
Header always set Access-Control-Allow-Methods "GET, OPTIONS"
Header always set Cache-Control "no-cache, no-store, must-revalidate"
```

### Principe des iframes

Les pages `*_iframe.html` sont servies depuis `avex-asso.org` et font leurs `fetch()` vers des fichiers JSON **sur le même domaine** — pas de CORS. Ces pages sont ensuite intégrées en `<iframe>` dans le dashboard AllSkEye.

> 📸 *[Capture : arborescence Infomaniak via FileZilla]*

---

## 12. Historique multi-nuits

### Fonctionnement

Le programme accumule les mesures nuit par nuit dans un accumulateur en mémoire. La clôture d'une nuit est déclenchée automatiquement lors de la transition nuit→jour (détectée quand `sun_alt > -6°` après une période nocturne).

### Données enregistrées par nuit

```json
{
  "date": "2026-05-10",
  "start": "22:15",
  "cloud_avg": 45.2,
  "cloud_min": 12.3,
  "stars_max": 487,
  "stars_avg": 312,
  "transp_avg": 0.654,
  "clear_mins": 180,
  "n_measures": 420
}
```

| Champ | Signification |
|---|---|
| `cloud_avg` | Couverture nuageuse moyenne sur toute la nuit |
| `cloud_min` | Meilleure fenêtre de la nuit (% minimum) |
| `stars_max` | Nombre max d'étoiles détectées en une image |
| `clear_mins` | Durée cumulée avec nuages < 30% |
| `transp_avg` | Transparence atmosphérique OWM moyenne |

### Persistance

L'historique est sauvegardé dans `D:\AllSkEye\night_history.json` (60 nuits maximum). Il survit aux redémarrages du programme.

### Affichage

> 📸 *[Capture : panneau historique avec tableau et graphiques]*

---

## 13. Démarrage automatique Windows

### Méthode : Planificateur de tâches Windows

Le programme Python tourne comme une tâche planifiée Windows, démarrée automatiquement au démarrage du PC avec les droits **SYSTEM** (équivalent administrateur, sans session utilisateur ouverte).

### Création de la tâche (terminal admin)

```batch
C:\Windows\System32\schtasks.exe /create ^
  /tn "GEVEX Allsky Analyzer" ^
  /tr "\"C:\Users\fredo\AppData\Local\Python\pythoncore-3.14-64\python.exe\" \"D:\AllSkEye\allsky_analyzer.py\"" ^
  /sc onstart /ru SYSTEM /rl HIGHEST /f
```

### Commandes de gestion

```batch
:: Démarrer
C:\Windows\System32\schtasks.exe /run /tn "GEVEX Allsky Analyzer"

:: Arrêter
C:\Windows\System32\schtasks.exe /end /tn "GEVEX Allsky Analyzer"

:: Statut
C:\Windows\System32\schtasks.exe /query /tn "GEVEX Allsky Analyzer"

:: Supprimer
C:\Windows\System32\schtasks.exe /delete /tn "GEVEX Allsky Analyzer" /f
```

### Logs

Le programme génère `D:\AllSkEye\allsky_analyzer.log` avec rotation automatique :
- Taille max : 5 Mo par fichier
- Archives gardées : 3 (`.log.1`, `.log.2`, `.log.3`)
- Total max : ~20 Mo

---

## 14. Structure des fichiers

### PC Observatoire (`D:\AllSkEye\`)

```
D:\AllSkEye\
├── allsky_analyzer.py          ← Programme principal Python
├── masque_etoile_pour_Claude.png ← Masque paysage (PNG N&B 3096×2080)
├── masque_etoile_pour_Claude.png ← Masque zones à exclure (arbres, bâtiments)
├── sky_status.json             ← Données ciel générées
├── sky_cloud_chart.png         ← Graphique nuages
├── sky_star_chart.png          ← Graphique étoiles
├── nina_status.json            ← État NINA
├── history_status.json         ← Historique 30 nuits
├── sky_history_chart.png       ← Graphique historique
├── night_history.json          ← Base historique (60 nuits)
├── star_max_ref.json           ← Référence auto-calibrée
└── allsky_analyzer.log         ← Logs (rotation 5Mo × 3)
```

### AllSkEye (`C:\Program Files\AllSkEye_0.9.29.2\`)

```
├── allskeyestatus.html         ← Dashboard (modifié)
├── sky_status_iframe.html      ← Iframe données ciel
├── nina_iframe.html            ← Iframe NINA
└── history_iframe.html         ← Iframe historique
```

### Masque PNG

> 📸 *[Capture : masque PNG — zones blanches = ciel analysé, zones noires = paysage exclus]*

Le masque est créé manuellement dans Photoshop à la résolution exacte des images JPG (3096×2080 px). Il exclut :
- La structure de l'abri (haut droite)
- Les arbres (bas gauche et bas droite)  
- La lumière parasite (bas droite)
- Le bord circulaire de l'optique fisheye

**Important :** bords nets obligatoires (pas de flou, pas de dégradé). Utiliser `Image → Réglages → Seuil` dans Photoshop avant export.

---

## 15. Dépannage

### Le programme ne démarre pas

```
PermissionError: C:\Program Files\AllSkEye_0.9.29.2\allsky_analyzer.log
```
→ Lancer le terminal **en administrateur**

### Le masque est introuvable

```
ERROR Masque introuvable : D:\AllSkEye\masque_etoile_pour_Claude.png
```
→ Vérifier que le fichier masque est bien dans `D:\AllSkEye\`

### Les données ciel ne s'affichent pas sur le dashboard

1. Vérifier que `https://avex-asso.org/ftapissier/gevex/sky_status.json` est accessible
2. Vérifier dans le log la présence de lignes `FTP ✓`
3. Vérifier que `history_iframe.html`, `sky_status_iframe.html` et `nina_iframe.html` sont présents sur Infomaniak

### NINA affiche "hors ligne"

- Vérifier que NINA est lancé et que le plugin ninaAPI est actif
- NINA doit être sur `192.168.1.21:1888` (configurable dans `NINA_BASE` du programme)
- Depuis internet, le panneau NINA se met à jour toutes les 30 secondes via Infomaniak

### La couverture nuageuse est incorrecte de nuit

- Vérifier que OWM répond (ligne `OWM [...]` dans le log)
- La calibration `star_max_ref` s'affine au fil des nuits — normale au début
- Avec pleine Lune, les valeurs sont moins précises (phénomène physique)

### L'historique reste vide

- Normal jusqu'à la première transition nuit→jour complète
- Vérifier la présence de `D:\AllSkEye\night_history.json` après une nuit

---

## 16. Évolutions possibles

### Court terme
- **Alertes email/SMS** : notification quand le ciel passe de nuageux à dégagé la nuit
- **LiveView NINA** : affichage de l'image en cours d'acquisition (endpoint `liveview` de ninaAPI)
- **SQM** : affichage de la qualité du ciel depuis les données AllSkEye

### Moyen terme
- **Safety Monitor ASCOM** : coupler l'analyse nuageuse à NINA via un driver ASCOM Safety Monitor — NINA arrêterait automatiquement la séquence si le ciel se couvre
- **Prévision de transparence** : croiser les données OWM prévisionnelles avec la transparence historique pour prédire les meilleures fenêtres d'observation

### Long terme
- **Machine Learning** : entraîner un modèle sur les paires (image allsky → % nuages réel) pour une détection plus précise que les méthodes HSV/variance
- **Multi-sites** : étendre le dashboard à d'autres gîtes astronomiques AVEX

---

## Crédits et références

- **AllSkEye** : https://allskeye.com
- **ninaAPI** : https://github.com/christian-photo/ninaAPI
- **OpenWeatherMap** : https://openweathermap.org
- **ephem** (bibliothèque Python) : https://rhodesmill.org/pyephem/
- **meteoblue** (carte interactive) : https://www.meteoblue.com
- **Météo-France** (widget prévisions) : https://meteofrance.com
- **moonphase.guide** (widget lunaire) : https://moonphase.guide
- **zeitverschiebung.net** (widget horloge) : https://www.zeitverschiebung.net

---

*Documentation générée avec l'assistance de Claude (Anthropic) — Mai 2026*  
*Gîte AVEX / GEVEX — Vimoutiers, Normandie — ftapissier@gmail.com*
