Audela
Audela

Intégrer Audela dans un serveur Internet

Intégrer Audela dans un serveur Internet

Cette page est destinée à présenter l'utilisation du logiciel Audela dans le cadre d'observations à grandes distances via le réseau Internet. Il est tout à fait possible d'appliquer cette méthode à un réseau local. Nous allons d'abord faire le point sur trois façons de piloter un observatoire distant.

L'utilisation la plus simple d'un réseau informatique, pour l'observation astronomique, consiste à se servir d'un logiciel qui capture l'écran de l'ordinateur de l'observatoire (celui qui pilote le télescope et la caméra) et transmet l'image sur l'écran d'un ordinateur placé dans une pièce au chaud. Parmi ces logiciels de contrôle de PC distants, citons:

Ce type de logiciel permet de prendre en main l'ordinateur distant comme si l'on était sur place. La copie d'écran peut s'afficher sur l'écran du navigateur et le clavier agit directement sur le PC distant. Ces logiciels ont fréquence de rafraîchissement lente. Plus problématique est que l'utilisateur peut effectuer n'importe quelle opération sur le PC distant sans aucune sécurité. L'usage de ces logiciels est donc réservé à une utilisation locale ou bien simplement pour un groupe fermé d'utilisateurs.

La deuxième façon d'effectuer des observations automatiques, consiste à piloter l'observatoire (télescope, CCD, etc.) avec Audela installé sur un ordinateur proche de l'observatoire (= ordinateur Jardin). Un second ordinateur (= ordinateur Maison), placé dans une pièce chaude située à quelques dizaines de mètres, permet de contrôler l'observatoire à distance. Dans ce cadre, on peut utiliser deux logiciels Audela qui vont échanger des commandes avec le protocole RPC défini à la page précédente:

Schéma d'utilisation d'un contrôle à distance par un réseau local

Si l'on souhaite piloter un observatoire très distant, il devient difficile d'avoir une connexion permanente. De plus, la quantité de données à transférer peut ralentir considérablement le contrôle. Dans ce cas, on préfère utiliser un navigateur Web pour envoyer les ordres de commandes à l'observatoire. C'est ce troisième mode de fonctionnement qui va être décrit en détail dans cette page. La technique utilisée consiste à transmettre, à l'observatoire, les données du formulaire Web. L'ordinateur de l'observatoire est équipé d'un logiciel nommé démon HTTPD (cf. description détaillé plus bas) dont le rôle est d'exécuter un logiciel spécialisé, capable de transformer la requête du formulaire en une commande pour Audela. Ce logiciel de transformation peut être Audela lui même, on le nomme Audela CGI.

Schéma d'utilisation d'un contrôle à distance par un réseau Internet

Cette méthode a des avantages: le fonctionnement asynchrone permet une plus grande sécurité en cas de coupure de réseau et l'analyse du formulaire permet de rejeter des requêtes mal formulées (temps de pose prohibitif, coordonnées erronnées, etc.). De plus, le navigateur Web peut être utilisé à partir de n'importe quel ordinateur situé en n'importe quel endroit de la Terre. Néanmoins, on perd l'intéractivité du réseau local. Dans tous les cas, il peut être utile d'équiper l'ordinateur de l'observatoire d'un logiciel de contrôle de PC distant (VNC, etc.) qui sera utilisé par l'administrateur afin d'effectuer la maintenance logiciel périodiquement.

Enfin, nous signalons aussi le projet de client/serveur pour Audela proposé par Rafael Gonzalez Fuentetaja. Ce projet propose l'écriture de scripts orientés objets pour Audela.

1. Qu'est-ce qu'un CGI ?

D'un point de vue utilisateur, un CGI (Common Gateway Interface) est un logiciel qui est activé par un bouton d'une page WEB. En créant une interface WEB adaptée (formulaire, etc.) qui appelle des CGI, il devient possible d'actionner un observatoire à distance. Le logiciel Audela peut être utilisé en tant que CGI spécialement optimisé pour des applications d'astronomie. En utilisant Audela en tant que CGI sur un serveur Web, il devient possible de générer des éphémérides, de créer un script Tcl pour une observation à prévoir ou bien piloter un observatoire en direct, tout cela à partir d'un navigateur Internet à plusieurs centaines de kilomètres de distance. L'observatoire automatique TAROT-1, situé à l'observatoire de la Côte d'Azur, fonctionne sur ce principe avec Audela en tant que CGI.

Techniquement, l'ordinateur de l'observatoire doit être relié a un réseau Internet. On peut créer facilement un tel réseau localement chez soi pour piloter l'observatoire qui se trouve au fond du jardin à partir d'un ordinateur placé dans la maison. Enfin, il faut installer un serveur HTTPD (=démon pour le protocole de transfert hyper texte) sur l'ordinateur qui est placé près de l'observatoire. Le serveur HTTPD est un logiciel qu'il faut rajouter et lancer (en tâche de fond). C'est lui qui va transformer votre ordinateur en serveur WEB et permet d'utiliser le navigateur avec le protocole http. Ainsi, l'ordinateur équipé d'un serveur HTTPD a pour mission d'attendre qu'un client se connecte à lui et lui demande un service. Le client est un navigateur WEB qui peut être installé sur un ordinateur distant (dans la maison). C'est en général la configuration classique d'utilisation.

Voici une liste de bon serveurs HTTPD gratuits :

Les systèmes d'exploitation Windows 2000 et NT disposent du serveur HTTPD IIS que l'on peut installer directement. Les distributions de Linux sont généralement fournies avec Apache. La distribution de Audela contient une archive spéciale pour installer facilement le serveur Xitami pour Windows.

