/********************/ /* BAOCONTROL */ /* */ /********************/ #include "baocontrol.h" /* Affiche à l'écran (si AfficheEcran==true) et sauvegarde dans le fichier BAOControl.log le message contenu dans la variable chaine */ void Affiche(std::string chaine, bool AfficheEcran) { FILE *pFile = NULL; pFile = fopen ("BAOControl.log", "a"); if (AfficheEcran) std::cout << chaine; fprintf (pFile, chaine.c_str()); os.str(""); fclose (pFile); } /*Affiche les messages d'erreur en rouge */ void Erreur(std::string chaine) { std::cout << red; Affiche(chaine, true); std::cout << black; } /*initialise une fenêtre graphique */ void initialiserFenetre() { XGCValues gcv; XFontStruct * fd; /*contacte le serveur*/ if ((d = XOpenDisplay(getenv("DISPLAY"))) == NULL) { Erreur("Impossible de contacter le serveur\n\n"); exit(1); } /*crée une fenêtre*/ w = XCreateSimpleWindow(d, RootWindow(d, DefaultScreen(d)), 0, 0, larg, haut, 2, BlackPixel(d, DefaultScreen(d)), WhitePixel(d, DefaultScreen(d))); /* Creation du double buffer */ db = XCreatePixmap(d, w, larg, haut, DefaultDepth(d, DefaultScreen(d))); /*chargement d'une police de caractères*/ if ((fd=XLoadQueryFont(d, "fixed")) == NULL) { Erreur("Impossible de charger la police fixed\n\n"); exit(1); } /*création d'un contexte graphique*/ gcv.font = fd->fid; gcv.foreground = BlackPixel(d, DefaultScreen(d)); noir = XCreateGC(d, w, GCFont | GCForeground, &gcv); gcv.foreground = 200*255; vert = XCreateGC(d, w, GCFont | GCForeground, &gcv); gcv.foreground = 255*256*256; rouge = XCreateGC(d, w, GCFont | GCForeground, &gcv); gcv.foreground = 200*256*256+200*256+200; gris = XCreateGC(d, w, GCFont | GCForeground, &gcv); /*affiche la fenêtre */ XMapWindow(d, w); } /* Dessine les éléments de la fenêtre graphique */ void Dessiner() { char chaine[100]; GC color; /* On efface la fenêtre */ XSetForeground(d, noir, WhitePixel(d, DefaultScreen(d))); XFillRectangle(d, db, noir, 0, 0, larg, haut); XSetForeground(d, noir, BlackPixel(d, DefaultScreen(d))); /* Affichage de la date et de l'heure */ int h=astro->Heu; int m=astro->Min; int s=astro->Sec; int j=astro->Jour; if (s==60) { s=0; m++; if (m==60) { m=0; h++; if (h==24) { h=0; j++; } } } sprintf(chaine, "%02i:%02i:%02i TU %02i/%02.0f/%04.0f JJ=%10.5f", h, m, s, j, astro->Mois, astro->Annee, astro->JJ); XDrawString(d, db, noir, 10, 10, chaine, strlen(chaine)); if (run) { sprintf(chaine, "Prochaine etape dans %4.1fs", (objets[runnum].JJ-astro->JJ)*3600.0*24.0); if ((objets[runnum].JJ-astro->JJ)*3600.0*24.0 >= 0.0) XDrawString(d, db, noir, 350, 10, chaine, strlen(chaine)); } /*affichage des cercles d'état*/ for (int i=0; i <20; i++) { for (int j=0; j<5; j++) { switch(Antennes[20*j+i].ok) { case 1 : color=vert; break; case 2 : color=rouge; break; default: color=gris; break; } XFillArc(d, db ,color, 10+i*30, 20+j*30, 15, 15, 0, 360*64); XDrawArc(d, db ,noir, 10+i*30, 20+j*30, 15, 15, 0, 360*64); } } /*Affichage des messages d'erreur*/ if (lognum>15) { for (int i=lognum-1; i>lognum-16; i--) { if ((logs[i].find("Err")!=string::npos) || (logs[i].find("ALERTE")!=string::npos)) color=rouge; else color=vert; XDrawString(d, db, color, 10, 15*12+(i-lognum+15)*12, logs[i].c_str(), strlen(logs[i].c_str())); } } else { for (int i=0; i> reponse; if (reponse.find("message")!=string::npos) { /* on ne garde que la partie intéressante */ reponse=reponse.substr(reponse.find("message")+9); reponse=reponse.substr(0, reponse.find("\"")); /*récupère l'adresse ip de l'antenne */ if (reponse.find(". (Antennes connectees")!=string::npos) { decomp=reponse.substr(0, reponse.find(". (Antennes connectees")); decomp=decomp.substr(decomp.rfind(".")+1); /*si cette antenne est déjà connectée, on change son état */ for (int i=0; i on change son état dans la fenêtre */ if ((reponse.find("ALERTE antenne ")!=string::npos) || (reponse.find("Erreur sur l antenne ")!=string::npos)) { decomp=reponse.substr(0, reponse.find(" :")); decomp=decomp.substr(decomp.rfind(".")+1); for (int i=0; i=MAXLOG-1) lognum=0; /*on actualise la fenêtre */ Dessiner(); } rouler((char *)reponse.c_str()); } /* Est-ce que la réponse du pilote indi_BAO est conforme à ce que l'on attendait ? */ bool VerifReponse(std::string reponseattendue) { std::string reponse; usleep(10000); // attendre 10 ms pour laisser le temps au pilote indi_BAO de répondre *client_socket >> reponse; if (reponse.find(reponseattendue)==string::npos) { //réponse inconnue -> une erreur ? os << "Réponse du pilote indi_BAO :" << std::endl << reponse << std::endl << std::endl << std::endl; Erreur(os.str()); } return true; } /*Récupération de la date et de l'heure et calcul du jour julien et du tsl */ void CalculJourJulien() { struct tm date; time_t t; struct timeval tv; struct timezone tz; time(&t); date=*gmtime(&t); gettimeofday(&tv, &tz); astro->Annee=(double)(date.tm_year+1900); astro->Mois=(double)(date.tm_mon+1); astro->Jour=(double)date.tm_mday; astro->Heu=(double)date.tm_hour; astro->Min=(double)date.tm_min; astro->Sec=(double)date.tm_sec+tv.tv_usec/1.0E6; astro->UTCP=0.0;//(double)date.tm_isdst; //Calcul du temps sidéral local et du JJ astro->CalculTSL(); } /* gestion du thread permettant l'actualisation de la fenêtre graphique et la récupération des messages d'indi_BAO */ void *my_thread_process (void * arg) { while (NoExit) { CalculJourJulien(); //Execution d'un fichier de mouvements if (run && numobjets>1 && runnumJJ>=objets[runnum].JJ && !objets[runnum].exec) { if (runnum==1) Affiche("Début de l'exécution du fichier de mouvements\n\n", true); os << "Suivi de l'objet n°" << runnum << std::endl; Affiche(os.str(), true); objets[runnum].exec=true; Goto(objets[runnum].ad, objets[runnum].de, Transit); } /*on arrive à la fin du mouvements i */ if (astro->JJ>=objets[runnum].JJ+objets[runnum].Duree/3600.0/24.0) { Abort(); /*fin de la commande run */ if (runnum+1>=numobjets) { Affiche("Fin de l'execution du fichier de mouvements\n\n", true); std::cout << std::endl << blue << ">"; run=false; runnum=1; numobjets=1; /*on sort du programme dans le cas ./BAOControl -r fileName */ if (exitrun) NoExit=false; } else { runnum++; } } } LireReponse(); Dessiner(); usleep(100000); //100 ms } pthread_exit (0); } /* Décomposition et vérification des dates, heures, AD et déclinaisons type = 0 -> Déclinaison/latitude type = 1 -> longitude type = 2 -> AD ou heure type = 3 -> date */ bool Decomposition(std::string chaine, char type, float *a1, float *a2, float *a3) { std::string car, s; int pos1, pos2; float a, b, c; if (type==3) car="/"; else car=":"; /* Y a-t-il 2 caractères : ou / à la suite ? */ int test=0; for (int i=0; i90.0 || a<-90.0)) return false; if ((type==1) && (a>180.0 || a<-180.0)) return false; if ((type==2) && (a>23.0 || a<0.0)) return false; if (b<0.0 || b>59.0) return false; if (c<0.0 || c>=60.0) return false; } else { if (a<0.0 || a>31.0) return false; if (b<0.0 || b>12.0) return false; } if (a1!=NULL) *a1=a; if (a2!=NULL) *a2=b; if (a3!=NULL) *a3=c; return true; } /* isole les différents éléments de la commande saisie par l'utilisateur */ bool DecompositionCommande(std::string chaine, std::string commande, std::string *chaine1, std::string *chaine2) { size_t pos; pos = chaine.find(commande); if (pos!=string::npos) { pos+=commande.length(); chaine=chaine.substr(pos); while (chaine[0] == ' ') chaine=chaine.substr(1); *chaine1=chaine.substr(0,chaine.find(" ")); if (chaine2!=NULL) { pos = chaine.find(" "); if (pos!=string::npos) { chaine=chaine.substr(pos+1); while (chaine[0] == ' ') chaine=chaine.substr(1); *chaine2=chaine.substr(0, chaine.find(" ")); } } } return true; } /*Envoie la longitude et la latitude du lieu d'observation au pilote indi_BAO */ bool EncoyerCoordGeographiques() { try { *client_socket << ""; *client_socket << ""; *client_socket << Latitude; *client_socket << ""; *client_socket << ""; *client_socket << Longitude; *client_socket << ""; *client_socket << ""; if (!VerifReponse("name=\"GEOGRAPHIC_COORD\" state=\"Ok\"")) { Erreur("ERREUR fct EncoyerCoordGeographiques : pas de réponse du pilote indi_BAO.\n\n"); return false; } } catch ( SocketException& e ) { os << "Exception was caught:" << e.description() << std::endl; Erreur(os.str()); return false; } std::cout << "Les coordonnées géographiques ont bien été envoyées au pilote indi_BAO" << std::endl << std::endl; return true; } /* Place les antennes en position de repos */ bool Park() { try { *client_socket << ""; *client_socket << ""; *client_socket << "On"; *client_socket << ""; *client_socket << ""; if (!VerifReponse("Envoi de la commande Park")) { Erreur("La commande PARK a échoué.\n\n");; return false; } } catch ( SocketException& e) { os << e.description() << "\n"; Erreur(os.str()); return false; } Affiche("Le pilote indi_BAO a bien reçu la commande PARK.\n\n", true); return true; } /* Annule le mouvement en cours */ bool Abort() { try { *client_socket << ""; *client_socket << ""; *client_socket << "On"; *client_socket << ""; *client_socket << ""; if (!VerifReponse("name=\"ABORT_MOTION\" state=\"Ok\"")) { Erreur("L'annulation a échoué.\n\n"); return false; } } catch ( SocketException& e) { os << e.description() << "\n"; Erreur(os.str()); return false; } Affiche("Le pilote indi_BAO a bien reçu la commande ABORT.\n\n", true); return true; } /*aller aux coordonnées ar et dec dans le mode transit ou tracking */ bool Goto(std::string ar, std::string dec, bool Transit) { try { *client_socket << ""; *client_socket << ""; if (Transit) *client_socket << "On"; else *client_socket << "Off"; *client_socket << ""; *client_socket << ""; if (Transit) *client_socket << "Off"; else *client_socket << "On"; *client_socket << ""; *client_socket << ""; if (!VerifReponse("name=\"ON_COORD_SET\"")) { Erreur("Le changement de mode TRANSIT/TRACKING a échoué.\n\n"); return false; } *client_socket << ""; *client_socket << ""; *client_socket << ar; *client_socket << ""; *client_socket << ""; *client_socket << dec; *client_socket << ""; *client_socket << ""; if (!VerifReponse("name=\"EQUATORIAL_EOD_COORD_REQUEST\"")) { Erreur("Le transfert des coordonnées de l'objet a échoué.\n\n"); return false; } } catch ( SocketException& e) { os << e.description() << "\n"; Erreur(os.str()); return false; } os << "Les nouvelles coordonnées AD=" << ar << " DEC=" << dec << " ont été envoyées au pilote indi_BAO.\n\n"; Affiche(os.str(), true); return true; } /*se connecter ou se déconnecter au pilote indi_BAO */ bool Connect(bool connect) { try { *client_socket << ""; if (connect) *client_socket << ""; else *client_socket << ""; *client_socket << "On"; *client_socket << ""; *client_socket << ""; if (connect) { if (!VerifReponse("BAORadio is online")) { Erreur("La connexion a échoué.\n\n"); return false; } } else { if (!VerifReponse("BAORadio is offline")) { Erreur("La déconnexion a échoué.\n\n"); return false; } } } catch ( SocketException& e ) { os << "Exception was caught:" << e.description() << std::endl; Erreur(os.str()); return false; } if (connect) { Affiche("La connexion a été établie avec le pilote indi_BAO.\n\n", true); EncoyerCoordGeographiques(); } else { Affiche("Confirmation de la déconnexion avec le pilote indi_BAO.\n\n", true); } return true; } /* Lecture des mouvements planifiés dans le fichier fileName */ bool LectureFichierMouvements(char * fileName) { char * section =(char * )malloc(80); char * key = (char *)malloc(80); char * chaine = (char *)malloc(80); char * value; Astro * AstroJJ; float a1, a2, a3, h; numobjets=1; os << "Lecture du fichier " << fileName << std::endl << std::endl; Affiche(os.str(), true); strcpy(section, "objet 1"); strcpy(key, "date"); while ((readINI(section, key, &value, fileName)) && (numobjetsJour=a1; AstroJJ->Mois=a2; AstroJJ->Annee=a3; AstroJJ->CalculJJ(0.0); objets[numobjets].JJ=AstroJJ->JJ; delete AstroJJ; } else { os << "La date de la rubrique [objet " << numobjets << "] est incorrecte !" << std::endl; Erreur(os.str()); return false; } strcpy(key, "heure"); if ((readINI(section, key, &value, fileName)) && (Decomposition(value, 2, &a1, &a2, &a3))) { os << " à " << value ; Affiche(os.str(), true); objets[numobjets].JJ+=(a1+a2/60.0+a3/3600.0)/24.0; sprintf(chaine, " TU -> JJ=%10.5f\n", objets[numobjets].JJ); Affiche(chaine, true); for (int i=1; iobjets[numobjets].JJ) { os << "Attention, les observations des objets " << i << " et " << numobjets << " se chevauchent !\n"; Erreur(os.str()); } } } else { os << "L'heure de la rubrique [objet " << numobjets << "] est incorrecte !" << std::endl; Erreur(os.str()); return false; } strcpy(key, "duree"); objets[numobjets].Duree=0.0; if (readINI(section, key, &value, fileName)) { os << "Durée de l'observation : " << value << " secondes" << std::endl; Affiche(os.str(), true); objets[numobjets].Duree=atof(value); } else { os << "La duree d'observation de la rubrique [objet " << numobjets << "] est incorrecte !" << std::endl; Erreur(os.str()); return false; } strcpy(key, "ad"); strcpy(objets[numobjets].ad, ""); if ((readINI(section, key, &value, fileName)) && (Decomposition(value, 2, NULL, NULL, NULL))) { os << "Ascension droite de l'objet : " << value << std::endl; Affiche(os.str(), true); strcpy(objets[numobjets].ad, value); } else { os << "L'ascension droite de la rubrique [objet " << numobjets << "] est incorrecte !" << std::endl; Erreur(os.str()); return false; } strcpy(key, "de"); strcpy(objets[numobjets].de, ""); if ((readINI(section, key, &value, fileName)) && (Decomposition(value, 0, NULL, NULL, NULL))) { os << "Déclinaison de l'objet : " << value << std::endl << std::endl; Affiche(os.str(), true); strcpy(objets[numobjets].de, value); } else { os << "La déclinaison de la rubrique [objet " << numobjets << "] est incorrecte !" << std::endl; Erreur(os.str()); return false; } objets[numobjets].exec=false; numobjets++; sprintf(section, "objet %i", numobjets); } return true; } /*Execute le fichier de mouvements */ bool Run(std::string fichier) { bool exec=LectureFichierMouvements((char *)fichier.c_str()); CalculJourJulien(); if (exec && numobjets>1) { if (objets[numobjets-1].JJ+objets[numobjets-1].Duree/3600.0/24.0 < astro->JJ) { Erreur("Le fichier contient des dates qui sont toutes périmées. Exécution annulée.\n\n"); if (exitrun) NoExit=false; return false; } else { os << "Execution du fichier " << fichier << " en attente..." << std::endl << std::endl; Affiche(os.str(), true); run=true; } } else { os << std::endl << "Le fichier " << fichier << " contient des erreurs ou n'existe pas...\n" << std::endl << std::endl; Erreur(os.str()); if (exitrun) NoExit=false; return false; } return true; } /*identification des commandes entrées par l'utilisateur */ void DecodageEntreesUtilisateur(std::string chaine) { std::string ar, de, fichier; if (chaine.find("goto")!=string::npos) { if (DecompositionCommande(chaine, "goto", &ar, &de) && Decomposition(ar, 2, NULL, NULL, NULL) && Decomposition(de, 0, NULL, NULL, NULL)) { Goto(ar, de, Transit); } else { Erreur("Erreur goto : le format de la commande est goto AD DEC\n \ L AD doit être de la forme xx:yy:zz (ex: 12:00:03 pour 12h 0m 3s)\n \ La déclinaison doit être de la forme +/-xx:yy:zz (ex: -12:50:01 pour -12° 50' 01'')\n\n"); } } if (chaine.find("abort")!=string::npos) { Abort(); if (chaine.find("run")!=string::npos) { run=false; runnum=1; numobjets=1; Affiche("Annulation de l'exécution du fichier de mouvements.\n\n", true); return; } } if (chaine.find("run")!=string::npos) { if (DecompositionCommande(chaine, "run", &fichier, NULL)) { Run(fichier); } else { Erreur("Erreur run : la commande run doit être suivie par un nom de fichier.\n\n"); } } if (chaine.find("connect")!=string::npos) { Connect(chaine.find("disconnect")==string::npos); } if (chaine.find("transit")!=string::npos) { Affiche("Mode transit activé.\n\n", true); Transit=true; } if (chaine.find("tracking")!=string::npos) { Affiche("Mode tracking activé.\n\n", true); Transit=false; } if (chaine.find("park")!=string::npos) { Park(); } if (chaine.find("help")!=string::npos) { std::cout << std::endl; std::cout << "connect : connecte le pilote INDI" << std::endl; std::cout << "disconnect : ferme la connexion avec le pilote INDI" << std::endl; std::cout << "goto AD Dec : pointe l'objet aux coordonnées AD Dec" << std::endl; std::cout << "transit : mode de suivi transit" << std::endl; std::cout << "tracking : mode de suivi tracking" << std::endl; std::cout << "run filename : execute le fichier filename" << std::endl; std::cout << "abort run : annule l'exécution du fichier de mouvements" << std::endl; std::cout << "abort : annule le mouvement en cours" << std::endl; std::cout << "park : place les antennes en position de repos" << std::endl; std::cout << "exit : sortir de BAOControl" << std::endl; std::cout << std::endl; } if (chaine.find("exit")!=string::npos) { Connect (false); NoExit=false; } } /* chargement des paramètres dans le fichier params */ bool ChargementParametres() { char * section =(char * )malloc(80); char * key = (char *)malloc(80); char * value; char * fileName = (char *)malloc(sizeof(char)*255); Affiche("Lecture du fichier de configuration 'params' :\n\n", true); strcpy(fileName,"params"); strcpy(section, "connexion indi"); strcpy(key, "serveur"); strcpy(Serveur, ""); if (readINI(section, key, &value, fileName)) { strcpy(Serveur, value); os << "serveur=" << Serveur << std::endl; Affiche(os.str(), true); } else { os << "Nom du serveur invalide !" << std::endl; Erreur(os.str()); return false; } strcpy(key, "port"); if (readINI(section, key, &value, fileName)) { Port=atoi(value); os << "port=" << Port << std::endl << std::endl; Affiche(os.str(), true); } else { os << "Numéro de port incorrect !" << std::endl; Erreur(os.str()); return false; } strcpy(section, "coordonnees geographiques"); strcpy(Latitude, ""); strcpy(Longitude, ""); strcpy(key, "latitude"); if ((readINI(section, key, &value, fileName)) && (Decomposition(value, 0, NULL, NULL, NULL))) { strcpy(Latitude, value); os << "latitude=" << Latitude << std::endl; Affiche(os.str(), true); } else { os << "La latitude est incorrecte !" << std::endl; Erreur(os.str()); return false; } strcpy(key, "longitude"); if ((readINI(section, key, &value, fileName)) && (Decomposition(value, 1, NULL, NULL, NULL))) { strcpy(Longitude, value); os << "longitude=" << Longitude << std::endl << std::endl; Affiche(os.str(), true); } else { os << "La longitude est incorrecte !" << std::endl; Erreur(os.str()); return false; } strcpy(section, "transit"); strcpy(key, "delai"); if (readINI(section, key, &value, fileName)) { delaitransit=atoi(value); os << "delai transit= " << delaitransit << " sec" << std::endl; Affiche(os.str(), true); } else { os << "Le paramètre transit est incorrect !" << std::endl; Erreur(os.str()); return false; } strcpy(section, "tracking"); strcpy(key, "delai"); if (readINI(section, key, &value, fileName)) { delaitracking=atoi(value); os << "delai tracking= " << delaitracking << " sec" << std::endl << std::endl; Affiche(os.str(), true); } else { os << "Le paramètre tracking est incorrect !" << std::endl; Erreur(os.str()); return false; } return true; } int main(int argc, char **argv) { std::string chaine; pthread_t th1; if (argc >1) { if (strstr(argv[1], "-h")!=NULL) { std::cout << "usage :\n \ BAOControl -h ou --help : affiche l'aide\n \ BAOControl -r FileName : execute les mouvements définis dans le fichier FileName\n\n"; return 0; } } for (int i=0; i'; getline(std::cin, chaine); std::cout << black; for (int i=0; i