source: BAORadio/libindi/libindi/BAOControl/baocontrol.cpp @ 619

Last change on this file since 619 was 619, checked in by frichard, 13 years ago
  • Property svn:executable set to *
File size: 62.1 KB
Line 
1/******************************/
2/* BAOCONTROL                 */
3/*                            */
4/* Franck RICHARD             */
5/* franckrichard033@gmail.com */
6/* Décembre 2011              */
7/******************************/
8
9
10#include "baocontrol.h"
11#include <termios.h>
12#include <unistd.h>
13
14
15
16/**************************************************************************************
17**Constructeur
18***************************************************************************************/
19
20BAOcontrol::BAOcontrol()
21{
22    float a1, a2, a3;
23
24    // Le choix de la couleur des caractÚres est adapté pour une fenêtre de terminal
25    // ayant un fond blanc. pour un fond noir, mettre couleurs=2 dans le fichier params
26
27    ChoixCouleurs=1;
28
29
30    Affiche("\n\n\n\n\n \
31 ******************************************\n \
32 *             BAORadio Control           *\n \
33 * Laboratoire de l'Accélérateur Linéaire *\n \
34 *                                        *\n \
35 *             v0.4  02/12/2011           *\n \
36 *        franckrichard033@gmail.com      *\n \
37 ******************************************\n\n\n", true);
38
39    //Initialisation des variables globales et des pointeurs
40
41
42    delaitransit  = 0;
43    delaitracking = 0;
44    lognum        = 0;
45    numAntennes   = 0;
46    numobjets     = 0;
47    runnum        = 1;
48
49    Pression      = 1013.0;
50    Temperature   = 10.0;
51
52    NoExit        = true;
53    Transit       = false;
54    run           = false;
55    exitrun       = false;
56
57    fd            = NULL;
58    client_socket = NULL;
59
60    // chaines de caractÚres et tableaux
61
62    LatitudeChar  = "";
63    LongitudeChar = "";
64    Serveur       = "";
65    Port          = "";
66
67    Antennes      = new DefAntenne[MAXANTENNES];
68    objets        = new DefObjets[MAXOBJETS];
69
70    //on initalise aussi les tableaux
71
72    for (int i=0; i<MAXANTENNES; i++)
73    {
74        Antennes[i].ok=0;
75        Antennes[i].ip=0;
76        Antennes[i].delta_az=0;
77        Antennes[i].delta_ha=0;
78    }
79
80    for (int i=0; i<MAXOBJETS; i++)
81    {
82        objets[i].JJ=0;
83        objets[i].exec=false;
84    }
85
86    // Chargement du fichier contenant les paramÚtres
87
88    if (!ChargementParametres("params"))
89    {
90        Erreur("Le fichier de configuration 'params' contient des erreurs ou n'existe pas.\n \
91        Merci de vérifier.\n\n");
92        exit(1);
93    }
94
95    // Conversion de la latitude et de la longitude en radians
96
97    Decomposition(LatitudeChar, 0, &a1, &a2, &a3);
98
99    double Latitude = (a1 + a2 / 60.0 + a3 / 3600.0) * Pidiv180;
100
101    Decomposition(LongitudeChar, 1, &a1, &a2, &a3);
102
103    double Longitude = Pi2 - ( a1 + a2 / 60.0 + a3 / 3600.0 ) * Pidiv180;
104
105    // Transfert de la latitude, longitude, pression, température à la classe Astro
106
107    DefinirLongitudeLatitude(Longitude, Latitude);
108
109    DefinirPressionTemp(Pression, Temperature);
110
111    // Ouverture du socket avec indi_BAO
112
113    client_socket = new ClientSocket("localhost", atoi(Port.c_str()) );
114
115    // On se connecte au pilote indi_BAO
116
117    Connect(true);
118}
119
120
121
122/**************************************************************************************
123** Destructeur
124***************************************************************************************/
125
126BAOcontrol::~BAOcontrol()
127{
128    // destruction des tableaux
129   
130    delete [] Antennes;
131    delete [] objets;
132
133    // destruction de la fenêtre graphique,des caractÚres
134
135    if (d!=NULL)
136    {
137        XFreeGC(d, noir);
138        XFreeGC(d, vert);
139        XFreeGC(d, rouge);
140        XFreeGC(d, gris);
141        XFreeFont(d, fd);
142        XDestroyWindow(d, w);
143        XCloseDisplay(d);
144    }
145
146    // destruction du socket
147
148    delete client_socket;
149}
150
151
152/**************************************************************************************
153** Affiche le message à l'écran (si AfficheEcran==true) et le sauvegarde dans le fichier
154** BAOControl.log
155***************************************************************************************/
156
157void BAOcontrol::Affiche(string Message, bool AfficheEcran)
158{
159    FILE *pFile = NULL;
160
161    if ( (pFile = fopen ("BAOcontrol.log", "a")) != NULL)
162    {
163        if (AfficheEcran) cout << Message;
164
165        fprintf (pFile, Message.c_str());
166
167        fclose (pFile);
168    }
169}
170
171void BAOcontrol::Affiche(stringstream *Message, bool AfficheEcran)
172{
173    Affiche(Message->str(), AfficheEcran);
174
175    // on efface le buffer
176
177    Message->str("");
178}
179
180
181/**************************************************************************************
182** Affiche les messages d'erreur en rouge
183***************************************************************************************/
184
185void BAOcontrol::Erreur(string chaine)
186{
187    ChoixCouleurs==1 ? cout << red1  : cout << red2;
188    Affiche(chaine, true);
189    ChoixCouleurs==1 ? cout << grey1 : cout << grey2;
190}
191
192void BAOcontrol::Erreur(stringstream *Message)
193{
194    Erreur(Message->str());
195
196    // on efface le buffer
197
198    Message->str("");
199}
200
201
202/**************************************************************************************
203** Initialise la fenêtre graphique
204***************************************************************************************/
205
206void BAOcontrol::initialiserFenetre()
207{
208    XGCValues gcv;
209
210    // contacte le serveur graphique
211
212    if ((d = XOpenDisplay(getenv("DISPLAY"))) == NULL)
213    {
214        Erreur("Impossible de contacter le serveur\n\n");
215        exit(1);
216    }
217
218    // crée une fenêtre
219
220    w = XCreateSimpleWindow(d, RootWindow(d, DefaultScreen(d)),
221                            0, 0, larg_fenetre, haut_fenetre,
222                            2, BlackPixel(d, DefaultScreen(d)),
223                            WhitePixel(d, DefaultScreen(d)));
224
225    // Création du double buffer
226
227    db = XCreatePixmap(d, w, larg_fenetre, haut_fenetre, DefaultDepth(d, DefaultScreen(d)));
228
229    // Chargement de la police de caractÚres
230
231    if ((fd = XLoadQueryFont(d, "fixed")) == NULL)
232    {
233        Erreur("Impossible de charger la police fixed\n\n");
234        exit(1);
235    }
236
237    // Création des couleurs
238
239    gcv.font = fd->fid;
240    gcv.foreground = BlackPixel(d, DefaultScreen(d));
241    noir = XCreateGC(d, w, GCFont | GCForeground, &gcv);
242
243    gcv.foreground = 200*255;
244    vert = XCreateGC(d, w, GCFont | GCForeground, &gcv);
245
246    gcv.foreground = 255*256*256;
247    rouge = XCreateGC(d, w, GCFont | GCForeground, &gcv);
248
249    gcv.foreground = 200*256*256+200*256+200;
250    gris = XCreateGC(d, w, GCFont | GCForeground, &gcv);
251
252    // Affichage de fenêtre
253
254    XMapWindow(d, w);
255}
256
257
258/**************************************************************************************
259** Dessine les éléments dans la fenêtre graphique
260***************************************************************************************/
261
262void BAOcontrol::Dessiner()
263{
264    char *chaine;
265    GC color;
266
267    chaine = new char [100];
268
269    // On efface la fenêtre
270
271    XSetForeground(d, noir, WhitePixel(d, DefaultScreen(d)));
272    XFillRectangle(d, db, noir, 0, 0, larg_fenetre, haut_fenetre);
273    XSetForeground(d, noir, BlackPixel(d, DefaultScreen(d)));
274
275    // On récupÚre la date et l'heure contenue dans la classe astro (et le jour julien)
276
277    double h  = GetHeure();
278    double mi = GetMin();
279    double s  = GetSec();
280    double a  = GetAnnee();
281    double m  = GetMois();
282    double j  = GetJour();
283    double JJ = GetJJ();
284
285    // on évite les affichages de l'heure du genre 12:56:60 ou 24:00:00
286
287    if (s==60) {
288        s = 0;
289        mi++;
290        if (mi == 60) {
291            mi = 0;
292            h++;
293            if (h == 24) {
294                h = 0;
295                j++;
296            }
297        }
298    }
299
300    //affichage de la date et de l'heure
301
302    sprintf(chaine, "%02.0f:%02.0f:%02.1f TU    %02.0f/%02.0f/%04.0f    JJ=%10.5f",
303            h, mi, s, j, m, a, JJ);
304
305    XDrawString(d, db, noir, 10, 10, chaine, strlen(chaine));
306
307    //En cas d'exécution d'un fichier de mouvements, on affiche la prochaine étape
308
309    if (run)
310    {
311        sprintf(chaine, "Prochaine etape dans %4.1fs", (objets[runnum].JJ - JJ) * 3600.0 * 24.0);
312
313        if ((objets[runnum].JJ - JJ) * 3600.0 * 24.0 >= 0.0)
314            XDrawString(d, db, noir, 350, 10, chaine, strlen(chaine));
315    }
316
317    // affichage des cercles d'état
318    // vert = l'antenne fonctionne
319    // rouge = problÚme détecté sur l'antenne
320    // gris = antenne non connectée
321
322    for (int i=0; i <20; i++)
323    {
324        for (int j=0; j<2; j++)
325        {
326            switch (Antennes[20*j+i].ok)
327            {
328            case 1 :
329                color=vert;
330                break;
331            case 2 :
332                color=rouge;
333                break;
334            default:
335                color=gris;
336                break;
337            }
338
339            XFillArc(d, db ,color, 10+i*30, 20+j*30, 15, 15, 0, 360*64);
340            XDrawArc(d, db ,noir,  10+i*30, 20+j*30, 15, 15, 0, 360*64);
341        }
342    }
343
344
345    // Affichage des messages d'indi_BAO
346    // gÚre aussi le défilement
347
348    if (lognum>10)
349    {
350        for (int i=lognum-1; i>lognum-11; i--)
351        {
352            if ((logs[i].find("Err")!=string::npos)
353                    || (logs[i].find("ALERTE")!=string::npos)) color=rouge;
354            else color=vert;
355            XDrawString(d, db, color, 10, 9*12+(i-lognum+10)*12, logs[i].c_str(), strlen(logs[i].c_str()));
356        }
357    }
358    else
359    {
360        for (int i=0; i<lognum; i++)
361        {
362            if ((logs[i].find("Err")!=string::npos)
363                    || (logs[i].find("ALERTE")!=string::npos)) color=rouge;
364            else color=vert;
365            XDrawString(d, db, color, 10, 9*12+i*12, logs[i].c_str(), strlen(logs[i].c_str()));
366        }
367    }
368
369    // On affiche la copie de l'écran une fois que tout est dessiné
370    // on évite ainsi les scientillements de la fenêtre
371
372    XCopyArea(d, db, w, noir, 0, 0, larg_fenetre, haut_fenetre, 0, 0);
373
374    // On force le rafraichissement de l'écran
375
376    XFlush(d);
377
378    delete [] chaine;
379}
380
381
382/**************************************************************************************
383** Gestion des événements affectant la fenêtre graphique
384***************************************************************************************/
385
386void BAOcontrol::rouler()
387{
388    XEvent e;
389
390    if (XCheckWindowEvent(d, w, ExposureMask, &e))
391    {
392        switch (e.type)
393        {
394        default:
395            //cout << "J'ai reçu un événement " <<  e.type << endl
396            break;
397        case Expose :
398            Dessiner();
399            break;
400        }
401    }
402}
403
404
405/**************************************************************************************
406** RécupÚre les messages envoyés par indi_BAO
407***************************************************************************************/
408
409void BAOcontrol::LireReponse()
410{
411    string reponse, memreponse, decomp;
412    bool test=false;
413
414    *client_socket >> reponse;
415   
416   // printf("%s\n", reponse.c_str());
417
418    do
419    {
420        if (reponse.find("message")!=string::npos)
421        {
422            // On ne garde que la partie intéressante
423            // La partie "message="...
424            reponse = reponse.substr(reponse.find("message") + 9);
425
426            memreponse = reponse;
427
428            // ...jusqu'au "
429            reponse=reponse.substr(0, reponse.find("\""));
430
431            // On récupÚre l'adresse ip de l'antenne qui nous parle
432            // et on met à jour le tableau des états des antennes
433
434            if (reponse.find(". (Antennes connectees")!=string::npos)
435            {
436                decomp = reponse.substr(0, reponse.find(". (Antennes connectees"));
437                decomp = decomp.substr(decomp.rfind(".")+1);
438
439                // si cette antenne est déjà connectée, on change son état
440               
441                if (atoi(decomp.c_str())!=0) for (int i=0; i<numAntennes; i++)
442                {
443                    if (atoi(decomp.c_str()) == Antennes[i].ip)
444                    {
445                        Antennes[i].ok=1;
446                        test=true;
447                        break;
448                    }
449                }
450
451                // ou si c'est une nouvelle antenne, on l'ajoute au tableau
452
453                if (!test)
454                {
455                    Antennes[numAntennes].ip = atoi(decomp.c_str());
456                    Antennes[numAntennes++].ok = 1;
457                }
458            }
459
460            // erreur sur une antenne -> on change son état dans la fenêtre
461
462            if  ((reponse.find("ALERTE antenne ")!=string::npos) ||
463                    (reponse.find("Erreur sur l antenne ")!=string::npos))
464            {
465                decomp = reponse.substr(0, reponse.find(" :"));
466                decomp = decomp.substr(decomp.rfind(".") + 1);
467
468                for (int i=0; i<numAntennes; i++)
469                {
470                    if (atoi(decomp.c_str()) == Antennes[i].ip)
471                    {
472                        Antennes[i].ok = 2;  // Erreur sur l'antenne i
473                    }
474                }
475            }
476
477            // On sauvegarde le message dans le tableau logs
478
479            stringstream os;
480
481            os << lognum << " : " << reponse;
482
483            Affiche(os.str() + "\n", false);
484
485            if (lognum<MAXLOG-1) logs[lognum++] = os.str();
486
487            reponse = memreponse;
488        } 
489        else reponse="";
490         
491
492    } while ( reponse !="" );
493
494     // on actualise la fenêtre
495
496        Dessiner();
497
498    // on envoie un message pour actualiser la fenêtre graphique
499
500    rouler();
501}
502
503
504
505/**************************************************************************************
506** Est-ce que la réponse du pilote indi_BAO est conforme à ce que l'on attendait ?
507***************************************************************************************/
508
509bool BAOcontrol::VerifReponse(string reponseattendue)
510{
511    string reponse = "";
512    string memreponse = "";
513    int    duree = 0;
514    bool   test = false;
515
516    // TODO :La réponse du driver ne vient pas tout de suite et on peut recevoir
517    // des messages intermédiaires un peu étranges impliquant la fonction CONNECT, pourquoi ?
518    // Là on lit les messages trois fois de suite pour essayer de voir passer le bon
519    // Essayer de voir si on ne peut pas faire mieux...
520
521    for (int i=0; i<3 ;i++)
522    {
523        do
524        {
525            usleep(1000); // attendre 1 ms pour laisser le temps au pilote indi_BAO de répondre
526
527            *client_socket >> reponse;
528
529            duree++;
530        }
531        while (reponse.length() == 0 && duree<10 ); // on attend un message pendant 10 ms max
532
533        // on ajoute tous les messages reçus dans memmreponse
534        // ->intéressant pour le debug
535
536        memreponse += reponse;
537
538        if (reponse.find(reponseattendue) != string::npos)
539        {
540            test = true;
541            break;
542        }
543    }
544
545    if (!test)
546    {
547        // réponse inconnue -> une erreur ?
548
549        int pos = memreponse.find("message=");
550
551        if ( pos != string::npos )
552        {
553            memreponse = memreponse.substr(pos + 9);
554
555            memreponse = memreponse.substr(0, memreponse.find("\""));
556
557            Erreur("Réponse du pilote indi_BAO :" + memreponse + "\n\n");
558        }
559
560        return false;
561    }
562
563    return true;
564}
565
566
567/**************************************************************************************
568** Calcul du jour julien et du temps sidéral local
569***************************************************************************************/
570
571void BAOcontrol::Update()
572{
573    struct tm date;
574    time_t t;
575    struct timeval tv;
576    struct timezone tz;
577
578    // On récupÚre la date et l'heure depuis l'horloge du systÚme
579
580    time(&t);
581    date=*gmtime(&t);
582    gettimeofday(&tv, &tz);
583
584    double Annee = (double)date.tm_year + 1900.0;
585    double Mois  = (double)date.tm_mon + 1.0;
586    double Jour  = (double)date.tm_mday;
587    double Heu   = (double)date.tm_hour;
588    double Min   = (double)date.tm_min;
589    double Sec   = (double)date.tm_sec + tv.tv_usec / 1.0E6;
590    double UTCP  = 0.0;//(double)date.tm_isdst;
591
592    /*Annee=2011;
593    Mois=6;
594    Jour=17;
595    Heu=15;
596    Min=53.0;
597    Sec=00.0;*/
598
599    // On actualise la date et l'heure dans la classe Astro
600
601    DefinirDateHeure(Annee, Mois, Jour, Heu, Min, Sec);
602
603    // On lance les calculs
604
605    CalculTSL();
606}
607
608
609/**************************************************************************************
610** gestion du thread permettant
611** -l'exécution d'une liste de mouvements programmés
612** -l'actualisation de la fenêtre graphique
613** -la récupération des messages du pilote indi_BAO
614***************************************************************************************/
615
616void *BAOcontrol::my_thread_process ()
617{
618    stringstream os;
619
620    // Tant ue l'utilisateur n'a pas taper la commande 'exit'
621    while (NoExit)
622    {
623        //On actualise le jour julien et le temps sidéral local
624
625        Update();
626
627        // On récupÚre le jour julien
628
629        double JJ = GetJJ();
630
631
632        // Faut-il executer un fichier de mouvements ?
633
634        if (run && numobjets>1 && runnum<numobjets)
635        {
636            // On lance le mouvement numéro runnum si la date correspond au début
637            // de son exécution et que ce mouvement n'a pas été encore réalisé
638
639            if (JJ >= objets[runnum].JJ && !objets[runnum].exec)
640            {
641                // petit message pour l'utilisateur
642
643                if ( runnum == 1 ) Affiche("Début de l'exécution du fichier de mouvements\n\n", true);
644
645                os << "Suivi de l'objet n°" << runnum << endl;
646                Affiche(&os, true);
647
648                // on indique que le mouvement est en cours d'exécution
649                //ou qu'il a été déjà exécuté
650
651                objets[runnum].exec=true;
652
653                //on envoie l'ordre goto correspondant
654
655                Goto(objets[runnum].ad, objets[runnum].de, Transit, J2000);
656            }
657
658
659            // On arrive à la fin de l'exécution du mouvements runnum
660
661            if (JJ >= objets[runnum].JJ + objets[runnum].Duree / 3600.0 / 24.0 )
662            {
663                // On interrompt le mouvement
664
665                Abort();
666
667                // S'il s'agit du dernier mouvement -> Fin de la commande run
668
669                if ( runnum + 1 >= numobjets )
670                {
671                    Affiche("Fin de l'execution du fichier de mouvements\n\n", true);
672
673                    // on réaffiche le prompt
674
675                    cout << endl;
676                    ChoixCouleurs==1 ? cout << blue1 : cout << blue2;
677                    cout << ">";
678
679                    // on réinitiale toutes les variables impliquées dans la commande run
680
681                    run         = false;
682                    runnum      = 1;
683                    numobjets   = 1;
684
685                    // On sort du programme dans le cas BAOControl -r fileName
686
687                    NoExit=!exitrun;
688                }
689                else
690                {
691                    // on passe au mouvement suivant
692
693                    runnum++;
694                }
695            }
696        }
697
698        // on lit et affiche la réponse des microcontrolleurs
699
700        LireReponse();
701
702        Dessiner();
703
704        // pause de 100 ms
705
706        usleep(100000);
707    }
708
709    // l'utilisateur a tapé exit... On sort du thread...
710
711
712    pthread_exit (0);
713}
714
715
716void* LancementThread(BAOcontrol * appli)
717{
718    appli->my_thread_process();
719
720    return 0;
721}
722
723
724
725/**************************************************************************************
726** Décrypte les commandes saisies par l'utilisateur
727** Exemples :
728** DecompositionCommande("goto 10:10:10 25:10:10", "goto", &chaine1, &chaine2)
729** retourne chaine1  = "10:10:10"
730**          chaine2  = "25:10:10"
731**
732** DecompositionCommande("goto messier 1","goto", &chaine1, NULL) (avec chaine2=NULLL)
733** retourne chaine1  = "messier 1"
734**          chaine2  = NULL
735***************************************************************************************/
736
737bool BAOcontrol::DecompositionCommande(string chaine, string commande, string *chaine1, string *chaine2)
738{
739    size_t pos = chaine.find(commande);
740
741    // si la commande est présente dans chaine, on continue
742
743    if (pos != string::npos)
744    {
745        // on s'intéresse aux caractÚres qui suivent la commande
746
747        pos += commande.length();
748
749        chaine = chaine.substr(pos);
750
751        // on ignore les espaces superflus
752
753        while (chaine[0] == ' ') chaine = chaine.substr(1);
754
755        // si on veut prendre les deux arguments d'une commande
756
757        if (chaine2 != NULL)
758        {
759            // on prend le premier bloc jusqu'au prochain espace -> c'est la chaine1
760
761            *chaine1 = chaine.substr(0, chaine.find(" "));
762
763            // puis on prend le deuxiÚme bloc -> c'est la chaine2
764            pos = chaine.find(" ");
765
766            if (pos != string::npos)
767            {
768                chaine = chaine.substr(pos + 1);
769
770                while (chaine[0] == ' ') chaine = chaine.substr(1);
771
772                *chaine2 = chaine.substr(0, chaine.find(" "));
773            }
774        }
775        else
776        {
777            // on prend tout d'un bloc aprÚs la commande -> chaine 1
778            // utile pour une commande du type "goto m 42" qui doit retourner "m 42" dans une
779            // même chaine
780
781            *chaine1 = chaine;
782        }
783    }
784
785    return true;
786}
787
788
789
790/**************************************************************************************
791** Envoie la longitude et la latitude du lieu d'observation au pilote indi_BAO
792***************************************************************************************/
793
794bool BAOcontrol::EnvoyerCoordGeographiques()
795{
796    // la communication avec le pilote indi_BAO
797    // se fait par l'envoie de fichiers xml
798    // d'où le cÃŽté complexe des commandes
799
800    try
801    {
802        *client_socket << "<newNumberVector device=\"BAO\" name=\"GEOGRAPHIC_COORD\">";
803        *client_socket << "<oneNumber name=\"LAT\">";
804        *client_socket << LatitudeChar;
805        *client_socket << "</oneNumber>";
806        *client_socket << "<oneNumber name=\"LONG\">";
807        *client_socket << LongitudeChar;
808        *client_socket << "</oneNumber>";
809        *client_socket << "</newNumberVector>";
810
811        if (!VerifReponse("name=\"GEOGRAPHIC_COORD\" state=\"Ok\""))
812        {
813            Erreur("ERREUR fct EnvoyerCoordGeographiques : pas de réponse du pilote indi_BAO.\n\n");
814
815            return false;
816        }
817    }
818
819    // un problÚme ?
820
821    catch ( SocketException& e )
822    {
823        Erreur("Exception was caught:" + e.description() + "\n");
824        return false;
825    }
826
827    Affiche("Les coordonnées géographiques ont bien été envoyées au pilote indi_BAO\n\n", true);
828
829    return true;
830}
831
832
833
834/**************************************************************************************
835** Place les antennes en position de repos
836***************************************************************************************/
837
838bool BAOcontrol::Park()
839{
840    try
841    {
842        *client_socket << "<newSwitchVector device=\"BAO\" name=\"\" >";
843        *client_socket << "<oneSwitch name=\"PARK\">";
844        *client_socket << "On";
845        *client_socket << "</oneSwitch>";
846        *client_socket << "</newSwitchVector>";
847
848        if (!VerifReponse("PARK OK"))
849        {
850            Erreur("La commande PARK a échoué.\n\n");;
851
852            return false;
853        }
854    }
855    catch ( SocketException& e)
856    {
857        Erreur("Exception was caught:" + e.description() + "\n");
858        return false;
859    }
860
861    Affiche("Le pilote indi_BAO a bien reçu la commande PARK.\n\n", true);
862
863    return true;
864}
865
866
867
868/**************************************************************************************
869** Annule le mouvement en cours
870***************************************************************************************/
871
872bool BAOcontrol::Abort()
873{
874    try
875    {
876        *client_socket << "<newSwitchVector device=\"BAO\" name=\"ABORT_MOTION\" >";
877        *client_socket << "<oneSwitch name=\"ABORT\">";
878        *client_socket << "On";
879        *client_socket << "</oneSwitch>";
880        *client_socket << "</newSwitchVector>";
881
882        if (!VerifReponse("ABORT OK"))
883        {
884            Erreur("L'annulation a échoué.\n\n");
885
886            return false;
887        }
888    }
889    catch ( SocketException& e)
890    {
891        Erreur("Exception was caught:" + e.description() + "\n");
892        return false;
893    }
894
895    Affiche("Le pilote indi_BAO a bien reçu la commande ABORT.\n\n", true);
896
897    return true;
898}
899
900
901
902/**************************************************************************************
903** Diriger l'antenne vers les coordonnées ar et dec et suivre l'objet
904** en activant le mode transit ou tracking.
905** si J2000 == true, cela signifie que les coordonnées ar et dec sont données dans le
906** le systÚme de coordonnées J2000 (écliptique et équinoxe du 1 janvier 2000 à 0 h TU)
907** Des calculs supplémentaires (précession, nutation, abérration) sont alors nécessaires
908***************************************************************************************/
909
910bool BAOcontrol::Goto(string ar, string dec, bool Transit, bool J2000)
911{
912    float  ar1, ar2, ar3;
913    float  dec1, dec2, dec3;
914    double arf, decf;
915    double azi, hau;
916
917
918     /*
919     //Pour les tests
920     ar="05:39:14.8";
921     dec="23:19:24.1";
922     printf("JJ=%10.10f\n", GetJJ());
923     J2000=true;
924     */
925
926    // Conversion de l'AD et de la déclinaison en radians
927
928    Decomposition(ar, 2, &ar1, &ar2, &ar3);
929    Decomposition(dec, 0, &dec1, &dec2, &dec3);
930   
931    arf  = ( ar1  + ar2 / 60.0  + ar3 / 3600.0 ) * 15.0 * Pidiv180;
932    decf = ( fabs(dec1) + dec2 / 60.0 + dec3 / 3600.0 ) * Pidiv180;
933
934    if (dec[0]=='-') decf = -decf;
935
936    // calculs pupplémentaires pour se ramener
937    // à l'époque de l'observation
938
939    if ( J2000 )
940    {
941        Precession(&arf, &decf);
942        NutationEtoile(&arf, &decf);
943        AberrationAnnuelle(&arf, &decf);
944    }
945
946    // on réécrit l'ar et la dec dans le format d'indi_BAO
947
948    ar  = DHMS(arf * N180divPi, true);
949
950    dec = DHMS(decf * N180divPi, false);
951
952    // on en informe l'utilisateur
953
954    Affiche("Coordonnées apparentes de l'objet :\n", true);
955
956    Affiche("AD=" + ar  + "   Dec=" + dec +"\n", true);
957
958   
959    /*
960    //Tests
961    Azimut(arf, decf, &azi, &hau);
962
963    hau=RefractionAtmospherique(hau);
964
965    Affiche("Coordonnées rectangulaires liées au lieu d'observation :\n", true);
966
967    printf("Azimut = %s   Hauteur = %s\n", DHMS(azi*N180divPi,false).c_str(), DHMS(hau*N180divPi, false).c_str());
968    */
969
970    // On transmet les coordonnées au pilote BAO
971
972    try
973    {
974        *client_socket << "<newSwitchVector device=\"BAO\" name=\"ON_COORD_SET\">";
975        *client_socket << "<oneSwitch name=\"TRANSIT\">";
976        if (Transit) *client_socket << "On";
977        else *client_socket << "Off";
978        *client_socket << "</oneSwitch>";
979
980        *client_socket << "<oneSwitch name=\"TRACKING\">";
981        if (Transit)  *client_socket << "Off";
982        else *client_socket << "On";
983        *client_socket << "</oneSwitch>";
984        *client_socket << "</newSwitchVector>";
985
986        if (!VerifReponse("name=\"ON_COORD_SET\""))
987        {
988            Erreur("Le changement de mode TRANSIT/TRACKING a échoué.\n\n");
989
990            return false;
991        }
992
993        *client_socket << "<newNumberVector device=\"BAO\" name=\"EQUATORIAL_EOD_COORD_REQUEST\">";
994        *client_socket << "<oneNumber name=\"RA\">";
995        *client_socket << ar;
996        *client_socket << "</oneNumber>";
997        *client_socket << "<oneNumber name=\"DEC\">";
998        *client_socket << dec;
999        *client_socket << "</oneNumber>";
1000        *client_socket << "</newNumberVector>";
1001
1002        if (!VerifReponse("name=\"EQUATORIAL_EOD_COORD_REQUEST\""))
1003        {
1004            Erreur("Le transfert des coordonnées de l'objet a échoué.\n\n");
1005
1006            return false;
1007        }
1008    }
1009    catch ( SocketException& e)
1010    {
1011        Erreur("Exception was caught:" + e.description() + "\n");
1012        return false;
1013    }
1014
1015    Affiche("Les nouvelles coordonnées AD=" + ar + " Dec=" + dec, true);
1016    Affiche(" ont été envoyées au pilote indi_BAO.\n\n", true);
1017    return true;
1018}
1019
1020
1021
1022/**************************************************************************************
1023** Se connecte ou se déconnecte au pilote indi_BAO
1024***************************************************************************************/
1025
1026bool BAOcontrol::Connect(bool connect)
1027{
1028    try
1029    {
1030        *client_socket << "<newSwitchVector device=\"BAO\" name=\"CONNECTION\">";
1031
1032        if (connect) *client_socket << "<oneSwitch name=\"CONNECT\">";
1033        else *client_socket << "<oneSwitch name=\"DISCONNECT\">";
1034
1035        *client_socket << "On";
1036        *client_socket << "</oneSwitch>";
1037        *client_socket << "</newSwitchVector>";
1038
1039        if (connect)
1040        {
1041            if (!VerifReponse("BAORadio is online"))
1042            {
1043                Erreur("La connexion a échoué.\n\n");
1044
1045                return false;
1046            }
1047        }
1048        else
1049        {
1050            if (!VerifReponse("BAORadio is offline"))
1051            {
1052                Erreur("La déconnexion a échoué.\n\n");
1053
1054                return false;
1055            }
1056        }
1057    }
1058
1059    catch ( SocketException& e )
1060    {
1061        Erreur("Exception was caught:" + e.description() + "\n");
1062        return false;
1063    }
1064
1065    if (connect)
1066    {
1067        Affiche("La connexion a été établie avec le pilote indi_BAO.\n\n", true);
1068
1069        EnvoyerCoordGeographiques();
1070    }
1071    else
1072    {
1073        Affiche("BAOcontrol s'est bien déconnecté du pilote indi_BAO.\n\n", true);
1074    }
1075
1076    return true;
1077}
1078
1079
1080/**************************************************************************************
1081** Gestion du clavier en mode raw pour la procédure d'alignement
1082***************************************************************************************/
1083
1084void mode_raw(int activer)
1085{
1086    static struct termios cooked;
1087    static int raw_actif = 0;
1088   
1089    if (raw_actif == activer)
1090        return;
1091   
1092    if (activer)
1093    {
1094        struct termios raw;
1095       
1096        tcgetattr(STDIN_FILENO, &cooked);
1097       
1098        raw = cooked;
1099        cfmakeraw(&raw);
1100        tcsetattr(STDIN_FILENO, TCSANOW, &raw);
1101    }
1102    else
1103        tcsetattr(STDIN_FILENO, TCSANOW, &cooked);
1104   
1105    raw_actif = activer;
1106}
1107
1108
1109/**************************************************************************************
1110** Alignement de l'antenne située à l'adresse ip
1111***************************************************************************************/
1112
1113bool BAOcontrol::Alignement(string ip)
1114{
1115   bool test=false;
1116   
1117   int i;
1118   
1119   if (ip.rfind(".") != string::npos) ip=ip.substr(ip.rfind(".")+1);
1120   
1121   for (i=0; i<numAntennes; i++)
1122   {
1123      if (atoi(ip.c_str()) == Antennes[i].ip) { test=true; break; }
1124   }
1125 
1126   if ((test) && (atoi(ip.c_str())!=0))
1127   {
1128         Affiche("Début de l'alignement de l'antenne.\n \
1129         Appuyez sur les touches Z,Q,D,X pour centrer l'objet dans le viseur.\n \
1130         (ESC pour arrêter et valider).\n\n", true);
1131         
1132         int c = 0;
1133         
1134         while (c!=27)
1135         {
1136           mode_raw(1);
1137           
1138           c = getchar();
1139           
1140           mode_raw(0);
1141           
1142           switch(c)
1143           {
1144             case 122 : Antennes[i].delta_ha++; Affiche("delta_ha + 1\n", true); break;
1145             case 100 : Antennes[i].delta_az++; Affiche("delta_az + 1\n", true); break;
1146             case 113 : Antennes[i].delta_az--; Affiche("delta_az - 1\n", true); break;
1147             case 120 : Antennes[i].delta_ha--; Affiche("delta_ha - 1\n", true); break;
1148           } 
1149           
1150           // Enregistrement des paramÚtres d'alignement des antennes
1151   
1152           EnregistrementParametresAlignement("/home/" + (string)getenv("USER") + "/AlignementAntennes.cfg");
1153         }         
1154   } 
1155   else
1156   {
1157         Erreur("L'antenne située à l'adresse ip indiquée n'existe pas\n\n");
1158         
1159         return false;
1160   }
1161   
1162   return true;
1163}
1164
1165
1166/**************************************************************************************
1167** Sauvegarde des paramÚtres d'alignement des antennes
1168***************************************************************************************/
1169
1170bool BAOcontrol::EnregistrementParametresAlignement(string fileName)
1171{
1172    string section;
1173    string key;
1174    string value;
1175    char ip[100];
1176
1177    stringstream os;
1178
1179    //Affiche("Enregistrement de l'alignement des antennes dans le fichier " + fileName + "\n", true);
1180
1181    //Enregistrement des corrections des l'antennes
1182
1183    for (int i=0; i< numAntennes; i++)
1184    {
1185        sprintf(ip, "%i", Antennes[i].ip);
1186        os << "Alignement antenne ip x.x.x." << (string)ip;
1187        section = os.str();
1188        os.str("");
1189        key     = "delta_az";
1190        os << Antennes[i].delta_az;
1191        value = os.str();
1192        os.str("");
1193
1194        writeINI((char*)section.c_str(), (char*)key.c_str(), (char*)value.c_str(), (char*)fileName.c_str());
1195
1196        key     = "delta_ha";
1197        os << Antennes[i].delta_ha;
1198        value = os.str();
1199        os.str("");
1200
1201        writeINI((char*)section.c_str(), (char*)key.c_str(), (char*)value.c_str(), (char*)fileName.c_str());
1202    }
1203
1204    return true;
1205}
1206
1207
1208
1209/**************************************************************************************
1210** Lecture des mouvements planifiés contenus dans le fichier fileName
1211***************************************************************************************/
1212
1213bool BAOcontrol::LectureFichierMouvements(string fileName)
1214{
1215    string section;
1216    string key;
1217    char * value   = NULL;
1218
1219    stringstream os;
1220    float a1, a2, a3, h;
1221
1222    numobjets=1;
1223
1224    Affiche("Lecture du fichier " + fileName +"\n\n", true);
1225
1226    //Lecture de la rubrique ParamÚtres
1227
1228    section = "parametres";
1229    key     = "mode";
1230
1231    if (readINI(section.c_str(), key.c_str(), &value, fileName.c_str()))
1232    {
1233        Transit = ( strstr(value, "transit") != NULL);
1234        delete [] value;
1235
1236        if (Transit) Affiche("Mode transit activé.\n", true);
1237        else Affiche("Mode tracking activé.\n", true);
1238    }
1239    else
1240    {
1241        Erreur("Le parametre mode est incorrect.\n");
1242        return false;
1243    }
1244
1245    key = "J2000";
1246
1247    if (readINI(section.c_str(), key.c_str(), &value, fileName.c_str()))
1248    {
1249        J2000 = ( strstr(value, "on") != NULL);
1250        delete [] value;
1251
1252        if (J2000) Affiche("Mode J2000 activé.\n\n", true);
1253        else Affiche("Mode J2000 désactivé.\n\n", true);
1254    }
1255    else
1256    {
1257        Erreur("Le parametre J2000 est incorrect.\n");
1258        return false;
1259    }
1260
1261    // Lecture de la liste des observations
1262
1263    section = "objet 1";
1264    key     = "date";
1265
1266
1267    while ((readINI(section.c_str(), key.c_str(), &value, fileName.c_str()))
1268            && (numobjets<MAXOBJETS))
1269    {
1270        os << "object n°" << numobjets << endl;
1271        Affiche(&os, true);
1272        delete [] value;
1273        value = NULL;
1274
1275
1276        // Lecture de la date et de l'heure de l'observation
1277
1278        key = "date";
1279
1280        if ((readINI(section.c_str(), key.c_str(), &value, fileName.c_str()))
1281                && (Decomposition(value, 3, &a1, &a2, &a3)))
1282        {
1283            Affiche("Date du début de l'observation : le " + (string)value, true);
1284            delete [] value;
1285            value = NULL;
1286
1287            objets[numobjets].JJ = CalculJJ(a3, a2, a1, 0.0);
1288        }
1289        else
1290        {
1291            os << "La date de la rubrique [objet " << numobjets << "] est incorrecte !" << endl;
1292            Erreur(&os);
1293            return false;
1294        }
1295
1296        key = "heure";
1297
1298        if ((readINI(section.c_str(), key.c_str(), &value, fileName.c_str()))
1299                && (Decomposition(value, 2, &a1, &a2, &a3)))
1300        {
1301            Affiche(" à " + (string)value, true) ;
1302            delete [] value;
1303            value = NULL;
1304
1305
1306            objets[numobjets].JJ += ( a1 + a2 / 60.0 + a3 / 3600.0 ) / 24.0;
1307
1308            os << " TU  -> JJ=" << fixed << objets[numobjets].JJ << scientific << endl;
1309
1310            Affiche(&os, true);
1311
1312            for (int i=1; i<numobjets; i++)
1313            {
1314                if (objets[i].JJ==objets[numobjets].JJ)
1315                {
1316                    os << "Attention, les observations des objets " << i << " et ";
1317                    os << numobjets << " sont définies à la même date !" << endl;
1318                    Erreur(&os);
1319                }
1320
1321                if (objets[i].JJ+objets[i].Duree/3600/24.0>objets[numobjets].JJ)
1322                {
1323                    os << "Attention, les observations des objets " << i << " et " ;
1324                    os << numobjets << " se chevauchent !" << endl;
1325                    Erreur(&os);
1326                }
1327            }
1328        }
1329        else
1330        {
1331            os << "L'heure de la rubrique [objet " << numobjets << "] est incorrecte !" << endl;
1332            Erreur(&os);
1333            return false;
1334        }
1335
1336
1337        // Lecture de la durée de l'observation
1338
1339        key = "duree";
1340
1341        objets[numobjets].Duree=0.0;
1342
1343        if (readINI(section.c_str(), key.c_str(), &value, fileName.c_str()))
1344        {
1345            Affiche("Durée de l'observation : " + (string)value + " secondes\n", true);
1346            objets[numobjets].Duree=atof(value);
1347            delete [] value;
1348            value = NULL;
1349        }
1350        else
1351        {
1352            os << "La duree d'observation de la rubrique [objet " << numobjets << "] est incorrecte !\n";
1353            Erreur(&os);
1354            return false;
1355        }
1356
1357        // Lecture de l'ascension droite de l'objet
1358
1359        key = "ad";
1360
1361        objets[numobjets].ad = "";
1362
1363        if ((readINI(section.c_str(), key.c_str(), &value, fileName.c_str()))
1364                && (Decomposition(value, 2, NULL, NULL, NULL)))
1365        {
1366            Affiche("Ascension droite de l'objet : " + (string)value + "\n", true);
1367            objets[numobjets].ad = value;
1368            delete [] value;
1369            value = NULL;
1370        }
1371        else
1372        {
1373            os << "L'ascension droite de la rubrique [objet " << numobjets << "] est incorrecte !";
1374            os << endl;
1375            Erreur(&os);
1376            return false;
1377        }
1378
1379        // Lecture de la déclinaison de l'objet
1380
1381        key = "de";
1382
1383        objets[numobjets].de = "";
1384
1385        if ((readINI(section.c_str(), key.c_str(), &value, fileName.c_str()))
1386                && (Decomposition(value, 0, NULL, NULL, NULL)))
1387        {
1388            Affiche("Déclinaison de l'objet : " + (string)value + "\n\n", true);
1389            objets[numobjets].de = value;
1390            delete [] value;
1391            value = NULL;
1392        }
1393        else
1394        {
1395            os << "La déclinaison de la rubrique [objet " << numobjets << "] est incorrecte !";
1396            os << endl;
1397            Erreur(&os);
1398            return false;
1399        }
1400
1401        objets[numobjets].exec = false;
1402
1403        // On passe à l'objet suivant
1404
1405        numobjets++;
1406
1407        os << "objet "<< numobjets;
1408
1409        section = os.str();
1410        os.str("");
1411    }
1412
1413    if (value) delete [] value;
1414
1415    return true;
1416}
1417
1418
1419
1420/**************************************************************************************
1421** Execute le fichier de mouvements
1422***************************************************************************************/
1423
1424bool BAOcontrol::Run(string fichier)
1425{
1426    stringstream os;
1427
1428    bool exec = LectureFichierMouvements(fichier);
1429
1430    Update();
1431
1432    if ( exec && numobjets>1 )
1433    {
1434        // Si le chargement du fichier s'est bien déroulé et qu'il y a plus d'un mouvement dedans
1435
1436        if (objets[numobjets-1].JJ + objets[numobjets-1].Duree / 3600.0 / 24.0 < GetJJ())
1437        {
1438            Erreur("Le fichier contient des dates qui sont toutes périmées. Exécution annulée.\n\n");
1439            NoExit=!exitrun;
1440            return false;
1441        }
1442        else
1443        {
1444            Affiche("Execution du fichier " + fichier + " en attente...\n\n", true);
1445            run=true;
1446        }
1447    }
1448    else
1449    {
1450        Erreur("\nLe fichier " + fichier + " contient des erreurs ou n'existe pas...\n\n\n");
1451        NoExit=!exitrun;
1452        return false;
1453    }
1454
1455    return true;
1456}
1457
1458
1459
1460/**************************************************************************************
1461** Décomposition et vérification des dates, heures, AD et déclinaisons
1462**
1463** type = 0 -> Déclinaison/latitude
1464** type = 1 -> longitude
1465** type = 2 -> AD ou heure
1466** type = 3 -> date
1467**
1468** Exemple de Decomposition("15:23:12", 2, a, b, c) retourne a=15, b=23, c=12
1469** si la chaine a un format incorrect, la fct retourne false
1470***************************************************************************************/
1471
1472bool BAOcontrol::Decomposition(string chaine, char type, float *a1, float *a2, float *a3)
1473{
1474    string car, s;
1475    float a, b, c;
1476
1477    // pour les heures et les coordonnées, on attend ":" comme caractÚre séparateur, sinon
1478    // on attend d'avoir des "/" pour une date
1479
1480    (type==3) ? car="/" : car=":";
1481
1482    // Y a-t-il 2 caractÚres ':' ou '/' dans la chaine ?
1483    // C'est indispensable dans tous les cas
1484
1485    int test=0;
1486    for (int i=0; i<chaine.length(); i++) if (chaine[i] == car[0]) test++;
1487    if (test<2) return false;
1488
1489    // Extraction des trois nombres
1490
1491    s = chaine.substr(0, chaine.find(car));
1492
1493    a = atoi(s.c_str());
1494
1495    s = chaine.substr(chaine.find(car)+1, chaine.rfind(car) - chaine.find(car) - 1);
1496
1497    b = atoi(s.c_str());
1498
1499    s = chaine.substr(chaine.rfind(car)+1);
1500
1501    c = Arrondi(atof(s.c_str())*100.0)/100.0;
1502
1503    //vérification de la cohérence des infos contenues dans la chaine
1504
1505    if (type < 3 )
1506    {
1507        // pour une déclinaison
1508        if ((type==0) && (a>90.0  || a<-90.0)) return false;
1509        // pour une AD
1510        if ((type==1) && (a>360.0 || a<0.0  )) return false;
1511        // pour une heure
1512        if ((type==2) && (a>23.0  || a<0.0  )) return false;
1513        // pour les minutes
1514        if (b<0.0 || b>59.0 ) return false;
1515        //pour les secondes
1516        if (c<0.0 || c>=60.0) return false;
1517    }
1518    else
1519    {
1520        //pour les jours
1521        if (a<0.0 || a>31.0) return false;
1522        //pour les mois
1523        if (b<0.0 || b>12.0) return false;
1524    }
1525
1526    if (a1!=NULL) *a1 = a;
1527    if (a2!=NULL) *a2 = b;
1528    if (a3!=NULL) *a3 = c;
1529
1530    return true;
1531}
1532
1533
1534
1535
1536/**************************************************************************************
1537** identification des commandes entrées par l'utilisateur
1538** puis exécution des commandes
1539***************************************************************************************/
1540
1541void BAOcontrol::DecodageEntreesUtilisateur(string chaine)
1542{
1543    string ar, de, objet, fichier;
1544    stringstream os;
1545
1546    // Permet de savoir si la derniÚre saisie de l'utilisateur
1547    // est une commande valide
1548    bool CommandeOK = false;
1549
1550
1551    // Commande goto
1552
1553    if ( chaine.find("goto") != string::npos )
1554    {
1555        CommandeOK = true;
1556
1557        // L'utilisateur a fait suivre la commande goto de l'indication J2000
1558
1559        if (J2000 = (chaine.find("j2000") != string::npos))
1560        {
1561            Affiche("Prise en compte de la précession, de la nutation et de l'aberration...\n", true);
1562
1563            // On je garde que la premiÚre partie de la chaine avant J2000
1564
1565            chaine = chaine.substr(0, chaine.find("J2000"));
1566        }
1567
1568        if (DecompositionCommande(chaine, "goto", &ar, &de) && Decomposition(ar, 2, NULL, NULL, NULL) && Decomposition(de, 0, NULL, NULL, NULL))
1569        {
1570            // L'utilisateur a indiqué deux coordonnées valides -> on exécute le goto
1571
1572            Goto(ar, de, Transit, J2000);
1573        }
1574        else
1575        {
1576            // L'utilisateur a indiqué un nom d'objet aprÚs le goto -> on lance la recherche sur internet
1577            // puis on envoie les coordonnées de l'objet au pilote indi_BAO
1578
1579            if ((DecompositionCommande(chaine, "goto", &objet, NULL)) && (chaine.find(":") == string::npos))
1580            {
1581                Coordonnees reponse;
1582               
1583                if (objet != "sun")
1584                {
1585                    reponse = ServeurNED(objet);
1586                   
1587                    if (reponse.ar!="" && reponse.dec!="")  Goto(reponse.ar, reponse.dec, Transit, true);
1588                }
1589                else
1590                {   
1591                    printf(" lancement\n");
1592                   
1593                    CalculARDecSoleil(&reponse);
1594                   
1595                    printf("%s   %s \n", reponse.ar.c_str(), reponse.dec.c_str());
1596                   
1597                    Goto(reponse.ar, reponse.dec, Transit, false);
1598                }               
1599            }
1600            else
1601            {
1602                Erreur("Erreur goto : le format de la commande est goto AD DEC\n \
1603                    L AD doit être de la forme xx:yy:zz   (ex: 12:00:03 pour 12h 0m 3s)\n \
1604                    La déclinaison doit être de la forme +/-xx:yy:zz (ex: -12:50:01 pour -12° 50' 01'')\n\n \
1605                    Il est egalement possible de faire suivre la commande d'un nom d'un objet\n \
1606                    Exemple goto M 31 ou encore goto ngc145\n \
1607                    Ne pas préciser dans ce cas J2000.\n\n");
1608            }
1609        }
1610    }
1611
1612    // Annulation du suivi en cours
1613
1614    if (chaine.find("abort") != string::npos)
1615    {
1616        CommandeOK = true;
1617
1618        Abort();
1619
1620        // Annulation de l'exécution d'un fichier de mouvements
1621
1622        if (chaine.find("run") != string::npos)
1623        {
1624            run=false;
1625            runnum=1;
1626            numobjets=1;
1627
1628            Affiche("Annulation de l'exécution du fichier de mouvements.\n\n", true);
1629
1630            return;
1631        }
1632    }
1633
1634    // Lance l'exécution d'un fichier de mouvements
1635
1636    if (chaine.find("run") != string::npos)
1637    {
1638        CommandeOK = true;
1639
1640        if (DecompositionCommande(chaine, "run", &fichier, NULL))
1641        {
1642            Run(fichier);
1643        }
1644        else
1645        {
1646            Erreur("Erreur run : la commande run doit être suivie par un nom de fichier.\n\n");
1647        }
1648    }
1649
1650    // se connecte/déconnecte au serveur
1651
1652    if (chaine.find("connect") != string::npos)
1653    {
1654        CommandeOK = true;
1655
1656        Connect(chaine.find("disconnect") == string::npos);
1657    }
1658
1659    // Active le mode de suivi "transit"
1660
1661    if (chaine.find("transit") != string::npos)
1662    {
1663        CommandeOK = true;
1664
1665        Affiche("Mode transit activé.\n\n", true);
1666
1667        Transit=true;
1668    }
1669
1670    // Active le mode de suivi "tracking"
1671
1672    if (chaine.find("tracking") != string::npos)
1673    {
1674        CommandeOK = true;
1675
1676        Affiche("Mode tracking activé.\n\n", true);
1677
1678        Transit=false;
1679    }
1680
1681    // Place les antennes en position de repos
1682
1683    if (chaine.find("park") != string::npos)
1684    {
1685        CommandeOK = true;
1686
1687        Park();
1688    }
1689
1690    // interroge un serveur de temps pour mettre l'horloge du PC à jour
1691
1692    if (chaine.find("updatetime") != string::npos)
1693    {
1694        CommandeOK = true;
1695
1696        int rc = system("sntp -s fr.pool.ntp.org");
1697
1698        if (WEXITSTATUS(rc) ==-1 || WEXITSTATUS(rc) ==127)
1699        {
1700            Erreur("La commande sntp n'est pas accessible. Merci de vérifier.\n\n");
1701        }
1702    }
1703
1704    // Affiche tous les paramÚtres du programme
1705
1706    if (chaine.find("status") != string::npos)
1707    {
1708        CommandeOK = true;
1709
1710        os << "Latitude = " << (string)LatitudeChar << "\n";
1711        os << "Longitude = " << (string)LongitudeChar << "\n\n";
1712        os << "Serveur Indi = " << (string)Serveur << "\n";
1713        os << "Port du serveur Indi = " << Port << "\n\n";
1714        os << "Pression atmosphérique  = " << Pression << " mBar\n";
1715        os << "Température = " << Temperature << " °C\n\n";
1716        Affiche(&os, true);
1717        if (Transit) Affiche("Mode Transit activé.\n\n", true);
1718        else Affiche ("Mode Tracking activé.\n\n", true);
1719    }
1720
1721    // interroge le serveur NED sur internet -> retourne les coordonnées de l'objet
1722
1723    if (chaine.find("search")!=string::npos)
1724    {
1725        string objet;
1726
1727        CommandeOK = true;
1728
1729        if (DecompositionCommande(chaine, "search", &objet, NULL))
1730        {
1731            ServeurNED(objet);
1732        }
1733    }
1734   
1735    // correction de l'alignement d'une antenne par rapport à l'objet visé
1736
1737    if (chaine.find("align")!=string::npos)
1738    {
1739        string antenne;
1740
1741        CommandeOK = true;
1742
1743        if (DecompositionCommande(chaine, "align", &antenne, NULL))
1744        {
1745            Alignement(antenne);
1746        }
1747        else
1748        {
1749            Erreur("Erreur align : la commande align doit être suivie par l'ip de l'antenne qui faut aligner.\n\n");
1750        }
1751    }
1752
1753    // Aide du programme
1754
1755    if (chaine.find("help") != string::npos)
1756    {
1757        CommandeOK = true;
1758
1759        cout << endl;
1760
1761        cout << "connect :           se connecte au pilote indi_BAO." << endl;
1762        cout << "disconnect :        se déconnecte du pilote indi_BAO." << endl;
1763        cout << "goto AD Dec :       pointe l'objet situé aux coordonnées apparentes AD Dec." << endl;
1764        cout << "                    AD doit être au format xx:yy:zz et dec au format +/-xx:yy:zz" << endl;
1765        cout << "                    exemple goto 12:10:05 -05:10:11 permettra de pointer l'objet" << endl;
1766        cout << "                    situé aux coordonnées AD=12h10m5s et dec=-5°10'11''" << endl;
1767        cout << "goto AD Dec J2000 : pointe l'objet situé aux coordonnées AD Dec dans le repÚre J2000." << endl;
1768        cout << "                    Avant de pointer l'objet, le programme calcule la précession, la nutation et l'aberration" << endl;
1769        cout << "                    pour ramener les coordonnées à l'écliptique et à l'équinoxe de l'observation." << endl;
1770        cout << "goto nom_objet :    interroge la base NED pour trouver les coordonnées de l'objet puis le pointe." << endl;
1771        cout << "                    exemples: goto m 31, goto messier 1, goto ngc 175, goto ic 434 etc..." << endl;
1772        cout << "                    Dans ce mode, les coordonnées sont automatiquement rapportées" << endl;
1773        cout << "                    à l'écliptique et à l'équinoxe de l'observation." << endl;
1774        cout << "                    Aussi, merci de ne pas faire suivre les coordonnées de l'indication J2000."<< endl;
1775        cout << "                    Goto sun permet de suivre le soleil." << endl;
1776        cout << "search nom_objet :  interroge le serveur NED sur internet et retourne les coordonnées de l'objet." << endl;
1777        cout << "align ip :          lance la procédure d'alignement de l'antenne d'adresse ip." << endl;
1778        cout << "transit :           active le mode de suivi transit." << endl;
1779        cout << "tracking :          active le mode de suivi tracking." << endl;
1780        cout << "status :            liste les paramÚtres du programme." << endl;
1781        cout << "run filename :      exécute le fichier de mouvements filename." << endl;
1782        cout << "abort run :         annule l'exécution du fichier de mouvements." << endl;
1783        cout << "abort :             annule le mouvement en cours." << endl;
1784        cout << "park :              place les antennes en position de repos." << endl;
1785        cout << "updatetime :        synchronise l'horloge du PC avec un serveur de temps." << endl;
1786        cout << "exit :              sortir de BAOControl." << endl;
1787
1788        cout << endl;
1789    }
1790
1791    // Bye !
1792
1793    if (chaine.find("exit")!=string::npos)
1794    {
1795        CommandeOK = true;
1796
1797        Abort();
1798
1799        Connect(false);
1800
1801        NoExit = false;
1802    }
1803
1804    // La commande n'a pas été identifiée !
1805
1806    if (!CommandeOK) Erreur("Commande inconnue... Tapez help pour obtenir la liste des commandes disponibles.\n\n");
1807}
1808
1809
1810/**************************************************************************************
1811** Interroge le serveur NED sur internet et retourne les coordonnées dans le repÚre J2000
1812** Si pas de réponse, alors message d'erreur et les coordonnées sont égales à AR="" dec=""
1813***************************************************************************************/
1814
1815Coordonnees BAOcontrol::ServeurNED(string objet)
1816{
1817    Coordonnees reponse;
1818    stringstream send;
1819
1820    FILE *pFile = NULL;
1821    int rc;
1822
1823    //initialsation des variables de retour
1824
1825    reponse.ar = "";
1826    reponse.dec = "";
1827
1828    // le nom de l'objet ne doit pas contenir des espace pour la requête NED
1829    // on les remplace par des '+'
1830
1831    for (int i=0; i<objet.length(); i++) if (objet[i] == ' ') objet[i]='+';
1832
1833    // Effacer le fichier result s'il existe dans le répertoire du programme
1834
1835    if ((pFile = fopen ("result", "r")) != NULL )
1836    {
1837        fclose (pFile);
1838        rc = system( "rm result");
1839    }
1840
1841    // On utilise l'utilitaire curl pour passer la requête au serveur NED
1842    // On sauvegarde le résultat dans le fichier result
1843
1844    send << "curl >> result \"http://ned.ipac.caltech.edu/cgi-bin/nph-objsearch?objname=";
1845    send << objet;
1846    send << "&extend=no&hconst=73&omegam=0.27&omegav=0.73&corr_z=1&out_csys=Equatorial&out_equinox=J2000.0";
1847    send << "&obj_sort=RA+or+Longitude&of=ascii_bar&zv_breaker=30000.0&list_limit=5&img_stamp=NO\"";
1848
1849    Affiche("Envoi de la requête au serveur NED...\n", true);
1850
1851    // on lance la requête
1852
1853    rc = system(send.str().c_str() );
1854
1855    // traitement du résultat
1856
1857    if (WEXITSTATUS(rc) ==-1 || WEXITSTATUS(rc) ==127)
1858    {
1859        Erreur("La commande curl n'est pas accessible. Merci de vérifier.\n\n");
1860    }
1861    else
1862    {
1863        // On a obtenu quelque chose
1864
1865        int nbRead = 0;
1866
1867        char *pBuf;
1868
1869        pBuf = new char [100000];
1870
1871        // On laisse un peu de temps au serveur pour répondre.
1872        // C'est pas vraiment indispensable mais bon...
1873
1874        sleep(1);
1875
1876        // On ouvre le fichier result
1877
1878        pFile = fopen ("result", "r");
1879
1880        if (pFile)
1881        {
1882            nbRead = readline (pFile, pBuf);
1883
1884            // Si le fichier n'est pas vide
1885            if (nbRead!=-1)
1886            {
1887                if (strstr(pBuf, "Error") != NULL)
1888                {
1889                    // Le fichier contient une indication d'erreur -> pas de réponse exploitable
1890
1891                    Affiche("\nLe serveur NED n'a pas trouvé de réponse à votre demande...\n", true);
1892                }
1893                else
1894                {
1895                    // on analyse la réponse
1896
1897                    Affiche("\nRéponse du serveur :\n", true);
1898
1899                    do
1900                    {
1901                        // on cherche la premiÚre suggestion de NED
1902                        // Il faudra peut-être un peu complexifier par la suite
1903
1904                        if (pBuf[0] == '1')
1905                        {
1906                            string chaine = (string)pBuf;
1907                            string chaine2;
1908
1909                            chaine=chaine.substr(chaine.find('|')+1);
1910
1911                            // affiche le nom de l'objet dans le serveur NED
1912
1913                            Affiche(chaine.substr(0, chaine.find('|')) + "\n", true);
1914
1915                            chaine = chaine.substr(chaine.find('|') + 1);
1916
1917                            chaine2 = chaine.substr(0, chaine.find('|'));
1918
1919                            double ar = atof(chaine2.c_str());
1920
1921                            // affiche l'ascension droite
1922
1923                            Affiche("AD (J2000) = " + DHMS(ar, true) + "\n", true);
1924
1925                            reponse.ar = DHMS(ar, true);
1926
1927                            chaine=chaine.substr(chaine.find('|')+1);
1928
1929                            chaine2 = chaine.substr(0, chaine.find('|'));
1930
1931                            double dec = atof(chaine2.c_str());
1932
1933                            // on affiche la déclinaison
1934
1935                            Affiche("Dec (J2000) = " + DHMS(dec, false)+"\n", true);
1936
1937                            reponse.dec = DHMS(dec, false);
1938                        }
1939
1940                        nbRead = readline (pFile, pBuf);
1941
1942                    } while (nbRead!=-1);
1943                }
1944            }
1945            else
1946            {
1947                Erreur("\nLa connexion semble impossible avec le serveur NED !\n\n");
1948            }
1949
1950            fclose(pFile);
1951        }
1952        else
1953        {
1954            Erreur("\nLa connexion semble impossible avec le serveur NED !\n\n");
1955        }
1956
1957        delete [] pBuf;
1958
1959        Affiche("\n", true);
1960    }
1961
1962    return reponse;
1963}
1964
1965
1966
1967/**************************************************************************************
1968** Lecture d'un fichier ligne aprÚs ligne
1969** retourne -1 à la fin
1970***************************************************************************************/
1971
1972int BAOcontrol::readline (FILE * pfile, char *tab)
1973{
1974    int nbchar = 0;
1975    char c;
1976
1977    while ((c = getc (pfile)) != '\n')
1978    {
1979        if (c == EOF)
1980        {
1981            break;
1982        }
1983        tab[nbchar++] = c;
1984    }
1985    tab[nbchar] = '\0';
1986
1987    while (nbchar>0 && tab[nbchar-1]==' ')
1988    {
1989        tab[--nbchar] = '\0';
1990    }
1991
1992    while (tab[0]==' ') for (int i=1; i<=nbchar; i++) tab[i-1] = tab[i];
1993
1994    if (c == EOF) nbchar=-1;
1995
1996    return (nbchar);
1997}
1998
1999
2000
2001/**************************************************************************************
2002** chargement des paramÚtres contenus dans le fichier params
2003***************************************************************************************/
2004
2005bool BAOcontrol::ChargementParametres(string fileName)
2006{
2007    string section;
2008    string key;
2009    char * value;
2010    stringstream os;
2011
2012
2013
2014    Affiche("Lecture du fichier de configuration 'params' :\n\n", true);
2015
2016
2017    /////////////////////////////////////////
2018    // Rubrique Coodonnées géographiques
2019
2020    section = "coordonnees geographiques";
2021
2022    key = "latitude";
2023
2024    if ((readINI(section.c_str(), key.c_str(), &value, fileName.c_str()))
2025            && (Decomposition(value, 0, NULL, NULL, NULL)))
2026    {
2027        LatitudeChar = (string)value;
2028        delete [] value;
2029        Affiche("latitude = " + LatitudeChar +"\n", true);
2030    }
2031    else
2032    {
2033        Erreur("La latitude est incorrecte !\n");
2034        return false;
2035    }
2036
2037
2038    key = "longitude";
2039
2040    if ((readINI(section.c_str(), key.c_str(), &value, fileName.c_str()))
2041            && (Decomposition(value, 1, NULL, NULL, NULL)))
2042    {
2043        LongitudeChar = (string)value;
2044        delete [] value;
2045        Affiche("longitude = " + LongitudeChar +"\n\n", true);
2046    }
2047    else
2048    {
2049        Erreur("La longitude est incorrecte !\n");
2050        return false;
2051    }
2052
2053
2054    /////////////////////////////////////////
2055    // rubrique connexion
2056
2057    section = "connexion indi";
2058
2059    key = "serveur";
2060
2061    if (readINI(section.c_str(), key.c_str(), &value, fileName.c_str()))
2062    {
2063        Serveur = (string)value;
2064        delete [] value;
2065        Affiche("serveur = " + Serveur +"\n", true);
2066    }
2067    else
2068    {
2069        Erreur("Nom du serveur invalide !\n");
2070        return false;
2071    }
2072
2073
2074    key = "port";
2075
2076    if (readINI(section.c_str(), key.c_str(), &value, fileName.c_str()))
2077    {
2078        Port = (string)value;
2079        delete [] value;
2080        Affiche("port = " + Port +"\n\n", true);
2081    }
2082    else
2083    {
2084        Erreur("Numéro de port incorrect !\n");
2085        return false;
2086    }
2087
2088
2089    /////////////////////////////////////////
2090    // Rubrique paramÚtres de l'atmosphÚre
2091
2092    section = "atmosphere";
2093
2094    key = "pression";
2095
2096    if (readINI(section.c_str(), key.c_str(), &value, fileName.c_str()))
2097    {
2098        Pression = atof(value);
2099        delete [] value;
2100        os << "pression = " << Pression << endl;
2101        Affiche(&os, true);
2102    }
2103    else
2104    {
2105        os << "La pression atmosph&rique est incorrecte !" << endl;
2106        Erreur(&os);
2107        return false;
2108    }
2109
2110    key = "temperature";
2111
2112    if (readINI(section.c_str(), key.c_str(), &value, fileName.c_str()))
2113    {
2114        Temperature=atof(value);
2115        delete [] value;
2116        os << "température = " << Temperature << endl << endl;
2117        Affiche(&os, true);
2118    }
2119    else
2120    {
2121        Erreur("La température est incorrecte !\n");
2122        return false;
2123    }
2124
2125
2126    /////////////////////////////////////////
2127    // Rubrique suivi
2128
2129    section = "suivi";
2130
2131    key = "mode";
2132
2133    if (readINI(section.c_str(), key.c_str(), &value, fileName.c_str()))
2134    {
2135        Transit = (strstr(value, "transit") != NULL);
2136        Affiche("mode suivi = " + (string)value + "\n", true);
2137        delete [] value;
2138    }
2139    else
2140    {
2141        Erreur("Le paramÚtre mode est incorrect !\n");
2142        return false;
2143    }
2144
2145
2146
2147    key = "delai_transit";
2148
2149    if (readINI(section.c_str(), key.c_str(), &value, fileName.c_str()))
2150    {
2151        delaitransit=atoi(value);
2152        delete [] value;
2153        os << "delai transit = " << delaitransit << " sec" << endl;
2154        Affiche(&os, true);
2155    }
2156    else
2157    {
2158        Erreur("Le paramÚtre delai_transit est incorrect !\n");
2159        return false;
2160    }
2161
2162
2163    key = "delai_tracking";
2164
2165    if (readINI(section.c_str(), key.c_str(), &value, fileName.c_str()))
2166    {
2167        delaitracking=atoi(value);
2168        delete [] value;
2169        os << "delai tracking = " << delaitracking << " sec" << endl << endl;
2170        Affiche(&os, true);
2171    }
2172    else
2173    {
2174        Erreur("Le paramÚtre delai_tracking est incorrect !\n");
2175        return false;
2176    }
2177
2178
2179    /////////////////////////////////////////
2180    // Rubrique divers
2181
2182    section = "divers";
2183
2184    key = "couleurs";
2185
2186    if (readINI(section.c_str(), key.c_str(), &value, fileName.c_str()))
2187    {
2188        ChoixCouleurs=atoi(value);
2189        delete [] value;
2190    }
2191    else
2192    {
2193        /*os << "Le paramÚtre couleurs est incorrect !" << endl;
2194        Erreur(os.str());
2195        return false;*/
2196    }
2197
2198    return true;
2199}
2200
2201
2202
2203/**************************************************************************************
2204** Routine principale
2205***************************************************************************************/
2206
2207int BAOcontrol::init(int argc, char **argv)
2208{
2209    string chaine;
2210
2211    pthread_t th1;
2212
2213    // gestion au démarrage des paramÚtres en ligne de commande
2214
2215    if ( argc >1 )
2216    {
2217        if (strstr(argv[1], "-h")!=NULL)
2218        {
2219            cout << "usage :\n \
2220       BAOControl -h ou --help : affiche l'aide\n \
2221       BAOControl -r FileName : exécute les mouvements définis dans le fichier FileName\n\n";
2222
2223            return 0;
2224        }
2225    }
2226
2227    if (argc == 1)  cout << "Tapez help pour obtenir la liste des commandes disponibles.\n" << endl << endl;
2228
2229    // On lance la fenêtre graphique
2230
2231    initialiserFenetre();
2232
2233    XSelectInput(d,w, ExposureMask );
2234
2235    // On lance le thread pour gérer la fenêtre graphique
2236    // la communication avec indi_BAO et le suivi des objets
2237
2238    if (pthread_create(&th1, NULL, (void*(*)(void*))LancementThread, this) < 0) {
2239        Erreur("Impossible de créer le thread\n");
2240        return -1;
2241    }
2242
2243
2244
2245    // si on a utilisé l'option -r en ligne de commande
2246    // alors on charge et on lance l'exécution d'un fichier de mouvements
2247
2248    if (argc == 3)
2249    {
2250        if (strstr(argv[1], "-r")!=NULL)
2251        {
2252            exitrun=true;
2253
2254            Run(argv[2]);
2255
2256            // on attend ici la fin de l'exécution du fichier de mouvements
2257
2258            do
2259            {
2260
2261            } while (NoExit);
2262        }
2263        else
2264        {
2265            Erreur("Usage incorrect\n\n");
2266        }
2267    }
2268    else
2269    {
2270        // Saisie et décodage des commandes entrées par l'utilisateur
2271
2272        do
2273        {
2274            // Prompt
2275            ChoixCouleurs==1 ? cout << blue1 : cout << blue2;
2276            cout << '>';
2277            // saisie
2278            getline(cin, chaine);
2279            ChoixCouleurs==1 ? cout << grey1 : cout << grey2;
2280
2281            // on met en minuscules
2282            for (int i=0; i<chaine.size();++i) chaine[i] = tolower(chaine[i]);
2283
2284            // on décode et exécute les commandes
2285            DecodageEntreesUtilisateur(chaine);   
2286           
2287        }
2288        while (NoExit);
2289
2290        pthread_join(th1 ,NULL);
2291        //pthread_detach(th1);
2292    }
2293
2294    return 0;
2295}
Note: See TracBrowser for help on using the repository browser.