Pour un observatoire très distant, l'ordinateur de l'observatoire, équipé du démon HTTPD, doit pouvoir être reconu sur l'Internet, soit par un numéro IP fixe, soit par un nom de domaine. Il existe des organismes qui peuvent attribuer un nom de domaine fixe pour un ordinateur qui possède des numéros IP variables (ce qui est le cas lorsque l'on transite par un fournisseur d'accès). Citons le logiciel WinIP (freeware) http://www.algenta.com/software/winip/ qui transmet le numéro IP, attribué par le fournisseur d'accès, et le nom de domaine choisi, à l'organisme ODS (http://www.ods.org/). Le nom de domaine est alors immédiatement utilisable pour se connecter au serveur HTTPD.

2. Installer Audela-CGI

Si l'on souhaite utiliser le serveur Xitami livré avec la distribution de Audela, passer directement au paragraphe 2.2.

2.1 Généralités

A partir de l'installation classique de Audela, effectuer les opérations suivantes :

On vérifiera le bon fonctionnement du serveur HTTPD en connectant un client (Netscape ou IE) sur le même ordinateur que celui qui contient le serveur. Entrer l'adresse URL suivante : http://127.0.0.1/ et constater qu'il y a bien une page d'accueil qui s'affiche. Le numéro IP 127.0.0.1 est le numéro IP de la machine locale, même si elle porte un autre numéro IP.

2.2. Installation de la distribution de Audela pour Windows

Dans la distribution du logiciel Audela, le fichier archive cgi-1.2.zip doit être décompacté. Il génère le dossier audela-1.2/cgiwin qui a les sous dossiers suivants:

Les version plus récentes du serveur Xitami contiennent d'autres dossiers inutilisés dans notre cas. Il faut compléter l'installation en copiant divers fichiers (attention à ne pas effacer les fichiers de leur emplacement d'origine afin de continuer à utiliser Audela de façon "classique") :

Premiers tests:

Cette page de formulaire HTML est générée par le fichier index.htm situé dans le dossier cgiwin/webpages. Cet emplacement correspond à l'adresse de base du serveur Xitami (http://127.0.0.1)

L'accès à cette page, depuis un autre ordinateur, nécessite de remplacer l'adresse 127.0.0.1 par l'adresse IP de l'ordinateur de l'observatoire (ou bien son nom de domaine symbolique) qui fait fonctionner le serveur HTTPD.

Pour les formulaires de dépôt de requête et de la visionneuse, il est conseillé d'éditer le fichier cfgcgi.tcl afin de changer les noms de dossiers pour enregistrer les fichiers de requête et d'images.

3. Exemple d'utilisation

3.1. Un cas simple, l'affichage des données du formulaire

Prenons un exemple simple. Le client remplit un formulaire HTML et désire que le CGI lui retourne simplement le contenu des données du formulaire sur une nouvelle page de son navigateur (c'est un exemple classique car il permet de tester le bon fonctionnement du serveur HTTPD). Cette page n'a pas vocation d'apprendre le langage HTML (de nombreux cours sont accessibles sur le Web) mais nous allons découvrir ici la syntaxe de base des formulaires. Le formulaire HTML pourrait ressembler à cela par exemple :
Entrer votre message

Apparemment, ce formulaire est composé d'une phrase, suivie d'un champ d'entrée de texte et d'un bouton pour démarrer l'exécution du script CGI. Derrière ce formulaire, se "cachent" les lignes HTML suivantes :

<form METHOD="POST" ACTION="/cgi-bin/audela.exe" TARGET="_blank">
 Entrer votre message <input NAME="message" VALUE="vive audela">
 <input TYPE=SUBMIT VALUE="test">
 <input NAME="mode" TYPE=HIDDEN VALUE="test1">
</form></center>

Le formulaire commence par la balise FORM qui sert à définir son commencement.

METHOD définit la façon dont les données seront transmises au script CGI. Il existe deux méthodes : POST et GET. La méthode POST est généralement employée car elle ne contient pas de limitation sur la longueur des données transmises au CGI.

ACTION définit le chemin d'accès au script CGI à exécuter. Ici , le logiciel audela.exe est installé dans le dossier cgi-bin du serveur HTTPD (à changer en audela tout court sous Linux). Changer cgi-bin en Scripts pour un démon IIS.

TARGET définit sur quel écran du navigateur seront envoyées les réponses du script CGI. L'argument "_blank" ouvre une nouvelle fenêtre du navigateur et le CGI peut donc y inscrire ses réponses. Attention, il y existe un bug dans Netscape6.0 qui ne permet pas d'employer normalement TARGET="_blank" et METHOD="post" ensemble.

La deuxième ligne du formulaire montre la phrase qui est affichée à l'écran suivi de la balise INPUT qui sert à définir un champ du formulaire. Le nom du champ est défini par NAME et sa valeur par défaut avec VALUE. Cela permet donc de montrer une zone de saisie de texte dans laquelle il y a un texte écrit par défaut. Il est évidemment possible d'effacer ce texte ou d'en placer un autre.

La troisième ligne définit un champ de TYPE SUBMIT. Il s'agit d'un champ très particulier puisqu'il va générer, sur l'écran du navigateur, un bouton qui lancera le script. L'argument VALUE sert à décorer le bouton avec un texte.

La quatrième ligne, définit un champ de TYPE HIDDEN (= caché en français). Il s'agit d'un champ caché à l'utilisateur et qui contient une donnée qui sera passée au script CGI sans jamais apparaître sur l'écran du navigateur. Le nom de ce champ s'appelle 'mode' et sa valeur est 'test1'. Nous utilisons habituellement le champ nommé 'mode' pour permettre à audela de savoir sur quel bouton l'utilisateur a appuyé. En effet, il peut y avoir plusieurs formulaires qui appellent le script CGI audela.exe sur une même page (ce qui est le cas de cette page !).

A présent, un appui sur le bouton 'test' active le logiciel audela CGI qui lance automatiquement le script Tcl nommé audela.tcl (principe général de audela.exe). Ce fichier audela.tcl est placé dans le dossier cgiwin/cgi-bin. Il n'a rien à voir avec celui situé dans le dossier binwin utilisé par Audela de façon classique. Examinons le contenu de cgiwin/cgi-bin/audela.tcl:

#
# Fichier : audela.tcl
#
# --- recupere les donnees du formulaire
# --- dans les arrays :
# --- cgiaudela(names)
# --- cgiaudela(values)
set numerror [ catch {
 source cgiutil.tcl
 # --- Verifie si le nom 'mode' existe
 # --- et execute le script test_1.tcl s'il vaut 'test1'.
 # --- Cela est code dans le formulaire de la page HTML
 # --- par la ligne <input NAME="mode" TYPE=HIDDEN VALUE="test1">
 set num [lsearch $cgiaudela(names) mode]
 if {$num>=0} {
 set value [lindex $cgiaudela(values) $num]
 if {$value=="test1"} {
 source test_1.tcl
 } elseif {$value=="ephem1"} {
 source ephem_1.tcl
 
 } elseif {$value=="req1"} {
 source req_1.tcl
 } elseif {$value=="visio1"} {
 source visio_1.tcl
 } else {
 cgiaudela_entete
 puts "<BODY>"
 puts "Le mode $value n'est pas disponible"
 puts "</BODY>"
 cgiaudela_fin
 }
 }
} msgerror ]
if {$numerror==1} {
 # --- Identificateur de l'entete de la page HTML pour le client
 puts -nonewline "Content-type: text/html\n\n\n"
 puts "<HTML>"
 puts "<HEADER>"
 puts "</HEADER>"
 puts "<BODY>"
 puts "Tarot CGI error<br>"
 puts "Report : $msgerror <br>"
 puts "</BODY>"
 puts "</HTML>"
}
# --- Fin du CGI
exit

Ce script Tcl produit une page HTML qui s'affichera sur l'écran du navigateur qui a appelé le CGI. Ce script pour audela ne montre aucune fonction graphique. Audela fonctionne donc sans interface lorsqu'il est employé ainsi en tant que CGI (il n'y pas pas besoin d'interface graphique puisque le code graphique est la page HTML générée pour le navigateur). Les paramètres du formulaire HTML sont décodés grâce au script cgiutil.tcl, appelé systématiquement au début de audela.tcl. En effet, les données de tous les champs du formulaire sont codées dans une seule chaîne de caractère. Le script cgiutil.tcl retrouve cette chaîne, la transcode en clair et la décompose en deux listes cgiaudela(names) et cgiaudela(values) qui contiennent respectivement les noms et les valeurs du formulaire. Le principe du transcodage est très bien décrit au chapitre 17 du livre "HTML et la programmation de serveurs WEB" P. Chaléat et D. Charnay édition Eyrolles (1996). Le listing du script cgiutil.tcl est donnée à la fin de cette page.

La suite du script audela.tcl sert à exécuter d'autres scripts Tcl en fonction de la valeur du champ 'mode'. Ainsi, le même programme CGI audela.exe est capable d'exécuter des fonctions très différentes en fonction de la valeur du champ 'mode'. Dans le cas présent, le champ de mode aura pour valeur test1. Le fichier du script test_1.tcl est présent dans le dossier cgiwin/cgi-bin. Voici son listing :

#
# Fichier : test_1.tcl
#
# --- entete HTML
cgiaudela_entete
puts "<BODY>"
# --- affiche la liste des champs NAME
puts "$cgiaudela(names) <BR>"
# --- affiche la liste des champs VALUE
puts "$cgiaudela(values) <BR>"
# --- fin HTML
puts "</BODY>"
cgiaudela_fin

Le texte HTML doit être écrit entre les balises <BODY> et </BODY>. Le script gciutil.tcl définit les fonctions cgiaudela_entete et cgiaudela_fin. L'envoi des données sur l'écran du navigateur est réalisé grâce à la fonction Tcl puts. Cette fonction, envoie la chaîne de caractères spécifiée sur le port stdout. Le résultat de ce script est le suivant :

message mode {vive audela} test1

Ces deux lignes sont normalement inscrites sur une nouvelle page du navigateur. On y retrouve le contenu des deux listes cgiaudela(names) et cgiaudela(values). Le script test_1.tcl tcl n'a qu'une utilité pédagogique pour permettre de montrer les grands principes de fonctionnement du logiciel audela utilisé en CGI. Les exemples qui vont suivre sont beaucoup plus utiles que test_1.tcl.

Notons que l'ensemble de l'exécution du script audela.tcl est enchassé dans une fonction catch. Cette fonction Tcl est très importante car elle a pour mission de détourner les erreurs et d'éviter un arrêt brutal de audela.exe suite à une erreur provoquée par l'interpréteur Tcl (erreur dans le script par exemple). L'emploi de la fonction catch permet de tuer proprement le process audela.exe en cas d'erreur. En effet, dans le cas de Windows NT le process CGI ne peut même pas être tué par l'administrateur et il peut donc, à terme, saturer la mémoire du PC !

3.2. Les éphémérides en ligne

Si l'utilisateur désire les éphémérides de toutes les planètes du système solaire pour la date actuelle, il appuiera sur le bouton ci dessous :

Derrière ce bouton, se "cachent" les lignes HTML suivantes :

<form METHOD="POST" ACTION="/cgi-bin/audela.exe" TARGET="_blank">
 <input TYPE=SUBMIT VALUE="Ephemerides">
 <input NAME="mode" TYPE=HIDDEN VALUE="ephem1">
</form>

Ce formulaire est encore plus simple que celui du test précédent. Il appelle encore audela.exe et entre dans audela.tcl tel qu'il a été défini précédemment. Le champ 'mode' contient la valeur 'ephem1'. Le listing de audela.tcl comporte une ligne conditionnelle (

if {$value=="ephem1"}
) qui exécute le script ephem_1.tcl si le 'mode' vaut 'ephem1'. Le fichier du script éphem_1.tcl est présent dans le dossier cgiwin/cgi-bin. Analysons son listing:

#
# Fichier : ephem_1.tcl
#
# --- entete HTML
cgiaudela_entete
puts "<BODY>"
# --- calcule et affiche la date ---
set d [mc_date2ymdhms now]
puts "Nous sommes le [lindex $d 2]/[lindex $d 1]/[lindex $d 0]\
[lindex $d 3]h[lindex $d 4]min<BR><BR>"
# --- calcule et affiche les ephemerides ---
set liste_ephem [mc_ephem * now {OBJENAME RAH RAM.M DECD DECM.M MAG}]
set n [expr [llength $liste_ephem]-1]
puts "<PRE>"
for {set k 0} {$k<$n} {incr k} {
 set ephem [lindex $liste_ephem $k]
 set planete [format "%7s" [lindex $ephem 0] ]
 set rah [format "%02d" [lindex $ephem 1] ]
 set ram [format "%05.2f" [lindex $ephem 2] ]
 set decd [format "%+03d" [lindex $ephem 3] ]
 set decm [format "%05.2f" [lindex $ephem 4] ]
 set mag [format "%+5.1f" [lindex $ephem 5] ]
 puts "${planete} ${rah}h${ram}m ${decd}&deg;${decm}'${mag}"
}
puts "</PRE>"
# --- fin HTML
puts "</BODY>"
cgiaudela_fin

Pour calculer les éphémérides, nous utilisons la fonction Tcl mc_ephem de la librairie d'extension libmc. Il n'y a aucune difficulté dans ce script si l'on maîtrise, bien sûr, la syntaxe du langage HTML. Rappelons que les fonctions Tcl puts envoient une chaîne de caractère (ici du code HTML) qui sera retournée vers le navigateur qui a appelé le script. Normalement, le script retourne le résultat sous la forme suivante :

Nous sommes le 4/1/2002 16h34min
 Sun 19h01.33m -22°41.44' -26.9
 Moon 11h48.93m +06°55.67' -10.6
Mercury 20h15.13m -21°38.33' -0.8
 Venus 18h51.46m -23°27.31' -3.9
 Mars 23h22.43m -04°44.12' +0.8
Jupiter 06h44.08m +23°03.93' -2.7
Saturn 06h08.56m +21°36.00' -0.2
Uranus 21h40.73m -14°38.64' +5.9
Neptune 20h39.80m -18°16.63' +8.0
 Pluto 17h03.87m -12°54.06' +13.9

Les fonctions de la librairie libmc sont suffisamment nombreuses pour permettre d'améliorer ces éphémérides.

3.3 Gérer un observatoire automatique distant

Observer à distance nécessite au moins un télescope automatique et une caméra CCD. On cherchera aussi probablement à assurer la couverture de l'instrument (abri, coupole, etc.) et un système de gardiennage (météo, intrusions, etc.), le tout automatisé. Nous allons nous intéresser uniquement au transfert des informations à caractère astronomiques qui doivent entrer et sortir de l'observatoire distant, à savoir : les ordres d'observation et la récupération des images acquises.

3.3.1. Principes

Nous allons mettre en place une utilisation via une page WEB. Ceci apporte un accès aisé et quasi universel, ce qui permet de consulter les données de son observatoire à partir de n'importe quelle borne internet. Le schéma ci dessous permet d'avoir une vue synoptique du système logiciel :

Schéma de principe de la gestion d'observations par une interface Web. Ce schéma n'inclut pas les fonctions de gardiennage de l'observatoire (ouverture du toit, etc.) qui peuvent être réalisées par un logiciel indépendant.

Au départ, l'utilisateur va remplir un formulaire HTML pour déposer une requête d'observation :

Formulaire de depot de requete

Entrer votre nom de user Entrer votre mot de passe Coordonnee RA Coordonnee DEC Temps de pose secondes Binning

Le code HTML de ce formulaire est le suivant et peut être inclus dans n'importe quelle page Web (nous avons volontairement omis les caractères accentués pour alléger la syntaxe du code HTML) :

<center><h2>Formulaire de depot de requete</h2></center>
<form METHOD="POST" ACTION="/cgi-bin/audela.exe">
 <input NAME="mode" TYPE=HIDDEN VALUE="req1">
 Entrer votre nom de user <input NAME="user" VALUE=""> <BR>
 Entrer votre mot de passe <input NAME="password" TYPE=PASSWORD VALUE=""> <BR>
 Coordonnee RA <input NAME="rq_ra" TYPE=TEXT SIZE=10 VALUE="3h45m23s"> <BR>
 Coordonnee DEC <input NAME="rq_dec" TYPE=TEXT SIZE=10 VALUE="10d5m23s"> <BR>
 Temps de pose <input NAME="rq_exptime" TYPE=TEXT SIZE=2 VALUE="10">&nbsp; secondes <BR>
 Binning <SELECT NAME="rq_binning" SIZE=1>
 <OPTION VALUE="1" > 1x1
 <OPTION VALUE="2" SELECTED> 2x2
 <OPTION VALUE="4"> 4x4
 </SELECT>&nbsp;<BR>
 <input TYPE=SUBMIT VALUE="Deposer la requete">
</form>

Par appui sur le bouton d'envoi, ce formulaire est décodé par le Démon HTTPD qui exécute alors Audela en tant que CGI. Le CGI Audela exécute à son tour le script audela.tcl précédemment décrit. Le formulaire de requête contient l'entrée :

<input
   NAME="mode" TYPE=HIDDEN VALUE="req1">
. Ainsi, le script audela.tcl va exécuter le script req_1.tcl. C'est ce dernier script qui va réellement traiter et mettre en forme l'information. Le but est de transformer les champs du formulaire HTML, exprimés en langage "humain" sous la forme de mots "opérationnels" pour l'observation. Concrètement, le rôle de req_1.tcl consiste à traduire les données du formulaire sous forme de variables Tcl qui seront utilisées lors de l'observation. Par exemple, le formulaire ci dessus sera converti sous la forme suivante:

# --- requete
set user robert
set ra 3h45m23s
set dec 10d5m23s
set exptime 10
set binning 2

Ce script Tcl peut alors être stocké sous la forme d'un fichier à un endroit précis du disque dur dans lequel on trouvera l'ensemble des fichiers de requêtes. Nous discuterons en détail du nom à donner à ces fichiers dans le paragraphe consacré au dépôt d'une requête d'observation. En fin d'exécution, le script req_1.tcl va générer un message HTML sur la page du navigateur, informant que la requête a bien été déposée. A la fin du script req_1.tcl, Audela CGI est tué par la fonction exit présente à la fin du script audela.tcl

De façon indépendante, un autre logiciel Audela fonctionne en permanence sur l'ordinateur qui pilote les instruments de l'observatoire (il peut fonctionner sur le même ordinateur que celui qui contient le serveur HTTPD et les scripts CGI ou bien il peut fonctionner sur un autre ordinateur relié à celui du serveur HTTPD par un réseau local). Lorsqu'il n'est pas en train de réaliser une observation, ce logiciel Audela va consulter les requêtes encore non effectuées et va en choisir une. Les critères de choix sont nombreux et variés (visibilité, contrainte de temps, etc.). Le système de gardiennage (météo, etc.) doit toujours être consulté avant de démarrer l'observation de la requête choisie. L'exécution d'une requête peut ressembler à la séquence de commandes suivantes:

# --- script d'observation
tel1 goto [list $ra $dec]
cam1 exptime $exptime
cam1 bin [list $binning $binning]
cam1 acq
vwait status_cam1
buf1 save image

A la fin de l'observation, Audela a "transformé" la requête en une image (les requêtes de cet exemple constituent des demandes de cette nature mais on pourrait compliquer la procédure d'observation pour répondre à d'autres besoins). Afin d'assurer une gestion efficace, on peut créer aussi un catalogue des images en précisant la requête associée, le nom de l'objet observé, etc. Dans l'exemple de cette page, nous n'utiliserons pas de tels catalogues afin de simplifier les choses.

La troisième et dernière phase de notre observation à distance, consiste à utiliser un formulaire HTML qui va servir à visualiser les images avec le navigateur Web.

Visionneuse

Entrer votre nom de user Entrer votre mot de passe

Le code HTML de ce formulaire est le suivant et peut être inclus dans n'importe quelle page Web :

<form METHOD="POST" ACTION="/cgi-bin/audela.exe">
 <input NAME="mode" TYPE=HIDDEN VALUE="visio1">
 Entrer votre nom de user <input NAME="user" VALUE=""> <BR>
 Entrer votre mot de passe <input NAME="password" TYPE=PASSWORD VALUE=""> <BR>
 <input TYPE=SUBMIT VALUE="Liste des images">
</form>

Ce formulaire comporte l'entrée

<input NAME="mode" TYPE=HIDDEN
       VALUE="visio1">
. Ainsi, le script audela.tcl va exécuter le script visio_1.tcl. Ce script va consulter les noms de fichiers images, puis va afficher les noms dans un formulaire sur une autre page HTML.

Visionneuse

L'appui sur le bouton "Visualiser" va appeler une seconde fois le script visio_1.tcl. Cette fois, son comportement sera différent car on a assigné le nom de l'image à visualiser (on le réalise techniquement grâce aux valeurs de mots clés du formulaire HTML interprétés différemment par le script). Ainsi, visio_1.tcl va charger l'image FITS en mémoire puis va enregistrer une copie au format JPEG. Le détail du script est donné au paragraphe consacré à la visionneuse. A la fin de son exécution, le script visio_1.tcl génère une page HTML dans laquelle le fichier JPEG va être inséré.

Nous venons de parcourir rapidement le chemin général des informations qui permettent de piloter un observatoire distant. La suite de l'exposé consiste à décrire, en détail, les scripts de dépôt de requête, le traitement de l'observation et la visionneuse. Nous allons rester dans un cadre simple. Le formulaire permettra de déposer une requête constituée de coordonnées à pointer et la réalisation d'une seule image sur le champ comme dans le cas décrit dans ce paragraphe. Il est évidemment possible de modifier ces scripts afin de permettre des stratégies d'observations plus compliquées. Dans ce cadre, on pourra s'intéresser aussi au Remote Telescope Markup Language (RTML) défini pour Hands On Universe (HOU).

3.3.2 Le dépôt d'une requête d'observation

Dans le contexte clients-serveur, il est préférable de ne pas permettre aux clients de faire n'importe quoi avec le télescope. Pour éviter cela, on peut utiliser le système de requêtes. Dans ce cas le serveur propose au client un cadre d'observation.

Concrètement, on a vu que cette demande est faite par le formulaire HTML qui appelle audela.exe en tant que CGI. Le client n'a qu'à remplir les champs du formulaire pour déposer la requête. Si l'on s'en réfère à ce qui a été présenté concernant les éphémérides, audela.exe va toujours lancer le script audela.tcl. Dans le cas présent, le formulaire contient la valeur req1 pour le nom mode. Ainsi, va s'exécuter le script req_1.tcl.

Le but du script req_1.tcl est d'examiner les valeurs que le client a écrites dans les champs du formulaire, de vérifier si l'observation demandée est possible et enfin, de générer un script TCL de requête qui pourra être exécuté par le second programme audela.exe qui pilote l'observatoire. Le fichier du script req_1.tcl est présent dans le dossier cgiwin/cgi-bin. Notons que nous n'avons pas mis de caractères accentués dans ces fichiers de scripts CGI de manière à ce qu'ils puissent être utilisés sur des ordinateurs de langue non française qui ne supportent pas les accents.

#
# req_1.tcl
#
# --- entete HTML
cgiaudela_entete
# --- Decode les parametres du formulaire HTML
set names $cgiaudela(names)
set values $cgiaudela(values)
set num [lsearch $names "user"] ; if {$num>=0} { set req(user) [lindex $values $num] }
set num [lsearch $names "password"] ; if {$num>=0} { set req(password) [lindex $values $num] }
set num [lsearch $names "rq_ra"] ; if {$num>=0} { set req(rq_ra) [lindex $values $num] }
set num [lsearch $names "rq_dec"] ; if {$num>=0} { set req(rq_dec) [lindex $values $num] }
set num [lsearch $names "rq_exptime"] ; if {$num>=0} { set req(rq_exptime) [lindex $values $num] }
set num [lsearch $names "rq_binning"] ; if {$num>=0} { set req(rq_binning)[lindex $values $num] }
# - variables communes a tous les scripts
source cfgcgi.tcl
# --- verifie que l'utilisateur est autorise
set k [lsearch $req(users) $req(user)]
if {$k=="-1"} {
 puts "User not authorized<BR>"
 puts "</BODY>"
 cgiaudela_fin
 return
}
if {$req(password)!=[lindex $req(passwords) $k]} {
 puts "User not authorized<BR>"
 puts "</BODY>"
 cgiaudela_fin
 return
}
# - on limite le temps de pose entre 1 et 60 secondes
set req(rq_exptime) [expr int($req(rq_exptime))]
if {($req(rq_exptime)<1)||($req(rq_exptime)>60)} {
 puts "Exptime between 1 and 60 seconds please !<BR>"
 puts "</BODY>"
 cgiaudela_fin
 return
}
# - on limite le binning à entre 1 et 4
set req(rq_binning) [expr int($req(rq_binning))]
if {($req(rq_binning)<1)||($req(rq_binning)>4)} {
 puts "Binning between 1 and 4 please !<BR>"
 puts "</BODY>"
 cgiaudela_fin
 return
}
# - contenu de la requete
set text ""
append text "set user $req(user)\n"
append text "set ra [mc_angle2deg $req(rq_ra)]\n"
append text "set dec [mc_angle2deg $req(rq_dec)]\n"
append text "set exptime $req(rq_exptime)\n"
append text "set binning $req(rq_binning)\n"
# - nom du fichier de requete : YYYYMMDD_hhmmss_user.req
set t [mc_date2iso8601 now]; # format YYYY-MM-DDThh:mm:ss
set name "[string range $t 0 3][string range $t 5 6][string range $t 8 9]_"
append name "[string range $t 11 12][string range $t 14 15][string range $t 17 18]_"
append name "$req(user).req"
set fullname "$rep(req)/$name"
# - enregistre le fichier de requete sur le disque
set f [open "$fullname" w]
puts -nonewline $f "$text"
close $f
# - message retourné sur le navigateur
puts "Requete $name bien enregistre<BR><BR>"
puts "<PRE>$text</PRE>"
puts "</BODY>"
cgiaudela_fin

Ce script décode les données du formulaire et génère un fichier de requête. Le fichier de requête prend un nom constitué de la date de dépôt de la requête suivi du nom de l'utilisateur. Cette façon de procéder permet de trier facilement les fichiers de requête par ordre chronologique.

L'appel au script

source cfgcgi.tcl
permet de configurer des variables qui seront communes aux scripts req_1.tcl, obscgi.tcl et visio_1.tcl. Voici son listing:

#
# cfgcgi.tcl
#
# --- repertoire de depot des requetes
set rep(req) d:/audela
# --- repertoire des images
set rep(visu) d:/audela
# --- definition du site d'observation
if {[info exists audace]==0} {
 # - Pas de contexte Audace
 set site {gps 2.1383 e 45.1234 125}
} else {
 # - Pour le contexte Audace
 set site "$audace(posobs,observateur,gps)"
}
# --- liste des utilisateurs autorises
set req(users) {robert alain}
set req(passwords) {audela audace}

Dans ce fichier on trouve la variable rep(req) qui contient le nom du dossier qui accueille les fichiers de requêtes (d:\audela par défaut). La requête ne peut être déposée que si l'on a entré un nom d'utilisateur (user) et un mot de passe (password). La liste des utilisateurs est codée dans le script cfgcgi.tcl par la liste Tcl req(users) et la liste des mots de passe respectifs par req(passwords). Dans cet exemple, on a deux utilisateurs: "robert" avec le mot de passe "audela" et "alain" avec le mot de passe "audace". Il est donc très facile de les changer et d'en ajouter.

Le fichier cfgcgi.tcl doit être dupliqué dans le dossier scripts de Audela pour pouvoir être utilisé par le fichier obscgi.tcl (cf. ci après).

3.3.3 Le script d'exécution des observations

Le logiciel Audela, présent sur l'ordinateur de l'observatoire, et qui fonctionne en permanence, va choisir les requêtes en entrée, et va générer les images correspondantes en sortie. Il convient donc d'écrire un script qui va effectuer l'analyse des requêtes à observer, exécuter la requête choisie et mettre à jour les bases de données des requêtes et des images. Normalement, ce logiciel devrait aussi surveiller l'environnement de l'observatoire (détecteur de pluie, etc.) afin de fermer la coupole le cas échéant. Nous ne décrirons pas cette partie dans cet exposé. Le fichier du script obscgi.tcl est présent dans le dossier scripts. Ne pas oublier aussi de vérifier que le fichier cfgcgi.tcl (configuration de variables communes aux différents scripts CGI) soit présent dans le dossier scripts et identique à celui présent dans le dossier cgiwin/cgi-bin.

#
# obscgi.tcl
#
# - variables communes a tous les scripts
source cfgcgi.tcl
# - creation des instruments
if {[info exists audace]==0} {
 # - Pas de contexte Audace
 ::tel::create lx200 com2 -num 1
 ::buf::create 1
 ::cam::create audine lpt1 -num 1
 cam1 buf 1
} else {
 # - Pour le contexte Audace
 if {[::tel::list]==""} {
 ::confTel::run
 tkwait window .confTel
 update
 }
 if {[::cam::list]==""} {
 ::confCam::run
 tkwait window .confCam
 update
 }
}
# - gestionnaire des observations
set sortie no
while {$sortie=="no"} {
 after 1000
 update
 # - Analyse les requêtes présentes sur le  disque
 set list_file ""
 catch {set list_file [lsort -increasing [glob "$rep(req)/*.req"]]} result
 set observable no
 if {[llength $list_file]!=0} {
 foreach file $list_file {
 source "$file"
 set result [mc_radec2altaz $ra $dec {gps 2.1383 e 45.1234 125} now]
 set h [lindex $result 2]
 set alt [lindex $result 1]
 if {((($h<60)||($h>300))&&($alt>30)&&($dec<50))} {
 set observable yes
 break
 }
 }
 }
 # - Traite la requete eventuellement choisie
 if {$observable=="yes"} {
 # - Nom du fichier image YYYMMDD_hhmmss_YYYMMDD_hhmmss_user.fit
 # |- date obs -| |- date req -|
 after 1000
 set reqname [file rootname [file tail $file]]
 set t [mc_date2iso8601 now]; # format YYYY-MM-DDThh:mm:ss
 set obsname "[string range $t 0 3][string range $t 5 6][string range $t 8 9]_"
 append obsname "[string range $t 11 12][string range $t 14 15][string range $t 17 18]_"
 set name "$obsname$reqname"
 set fullname "$rep(visu)/$name"
 # - Pointe le télescope
 tel1 goto [list $ra $dec]
 # - Réalise l'image CCD
 cam1 exptime $exptime
 cam1 bin [list $binning $binning]
 cam1 acq
 vwait status_cam1
 # - Enregistre l'image sur le disque
 buf1 save "$fullname"
 # - detruit le fichier requete exécuté
 file delete "$file"
 }
}
if {[info exists audace]==0} {
 ::tel::delete 1
 ::buf::delete 1
 ::cam::delete 1
}

Ce script analyse, toutes les secondes, l'ensemble des fichiers *.req présents sur le disque dans le dossier spécifié par la variable Tcl req(req) défini dans le script cfgcgi.tcl. Ces fichiers sont triés par ordre chronologique de dépôt de requête. Pour chaque requête, on calcule la hauteur et l'angle horaire théorique actuel. Si l'angle horaire est situé à moins de 60 degrés du méridien et que la hauteur sur l'horizon est supérieure à 30 degrés, alors on accepte de traiter la requête (la variable observable prend la valeur "yes"). On a ajouté une condition supplémentaire sur la valeur de la déclinaison afin tenir compte de la limitation mécanique en déclinaison à cause de la fourche (cas d'un LX200). Pour que ce script fonctionne correctement, il est nécessaire que l'heure du système d'exploitation soit exprimée en temps universel et non pas en temps légal.

Les fichiers images générés ont pour nom la date de début d'observation, suivi du nom que la requête associée. Cette façon de procéder permet de trier facilement les fichiers images en ordre chronologique.

3.3.4 La visionneuse

L'accès aux images par une interface Web se fait par le format Jpeg. Le script visio_1.tcl permet donc de transformer un fichier FITS en un fichier Jpeg et de générer la page HTML qui affiche le Jpeg. Le fichier du script visio_1.tcl est présent dans le dossier cgiwin/cgi-bin.

#
# visio_1.tcl
#
# --- entete HTML
cgiaudela_entete
# --- Decode les parametres du formulaire HTML
set names $cgiaudela(names)
set values $cgiaudela(values)
set num [lsearch $names "user"] ; if {$num>=0} { set req(user) [lindex $values $num] }
set num [lsearch $names "password"] ; if {$num>=0} { set req(password) [lindex $values $num] }
set num [lsearch $names "name"] ; if {$num>=0} { set req(name) [lindex $values $num] }
# - variables communes a tous les scripts
source cfgcgi.tcl
# --- verifie que l'utilisateur est autorise
set k [lsearch $req(users) $req(user)]
if {$k=="-1"} {
 puts "User not authorized<BR>"
 puts "</BODY>"
 cgiaudela_fin
 return
}
if {$req(password)!=[lindex $req(passwords) $k]} {
 puts "User not authorized<BR>"
 puts "</BODY>"
 cgiaudela_fin
 return
}
# - chemin Web d'accès aux images Jpeg
set rep(www) "."
if {[info exists req(name)]==1} {
 # - Si un nom de fichier existe alors on fait la copie Jpeg
 ::buf::create 1
 buf1 load $rep(visu)/$req(name)
 # - dimensions de l'image
 set result [buf1 format]
 set naxis1 [lindex $result 0]
 set naxis2 [lindex $result 1]
 # - seuils automatiques pour la visualisation
 set result [buf1 autocuts]
 set sh [lindex $result 0]
 set sb [lindex $result 1]
 # - on élimine tous les fichiers Jpeg dejà existants
 set list_file ""
 catch {set list_file [lsort -increasing [glob $rep(www)/*.jpg]]} result
 if {[llength $list_file]!=0} {
 foreach file $list_file {
 file delete $file
 }
 }
 # - création du nom pour le fichier Jpeg
 set t [mc_date2iso8601 now]; # format YYYY-MM-DDThh:mm:ss
 set jpgname "[string range $t 0 3][string range $t 5 6][string range $t 8 9]_"
 append jpgname "[string range $t 11 12][string range $t 14 15][string range $t 17 18]"
 set fullname "$rep(www)/$jpgname"
 # - Enregistrement de l'image en format Jpeg (qualité=85)
 buf1 savejpeg $fullname 85 $sb $sh
 ::buf::delete 1
 puts "<center><h3>$req(name)</h3></center><BR>"
 puts "<img SRC=\"$jpgname.jpg\" height=$naxis2 width=$naxis1>"
} else {
 catch {set list_file [lsort -increasing [glob $rep(visu)/*.fit]]} result
 if {[llength $list_file]!=0} {
 # - crée un formulaire contenant la liste des fichiers
 puts "<center><h2>Visionneuse</h2></center>"
 puts "<form METHOD=\"POST\" ACTION=\"/cgi-bin/audela.exe\"> "
 puts "<input NAME=\"mode\" TYPE=HIDDEN VALUE=\"visio1\"> "
 puts "<input NAME=\"user\" TYPE=HIDDEN VALUE=\"$req(user)\"> "
 puts "<input NAME=\"password\" TYPE=HIDDEN VALUE=\"$req(password)\">"
 puts "<input TYPE=SUBMIT VALUE=\"Visualiser\"> "
 puts "<SELECT NAME=\"name\" SIZE=1> "
 foreach file $list_file {
 set file [file rootname [file tail $file]]
 puts " <OPTION VALUE=\"$file.fit\" > $file.fit "
 }
 puts "</SELECT>"
 puts "</form></center>"
 } else {
 puts "There is no image acquired !"
 }
}
puts "</BODY>"
cgiaudela_fin

Comme les navigateurs possèdent des caches de fichiers, il faut toujours nommer le fichier Jpeg par un nouveau nom afin de rafraîchir l'image Jpeg affichée dans la page Web. Dans le script, on supprime tous les fichiers Jpeg du disque avant de créer le nouveau fichier.

Les noms d'utilisateurs et les mots de passe sont identiques à ceux du script req_1.tcl.

4. Le listing du script cgiutil.tcl

Ce script permet de transcoder les données des formulaires CGI et retourne deux listes. De plus, ce script définit quelques petites fonctions utiles comme l'entête d'une page HTML écrite par un CGI (c'est un peu différent d'une page HTML classique).

#
# Fichier : gciutil.tcl
#
global cgiaudela
# ================================
# ==== PROC pour decodage CGI ====
# ================================
proc cgiaudela_transcode { chaine } {
 # --- remplace %XX par la valeur ASCII de l'hexadecimal XX
 # par exemple : %2B est remplacé par le caractere ASCII decimal 43 (+)
 set chaine_out ""
 set n [string length $chaine]
 for {set k 0} {$k<$n} {incr k} {
 set car [string index $chaine $k]
 if {$car=="%"} {
 set car [subst "\\x[string range $chaine [expr $k+1] [expr $k+2]]" ]
 incr k 2
 }
 append chaine_out $car
 }
 return $chaine_out
}
# ===============================
# ==== PROC pour entete HTML ====
# ===============================
proc cgiaudela_entete { } {
 # --- Identification d'une page HTML pour le client
 puts "Content-type: text/html\n\n\n"
 # --- Debut du texte HTML
 puts "<HTML>"
}
# ===============================
# ==== PROC pour entete HTML ====
# ===============================
proc cgiaudela_fin { } {
 # --- fin du texte HTML
 puts "</HTML>"
}
# ================================================
# ==== DECODAGE des donnees du formulaire CGI ====
# ================================================
set cgiaudela(names) {}
set cgiaudela(values) {}
set cgiaudela(listenv) [array names env]
# --- decode le type de methode ---
set cgiaudela(REQUEST_METHOD) ""
if {[lsearch $cgiaudela(listenv) REQUEST_METHOD]!=-1} {
 set cgiaudela(REQUEST_METHOD) $env(REQUEST_METHOD)
}
# --- s'il n'y a pas de methode alors on sort ---
if {$cgiaudela(REQUEST_METHOD)==""} {
 return
}
# --- detecte Netscape 6.0 pour signaler la presence du bug TARGET
# --- qui change la methode POST en GET !
set cgiaudela(bug,target) "no"
catch {
 if {[string first "Netscape6/6.0" $env(HTTP_USER_AGENT)]!=-1}{
 set cgiaudela(bug,target) "yes"
 }
}

# --- extrait la chaine des champs d'entree selon la methode ---
set cgiaudela(QUERY_STRING) ""
if {$cgiaudela(REQUEST_METHOD)=="GET"} {
 set cgiaudela(error) [catch { \
 set cgiaudela(QUERY_STRING) $env(QUERY_STRING) \
 } ]
 if {$cgiaudela(error)==1} {
 return
 }
}
if {$cgiaudela(REQUEST_METHOD)=="POST"} {
 set cgiaudela(CONTENT_LENGTH) $env(CONTENT_LENGTH)
 catch {set cgiaudela(QUERY_STRING) \
 [read stdin $cgiaudela(CONTENT_LENGTH)]} cgiaudela(error)
 if {$cgiaudela(error)==1} {
 catch {set cgiaudela(tty) [open "../stdin.txt" "r"]}
 cgiaudela(error)
 if {$cgiaudela(error)==1} {
 return
 }
 catch {set cgiaudela(QUERY_STRING) [read $cgiaudela(tty) \
 $cgiaudela(CONTENT_LENGTH)]}
 cgiaudela(error)
 close $cgiaudela(tty)
 }
}
#set ttyf [open "env.txt" w]
#puts $ttyf "bug_target=$cgiaudela(bug,target)"
#foreach a $cgiaudela(listenv) {
# puts $ttyf "$a = $env($a)"
#}
#close $ttyf
# --- fractionne la chaine en une liste (separateur &)
set cgiaudela(liste) [split $cgiaudela(QUERY_STRING) "&"]
# --- transcode tous les caracteres et genere les deux listes
foreach cgiaudela(champ) $cgiaudela(liste) {
 # --- les + sont convertis en espaces
 regsub -all {[+]} [lindex $cgiaudela(champ) 0] " " cgiaudela(champ)
 # --- le champ est partage en deux
 set cgiaudela(champ) [split $cgiaudela(champ) "="]
 # --- les champs sont transcodes
 lappend cgiaudela(names) [cgiaudela_transcode [lindex $cgiaudela(champ) 0]]
lappend cgiaudela(values) [cgiaudela_transcode [lindex $cgiaudela(champ) 1]]
}

| English Version | Mailing List Audela | ©2004 Audela | Design TechnoSpeak