source: BAORadio/libindi/libindi/drivers/telescope/BAO.cpp @ 695

Last change on this file since 695 was 695, checked in by frichard, 12 years ago
File size: 114.3 KB
Line 
1/*
2#############################
3##
4## BAORadio Indi driver
5## Franck RICHARD
6## franckrichard033@gmail.com
7## Décembre 2011
8##
9#############################
10*/
11
12#include "BAO.h"
13
14
15auto_ptr<BAO> telescope(0);
16
17const int  POLLMS = 1;                                  // Period of update, 1 ms.
18
19const char *mydev = "BAO";                              // Name of our device.
20
21const char *BASIC_GROUP    = "Main Control";            // Main Group
22const char *OPTIONS_GROUP  = "Options";                 // Options Group
23const char *RAQ_GROUP      = "Raquette";                // Options Group
24const char *ALIG_GROUP     = "Alignement";              // Options Group
25
26#define targetRA    EquatorialCoordsWN[0].value
27#define targetDEC   EquatorialCoordsWN[1].value
28
29
30
31static void ISPoll(void *);
32
33void* LancementThread(BAO * appli);
34
35
36
37/**************************************************************************************
38** Initialisation de la classe BAO
39**
40***************************************************************************************/
41
42BAO::BAO()
43{
44    init_properties();
45
46    // Le bouton connect de la boîte de dialogue d'indi_BAO
47    // est dans l'état IDLE au démarrage
48
49    ConnectSP.s           = IPS_IDLE;
50
51    // derniÚre actualisation
52
53    lastRA                = 0.0;
54    lastDEC               = 0.0;
55
56    // Jour julien de la derniÚre actualisation
57
58    JJAnc                 = 0.0;
59
60    // Variables d'état
61
62    currentSet            =  0;
63
64    // Nombre d'antennes connectées
65
66    SocketsNumber         =  1;
67
68    // Le mode tracking est activé par défaut
69
70    TrackingMode          =  BAO_TRACKING;
71
72    // Méthode d'alignement par défaut
73
74    MethodeAlignement     = SIMPLE;
75
76    // délais en sec entre deux actualisations
77    // dans les modes transit et tracking
78
79    // Délai entre 2 actualisations dans le mode transit (en sec)
80
81    ActualisationTMTransit  = UPDATETRANSITDELAY;
82
83    // Délai entre 2 actualisations dans le mode tracking (en sec)
84
85    ActualisationTMTracking = UPDATETRACKINGDELAY;
86
87    // cette variable vaut "true" lorsque le thread de l'aplication a été initialisé
88
89    InitThreadOK          = false;
90
91    // UpdatedGoto = true lorsque le dernier goto a bien été réalisé jusqu'au bout
92
93    UpdatedGoto           = true;
94
95    // RealisationGoto = true lorsque les étapes nécessaires à la réalisation d'un goto
96    // sont en cours d'execution
97
98    RealisationGoto       = false;
99
100    // = true si l'utilisateur demande l'annulation du mouvement en cours
101
102    Abort                 = false;
103
104    // = true si l'utilisateur demande de mettre les antennes en mode park
105
106    Park                  = false;
107
108    // = true si un objet est actuellement suivi par les antennes
109
110    Suivi                 = false;
111
112    // = true si l'utilisateur sort de l'application -> permet de fermer le thread
113
114    Exit                  = false;
115
116    AutoriserTourComplet  = false;
117
118
119    // Initialisation des paramÚtres atmosphériques par défaut
120
121    Pression              = 1013.0;
122
123    Temp                  = 10.0;
124
125    // ParamÚtres de la raquette
126
127    delta_az              = 0;
128    delta_ha              = 0;
129    VitesseRaquette       = 3;
130    targetAlignmentIP     = -1;
131
132    // Ces deux variables définissent un intervalle où l'azimut (exprimée en pas codeur)
133    // de l'object pointé va évoluer au cours du suivi...
134
135    azmincodeur = MINAZCODEURS;
136    azmaxcodeur = MAXAZCODEURS;
137
138
139    // initialisation des sockets (Antennes)
140
141    for (int i=0; i<MAXHOSTNAME; i++)
142    {
143        Sockets[i].Connected         = false;
144        Sockets[i].IP                = "";
145        Sockets[i].TargetPosition.= 0.0;
146        Sockets[i].TargetPosition.= 0.0;
147        Sockets[i].AlignementAntenne = new Alignement();
148
149        if (Sockets[i].AlignementAntenne) Sockets[i].AlignementAntenne->InitAlignement();
150    }
151
152    // initialisations supplémentaires
153
154    InitAntennes();
155
156    // Numéro de version
157
158    AfficherLog("Indi server BAORadio...\nDriver Version: %s (%s)\n",VERSION, VERSION_DATE);
159
160    //connect_telescope();
161}
162
163
164
165/**************************************************************************************
166** Destructeur
167**
168***************************************************************************************/
169
170BAO::~BAO()
171{
172    // On informe le thread que nous allons sortir
173
174    Exit = true;
175
176    // On lui laisse une seconde pour qu'il se termine
177
178    sleep(1);
179
180    // destruction du thread
181
182    pthread_join(th1, NULL);
183
184    // destruction des objets AlignementAntennes
185
186    for (int i=0; i<MAXHOSTNAME; i++)
187    {
188        delete Sockets[i].AlignementAntenne;
189    }
190
191    // Petit message à l'attention de l'utilisateur
192    // permet de savoir si le destructeur a bien été atteint
193
194    AfficherLog("Sortie de indi_BAO\n");
195}
196
197
198
199/**************************************************************************************
200** Affiche le message à l'écran puis sauvegarde le message dans le fichierBAO_indi.log
201**
202***************************************************************************************/
203
204void BAO::AfficherLog(const char* fmt,...)
205{
206    static bool avertissement = false;
207
208    va_list ap;
209
210    FILE *pFile = NULL;
211
212    string fichier;
213
214    va_start (ap, fmt);
215
216    vfprintf (stderr, fmt, ap);
217
218    va_end (ap);
219
220    fichier = "/home/" + (string)getenv("USER") + "/BAO_indi.log";
221
222    //Si le fichier log a une taille > 3M -> on efface le fichier
223
224    //if ( Taille(fichier) > TAILLEMAXLOGS ) remove(fichier.c_str());
225
226    if ( (pFile = fopen(fichier.c_str(), "a")) != NULL)
227    {
228        time_t rawtime;
229        struct tm * timeinfo;
230
231        char buffer[80];
232
233        // On sauvegarde la date et l'heure
234
235        time ( &rawtime );
236        timeinfo = localtime ( &rawtime );
237        strftime (buffer, 80,"%c    ",timeinfo);
238        fprintf(pFile, "%s", buffer);
239
240        // On sauvegarde le message dans le fichier log
241        va_start (ap, fmt);
242
243        vfprintf(pFile, fmt, ap);
244
245        va_end (ap);
246
247        fclose(pFile);
248    }
249    else
250    {
251        if (!avertissement)
252        {
253            string chaine = "Impossible d'écrire dans le fichier " + fichier;
254            chaine +="\nMerci de vérifier les permissions\n";
255            chaine += "ou exécutez le programme en mode superutilisateur.\n\n";
256
257            va_start (ap, fmt);
258
259            vfprintf (stderr, chaine.c_str(), ap);
260
261            va_end (ap);
262
263            avertissement = true;
264        }
265    }
266}
267
268
269
270/************************************************************************************
271** Initialisation des paramÚtres des antennes
272**
273************************************************************************************/
274
275void BAO::InitAntennes()
276{
277    for (int i=0; i<MAXHOSTNAME; i++)
278    {
279        Sockets[i].status             = 0;
280        Sockets[i].sendalertes        = 0;
281        Sockets[i].AttenteExecution   = 0;
282        Sockets[i].AnomaliesExecution = 0;
283        Sockets[i].etape              = 0;
284
285        Sockets[i].ack_status         = false;
286        Sockets[i].ack_pos            = false;
287        Sockets[i].ack_park           = false;
288        Sockets[i].ack_abort          = false;
289        Sockets[i].ack_goto           = false;
290
291        Sockets[i].PosValides         = false;
292        Sockets[i].GotoOk             = false;
293    }
294}
295
296
297
298/**************************************************************************************
299** Initialisation des boutons et des zones d'affichage dans la boîte de dialogue INDI
300** se référer à la documentation d'INDI
301**
302***************************************************************************************/
303
304void BAO::init_properties()
305{
306    // Connection
307    IUFillSwitch(&ConnectS[0], "CONNECT", "Connect", ISS_OFF);
308    IUFillSwitch(&ConnectS[1], "DISCONNECT", "Disconnect", ISS_ON);
309    IUFillSwitchVector(&ConnectSP, ConnectS, NARRAY(ConnectS), mydev, "CONNECTION", "Connection", BASIC_GROUP, IP_RW, ISR_1OFMANY, 60, IPS_IDLE);
310
311    // Coord Set
312    IUFillSwitch(&OnCoordSetS[0], "TRANSIT", "Transit", ISS_ON);
313    IUFillSwitch(&OnCoordSetS[1], "TRACKING", "Tracking", ISS_OFF);
314    IUFillSwitchVector(&OnCoordSetSP, OnCoordSetS, NARRAY(OnCoordSetS), mydev, "ON_COORD_SET", "On Set", BASIC_GROUP, IP_RW, ISR_1OFMANY, 0, IPS_IDLE);
315
316    // Abort
317    IUFillSwitch(&AbortSlewS[0], "ABORT", "Abort", ISS_OFF);
318    IUFillSwitchVector(&AbortSlewSP, AbortSlewS, NARRAY(AbortSlewS), mydev, "ABORT_MOTION", "Abort", BASIC_GROUP, IP_RW, ISR_ATMOST1, 0, IPS_IDLE);
319
320    // Park
321    IUFillSwitch(&ParkS[0], "PARK", "Park", ISS_OFF);
322    IUFillSwitchVector(&ParkSP, ParkS, NARRAY(ParkS), mydev, "", "Park", BASIC_GROUP, IP_RW, ISR_ATMOST1, 0, IPS_IDLE);
323
324    // Object Name
325    IUFillText(&ObjectT[0], "OBJECT_NAME", "Name", "--");
326    IUFillTextVector(&ObjectTP, ObjectT, NARRAY(ObjectT), mydev, "OBJECT_INFO", "Object", BASIC_GROUP, IP_RW, 0, IPS_IDLE);
327
328    // Equatorial Coords - SET
329    IUFillNumber(&EquatorialCoordsWN[0], "RA", "RA  H:M:S", "%10.6m",  0., 24., 0., 0.);
330    IUFillNumber(&EquatorialCoordsWN[1], "DEC", "Dec D:M:S", "%10.6m", -90., 90., 0., 0.);
331    IUFillNumberVector(&EquatorialCoordsWNP, EquatorialCoordsWN, NARRAY(EquatorialCoordsWN), mydev, "EQUATORIAL_EOD_COORD_REQUEST" , "Equatorial JNow", BASIC_GROUP, IP_WO, 0, IPS_IDLE);
332
333    //Command
334    IUFillText(&CommandT[0], "COMMAND", "Command", "");
335    IUFillTextVector(&CommandTP, CommandT, NARRAY(CommandT), mydev, "COMMAND_SET", "Command", BASIC_GROUP, IP_WO, 0, IPS_IDLE);
336
337
338    // Alignement- bouton Alt+
339    IUFillSwitch(&AlignementAltp[0], "ALTP", "Alt+", ISS_OFF);
340    IUFillSwitchVector(&AlignementAltpP, AlignementAltp, NARRAY(AlignementAltp), mydev, "ALT_P", "Alt+", RAQ_GROUP, IP_RW, ISR_ATMOST1, 0, IPS_IDLE);
341
342    // Alignement- bouton Az
343    IUFillSwitch(&AlignementAz[0], "AZM", "Az-", ISS_OFF);
344    IUFillSwitch(&AlignementAz[1], "AZP", "Az+", ISS_OFF);
345    IUFillSwitchVector(&AlignementAzP, AlignementAz, NARRAY(AlignementAz), mydev, "AZ", "Azimut", RAQ_GROUP, IP_RW, ISR_ATMOST1, 0, IPS_IDLE);
346
347
348    // Alignement- bouton Alt-
349    IUFillSwitch(&AlignementAltn[0], "ALTN", "Alt-", ISS_OFF);
350    IUFillSwitchVector(&AlignementAltnP, AlignementAltn, NARRAY(AlignementAltn), mydev, "ALT_N", "Alt-", RAQ_GROUP, IP_RW, ISR_ATMOST1, 0, IPS_IDLE);
351
352    // Vitesse Raquette - bouton Az
353    IUFillSwitch(&RaquetteN[0], "RAQ1", "1x", ISS_OFF);
354    IUFillSwitch(&RaquetteN[1], "RAQ10", "10x", ISS_OFF);
355    IUFillSwitchVector(&RaquetteNP, RaquetteN, NARRAY(RaquetteN), mydev, "RAQ", "Vitesse raquette", RAQ_GROUP, IP_RW, ISR_ATMOST1, 0, IPS_IDLE);
356
357
358    // Alignement Coords - SET
359    IUFillText(&AlignementIP[0], "IP", "IP", "");
360    IUFillTextVector(&AlignementIPP, AlignementIP, NARRAY(AlignementIP), mydev, "ALIGNEMENT_IP", "Alignment IP", ALIG_GROUP, IP_WO, 0, IPS_IDLE);
361
362
363    // Alignment validation
364    IUFillSwitch(&AlignementOk[0], "OK", "Valider", ISS_OFF);
365    IUFillSwitch(&AlignementOk[1], "SAUV", "Sauvegarder", ISS_OFF);
366    IUFillSwitchVector(&AlignementOkP, AlignementOk, NARRAY(AlignementOk), mydev, "ALIGNMENT_OK", "Validation", ALIG_GROUP, IP_RW, ISR_1OFMANY, 0, IPS_IDLE);
367
368    // Alignment reset
369    IUFillSwitch(&AlignementReset[0], "RESET", "Reset", ISS_OFF);
370    IUFillSwitchVector(&AlignementResetP, AlignementReset, NARRAY(AlignementReset), mydev, "ALIGNMENT_RESET", "Reset", ALIG_GROUP, IP_RW, ISR_1OFMANY, 0, IPS_IDLE);
371
372    // Alignment Set
373    IUFillSwitch(&AlignmentS[0], "SIMPLE", "Simple", ISS_ON);
374    IUFillSwitch(&AlignmentS[1], "AFFINE", "Affine", ISS_OFF);
375    IUFillSwitch(&AlignmentS[2], "TAKI", "Taki", ISS_OFF);
376    IUFillSwitchVector(&AlignmentSP, AlignmentS, NARRAY(AlignmentS), mydev, "ALIGNMENT_SET", "Alignment method", ALIG_GROUP, IP_RW, ISR_1OFMANY, 0, IPS_IDLE);
377
378
379    // Geographic coord - SET
380    IUFillNumber(&GeographicCoordsWN[0], "LAT", "Lat  D", "%10.6m",  -90., 90., 0., 0.);
381    IUFillNumber(&GeographicCoordsWN[1], "LONG", "Long D", "%10.6m", 0., 360., 0., 0.);
382    IUFillNumberVector(&GeographicCoordsWNP, GeographicCoordsWN, NARRAY(GeographicCoordsWN), mydev, "GEOGRAPHIC_COORD" , "Geographic coords", OPTIONS_GROUP, IP_WO, 0, IPS_IDLE);
383
384    // Pression température - SET
385    IUFillNumber(&PressionTempWN[0], "Pression", "Pression mb", "%4.0f",  0., 1500., 0., 0.);
386    IUFillNumber(&PressionTempWN[1], "Temperature", "Temperature °c", "%3.0f", -50., +50., 0., 0.);
387    IUFillNumberVector(&PressionTempWNP, PressionTempWN, NARRAY(PressionTempWN), mydev, "PRESSION_DATA" , "Pression, Temperature", OPTIONS_GROUP, IP_WO, 0, IPS_IDLE);
388
389    // Actualisation - SET
390    IUFillNumber(&ActualisationN1[0], "DELAY", "Transit delay (s)", "%3.0f",  0., 3600., 0., 0.);
391    IUFillNumberVector(&ActualisationNP1, ActualisationN1, NARRAY(ActualisationN1), mydev, "DELAY1" , "", OPTIONS_GROUP, IP_WO, 0, IPS_IDLE);
392
393    IUFillNumber(&ActualisationN2[0], "DELAY", "Tracking delay (s)", "%3.0f",  0., 3600., 0., 0.);
394    IUFillNumberVector(&ActualisationNP2, ActualisationN2, NARRAY(ActualisationN2), mydev, "DELAY2" , "", OPTIONS_GROUP, IP_WO, 0, IPS_IDLE);
395}
396
397
398/**************************************************************************************
399** Définition de tous les vecteurs de la boîte de dialogue INDI
400** Cette procédure doit être obligatoirement présente dans tous pilotes Indi
401**
402***************************************************************************************/
403
404void BAO::ISGetProperties(const char *dev)
405{
406
407    if (dev && strcmp (mydev, dev))
408        return;
409
410    // Main Control
411    IDDefSwitch(&ConnectSP, NULL);
412    IDDefText(&ObjectTP, NULL);
413    IDDefNumber(&EquatorialCoordsWNP, NULL);
414    IDDefText(&CommandTP, NULL);
415    IDDefSwitch(&OnCoordSetSP, NULL);
416    IDDefSwitch(&AbortSlewSP, NULL);
417    IDDefSwitch(&ParkSP, NULL);
418
419    // Raquette
420    IDDefSwitch(&AlignementAltpP, NULL);
421    IDDefSwitch(&AlignementAzP, NULL);
422    IDDefSwitch(&AlignementAltnP, NULL);
423
424    //alignement
425    IDDefSwitch(&RaquetteNP, NULL);
426    IDDefText(&AlignementIPP, NULL);
427    IDDefSwitch(&AlignementOkP, NULL);
428    IDDefSwitch(&AlignementResetP, NULL);
429    IDDefSwitch(&AlignmentSP, NULL);
430
431    // Options
432    IDDefNumber(&ActualisationNP1, NULL);
433    IDDefNumber(&ActualisationNP2, NULL);
434    IDDefNumber(&PressionTempWNP, NULL);
435    IDDefNumber(&GeographicCoordsWNP, NULL);
436}
437
438
439/**************************************************************************************
440** Initialisation des vecteurs de la boîte Indi
441** Cette procédure doit être obligatoirement présente dans tous pilotes Indi
442**
443***************************************************************************************/
444
445void BAO::reset_all_properties()
446{
447    ConnectSP.s                 = IPS_IDLE;
448    OnCoordSetSP.s              = IPS_IDLE;
449    AlignmentSP.s               = IPS_IDLE;
450    AlignementAltpP.s           = IPS_IDLE;
451    AlignementAltnP.s           = IPS_IDLE;
452    AlignementAzP.s             = IPS_IDLE;
453    AlignementIPP.s             = IPS_IDLE;
454    AlignementOkP.s             = IPS_IDLE;
455    RaquetteNP.s                = IPS_IDLE;
456    AlignementResetP.s          = IPS_IDLE;
457    AbortSlewSP.s               = IPS_IDLE;
458    ParkSP.s                    = IPS_IDLE;
459    ObjectTP.s                  = IPS_IDLE;
460    EquatorialCoordsWNP.s       = IPS_IDLE;
461    CommandTP.s                 = IPS_IDLE;
462    PressionTempWNP.s           = IPS_IDLE;
463    GeographicCoordsWNP.s       = IPS_IDLE;
464    ActualisationNP1.s          = IPS_IDLE;
465    ActualisationNP2.s          = IPS_IDLE;
466
467    IUResetSwitch(&OnCoordSetSP);
468    IUResetSwitch(&AlignmentSP);
469    IUResetSwitch(&AlignementAltpP);
470    IUResetSwitch(&AlignementAzP);
471    IUResetSwitch(&AlignementAltnP);
472    IUResetSwitch(&AlignementOkP);
473    IUResetSwitch(&AlignementResetP);
474    IUResetSwitch(&RaquetteNP);
475    IUResetSwitch(&AbortSlewSP);
476    IUResetSwitch(&ParkSP);
477
478    OnCoordSetS[0].s = ISS_ON;
479    AlignmentS[0].s = ISS_ON;
480    AlignementAltp[0].s = ISS_OFF;
481    AlignementAltn[0].s = ISS_OFF;
482    AlignementAz[0].s = ISS_OFF;
483    AlignementAz[1].s = ISS_OFF;
484    ConnectS[0].s = ISS_OFF;
485    ConnectS[1].s = ISS_ON;
486
487    IDSetSwitch(&ConnectSP, NULL);
488    IDSetSwitch(&OnCoordSetSP, NULL);
489    IDSetSwitch(&AlignmentSP, NULL);
490    IDSetSwitch(&AlignementAltpP, NULL);
491    IDSetSwitch(&AlignementAzP, NULL);
492    IDSetSwitch(&AlignementAltnP, NULL);
493    IDSetSwitch(&AlignementOkP, NULL);
494    IDSetSwitch(&AlignementResetP, NULL);
495    IDSetSwitch(&RaquetteNP, NULL);
496    IDSetSwitch(&AbortSlewSP, NULL);
497    IDSetSwitch(&ParkSP, NULL);
498    IDSetText(&ObjectTP, NULL);
499    IDSetText(&CommandTP, NULL);
500    IDSetText(&AlignementIPP, NULL);
501    IDSetNumber(&EquatorialCoordsWNP, NULL);
502    IDSetNumber(&PressionTempWNP, NULL);
503    IDSetNumber(&GeographicCoordsWNP, NULL);
504    IDSetNumber(&ActualisationNP1, NULL);
505    IDSetNumber(&ActualisationNP2, NULL);
506}
507
508
509
510
511
512
513/**************************************************************************************
514** En cas de changement de texte dans la boîte de dialogue (par exemple : changement du
515** nom de l'objet) alors suivre l'objet...
516** Cette fonction n'est pas utilisée
517** TODO: faut-il proposer cette fonction depuis la boîte alors qu'il est déjà
518** possible de le faire depuis  Kstars et BAOcontrol ?
519**
520**
521***************************************************************************************/
522
523void BAO::ISNewText (const char *dev, const char *name, char *texts[], char *names[], int n)
524{
525    // Ignore if not ours
526    if (strcmp (dev, mydev))
527        return;
528
529    if (is_connected() == false)
530    {
531        IDMessage(mydev, "Error ! Please connect before issuing any commands.");
532        reset_all_properties();
533        return;
534    }
535
536    // ===================================
537    // Object Name
538    // ===================================
539    if (!strcmp (name, ObjectTP.name))
540    {
541        if (IUUpdateText(&ObjectTP, texts, names, n) < 0)
542            return;
543
544        ObjectTP.s = IPS_OK;
545        IDSetText(&ObjectTP, NULL);
546        return;
547    }
548
549
550    // ===================================
551    // Adresse IP de l'antenne qu'il faut aligner
552    // ===================================
553    if (!strcmp (name, AlignementIPP.name))
554    {
555        if (IUUpdateText(&AlignementIPP, texts, names, n) < 0)
556            return;
557
558        IText *eqp = IUFindText (&AlignementIPP, names[0]);
559
560        int i;
561
562        if (eqp == &AlignementIP[0])
563        {
564            string ip = texts[0];
565
566            bool IPvalide = false;
567
568            // est-ce que l'adresse ip correspond à l'adresse d'une antenne connectée ?
569
570            for ( i=1; i<SocketsNumber; i++) if ( Sockets[i].Connected )
571                {
572                    if (Sockets[i].IP == ip) {
573                        IPvalide = true;
574                        break;
575                    }
576                }
577
578            if ( IPvalide )
579            {
580                targetAlignmentIP = i;
581                AlignementIPP.s = IPS_OK ;
582                IDSetText(&AlignementIPP, "L antenne %s est maintenant prete pour l alignement", Sockets[targetAlignmentIP].IP.c_str() );
583
584                Sockets[targetAlignmentIP].AlignementAntenne->AlignementEnCours = 1;
585
586                Sockets[targetAlignmentIP].AlignementAntenne->Matrice_ok = false;
587            }
588            else
589            {
590                targetAlignmentIP = -1;
591                AlignementIPP.s = IPS_ALERT ;
592                IDSetText(&AlignementIPP, "L antenne indiquee n est pas connectee !");
593            }
594        }
595        return;
596    }
597
598
599    // ===================================
600    // Commands
601    // ===================================
602    if (!strcmp (name, CommandTP.name))
603    {
604        if (IUUpdateText(&CommandTP, texts, names, n) < 0)
605            return;
606
607        IText *eqp = IUFindText (&CommandTP, names[0]);
608
609
610        if (eqp == &CommandT[0])
611        {
612            char chaine[1000];
613
614            bool result = false;
615
616            strcpy(chaine, texts[0]);
617
618            if (chaine[0] == 'G')
619            {
620                //commande goto
621
622                for (int i = 1; i<=strlen(chaine); i++) chaine[i-1]=chaine[i];
623
624                IDLog("%s", chaine);
625
626                for (int i = 1; i<SocketsNumber; i++ )
627                {
628                    if (Sockets[i].Connected)
629                    {
630                        result = COMMANDE(i, (char*)"G", chaine);
631                    }
632                }
633            }
634            else if (chaine[0] == 'X')
635            {
636                if (targetAlignmentIP != -1)
637                {
638                    IDSetText(&CommandTP, "Position:/%05d/%05d\n", Sockets[targetAlignmentIP].Pos.x, Sockets[targetAlignmentIP].Pos.y );
639
640                    return;
641                }
642            }
643            else if (chaine[0] == 'D')
644            {
645                if (targetAlignmentIP != -1)
646                {
647                    IDSetText(&CommandTP, "Deltas:/%05d/%05d\n", delta_az, delta_ha );
648
649                    return;
650                }
651            }
652            else if (chaine[0] == 'M')
653            {
654                IDSetText(&CommandTP, "Calcul des matrices de correction\n" );
655
656                if  (Sockets[targetAlignmentIP].AlignementAntenne->nbrcorrections >=3 )
657                {
658                    Sockets[targetAlignmentIP].AlignementAntenne->AlignementEnCours = 0;
659                   
660                    Sockets[targetAlignmentIP].AlignementAntenne->InitParametresInstrument();
661                   
662                    Sockets[targetAlignmentIP].AlignementAntenne->CalculerMatriceCorrection(targetRA, targetDEC);
663                   
664                     Sockets[targetAlignmentIP].AlignementAntenne->EnregistrementParametresAlignement(
665                        Sockets[targetAlignmentIP].IP,
666                        "/home/" + (string)getenv("USER") + "/AlignementAntennes.cfg");
667                }
668                else
669                {
670                    Sockets[targetAlignmentIP].AlignementAntenne->Identity();
671
672                    Sockets[targetAlignmentIP].AlignementAntenne->Matrice_ok = false;
673                }
674            }
675            else if (chaine[0] == 'R')
676            {
677                IDSetText(&CommandTP, "Reinitialisation de la matrice de correction\n" );
678
679                 Sockets[targetAlignmentIP].AlignementAntenne->InitParametresInstrument();
680                 
681                 Sockets[targetAlignmentIP].AlignementAntenne->Identity();
682
683                Sockets[targetAlignmentIP].AlignementAntenne->Matrice_ok = false;
684               
685                 Sockets[targetAlignmentIP].AlignementAntenne->EnregistrementParametresAlignement(
686                        Sockets[targetAlignmentIP].IP,
687                        "/home/" + (string)getenv("USER") + "/AlignementAntennes.cfg");
688            }
689            else if (chaine[0] == 'O')
690            {
691                IDSetText(&CommandTP, "Optimisation de la geometrie de l antenne\n" );
692
693                if (targetAlignmentIP != -1)
694                {
695                    Sockets[targetAlignmentIP].AlignementAntenne->OptimisationGeometrieAntenne(true);
696
697                    IDSetSwitch(&AlignementOkP, "Les parametres de l alignement ont ete sauvegardes apres optimisation");
698
699                    Sockets[targetAlignmentIP].AlignementAntenne->EnregistrementParametresAlignement(
700                        Sockets[targetAlignmentIP].IP,
701                        "/home/" + (string)getenv("USER") + "/AlignementAntennes.cfg");
702                }
703            }
704            else if (chaine[0] == 'C')
705            {
706                if (targetAlignmentIP != -1)
707                {
708                    stringstream os;
709
710                    double a, b;
711
712                    os << "Corrections:";
713
714                    Azimut( targetRA * 15.0 * Pidiv180,
715                            targetDEC * Pidiv180, &a, &b);
716                    os << a << ",";
717                    os << b << ",";
718
719                    os << "/";
720
721                    for (int i=0; i<Sockets[targetAlignmentIP].AlignementAntenne->nbrcorrections; i++)
722                    {
723                        if (Sockets[targetAlignmentIP].AlignementAntenne->SelectionnePourCalculMatrice[i])
724                        {
725                            os << i << ",";
726                        }
727                    }
728
729                    os << "/";
730
731                    for (int i=0; i<Sockets[targetAlignmentIP].AlignementAntenne->nbrcorrections; i++)
732                    {
733                        if (Sockets[targetAlignmentIP].AlignementAntenne->tsl[i] != 0.0)
734                        {
735                            Azimut( Sockets[targetAlignmentIP].AlignementAntenne->ad[i]
736                                    - Sockets[targetAlignmentIP].AlignementAntenne->tsl[i] + GetTSL(),
737                                    Sockets[targetAlignmentIP].AlignementAntenne->de[i], &a, &b);
738                            os << a << ",";
739                            os << b << ",";
740
741                            Azimut( Sockets[targetAlignmentIP].AlignementAntenne->delta_ad[i]
742                                    - Sockets[targetAlignmentIP].AlignementAntenne->tsl[i] + GetTSL(),
743                                    Sockets[targetAlignmentIP].AlignementAntenne->delta_de[i]
744                                    , &a, &b);
745
746                            os << a << ",";
747                            os << b << ",";
748                        }
749                    }
750
751                    os << "/";
752
753                    for (int i=0; i<Sockets[targetAlignmentIP].AlignementAntenne->nbrcorrections; i++)
754                    {
755                        if (Sockets[targetAlignmentIP].AlignementAntenne->tsl[i] != 0.0 && Sockets[targetAlignmentIP].AlignementAntenne->Matrice_ok)
756                        {
757                            Azimut( Sockets[targetAlignmentIP].AlignementAntenne->ad[i]
758                                    - Sockets[targetAlignmentIP].AlignementAntenne->tsl[i] + GetTSL(),
759                                    Sockets[targetAlignmentIP].AlignementAntenne->de[i], &a, &b);
760
761                            Coord vect, r;
762
763
764                            if (Sockets[targetAlignmentIP].AlignementAntenne->MethodeAlignement == SIMPLE)
765                            {
766
767                                b = Sockets[targetAlignmentIP].AlignementAntenne->Motor2Alt(Sockets[targetAlignmentIP].AlignementAntenne->Alt2Motor2(b * N180divPi)) * Pidiv180;
768
769                                vect.x = cos(a) * cos(b);
770                                vect.y = sin(a) * cos(b);
771                                vect.z = sin(b);
772
773
774                                // Application de la matrice SIMPLE
775
776                                Sockets[targetAlignmentIP].AlignementAntenne->AppliquerMatriceCorrectionSimple(&r, vect);
777
778
779                                // Là on doit repasser des coordonnées rectangulaires
780                                // aux coordonnées sphériques
781
782                                if (r.x != 0.0)
783                                {
784                                    a = atan( r.y / r.x );
785
786                                    if (r.x < 0) a += Pi;
787                                }
788                                else a = Pidiv2;
789
790                                b = asin(r.z);
791                            }
792                            else
793                            {
794                                double c, d;
795
796                                Sockets[targetAlignmentIP].AlignementAntenne->AzHa2XY(a, b, &c, &d);
797                                vect.x = c;
798                                vect.y = d;
799                                vect.z = 1.0;
800
801                                AfficherLog("az=%5.2f ha=%5.2f x=%5.2f y=%5.2f\n", a, b, c, d);
802                                // Application de la matrice SIMPLE
803
804                                Sockets[targetAlignmentIP].AlignementAntenne->AppliquerMatriceCorrectionAffine(&r, vect);
805
806
807                                AfficherLog("r.x=%5.2f r.y=%5.2f d=%5.2f\n", r.x, r.y,sqrt(r.x*r.x+r.y*r.y));
808                                a = atan(r.y/r.x);
809                                if (r.x < 0) a += Pi;
810
811                                b= Pidiv2-(sqrt(r.x*r.x+r.y*r.y));
812                            }
813
814
815                            os << a << ",";
816                            os << b << ",";
817                        }
818                    }
819
820                    IDSetText(&CommandTP, "%s", os.str().c_str() );
821
822                    return;
823                }
824            }
825            else
826            {
827                for (int i = 1; i<SocketsNumber; i++ )
828                {
829                    if (Sockets[i].Connected)
830                    {
831                        result = COMMANDE(i, chaine, (char*)"");
832                    }
833                }
834            }
835
836            (result) ? CommandTP.s = IPS_OK : CommandTP.s = IPS_ALERT;
837
838            IDSetText(&CommandTP, NULL);
839        }
840        return;
841    }
842}
843
844
845
846/**************************************************************************************
847** En cas de changement d'une valeur numérique dans la boîte de dialogue Indi
848** Exemple : longitude, latitude, ar, dec etc...) -> prendre en compte les modifications
849**
850** const char *dev  contient le nom du dispositif recevant le message (ici indi_BAO)
851** const char *name reçoit  le nom de la rubrique modifiée par l'utilisateur
852** (ex : les coordonnées géographiques, les coordonnées horaires de l'objet etc...)
853** double names[] contient la liste de tous les champs modifiables dans chaque rubrique
854** (ex : longitude et latitude dans la rubrique coordonnées géographiques
855** char *values[] contient toutes les valeurs (numériques ou non) mais toujours exprimées
856** sous la forme d'une chaîne de caractÚres
857**
858***************************************************************************************/
859
860void BAO::ISNewNumber (const char *dev, const char *name, double values[], char *names[], int n)
861{
862
863    // Ignore if not ours
864
865    if (strcmp (dev, mydev))
866        return;
867
868    // Si pas de connexion -> on sort
869
870    if (is_connected() == false)
871    {
872        IDMessage(mydev, "Error ! BAO is offline. Please connect before issuing any commands.");
873
874        reset_all_properties();
875
876        return;
877    }
878
879
880    // ===================================
881    // Geographic  Coords
882    // ===================================
883
884    if (!strcmp (name, GeographicCoordsWNP.name))
885    {
886        // l'utilisateur a modifié une des coordonnées géographiques de la boite indi
887
888        int i = 0, nset = 0;
889
890        // En cas d'erreur, on doit pouvoir sortir avec des paramÚtres par défaut
891        // ici la latitude et la longitude valent 0.0
892
893        Latitude  = 0.0;
894        Longitude = 0.0;
895
896        // pour ce vecteur, on sait qu'il y a n éléments possibles
897        // Exemple pour la rubrique coordonnées géographique de la boîte indi
898        // il y a deux éléments : la longitude et la latitude
899        // pour la rubrique alignement, il y a en a trois : simple, affine et taki
900
901        for (i = 0; i < n; i++)
902        {
903            // pour chacun d'entre eux, on regarde si le nom passé en argument de la fonction (*name)
904            // correspond bien à l'un des éléments du vecteur GeographicCoordsWNP
905
906            INumber *eqp = IUFindNumber (&GeographicCoordsWNP, names[i]);
907
908            if (eqp == &GeographicCoordsWN[0])
909            {
910                // ici on a identifié la zone latitude de la boîte de dialogue
911                // Value[i] contient la chaîne de caractÚre correspondante dans la boîte
912                // C'est la valeur saisie par l'utilisateur
913
914                Latitude = values[i];
915
916                // On doit vérifier que la latitude est dans un intervalle correct
917
918                nset += Latitude >= -90.0 && Latitude <= 90.0;
919
920                // on convertit en radians
921
922                Latitude *= Pidiv180;
923            }
924            else if (eqp == &GeographicCoordsWN[1])
925            {
926                // ici on a identifié une modification dans la rubrique longitude
927
928                Longitude = values[i];
929
930                // dans l'intervalle ?
931
932                nset += Longitude >= 0.0 && Longitude <= 360.0;
933
934                // en radians
935
936                Longitude *= -Pidiv180;
937            }
938        }
939
940        // Si la longitude et la latitude sont correctes
941        // on envoie les coordonnées à la classe Astro
942        if (nset == 2)
943        {
944            // Vérification
945            // AfficherLog("Geographic : RA %5.2f - DEC %5.2f\n", Latitude, Longitude);
946
947            // nset vaut 2, nous sommes donc sûrs qu'il n'y a pas de problÚme dans les valeurs
948            // saisies par l'utilisateur
949            // voir le code plus haut pour comprendre...
950
951            // On change la couleur de la "diode" de la rubrique coordonnées
952            // géographiques de la boîte en vert
953
954            GeographicCoordsWNP.s = IPS_OK;
955
956            // pas de message d'erreur dans la boîte
957
958            IDSetNumber(&GeographicCoordsWNP, NULL);
959        }
960        else
961        {
962            // quelque chose cloche
963            // peut-être l'une des valeurs saisies par l'utilisateur n'est-elle pas dans
964            // le bon intervalle ? ex : lat = 150°
965
966            // on change la couleur de la diode
967
968            GeographicCoordsWNP.s = IPS_ALERT;
969
970            // on affiche un message d'erreur
971
972            IDSetNumber(&GeographicCoordsWNP, "Latitude or Longitude missing or invalid");
973
974            // on fixe arbitrairement les valeurs à 0
975
976            Latitude  = 0.0;
977            Longitude = 0.0;
978        }
979
980        // c'est bon. On peut donc transmettre les nouvelles valeurs à la classe astro
981        // qui utilisera ces informations pur calculer l'azimut des objets et le temps sidéral local en particulier...
982
983        DefinirLongitudeLatitude(Longitude, Latitude);
984
985        return;
986    }
987
988
989    // ===================================
990    // Equatorial Coords
991    // ===================================
992    if (!strcmp (name, EquatorialCoordsWNP.name))
993    {
994        int i = 0, nset = 0;
995
996        double newRA =0.0, newDEC =0.0;
997
998        // nous avons le même principe de fonctionnement que pour les coordonnées géographiques
999
1000        for (i = 0; i < n; i++)
1001        {
1002            INumber *eqp = IUFindNumber (&EquatorialCoordsWNP, names[i]);
1003
1004            if (eqp == &EquatorialCoordsWN[0])
1005            {
1006                // on a compris que l'utilisateur avait changé l'ascension droite de l'objet
1007
1008                // on affecte la nouvelle valeur à newRA
1009
1010                newRA = values[i];
1011
1012                // Est-ce que cette valeur est dans le bon intervalle ?
1013
1014                nset += newRA >= 0 && newRA <= 24.0;
1015            }
1016            else if (eqp == &EquatorialCoordsWN[1])
1017            {
1018                // même chose pour la déclinaison
1019                newDEC = values[i];
1020
1021                nset += newDEC >= -90.0 && newDEC <= 90.0;
1022            }
1023        }
1024
1025
1026        // si les coordonnées de l'objet sont correctes
1027
1028        if (nset == 2)
1029        {
1030            char RAStr[32], DecStr[32];
1031            double targetAZ, targetAlt;
1032
1033            // On garde une trace des nouvelles coordonnées saisies par l'utilisateur
1034
1035            targetRA  = newRA;
1036            targetDEC = newDEC;
1037
1038            // Réinitialisation des deltas
1039
1040            delta_az = 0;
1041            delta_ha = 0;
1042
1043            if (targetAlignmentIP != -1 && Sockets[targetAlignmentIP].AlignementAntenne->AlignementEnCours != 0)
1044            {
1045                Sockets[targetAlignmentIP].AlignementAntenne->delta_ad[Sockets[targetAlignmentIP].AlignementAntenne->nbrcorrections] =
1046                    targetRA * 15.0 * Pidiv180;
1047
1048                Sockets[targetAlignmentIP].AlignementAntenne->delta_de[Sockets[targetAlignmentIP].AlignementAntenne->nbrcorrections] =
1049                    targetDEC * Pidiv180;
1050            }
1051
1052            for (int i=0; i<SocketsNumber; i++) if (Sockets[i].Connected)
1053                {
1054                    if ( Sockets[i].AlignementAntenne->AlignementEnCours == 0 )
1055                    {
1056                        Sockets[i].AlignementAntenne->CalculerMatriceCorrection(targetRA, targetDEC);
1057                    }
1058                }
1059
1060
1061
1062            // on les affiche dans les logs
1063
1064            fs_sexa(RAStr, newRA, 2, 3600);
1065            fs_sexa(DecStr, newDEC, 2, 3600);
1066
1067            AfficherLog("We received JNow RA %s - DEC %s\n", RAStr, DecStr);
1068
1069            // on convertit les coordonnées équatoriales de la zone du ciel observée
1070            // en unités de codeurs des moteurs
1071
1072            ADDEC2Motor(newRA, newDEC);
1073
1074            // on déclenche le goto
1075
1076            if (process_coords() == false)
1077            {
1078                EquatorialCoordsWNP.s = IPS_ALERT;
1079
1080                IDSetNumber(&EquatorialCoordsWNP, NULL);
1081            }
1082        }
1083        else
1084        {
1085            EquatorialCoordsWNP.s = IPS_ALERT;
1086
1087            IDSetNumber(&EquatorialCoordsWNP, "Error ! RA or Dec missing or invalid");
1088        }
1089
1090        return;
1091    }
1092
1093
1094    // ===================================
1095    // Pression, Temperature
1096    // ===================================
1097    if (!strcmp (name, PressionTempWNP.name))
1098    {
1099        int i = 0, nset = 0;
1100
1101        double newPression =0.0, newTemperature =0.0;
1102
1103        // nous avons le même principe de fonctionnement que pour les coordonnées géographiques
1104
1105        for (i = 0; i < n; i++)
1106        {
1107            INumber *eqp = IUFindNumber (&PressionTempWNP, names[i]);
1108
1109            if (eqp == &PressionTempWN[0])
1110            {
1111                // on a compris que l'utilisateur a changé l'ascension droite de l'objet
1112
1113                // on affecte la nouvelle valeur à newRA
1114
1115                newPression = values[i];
1116
1117                // Est-ce que cette valeur est dans le bon intervalle ?
1118
1119                nset += newPression >= 0.0 && newPression <= 1500.0;
1120            }
1121            else if (eqp == &PressionTempWN[1])
1122            {
1123                //même chose pour la déclinaison
1124                newTemperature = values[i];
1125
1126                nset += newTemperature >= -50.0 && newTemperature <= 50.0;
1127            }
1128        }
1129
1130
1131        // si les coordonnées de l'objet sont correctes
1132
1133        if (nset == 2)
1134        {
1135            PressionTempWNP.s = IPS_OK;
1136
1137            IDSetNumber(&PressionTempWNP, NULL);
1138
1139            Pression = newPression;
1140            Temp = newTemperature;
1141        }
1142        else
1143        {
1144            PressionTempWNP.s = IPS_ALERT;
1145
1146            IDSetNumber(&PressionTempWNP, "Error ! Bad values for pression or temperature");
1147        }
1148
1149        return;
1150    }
1151
1152
1153    // ===================================
1154    // Actualisation
1155    // ===================================
1156    if (!strcmp (name, ActualisationNP1.name))
1157    {
1158        // on a ici exactement le même fonctionnement que précédemment
1159        // on rÚgle ici les valeurs des délais entre deux actualisations
1160        // de la position en mode transit et tracking
1161        // Retourne un message d'erreur si les durées ne sont pas exprimées
1162        // dans un intervalle > 0 et < 3600
1163
1164        double newAct1 = 1.0;
1165
1166        for (int i = 0; i < n; i++)
1167        {
1168            INumber *eqp = IUFindNumber (&ActualisationNP1, names[i]);
1169
1170            if (eqp == &ActualisationN1[0])
1171            {
1172                newAct1 = values[i];
1173
1174                if ( newAct1 >= 0.0 && newAct1 <= 3600.0 )
1175                {
1176                    ActualisationTMTransit = newAct1;
1177
1178                    ActualisationNP1.s = IPS_OK;
1179
1180                    IDSetNumber(&ActualisationNP1, NULL);
1181                }
1182                else
1183                {
1184                    ActualisationNP1.s = IPS_ALERT;
1185
1186                    IDSetNumber(&ActualisationNP1, "Error ! Delay invalid");
1187                }
1188            }
1189        }
1190    }
1191
1192    if (!strcmp (name, ActualisationNP2.name))
1193    {
1194        double newAct2 = 1.0;
1195
1196        for (int i = 0; i < n; i++)
1197        {
1198            INumber *eqp = IUFindNumber (&ActualisationNP2, names[i]);
1199
1200            if (eqp == &ActualisationN2[0])
1201            {
1202                newAct2 = values[i];
1203
1204                if ( newAct2 >= 0.0 && newAct2 <= 3600.0 )
1205                {
1206                    ActualisationTMTracking = newAct2;
1207
1208                    ActualisationNP2.s = IPS_OK;
1209
1210                    IDSetNumber(&ActualisationNP2, NULL);
1211                }
1212                else
1213                {
1214                    ActualisationNP2.s = IPS_ALERT;
1215                    IDSetNumber(&ActualisationNP2, "Error ! Delay invalid");
1216                }
1217            }
1218        }
1219    }
1220}
1221
1222
1223
1224/**************************************************************************************
1225** L'utilisateur clique sur l'un des boutons de la boîte Indi
1226** Même observation que pour la procédure précédente
1227**
1228***************************************************************************************/
1229
1230void BAO::ISNewSwitch (const char *dev, const char *name, ISState *states, char *names[], int n)
1231{
1232    // ignore if not ours //
1233    if (strcmp (mydev, dev))
1234        return;
1235
1236
1237
1238    double az, ha, ad, de;
1239
1240    ad = targetRA * 15.0 * Pidiv180;
1241
1242    de = targetDEC * Pidiv180;
1243
1244    CalculTSL();
1245
1246    Azimut(ad, de, &az, &ha);
1247
1248    ha = RefractionAtmospherique(ha) ;
1249
1250
1251
1252
1253    // ===================================
1254    // Connect Switch
1255    // ===================================
1256    if (!strcmp (name, ConnectSP.name))
1257    {
1258        if (IUUpdateSwitch(&ConnectSP, states, names, n) < 0)
1259            return;
1260
1261        connect_telescope();
1262
1263        return;
1264    }
1265
1266    if (is_connected() == false)
1267    {
1268        IDMessage(mydev, "Error ! BAORadio is offline. Please connect before issuing any commands.");
1269        reset_all_properties();
1270        return;
1271    }
1272
1273    // ===================================
1274    // Coordinate Set
1275    // ===================================
1276    if (!strcmp(name, OnCoordSetSP.name))
1277    {
1278        if (IUUpdateSwitch(&OnCoordSetSP, states, names, n) < 0)
1279            return;
1280
1281        currentSet = get_switch_index(&OnCoordSetSP);
1282        OnCoordSetSP.s = IPS_OK;
1283        IDSetSwitch(&OnCoordSetSP, NULL);
1284    }
1285
1286    // ===================================
1287    // Alignment Set
1288    // ===================================
1289    if (!strcmp(name, AlignmentSP.name))
1290    {
1291        if (IUUpdateSwitch(&AlignmentSP, states, names, n) < 0)
1292            return;
1293
1294        MethodeAlignement = get_switch_index(&AlignmentSP) + 1 ;
1295
1296        AlignmentSP.s = IPS_OK;
1297        IUResetSwitch(&AlignmentSP);
1298        IDSetSwitch(&AlignmentSP, NULL);
1299
1300        for (int i=0; i<MAXHOSTNAME; i++)
1301        {
1302            switch (MethodeAlignement)
1303            {
1304            case 1 :
1305                Sockets[i].AlignementAntenne->MethodeAlignement = SIMPLE;
1306                break;
1307            case 2 :
1308                Sockets[i].AlignementAntenne->MethodeAlignement = AFFINE;
1309                break;
1310            case 3 :
1311                Sockets[i].AlignementAntenne->MethodeAlignement = TAKI;
1312                break;
1313            }
1314        }
1315
1316        return;
1317    }
1318
1319    // ===================================
1320    // Alignment Speed
1321    // ===================================
1322    if (!strcmp(name, RaquetteNP.name))
1323    {
1324        if (IUUpdateSwitch(&RaquetteNP, states, names, n) < 0)
1325            return;
1326
1327        RaquetteNP.s = IPS_OK;
1328
1329        switch (get_switch_index(&RaquetteNP))
1330        {
1331        case 0 :
1332            IUResetSwitch(&RaquetteNP);
1333            IDSetSwitch(&RaquetteNP, "La vitesse de la raquette est fixee a 1x");
1334            VitesseRaquette = 1;
1335            break;
1336        case 1 :
1337            IUResetSwitch(&RaquetteNP);
1338            IDSetSwitch(&RaquetteNP, "La vitesse de la raquette est fixee a 3x");
1339            VitesseRaquette = 3;
1340            break;
1341        }
1342
1343        return;
1344    }
1345
1346    // ===================================
1347    // Alignment Reset
1348    // ===================================
1349    if (!strcmp(name, AlignementResetP.name))
1350    {
1351        if (IUUpdateSwitch(&AlignementResetP, states, names, n) < 0)
1352            return;
1353
1354        if ( targetAlignmentIP < 0 )
1355        {
1356            AlignementResetP.s = IPS_ALERT;
1357            IDSetSwitch(&AlignementResetP, "Veuillez indiquer l adresse IP de l antenne a calibrer");
1358
1359            return;
1360        }
1361
1362        AlignementResetP.s = IPS_OK;
1363        IDSetSwitch(&AlignementResetP, "Les parametres de l alignement de l antenne ont ete reinitialises");
1364
1365        Sockets[targetAlignmentIP].AlignementAntenne->InitAlignement();
1366
1367        sleep(1);
1368
1369        Sockets[targetAlignmentIP].AlignementAntenne->EnregistrementParametresAlignement(
1370            Sockets[targetAlignmentIP].IP,
1371            "/home/" + (string)getenv("USER") + "/AlignementAntennes.cfg");
1372
1373
1374        IUResetSwitch(&AlignementResetP);
1375        AlignementResetP.s = IPS_IDLE;
1376        IDSetSwitch(&AlignementResetP, NULL);
1377
1378        return;
1379    }
1380
1381
1382
1383    // ===================================
1384    // Alignment buttons
1385    // ===================================
1386    if (!strcmp(name, AlignementAltpP.name))
1387    {
1388        if (IUUpdateSwitch(&AlignementAltpP, states, names, n) < 0)
1389            return;
1390
1391        delta_ha += VitesseRaquette;
1392
1393        az  = VerifAngle(az + (double)delta_az * PasDeltaAz);
1394
1395        ha += (double)delta_ha * PasDeltaHa;
1396
1397        //   ISPoll();
1398
1399        AlignementAltpP.s = IPS_IDLE;
1400
1401        IDSetSwitch(&AlignementAltpP, "Delta en azimut = %s  delta en hauteur = %s  az = %s  ha = %s (Vitesse raquette = %d)\n",
1402                    DHMS(delta_az * PasDeltaAz * N180divPi, false).c_str(),
1403                    DHMS(delta_ha * PasDeltaHa * N180divPi, false).c_str(),
1404                    DHMS(az * N180divPi, false).c_str(),
1405                    DHMS(ha * N180divPi, false).c_str(),
1406                    VitesseRaquette);
1407        IUResetSwitch(&AlignementAltpP);
1408
1409        return;
1410    }
1411
1412    if (!strcmp(name, AlignementAltnP.name))
1413    {
1414        if (IUUpdateSwitch(&AlignementAltnP, states, names, n) < 0)
1415            return;
1416
1417        delta_ha -= VitesseRaquette;
1418
1419        az  = VerifAngle(az + (double)delta_az * PasDeltaAz);
1420
1421        ha += (double)delta_ha * PasDeltaHa;
1422
1423        //   ISPoll();
1424
1425        AlignementAltnP.s = IPS_IDLE;
1426
1427        IDSetSwitch(&AlignementAltnP, "Delta en azimut = %s  delta en hauteur = %s  az = %s  ha = %s (Vitesse raquette = %d)\n",
1428                    DHMS(delta_az * PasDeltaAz * N180divPi, false).c_str(),
1429                    DHMS(delta_ha * PasDeltaHa * N180divPi, false).c_str(),
1430                    DHMS(az * N180divPi, false).c_str(),
1431                    DHMS(ha * N180divPi, false).c_str(),
1432                    VitesseRaquette);
1433        IUResetSwitch(&AlignementAltnP);
1434
1435        return;
1436    }
1437
1438    if (!strcmp(name, AlignementAzP.name))
1439    {
1440        if (IUUpdateSwitch(&AlignementAzP, states, names, n) < 0)
1441            return;
1442
1443        switch (get_switch_index(&AlignementAzP))
1444        {
1445        case 0 :
1446            delta_az -= VitesseRaquette;
1447            break;
1448        case 1 :
1449            delta_az += VitesseRaquette;
1450            break;
1451        }
1452
1453        az  = VerifAngle(az + (double)delta_az * PasDeltaAz);
1454
1455        ha += (double)delta_ha * PasDeltaHa;
1456
1457        // ISPoll();
1458
1459        AlignementAzP.s = IPS_IDLE;
1460
1461        IDSetSwitch(&AlignementAzP, "Delta en azimut = %s  delta en hauteur = %s  az = %s  ha = %s (Vitesse raquette = %d)\n",
1462                    DHMS(delta_az * PasDeltaAz * N180divPi, false).c_str(),
1463                    DHMS(delta_ha * PasDeltaHa * N180divPi, false).c_str(),
1464                    DHMS(az * N180divPi, false).c_str(),
1465                    DHMS(ha * N180divPi, false).c_str(),
1466                    VitesseRaquette);
1467        IUResetSwitch(&AlignementAzP);
1468
1469        return;
1470    }
1471
1472    if (!strcmp(name, AlignementOkP.name))
1473    {
1474        if (IUUpdateSwitch(&AlignementOkP, states, names, n) < 0)
1475            return;
1476
1477        if ( targetAlignmentIP < 0 )
1478        {
1479            AlignementOkP.s = IPS_ALERT;
1480            IDSetSwitch(&AlignementOkP, "Veuillez indiquer l adresse IP de l antenne a calibrer");
1481
1482            return;
1483        }
1484
1485        AlignementOkP.s = IPS_OK;
1486        IDSetSwitch(&AlignementOkP, NULL);
1487
1488        switch (get_switch_index(&AlignementOkP))
1489        {
1490            // Validation de l'alignement en cours...
1491
1492        case 0 :
1493        {
1494            float a, b, c;
1495            double az, ha, ad, de, ad2, de2;
1496
1497            int num = Sockets[targetAlignmentIP].AlignementAntenne->nbrcorrections;
1498
1499
1500
1501            stringstream os;
1502
1503            AfficherLog("Alignement de l antenne %s avec l objet situe en RA %s - DEC %s\n",
1504                        Sockets[targetAlignmentIP].IP.c_str(),
1505                        DHMS(targetRA * 15.0, true).c_str(),
1506                        DHMS(targetDEC, false     ).c_str());
1507
1508            AfficherLog("(ad1=%s de1=%s) -> (ad2=%s de2=%s)\n",
1509                        DHMS(Sockets[targetAlignmentIP].AlignementAntenne->ad[num]  * N180divPi, true ).c_str(),
1510                        DHMS(Sockets[targetAlignmentIP].AlignementAntenne->de[num]  * N180divPi, false).c_str(),
1511                        DHMS(Sockets[targetAlignmentIP].AlignementAntenne->delta_ad[num] * N180divPi, true ).c_str(),
1512                        DHMS(Sockets[targetAlignmentIP].AlignementAntenne->delta_de[num] * N180divPi, false).c_str());
1513
1514            AfficherLog("delta_az=%i delta_ha=%i\n", delta_az, delta_ha);
1515
1516            Sockets[targetAlignmentIP].AlignementAntenne->nbrcorrections++;
1517
1518            delta_az = 0;
1519            delta_ha = 0;
1520
1521            IDSetSwitch(&AlignementOkP, "Les parametres de l alignement ont ete valides");
1522
1523        }
1524        break;
1525
1526        // Sauvegarde de l'alignement en cours...
1527
1528        case 1 :
1529        {
1530            /*if  (Sockets[targetAlignmentIP].AlignementAntenne->nbrcorrections >=3 )
1531            {
1532                // IDLog("Calcul matrice\n", true);
1533                Sockets[targetAlignmentIP].AlignementAntenne->AlignementEnCours = 0;
1534                Sockets[targetAlignmentIP].AlignementAntenne->CalculerMatriceCorrection(targetRA, targetDEC);
1535            }
1536            else
1537            {
1538                Sockets[targetAlignmentIP].AlignementAntenne->Identity();
1539
1540                Sockets[targetAlignmentIP].AlignementAntenne->Matrice_ok = false;
1541            }*/
1542
1543            IDSetSwitch(&AlignementOkP, "Les parametres de l alignement ont ete sauvegardes");
1544
1545            Sockets[targetAlignmentIP].AlignementAntenne->EnregistrementParametresAlignement(
1546                Sockets[targetAlignmentIP].IP,
1547                "/home/" + (string)getenv("USER") + "/AlignementAntennes.cfg");
1548        }
1549        break;
1550        }
1551
1552
1553        AlignementOkP.s = IPS_IDLE;
1554        IUResetSwitch(&AlignementOkP);
1555        IDSetSwitch(&AlignementOkP, NULL);
1556
1557        return;
1558    }
1559
1560
1561    // ===================================
1562    // Abort slew
1563    // ===================================
1564    if (!strcmp (name, AbortSlewSP.name))
1565    {
1566        Abort = true;
1567
1568        IUResetSwitch(&AbortSlewSP);
1569
1570        if (EquatorialCoordsWNP.s == IPS_OK)
1571        {
1572            AbortSlewSP.s = IPS_OK;
1573            EquatorialCoordsWNP.s = IPS_IDLE;
1574            ObjectTP.s = IPS_IDLE;
1575            CommandTP.s = IPS_IDLE;
1576
1577            IDSetSwitch(&ConnectSP, "Envoi de la commande Abort\n");
1578            IDSetNumber(&EquatorialCoordsWNP, NULL);
1579            IDSetText(&ObjectTP, NULL);
1580            IDSetText(&CommandTP, NULL);
1581        }
1582
1583        return;
1584    }
1585
1586
1587    // ===================================
1588    // Park
1589    // ===================================
1590    if (!strcmp (name, ParkSP.name))
1591    {
1592        Park=true;
1593
1594        IUResetSwitch(&ParkSP);
1595
1596        if (EquatorialCoordsWNP.s == IPS_OK)
1597        {
1598            AbortSlewSP.s = IPS_OK;
1599            EquatorialCoordsWNP.s = IPS_IDLE;
1600            ObjectTP.s = IPS_IDLE;
1601            CommandTP.s = IPS_IDLE;
1602
1603            IDSetSwitch(&ConnectSP, "Envoi de la commande Park\n");
1604            IDSetNumber(&EquatorialCoordsWNP, NULL);
1605            IDSetText(&ObjectTP, NULL);
1606            IDSetText(&CommandTP, NULL);
1607        }
1608
1609        return;
1610    }
1611}
1612
1613
1614
1615/**************************************************************************************
1616** Gestion du thread
1617** permet de suivre la connexion/déconnexion des antennes toutes les secondes
1618**
1619** l'utilisation d'un thread permet de contourner le problÚme de la fonction accept
1620** qui est bloquante.
1621** L'adresse IP de l'antenne qui a effectué la connexion est consignée dans la variable IP
1622** de la structure Sockets. L'état de l'antenne (connected) est placée à true
1623**
1624***************************************************************************************/
1625
1626void *BAO::pThreadSocket ()
1627{
1628    do
1629    {
1630        try
1631        {
1632            server.accept( Sockets[SocketsNumber].new_sock );
1633
1634            Sockets[SocketsNumber].IP = server.recupip(Sockets[SocketsNumber].new_sock);
1635
1636            Sockets[SocketsNumber].AlignementAntenne->MethodeAlignement = MethodeAlignement;
1637
1638            Sockets[SocketsNumber++].Connected = true;
1639
1640            InitThreadOK = true;
1641        }
1642        catch ( SocketException& e )
1643        {
1644            /*AfficherLog("Indi_BAO, pThreadSocket exception : ");
1645            AfficherLog(e.description().c_str());
1646            AfficherLog("\n");*/
1647        }
1648
1649        sleep(1); // faire une pause pour éviter de consommer trop de temps CPU -> à vérifier
1650    }
1651    while (!Exit);
1652
1653    pthread_exit (0);
1654}
1655
1656
1657
1658/**************************************************************************************
1659** Astuce pour lancer le thread depuis la classe BAO
1660**
1661***************************************************************************************/
1662
1663void* LancementThread(BAO * appli)
1664{
1665    appli->pThreadSocket();
1666
1667    return 0;
1668}
1669
1670
1671/**************************************************************************************
1672** Extraction de la position de l'antenne aprÚs l'envoi de la commande P
1673** Le retour de la commande P est POSITION/valeur_az/valeur_alt/
1674** Ce retour est envoyé dans la chaîne str
1675** ExtractPosition retourne une structure Position contenant Valeur_az et Valeur_alt
1676** Ex: ExtractPosition("POSITION/0100/0001/", result)  retourne result.x=100 et result.y=1
1677**
1678***************************************************************************************/
1679
1680bool BAO::ExtractPosition(string str, Position *result)
1681{
1682    string str2;
1683
1684    int pos = str.find("/");
1685
1686    if (pos != string::npos)
1687    {
1688        str2 = str.substr(pos + 1);
1689
1690        pos = str2.find("/");
1691
1692        if (pos != string::npos)
1693        {
1694            result->x = atol( str2.substr(0, pos).c_str() );
1695
1696            result->y = atol( str2.substr(pos + 1).c_str() );
1697
1698            return true;
1699        }
1700    }
1701
1702    AfficherLog((str +" failed !\n").c_str());
1703
1704    return false;
1705}
1706
1707
1708/************************************************************************************
1709** Cette procédure, aprÚs avoir appliqué la matrice de rotation aux coordonnées de l'objet
1710** visées par l'utilisateur, effectue les conversions en unités codeurs des paraboles
1711** (càd en nb de tours des deux axes moteurs depuis la position PARK)
1712**
1713************************************************************************************/
1714
1715void BAO::ADDEC2Motor(double newRA, double newDEC)
1716{
1717    double targetAz;
1718    double targetAlt;
1719    double newRA2  = newRA * 15.0 * Pidiv180;
1720    double newDEC2 = newDEC * Pidiv180;
1721    double hautmin = HAUTMIN;
1722    char AzStr[32];
1723    char AltStr[32];
1724    Coord result, vect;
1725
1726
1727    // Pour toutes les antennes connectées
1728
1729    for (int i=0; i<SocketsNumber; i++)
1730    {
1731        // On vérifie qu'elles sont encore connectées
1732
1733        if (Sockets[i].Connected)
1734        {
1735            newRA  = newRA2;
1736            newDEC = newDEC2;
1737
1738            // Dans les modes d'alignement AFFINE et TAKI, on applique la matrice de correction
1739            // sur les coordonnées horaires de l'objet visé
1740
1741            // il faut vérifier auparavant que la matrice de rotation est disponible
1742            // pour l'antenne i
1743
1744            if  (Sockets[i].AlignementAntenne->Matrice_ok)
1745            {
1746                // On est bien dans le cas de l'alignement AFFINE ou Taki
1747
1748                /* if ( Sockets[i].AlignementAntenne->MethodeAlignement ==  AFFINE ||
1749                         Sockets[i].AlignementAntenne->MethodeAlignement ==  TAKI )
1750                 {
1751                     // On crée un vecteur avec pour coordonnées
1752                     // x = Angle horaire de l'objet visé
1753                     // y = déclinaison de l'objet
1754                     // z = 1.0
1755                     // Voir la documentation pour plus d'explications sur le calcul affine/taki
1756
1757                     vect.x = VerifAngle( newRA2 + GetTSL() );
1758                     vect.y = newDEC2;
1759                     vect.z = 1.0;
1760
1761                     // Message pour l'utilisateur et les logs
1762
1763                     AfficherLog("Application de la matrice AFFINE/TAKI\n", true);
1764                     AfficherLog("Coordonnees initiales: AD = %s  Dec = %s\n", DHMS(newRA2*N180divPi, true ).c_str(),
1765                                 DHMS(newDEC2*N180divPi, false ).c_str());
1766
1767                     // On applique la matrice de transformation
1768
1769                     switch (Sockets[i].AlignementAntenne->MethodeAlignement)
1770                     {
1771                     case AFFINE :
1772                         Sockets[i].AlignementAntenne->AppliquerMatriceCorrectionAffine(&result, vect);
1773                         break;
1774                     case TAKI   :
1775                         Sockets[i].AlignementAntenne->AppliquerMatriceCorrectionTaki( &result, vect);
1776                         break;
1777                     }
1778
1779                     // On récupÚre les nouvelles coordonnées. z ne nous intéresse pas
1780
1781                     newRA  = VerifAngle(result.x - GetTSL());
1782                     newDEC = result.y;
1783
1784                     AfficherLog("Coordonnees finales: AD = %s  Dec = %s\n", DHMS(newRA*N180divPi, true ).c_str(),
1785                                 DHMS(newDEC*N180divPi, false ).c_str());
1786                 }*/
1787
1788            }
1789            else
1790            {
1791                if (Sockets[i].AlignementAntenne->AlignementEnCours != 0)
1792                {
1793                    // Si la matrice n'est pas prête, c'est que la procédure d'alignement de l'antenne i n'est pas encore achevée.
1794                    // On se contente ici d'appliquer des deltas en ascension droite et en déclinaison. Ces deltas sont envoyés de BAOcontrol
1795                    // au driver indi_BAO par l'intermédiaire du fichier AlignementAntennes.cfg
1796                    // Consultez la documentation pour comprendre le principe de fonctionnement de l'alignement et de la communication
1797                    // entre les deux programmes
1798
1799                    double az, ha, ad, de;
1800                   
1801                    int num = Sockets[i].AlignementAntenne->nbrcorrections;
1802
1803                    Sockets[i].AlignementAntenne->ad[num] = newRA2;
1804
1805                    Sockets[i].AlignementAntenne->de[num] = newDEC2;
1806
1807                    //CalculTSL();
1808
1809                    Sockets[i].AlignementAntenne->tsl[num] = GetTSL();
1810
1811                    Azimut(newRA2, newDEC2, &az, &ha);
1812
1813                    //ha = RefractionAtmospherique(ha) ;
1814
1815                    az  = VerifAngle(az + (double)delta_az * PasDeltaAz);
1816
1817                    ha += (double)delta_ha * PasDeltaHa;
1818
1819                    AzHa2ADDe( az, ha, &ad, &de );
1820
1821                    Sockets[i].AlignementAntenne->delta_ad[num] = ad;
1822
1823                    Sockets[i].AlignementAntenne->delta_de[num] = de;
1824
1825                    newRA  = ad;
1826                    newDEC = de;
1827
1828                    // if newRA et newDEC = 0 -> on sort
1829
1830                    if ( newRA == 0 && newDEC == 0) return;
1831
1832                    AfficherLog("Alignement en cours.\n", true);
1833
1834                    AfficherLog("Nouvelles Coordonnées AD =%s  Dec = %s    Ncorrections=%i\n",
1835                                DHMS(newRA*N180divPi, true).c_str(),
1836                                DHMS(newDEC*N180divPi, false).c_str(),Sockets[i].AlignementAntenne->nbrcorrections);
1837                }
1838            }
1839
1840            // Calcule la hauteur et l'azimut de la zone du ciel pointée (en fonction de la date et du lieu d'observation)
1841
1842            Azimut( newRA, newDEC, &targetAz, &targetAlt);
1843
1844            // Si la méthode d'alignement est la méthode SIMPLE, alors on doit cette fois-ci appliquer la matrice
1845            // de correction au coordonnées horizontales et non aux coordonnées horaires comme ce que nous
1846            // avons vu plus haut
1847
1848            if  (Sockets[i].AlignementAntenne->Matrice_ok /*&& Sockets[i].AlignementAntenne->MethodeAlignement == SIMPLE*/)
1849            {
1850                // AprÚs s'être assurer que nous utilisons la méthode SIMPLE et que la matrice de rotation est ok
1851
1852                AfficherLog("Application de la matrice SIMPLE (det=%10.8f)\n", Sockets[i].AlignementAntenne->Determinant(), true);
1853                AfficherLog("Coordonnees initiales: Azi = %s  Haut = %s\n", DHMS(targetAz*N180divPi, false ).c_str(),
1854                            DHMS(targetAlt*N180divPi, false ).c_str());
1855
1856                // On constitue un vecteur vect
1857                // Les coordonnées du vecteur correspondent à la position
1858                // d'un point défini par une latitude targetAlt et une longitude targetAz
1859                // sur une sphÚre de rayon 1.
1860                // On reconnaît les formules de passage des coordonnées
1861                // sphériques aux coordonnées rectangulaires
1862
1863                if (Sockets[i].AlignementAntenne->MethodeAlignement == SIMPLE)
1864                {
1865                    //TODO :: à vérifier en détails
1866
1867                    // Calcul de la hauteur minimale accessible par l'inbstrument lorsque la matrice de correction est activée
1868
1869                    double targetAltL = Sockets[i].AlignementAntenne->Motor2Alt(Sockets[i].AlignementAntenne->Alt2Motor2(HAUTMIN)) * Pidiv180;
1870
1871                    vect.x = cos(targetAltL);
1872                    vect.y = 0.0;
1873                    vect.z = sin(targetAltL);
1874
1875                    Sockets[i].AlignementAntenne->AppliquerMatriceCorrectionSimple(&result, vect);
1876
1877                    hautmin = asin(result.z) * N180divPi;
1878
1879                    AfficherLog("Hauteur  %5.0f\n", hautmin);
1880
1881                    // Calcul de la hauteur de l'objet suivi aprÚs application de la matrice de correction
1882
1883                    double targetAltC = Sockets[i].AlignementAntenne->Motor2Alt(Sockets[i].AlignementAntenne->Alt2Motor2(targetAlt * N180divPi)) * Pidiv180;
1884
1885                    vect.x = cos(targetAz) * cos(targetAltC);
1886                    vect.y = sin(targetAz) * cos(targetAltC);
1887                    vect.z = sin(targetAltC);
1888
1889                    Sockets[i].AlignementAntenne->AppliquerMatriceCorrectionSimple(&result, vect);
1890
1891
1892                    // Là on doit repasser des coordonnées rectangulaires
1893                    // aux coordonnées sphériques
1894
1895                    if (result.x != 0.0)
1896                    {
1897                        targetAz = atan( result.y / result.x );
1898
1899                        if (result.x < 0) targetAz += Pi;
1900                    }
1901                    else targetAz = Pidiv2;
1902
1903                    targetAz  = VerifAngle(targetAz);
1904
1905                    targetAlt = asin(result.z);
1906                }
1907                else
1908                {
1909                    Sockets[i].AlignementAntenne->AzHa2XY(targetAz, targetAlt, &vect.x, &vect.y);
1910
1911                    vect.z = 1.0;
1912
1913
1914
1915                    Sockets[i].AlignementAntenne->AppliquerMatriceCorrectionAffine(&result, vect);
1916
1917                    // Là on doit repasser des coordonnées rectangulaires
1918                    // aux coordonnées sphériques
1919
1920
1921
1922                    targetAz = atan(result.y/result.x);
1923                    if (result.x < 0) targetAz += Pi;
1924
1925                    targetAlt= Pidiv2 - sqrt(result.x*result.x+result.y*result.y);
1926
1927
1928                    AfficherLog("Coordonnees finales: Azi = %s  Haut = %s\n", DHMS(VerifAngle(targetAz)*N180divPi, false ).c_str(),
1929                                DHMS(targetAlt*N180divPi, false ).c_str());
1930                }
1931            }
1932
1933            // Correction de la réfraction atmosphérique
1934
1935            targetAlt = RefractionAtmospherique(targetAlt);
1936
1937            // On ajoute Pi pour que le sud soit à 0° d'azimut
1938
1939            targetAz = VerifAngle( targetAz + Pi );
1940
1941            // On convertit les angles précédents en degrés
1942
1943            targetAlt *= N180divPi;
1944            targetAz  *= N180divPi;
1945
1946            // Affichage dans les logs
1947
1948            fs_sexa(AzStr, targetAz, 2, 3600);
1949            fs_sexa(AltStr, targetAlt, 2, 3600);
1950
1951            AfficherLog("Coordonnees horizontales finales: Azi = %s  Haut= %s\n", AzStr, AltStr);
1952
1953
1954            // Conversion des deux angles en pas codeurs
1955
1956            if ( targetAlt < hautmin )
1957            {
1958                // L'objet est trop bas ( < 30°). On annule le suivi...
1959
1960                IDSetSwitch(&OnCoordSetSP, "Erreur ! L objet suivi est situe a moins de 30 deg au-dessus de l horizon. Goto annule.");
1961
1962                Suivi = false;
1963
1964                RealisationGoto = false;
1965
1966                InitAntennes();
1967
1968                return;
1969            }
1970            else
1971            {
1972                // Si la hauteur est supérieure à 90°, on doit ajouter 180° à l'azimut et corriger
1973                // la hauteur en appliquant hauteur=180°-hauteur
1974
1975                if (targetAlt > 90.0)
1976                {
1977                    targetAlt = 180.0 - targetAlt;
1978                    targetAz += 180.0;
1979                }
1980
1981                if ( targetAlt < hautmin ) targetAlt = hautmin;
1982
1983                // On applique la formule de Marc pour convertir la hauteur en nombre de pas codeur alt
1984
1985                Sockets[i].TargetPosition.y = (int) Arrondi( Sockets[i].AlignementAntenne->Alt2Motor( targetAlt ) );
1986
1987                //4000 pas pour 360° sur l'axe az
1988
1989                Sockets[i].TargetPosition.x = (int) Arrondi( targetAz * (double)NBREPASCODEURSAZ / 360.0);
1990
1991                // On ajoute les deltas en AZ et en HA pour la raquette hors procédure d'alignement
1992
1993
1994                if (Sockets[i].AlignementAntenne->AlignementEnCours == 0)
1995                {
1996                    Sockets[i].TargetPosition.x += delta_az;
1997
1998                    Sockets[i].TargetPosition.y += delta_ha;
1999
2000                    //Sockets[i].TargetPosition.x = (int) Arrondi( VerifAngle( targetAz * Pidiv180 + (double)delta_az * PasDeltaAz ) * N180divPi * (double)NBREPASCODEURSAZ / 360.0);
2001
2002                    //Sockets[i].TargetPosition.y = (int) Arrondi( Sockets[i].AlignementAntenne->Alt2Motor( targetAlt + (double)delta_ha * PasDeltaHa * N180divPi) );
2003                }
2004
2005
2006                //TODO : à vérifier
2007
2008                // est-ce que le transit de l'objet suivi va nous emmener à sortir de l'intervalle [MINAZCODEURS..MAXAZCODEURS] ?
2009
2010                AutoriserTourComplet = false;
2011
2012                if ( azmincodeur < MINAZCODEURS ) {
2013                    azmincodeur += NBREPASCODEURSAZ;
2014                    azmaxcodeur += NBREPASCODEURSAZ;
2015                    //  AutoriserTourComplet = true;
2016                    AfficherLog("azmincodeur < MINAZCODEURS\n");
2017                }
2018
2019                if ( azmaxcodeur > MAXAZCODEURS ) {
2020                    azmincodeur -= NBREPASCODEURSAZ;
2021                    azmaxcodeur -= NBREPASCODEURSAZ;
2022                    // AutoriserTourComplet = true;
2023                    AfficherLog("azmaxcodeur > MAXAZCODEURS\n");
2024                }
2025
2026                AfficherLog("Intervalle autorise pour le suivi de l objet en azimut [%i..%i]\n", azmincodeur, azmaxcodeur );
2027                AfficherLog("Position initiale en Az = %i\n", Sockets[i].TargetPosition.x);
2028
2029                if ( Sockets[i].TargetPosition.x < azmincodeur ) {
2030                    Sockets[i].TargetPosition.x += NBREPASCODEURSAZ;
2031                    AutoriserTourComplet = true;
2032                    AfficherLog("TargetPosition.x < azmincodeur\n");
2033                }
2034
2035                if ( Sockets[i].TargetPosition.x > azmaxcodeur ) {
2036                    Sockets[i].TargetPosition.x -= NBREPASCODEURSAZ;
2037                    AutoriserTourComplet = true;
2038                    AfficherLog("TargetPosition.x > azmaxcodeur\n");
2039                }
2040
2041                if ( Sockets[i].TargetPosition.x < MINAZCODEURS ) {
2042                    Sockets[i].TargetPosition.x += NBREPASCODEURSAZ;
2043                    AutoriserTourComplet = true;
2044                    AfficherLog("TargetPosition.x < MINAZCODEURS\n");
2045                }
2046
2047                if ( Sockets[i].TargetPosition.x > MAXAZCODEURS ) {
2048                    Sockets[i].TargetPosition.x -= NBREPASCODEURSAZ;
2049                    AutoriserTourComplet = true;
2050                    AfficherLog("TargetPosition.x > MAXAZCODEURS\n");
2051                }
2052
2053                if (fabs(Sockets[i].Pos.x - Sockets[i].TargetPosition.x) > MAXAZCODEURS / 2)
2054                {
2055                    AutoriserTourComplet = true;
2056                    AfficherLog("| Pos.x - TargetPosition.x | > MAXAZCODEURS / 2\n");
2057                }
2058
2059                // Message de debug
2060
2061                AfficherLog("Position finale :  Az = %i  Alt = %i\n", Sockets[i].TargetPosition.x, Sockets[i].TargetPosition.y);
2062            }
2063        }
2064    }
2065}
2066
2067
2068
2069/************************************************************************************
2070** Retourne le nombre d'antennes actuellement connectées
2071**
2072************************************************************************************/
2073
2074int BAO::AntennesConnectees()
2075{
2076    int num = 0;
2077
2078    for (int i=1; i<SocketsNumber; i++) if (Sockets[i].Connected) num++;
2079
2080    return num;
2081}
2082
2083
2084
2085/**************************************************************************************
2086** En cas de problÚme
2087** Déconnecter l'antenne utilisant le socket num
2088***************************************************************************************/
2089
2090void BAO::DeconnecterSocket(int num)
2091{
2092    if (Sockets[num].Connected) AfficherLog("Deconnexion de l antenne : %s\n", Sockets[num].IP.c_str());
2093    Sockets[num].new_sock.shutdown();
2094    Sockets[num].Connected = false;
2095    Sockets[num].IP = "";
2096}
2097
2098
2099
2100
2101/**************************************************************************************
2102** Procédure principale
2103** Elle est appelée toutes les ms
2104**
2105***************************************************************************************/
2106
2107void BAO::ISPoll()
2108{
2109    static int memSocketsNumber = -1;      // Combien y avait-il d'antennes connectées lors de l'appel précédent d'ISPoll ?
2110    static unsigned int compt   =  0;      // Compteur de la fonction ISPoll
2111
2112    struct tm date;
2113    time_t t;
2114    struct timeval tv;
2115    struct timezone tz;
2116
2117    //si pas de connexion avec le serveur d'indi -> on sort
2118
2119    if (!is_connected()) return;
2120
2121
2122    // toutes les 100 millisec, on actualise le jour julien
2123    // le temps sidéral local etc...
2124
2125    if ( compt%100 == 0 )
2126    {
2127        //Récupération de la date et de l'heure
2128
2129        time(&t);
2130        date=*gmtime(&t);
2131        gettimeofday(&tv, &tz);
2132
2133        double Annee = (double)(date.tm_year + 1900);
2134        double Mois  = (double)(date.tm_mon + 1);
2135        double Jour  = (double)date.tm_mday;
2136        double Heu   = (double)date.tm_hour;
2137        double Min   = (double)date.tm_min;
2138        double Sec   = (double)date.tm_sec+tv.tv_usec/1.0E6;
2139        double UTCP  = 0.0;//(double)date.tm_isdst;
2140
2141        // On transmet la date et l'heure à la classe Astro
2142
2143        DefinirDateHeure(Annee, Mois, Jour, Heu, Min, Sec);
2144
2145        // Puis on calcule le temps sidéral local, le JJ etc.
2146
2147        CalculTSL();
2148
2149
2150        // On charge les paramÚtres de correction des antennes toutes les demi-secondes
2151
2152        /*
2153        if ( compt%500 == 0  && tv.tv_usec/1.0E6 > 0.5 )
2154            {
2155                for (int i=1; i<SocketsNumber; i++)
2156                {
2157                    if (Sockets[i].Connected)
2158                    {
2159                        // Si l'antenne i est connectée, on charge les paramÚtres
2160                        Sockets[i].AlignementAntenne->TransmettreParametresClasseAstro(Annee, Mois, Jour, Heu, Min, Sec, Longitude, Latitude, Pression, Temp);
2161
2162                        // AfficherLog("chargement taki\n");
2163                        //  Sockets[i].AlignementAntenne->ChargementParametresAlignement(Sockets[i].IP, "/home/" + (string)getenv("USER") + "/AlignementAntennes.cfg", targetRA * 15 * Pidiv180, targetDEC * Pidiv180);
2164                    }
2165                }
2166            }*/
2167    }
2168
2169
2170
2171    // Il faut que le thread soit actif
2172
2173    if (InitThreadOK)
2174    {
2175
2176        // Nouvelle connexion sur le socket ?
2177
2178        if (SocketsNumber > memSocketsNumber)
2179        {
2180            memSocketsNumber = SocketsNumber;
2181
2182            IDSetSwitch(&ConnectSP, "Connexion de l antenne %s (Antennes connectees : %i)",
2183                        Sockets[SocketsNumber-1].IP.c_str(), AntennesConnectees());
2184
2185            Sockets[SocketsNumber-1].AlignementAntenne->TransmettreParametresClasseAstro(GetAnnee(), GetMois(), GetJour(), GetHeure(), GetMin(), GetSec(), GetLongitude(), GetLatitude(), GetPression(), GetTemperature());
2186
2187
2188            // Chargement des paramÚtres d'alignement de l'antenne
2189
2190            Sockets[SocketsNumber-1].AlignementAntenne->ChargementParametresAlignement(
2191                Sockets[SocketsNumber-1].IP,
2192                "/home/" + (string)getenv("USER") + "/AlignementAntennes.cfg",
2193                targetRA * 15 * Pidiv180,
2194                targetDEC * Pidiv180);
2195
2196        }
2197
2198
2199        /////////////////////////////////////////////////
2200        // Début des échanges avec les micro-contrÃŽleurs
2201
2202        // Analyse des réponses des micro-contrÃŽleurs
2203
2204        for (int i=1; i<SocketsNumber; i++)
2205        {
2206            if (Sockets[i].Connected)
2207            {
2208                try
2209                {
2210                    string reponse, buffereponse;
2211
2212                    // on récupÚre la réponse du micro-contrÃŽleur
2213
2214                    Sockets[i].new_sock >> reponse;
2215
2216                    // Dans le cas où plusieurs trames seraient arrivées entre deux appels de POLLMS
2217                    // les traiter successivement
2218
2219                    // d'où l'intérêt de mettre un '\n' à la fin des trames
2220                    // pour différencier une trame de la précédente
2221
2222                    int pos = reponse.find("\n");
2223
2224                    // S'il y a une réponse
2225
2226                    while ((pos != string::npos) && (reponse.length() > 1))
2227                    {
2228                        // on garde en stock la deuxiÚme partie de la trame
2229                        // pour un traitement ultérieur
2230
2231                        buffereponse = reponse.substr(pos + 1);
2232
2233                        // Partie traitée
2234
2235                        reponse = reponse.substr(0, pos);
2236
2237                        // on l'affiche dans le log
2238
2239                        AfficherLog("Reponse recue de %s : %s\n", Sockets[i].IP.c_str(), reponse.c_str());
2240
2241                        // On vérifie ici les acknowledges
2242
2243                        if ((reponse.find("ACK") != string::npos) && (reponse.find("NACK") == string::npos))
2244                        {
2245                            if (reponse.find("POSITION")  != string::npos)
2246                            {
2247                                Sockets[i].ack_pos   = true;
2248                            }
2249                            else if (reponse.find("GOTO") != string::npos)
2250                            {
2251                                Sockets[i].ack_goto  = true;
2252                            }
2253                            else if (reponse.find("PARK") != string::npos)
2254                            {
2255                                Sockets[i].ack_park  = true;
2256                            }
2257                            else if (reponse.find("ABORT")!= string::npos)
2258                            {
2259                                Sockets[i].ack_abort = true;
2260                            }
2261                        }
2262                        else
2263                        {
2264                            // Réponse à la requête POSITION
2265
2266                            if (reponse.find("POSITION") != string::npos)
2267                            {
2268                                // Il y a une erreur signalée par le micro-contrÃŽleur
2269
2270                                if (reponse.find("NACK") != string::npos)
2271                                {
2272                                    // ProblÚme concernant la commande P
2273                                    // On affiche dans la boîte indi un voyant de couleur rouge
2274                                    // et on affiche un message d'erreur
2275
2276                                    OnCoordSetSP.s = IPS_ALERT;
2277
2278                                    IDSetSwitch(&OnCoordSetSP, "ALERTE antenne %s : position de l antenne inconnue !\n",
2279                                                Sockets[i].IP.c_str());
2280                                    AfficherLog("ALERTE antenne %s : position de l antenne inconnue !\n",
2281                                                Sockets[i].IP.c_str());
2282
2283                                    // La position de l'antenne st donc inconnue
2284
2285                                    Sockets[i].PosValides = false;
2286
2287                                    // On déconnecte l'antenne
2288
2289                                    Sockets[i].Connected  = false;
2290                                }
2291                                else if (Sockets[i].ack_pos)
2292                                {
2293                                    // La position devrait être valide si on arrive ici...
2294
2295                                    Sockets[i].PosValides = ExtractPosition(reponse, &Sockets[i].Pos);
2296
2297                                    if ( Sockets[i].PosValides )
2298                                    {
2299                                        // La fonction extractPositon confirme que les positions transmises
2300                                        // par le micro-contrÃŽleur sont valides
2301
2302                                        OnCoordSetSP.s = IPS_OK;
2303
2304                                        // message dans les logs
2305
2306                                        IDSetSwitch(&OnCoordSetSP, "Antenne %s : POSITION OK  (x=%i, y=%i)\n",
2307                                                    Sockets[i].IP.c_str(), Sockets[i].Pos.x, Sockets[i].Pos.y);
2308                                    }
2309                                    else
2310                                    {
2311                                        // Erreur repérée par la fonction ExtractPosition
2312
2313                                        OnCoordSetSP.s = IPS_ALERT;
2314
2315                                        // On en informe l'utilisateur
2316
2317                                        IDSetSwitch(&OnCoordSetSP, "Antenne %s : La position n est pas valide !\n",
2318                                                    Sockets[i].IP.c_str());
2319                                        AfficherLog("Antenne %s : La position n est pas valide !\n",
2320                                                    Sockets[i].IP.c_str());
2321
2322                                    }
2323                                }
2324                            }
2325
2326                            //réponse à la requête PARK
2327
2328                            if (reponse.find("PARK") != string::npos)
2329                            {
2330                                if (reponse.find("NACK") != string::npos)
2331                                {
2332                                    // Une erreur  est retournée par le micro-contrÃŽleur concernant la commande Park
2333                                    // On affiche le voyant Park en rouge dans la boîte indi...
2334
2335                                    ParkSP.s = IPS_ALERT;
2336
2337                                    // ... et on affiche un message d'erreur
2338
2339                                    IDSetSwitch(&ParkSP, "ALERTE antenne %s : erreur PARK !\n", Sockets[i].IP.c_str());
2340                                    AfficherLog("ALERTE antenne %s : erreur ABORT !\n",  Sockets[i].IP.c_str());
2341                                }
2342                                else if (Sockets[i].ack_park && reponse.find("OK")!=string::npos)
2343                                {
2344                                    // PARK ok !
2345
2346                                    ParkSP.s = IPS_OK;
2347
2348                                    IDSetSwitch(&ParkSP, "Antenne %s : PARK OK\n",  Sockets[i].IP.c_str());
2349                                }
2350                            }
2351
2352                            //réponse à la requête ABORT
2353
2354                            if (reponse.find("ABORT") != string::npos)
2355                            {
2356                                if (reponse.find("NACK") != string::npos)
2357                                {
2358                                    // Une erreur  est retournée par le micro-contrÃŽleur concernant la commande Abort
2359                                    // On affiche le voyant Park en rouge dans la boîte indi...
2360
2361                                    AbortSlewSP.s = IPS_ALERT;
2362
2363                                    // ... et on affiche un message d'erreur
2364
2365                                    IDSetSwitch(&AbortSlewSP, "ALERTE antenne %s : erreur ABORT !\n",  Sockets[i].IP.c_str());
2366                                    AfficherLog("ALERTE antenne %s : erreur ABORT !\n",  Sockets[i].IP.c_str());
2367                                }
2368                                else if (Sockets[i].ack_abort && reponse.find("OK")!=string::npos)
2369                                {
2370                                    // OK !
2371
2372                                    AbortSlewSP.s = IPS_OK;
2373
2374                                    IDSetSwitch(&AbortSlewSP, "Antenne %s : ABORT OK\n",  Sockets[i].IP.c_str());
2375                                }
2376                            }
2377
2378                            //réponse à la requête GOTO
2379
2380                            if (reponse.find("GOTO") != string::npos)
2381                            {
2382                                if (reponse.find("NACK") != string::npos)
2383                                {
2384                                    // Une erreur  est retournée par le micro-contrÃŽleur concernant la commande Goto
2385                                    // On affiche le voyant Park en rouge dans la boîte indi...
2386
2387                                    OnCoordSetSP.s = IPS_ALERT;
2388
2389                                    // Message d'erreur
2390
2391                                    IDSetSwitch(&OnCoordSetSP, "ALERTE antenne %s : Erreur NACK GOTO ! (Retour : %s)\n",  Sockets[i].IP.c_str(), reponse.c_str());
2392                                    AfficherLog("ALERTE antenne %s : Erreur NACK GOTO ! (Retour : %s)\n",  Sockets[i].IP.c_str(), reponse.c_str());
2393                                    // On déconnecte l'antenne. Elle ne semble pas en mesure d'exécuter les ordres goto
2394
2395                                    // 02/04/2012 Le fait de recevoir un nack/eos ne nécessite pas de devoir déconnecter l'antenne
2396                                    // DeconnecterSocket(i);
2397                                }
2398                                else if (Sockets[i].ack_goto)
2399                                {
2400                                    if (reponse.find("OK") != string::npos)
2401                                    {
2402                                        // On a ici la confirmation que l'antenne 'i' a bien réalisé le goto
2403
2404                                        // On prend note
2405
2406                                        Sockets[i].GotoOk = true;
2407
2408                                        // Voyant en vert dans la boîte Indi
2409
2410                                        OnCoordSetSP.s = IPS_OK;
2411
2412                                        // Message pour l'utilisateur
2413
2414                                        IDSetSwitch(&OnCoordSetSP, "Antenne %s : GOTO OK.\n",  Sockets[i].IP.c_str());
2415
2416                                        // Fin du Goto pour toutes les antennes ?
2417                                        // On compte les antennes connectées qui ont réalisé le dernier ordre goto
2418
2419                                        int num = 0;
2420
2421                                        for (int j=1; j<SocketsNumber; j++)
2422                                        {
2423                                            if (Sockets[j].Connected)
2424                                            {
2425                                                if (Sockets[j].GotoOk) num++;
2426                                            }
2427                                        }
2428
2429                                        // Si le nombre d'antennes connectées est > 0
2430                                        // et que toutes les antennes connectées ont
2431                                        // réalisé le goto alors...
2432
2433                                        if ((num == AntennesConnectees()) && (num>0))
2434                                        {
2435                                            // C'est bon ! Tout marche bien...
2436                                            // On actualise l'AD et la Dec dans la boîte de dialogue
2437
2438                                            lastRA  = targetRA;
2439                                            lastDEC = targetDEC;
2440
2441                                            // On a fini le mouvement. Il n'y a donc plus d'étape à faire
2442                                            // dans le processus de réalisation d'un goto
2443                                            // RealisationGoto vaut donc false
2444
2445                                            RealisationGoto = false;
2446
2447                                            // Réinitialisation des paramÚtres des antennes en vue d'un prochain goto
2448
2449                                            InitAntennes();
2450
2451                                            // On dessine les voyants de la boîte de dialogue en vert
2452
2453                                            OnCoordSetSP.s = IPS_OK;
2454                                            EquatorialCoordsWNP.s = IPS_OK;
2455                                            IDSetNumber (&EquatorialCoordsWNP, NULL);
2456
2457                                            // Confirmation dans la boîte de dialogue que toutes
2458                                            // les antennes sont OK
2459
2460                                            IDSetSwitch(&OnCoordSetSP, "GOTO OK !");
2461
2462                                            UpdatedGoto = true;
2463                                        }
2464                                    }
2465                                }
2466                            }
2467                        }
2468
2469                        // On passe à la trame suivante si memreponse n'est pas vide
2470
2471                        reponse = buffereponse;
2472                        pos     = reponse.find("\n");
2473                    }
2474                }
2475                catch (SocketException& e) //Aïe
2476                {
2477                    // Une exception concerne le socket i
2478
2479                    // On déconnecte l'antenne pour plus de sécurité
2480
2481                    DeconnecterSocket(i);
2482
2483                    AfficherLog("Indi_BAO, SocketException IsPoll : ");
2484                    AfficherLog(e.description().c_str());
2485                    AfficherLog("\n");
2486                }
2487            }
2488        }
2489
2490
2491        ///////////////////////////////////////
2492        // L'utilisateur a demandé l'annulation du mouvement en cours
2493
2494        if (Abort)
2495        {
2496            // On arrête le suivi d'un objet
2497
2498            Suivi = false;
2499
2500            // On arrête l'enchaînement des actions nécessaires à la réalisation d'un goto
2501
2502            RealisationGoto = false;
2503
2504            // On envoie l'ordre ABORT à toutes les antennes
2505
2506            for (int i=1; i<SocketsNumber; i++)
2507            {
2508                if (Sockets[i].Connected)
2509                {
2510                    if (!ABORT(i)) Sockets[i].sendalertes++;
2511                }
2512            }
2513
2514            // Message à destination de l'utilisateur et des logs
2515
2516            IDSetSwitch(&OnCoordSetSP, "ABORT OK !");
2517
2518            // Réinititialisation des paramÚtres des antennes
2519
2520            InitAntennes();
2521
2522            //Pour permettre de refaire un abort
2523
2524            Abort = false;
2525        }
2526
2527        ///////////////////////////////////////
2528        // L'utilisateur a demandé de mettre les antennes au repos
2529
2530        if (Park)
2531        {
2532            // On arrête le suivi d'un objet
2533
2534            Suivi = false;
2535
2536            // On arrête l'enchaînement des actions
2537            // pour réaliser un goto
2538
2539            RealisationGoto = false;
2540
2541            // On envoie l'ordre PARK à toutes les antennes
2542
2543            for (int i=1; i<SocketsNumber; i++)
2544            {
2545                if (Sockets[i].Connected)
2546                {
2547                    if (!PARK(i)) Sockets[i].sendalertes++;
2548                }
2549            }
2550
2551            IDSetSwitch(&OnCoordSetSP, "PARK OK !");
2552
2553            // Réinititialisation des paramÚtres des antennes
2554
2555            InitAntennes();
2556
2557            // Pour permettre de refaire un park
2558
2559            Park = false;
2560        }
2561
2562
2563        ///////////////////////////////////////
2564        // Gestion du suivi
2565
2566        if ((Suivi) && (UpdatedGoto))
2567        {
2568            // Délais entre deux actualisations
2569
2570            // Actualisation toutes les 15 minutes en mode transit (par défaut)
2571
2572            double delai = ActualisationTMTransit / 3600.0 / 24.0;
2573
2574            // et 5 secs en mode tracking (par défaut)
2575
2576            if (TrackingMode == BAO_TRACKING) delai = ActualisationTMTracking / 3600.0 / 24.0;
2577
2578
2579            // On actualise la position si le délai est dépassé
2580
2581            if (GetJJ() - JJAnc > delai)
2582            {
2583                // Cette variable vaut true lorsque le goto a été réalisé
2584
2585                UpdatedGoto = false;
2586
2587                // Conversion des coordonnées en pas moteur
2588
2589                ADDEC2Motor(targetRA, targetDEC);
2590
2591                // On réinitialise les antennes en vue du goto
2592
2593                InitAntennes();
2594
2595                // On lance le processus d'actualisation du goto
2596
2597                RealisationGoto = true;
2598
2599                // On sauvegarde la date
2600
2601                JJAnc = GetJJ();
2602            }
2603
2604            //Plus d'antenne ! On arrête le suivi
2605
2606            if (AntennesConnectees() == 0)
2607            {
2608                if ( compt % 1000 == 0)
2609                {
2610                    IDSetSwitch(&OnCoordSetSP, "Erreur ! Plus d antennes connectees !");
2611
2612                    if (Suivi) AfficherLog("Arrêt du suivi !");
2613
2614                    RealisationGoto=false;
2615
2616                    Suivi=false;
2617
2618                    InitAntennes();
2619                }
2620            }
2621        }
2622
2623
2624
2625        // Exécution de la procédure complÚte d'un goto :
2626        // 1Úre étape : envoi de la commande POSITION à toutes les antennes
2627        // 2Úme étape : Vérification de l'acknowledge de la commande POSITION pour chaque antenne
2628        // 3Úme étape : Les positions retournées par les antennes sont-elles valides ?
2629        // 4Úme étape : Si oui, envoie de la commande goto à toutes les antennes
2630        // 5Úme étape : est-ce que toutes les antennes ont envoyé l'acknowledge de la commande goto ?
2631        // 6Úme étape : les antennes ont toutes répondu GOTO OK !
2632
2633        if (RealisationGoto)
2634        {
2635            for (int i=1; i<SocketsNumber; i++)
2636            {
2637                // On ne parle qu'aux antennes connectées
2638
2639                if (Sockets[i].Connected)
2640                {
2641                    // En fonction de l'étage de la réalisation d'un goto par l'antenne i
2642
2643                    switch (Sockets[i].etape)
2644                    {
2645
2646                        // Envoi de la commande POS
2647
2648                    case 0 :
2649                    {
2650                        // On doit initialiser l'acknowledge à false
2651
2652                        Sockets[i].ack_pos    = false;
2653
2654                        // et considérer que la position de l'antenne n'est pas valide
2655
2656                        Sockets[i].PosValides = false;
2657
2658                        // avant d'envoyer l'ordre POSITION
2659
2660                        if (!POSITION(i)) Sockets[i].sendalertes++;
2661
2662                        // On passe à l'étage suivante
2663
2664                        Sockets[i].etape++;
2665                    }
2666                    break;
2667
2668
2669                    // A-ton bien reçu l'ack POS ?
2670
2671                    case 1 :
2672                    {
2673                        if (Sockets[i].ack_pos)
2674                        {
2675                            // tout marche bien. On a bien reçu l'acknowledge de l'antenne i
2676
2677                            // Il n'y a donc aucune attente supplémentaire pour recevoir la réponse
2678                            Sockets[i].AttenteExecution = 0;
2679
2680                            // Pas d'anomalie à consigner
2681                            Sockets[i].AnomaliesExecution = 0;
2682
2683                            // On passe à l'étape suivante
2684                            Sockets[i].etape++;
2685
2686                            //permet de rester sur le même socket malgré la boucle -> plus rapide
2687                            i--;
2688                        }
2689                        else
2690                        {
2691                            // On réitÚre l'ordre précédent si rien ne se passe
2692
2693                            // On garde une trace de l'anomalie
2694
2695                            Sockets[i].AttenteExecution++;
2696
2697                            if (Sockets[i].AttenteExecution > MAXATTENTE)
2698                            {
2699                                // on recommence depuis le début.
2700                                // Peut-être que l'antenne n'a pas reçu l'ordre ?
2701                                Sockets[i].etape = 0;
2702                                Sockets[i].AttenteExecution = 0;
2703
2704                                // Pas de réponse. On consigne une erreur grave
2705                                Sockets[i].AnomaliesExecution++;
2706                            }
2707
2708                            // Les erreurs graves s'accumulent. Pas de réponse aprÚs plusieurs minutes
2709                            // -> Il faut déconnecter l'antenne
2710                            if (Sockets[i].AnomaliesExecution > MAXANOMALIES)
2711                            {
2712                                //Voyant en rouge dans la boîte Indi
2713
2714                                OnCoordSetSP.s = IPS_ALERT;
2715
2716                                //Message à l'attention de l'utilisateur
2717
2718                                IDSetSwitch(&OnCoordSetSP, "Erreur sur l antenne %s : pas d acknowledge recu apres l ordre POSITION. \
2719Fin du suivi. Verifier les connexions.\n", Sockets[i].IP.c_str());
2720                                AfficherLog("Erreur sur l antenne %s : pas d acknowledge recu apres l ordre POSITION. \
2721Fin du suivi. Verifier les connexions.\n", Sockets[i].IP.c_str());
2722
2723                                Suivi=false;
2724
2725                                RealisationGoto = false;
2726
2727                                InitAntennes();
2728
2729                                // On déconnecte l'antenne
2730
2731                                // DeconnecterSocket(i);
2732                            }
2733                        }
2734                    }
2735                    break;
2736
2737
2738                    //Les valeurs retournées pas la commande POSITION sont-elles valides ?
2739
2740                    case 2 :
2741                    {
2742                        if (Sockets[i].PosValides)
2743                        {
2744                            // Tout vas bien
2745                            // On ne consigne aucune anomalie
2746
2747                            Sockets[i].AttenteExecution = 0;
2748                            Sockets[i].AnomaliesExecution = 0;
2749
2750                            //On passe à l'étape suivante
2751
2752                            Sockets[i].etape++;
2753                        }
2754                        else
2755                        {
2756                            // on réitÚre l'ordre précédent si rien ne se passe
2757
2758                            Sockets[i].AttenteExecution++;
2759
2760                            if (Sockets[i].AttenteExecution > MAXATTENTE)
2761                            {
2762                                // on attend encore la réponse posvalides
2763
2764                                Sockets[i].etape = 2;
2765                                Sockets[i].AttenteExecution = 0;
2766
2767                                // On consigne une erreur grave. L'antenne tarde à répondre
2768
2769                                Sockets[i].AnomaliesExecution++;
2770                            }
2771
2772                            // Aucune réponse de l'antenne depuis plusieurs minutes
2773                            // On la déconnecte
2774
2775                            if (Sockets[i].AnomaliesExecution > MAXANOMALIES)
2776                            {
2777                                // Voyant en rouge
2778
2779                                OnCoordSetSP.s = IPS_ALERT;
2780
2781                                //Message d'erreur
2782
2783                                IDSetSwitch(&OnCoordSetSP, "Erreur sur l antenne %s : la position retournee n est pas valide. \
2784Fin du suivi. Verifier les connexions.\n", Sockets[i].IP.c_str());
2785                                AfficherLog("Erreur sur l antenne %s : la position retournee n est pas valide. \
2786Fin du suivi. Verifier les connexions.\n", Sockets[i].IP.c_str());
2787
2788                                Suivi=false;
2789
2790                                RealisationGoto = false;
2791
2792                                InitAntennes();
2793
2794                                //Déconnexion de l'antenne
2795
2796                                // DeconnecterSocket(i);
2797                            }
2798                        }
2799                    }
2800                    break;
2801
2802
2803
2804                    // On peut remarquer qu'il n'y a pas de case 3 ici...
2805                    // L'envoie de la commande goto se fait portant pendant l'étape 3 en dehors du switch
2806                    // Voir le code plus loin...
2807
2808
2809                    // A-ton reçu l'acknowledge de la commande goto ?
2810
2811                    case 4 :
2812                    {
2813                        if (Sockets[i].ack_goto)
2814                        {
2815                            Sockets[i].AttenteExecution = 0;
2816                            Sockets[i].AnomaliesExecution = 0;
2817                            Sockets[i].etape++; // on passe à l'étape suivante
2818                        }
2819                        else
2820                        {
2821                            // on réitÚre l'ordre précédent si rien ne se passe
2822                            Sockets[i].AttenteExecution++;
2823
2824                            if (Sockets[i].AttenteExecution > MAXATTENTE)
2825                            {
2826                                // On prolonge l'attente pour recevoir l'acknowledge du goto
2827                                Sockets[i].etape = 4;
2828                                Sockets[i].AttenteExecution = 0;
2829                                Sockets[i].AnomaliesExecution++;
2830                            }
2831
2832                            if (Sockets[i].AnomaliesExecution > MAXANOMALIES)
2833                            {
2834                                OnCoordSetSP.s = IPS_ALERT;
2835
2836                                IDSetSwitch(&OnCoordSetSP, "Erreur sur l antenne %s : pas d acknowledge recu apres l ordre GOTO. Fin du suivi. Verifier les connexions.\n", Sockets[i].IP.c_str());
2837                                AfficherLog("Erreur sur l antenne %s : pas d acknowledge recu apres l ordre GOTO. Fin du suivi. Verifier les connexions.\n", Sockets[i].IP.c_str());
2838
2839                                Suivi=false;
2840
2841                                RealisationGoto = false;
2842
2843                                InitAntennes();
2844
2845                                // DeconnecterSocket(i);
2846                            }
2847                        }
2848                    }
2849                    break;
2850
2851
2852                    //  Confirmation goto ok ?
2853
2854                    case 5 :
2855                    {
2856                        if (Sockets[i].GotoOk)
2857                        {
2858                            // On a bien reçu Goto Ok pour l'antenne i !
2859
2860                            Sockets[i].AttenteExecution = 0;
2861                            Sockets[i].AnomaliesExecution = 0;
2862
2863                            //On passe à l'étape suivante
2864                            Sockets[i].etape++;
2865                        }
2866                        else
2867                        {
2868                            // on réitÚre l'ordre précédent si rien ne se passe
2869                            Sockets[i].AttenteExecution++;
2870
2871                            if (Sockets[i].AttenteExecution > MAXATTENTE)
2872                            {
2873                                // On prolonge l'attente afin de recevoir un GOTO OK
2874
2875                                Sockets[i].etape = 5;
2876                                Sockets[i].AttenteExecution = 0;
2877                                Sockets[i].AnomaliesExecution++;
2878                            }
2879
2880                            // On déconnecte l'antenne s'il n'y a pas de confirmation du goto au bout de 2 minutes
2881                            if (Sockets[i].AnomaliesExecution > MAXANOMALIESGOTO)
2882                            {
2883                                // Alerte sur une antenne
2884                                OnCoordSetSP.s = IPS_ALERT;
2885
2886                                // Message d'erreur
2887                                IDSetSwitch(&OnCoordSetSP, "Erreur sur l antenne %s : l antenne n a pas renvoye GOTO/OK. Fin du suivi. Verifier les connexions.\n", Sockets[i].IP.c_str());
2888                                AfficherLog("Erreur sur l antenne %s : l antenne n a pas renvoye GOTO/OK. Fin du suivi. Verifier les connexions.\n", Sockets[i].IP.c_str());
2889
2890                                Suivi=false;
2891
2892                                RealisationGoto = false;
2893
2894                                InitAntennes();
2895
2896
2897                                //Déconnexion de l'antenne
2898                                // DeconnecterSocket(i);
2899                            }
2900                        }
2901                    }
2902                    break;
2903                    }
2904                }
2905            }
2906        }
2907
2908
2909        ///////////////////////////////////////
2910        // Réalisation d'un goto - traitement de l'étape 3
2911        // On place cette partie du traitement en dehors du switch et de la boucle
2912        // pour pouvoir envoyer les gotos à toutes les antennes lorsque l'on a la confirmation
2913        // qu'elles sont toutes prêtes à exécuter cet ordre (être à l'étape 3 pour un socket)
2914        // -> meilleure synchronisation
2915
2916        // On compte les antennes rendues à l'étape 3 et qui attendent
2917
2918        int num = 0;
2919
2920        for (int i=1; i<SocketsNumber; i++)
2921        {
2922            // Uniquement les antennes connectées
2923
2924            if (Sockets[i].Connected)
2925            {
2926                if (Sockets[i].etape == 3) num++; // num antennes sont prêtes à recevoir l'ordre GOTO
2927            }
2928        }
2929
2930        // Toutes les antennes connectées sont prêtes à recevoir l'ordre goto
2931
2932        if ((num == AntennesConnectees()) && (num>0))
2933        {
2934            for (int i=1; i<SocketsNumber; i++ )
2935            {
2936                if (Sockets[i].Connected)
2937                {
2938                    // On envoie l'ordre
2939
2940                    Sockets[i].ack_goto = false;
2941                    Sockets[i].AttenteExecution = 0;
2942                    Sockets[i].AnomaliesExecution = 0;
2943
2944                    if (!GOTO(i, Sockets[i].TargetPosition.x - Sockets[i].Pos.x, Sockets[i].TargetPosition.y - Sockets[i].Pos.y )) Sockets[i].sendalertes++;
2945
2946                    Sockets[i].etape++;
2947                }
2948            }
2949        }
2950
2951        ///////////////////////////////////////
2952        // Opération garbage
2953        // Détection d'anomalies sur le socket i.
2954        // Ce n'est pas normal ici. Il faut déconnecte l'antenne
2955
2956        for (int i=1; i<SocketsNumber; i++)
2957        {
2958            if (Sockets[i].Connected)
2959            {
2960                if (Sockets[i].sendalertes > 0)
2961                {
2962                    // Alarme dans la boîte Indi
2963
2964                    OnCoordSetSP.s = IPS_ALERT;
2965
2966                    // Erreur dans les logs
2967
2968                    IDSetSwitch(&OnCoordSetSP, "Erreur sur l antenne %s : Fin du suivi. Vérifier les connexions.\n", Sockets[i].IP.c_str());
2969                    AfficherLog("Erreur sur l antenne %s : Fin du suivi. Vérifier les connexions.\n", Sockets[i].IP.c_str());
2970
2971                    Suivi=false;
2972
2973                    RealisationGoto = false;
2974
2975                    InitAntennes();
2976
2977                    // Déconnexion antenne
2978
2979                    // DeconnecterSocket(i);
2980                }
2981            }
2982        }
2983    }
2984
2985    //incrémentation du compteur
2986
2987    compt++;
2988}
2989
2990
2991
2992/**************************************************************************************
2993** Mode transit ou tracking
2994**
2995***************************************************************************************/
2996
2997bool BAO::process_coords()
2998{
2999    int posaz = 0;
3000
3001    switch (currentSet)
3002    {
3003        // Transit
3004
3005    case BAO_TRANSIT:
3006
3007        // Éteindre les voyants dans la boîte de dialogue Indi
3008        EquatorialCoordsWNP.s = IPS_BUSY;
3009        AbortSlewSP.s = IPS_IDLE;
3010        ParkSP.s = IPS_IDLE;
3011
3012        IDSetNumber (&EquatorialCoordsWNP, NULL);
3013        IDSetSwitch (&AbortSlewSP, NULL);
3014        IDSetSwitch (&ParkSP, NULL);
3015
3016        // On cherche l'azimut de l'objet lorsque celui-ci passera en-dessous de 30°
3017        // Cette recherche est nécessaire pour optimiser le suivi et éviter
3018        // les rotations inutiles
3019
3020        for (int i=1; i<SocketsNumber; i++ )
3021        {
3022            if ((Sockets[i].Connected) && (Sockets[i].PosValides))
3023            {
3024                posaz = Sockets[i].Pos.x;
3025                break;
3026            }
3027        }
3028
3029        RechercheAzimutFinSuivi(targetRA * 15.0 * Pidiv180, targetDEC * Pidiv180, posaz, &azmincodeur, &azmaxcodeur);
3030
3031        // On prépare les antennes pour le prochain goto
3032
3033        InitAntennes();
3034
3035        // On garde la trace du début du Goto pour enchaîner les actualisations
3036
3037        JJAnc = GetJJ();
3038
3039        // Conversion des coordonnées horaires en pas moteur
3040
3041        ADDEC2Motor(targetRA, targetDEC);
3042
3043        // Mode transit activé
3044
3045        TrackingMode = BAO_TRANSIT;
3046
3047        // On suit un objet
3048
3049        Suivi = true;
3050
3051        // Aucun goto n'a été encore réalisé
3052
3053        UpdatedGoto = false;
3054
3055        // Mais on se lance dans la réalisation d'un goto
3056
3057        RealisationGoto = true;
3058
3059        break;
3060
3061        // Tracking
3062
3063    case BAO_TRACKING:
3064
3065        // Éteindre les voyants dans la boîte de dialogue Indi
3066
3067        EquatorialCoordsWNP.s = IPS_BUSY;
3068        AbortSlewSP.s = IPS_IDLE;
3069        ParkSP.s = IPS_IDLE;
3070
3071        IDSetNumber (&EquatorialCoordsWNP, NULL);
3072        IDSetSwitch (&AbortSlewSP, NULL);
3073        IDSetSwitch (&ParkSP, NULL);
3074
3075        // On cherche l'azimut de l'objet lorsque celui-ci passera en-dessous de 30°
3076        // Cette recherche est nécessaire pour optimiser le suivi et éviter
3077        // les rotations inutiles
3078
3079        for (int i=1; i<SocketsNumber; i++ )
3080        {
3081            if ((Sockets[i].Connected) && (Sockets[i].PosValides))
3082            {
3083                posaz = Sockets[i].Pos.x;
3084                break;
3085            }
3086        }
3087
3088        RechercheAzimutFinSuivi(targetRA * 15.0 * Pidiv180, targetDEC * Pidiv180, posaz, &azmincodeur, &azmaxcodeur);
3089
3090        InitAntennes();
3091
3092        JJAnc = GetJJ();
3093
3094        ADDEC2Motor(targetRA, targetDEC);
3095
3096        TrackingMode = BAO_TRACKING;
3097
3098        Suivi = true;
3099
3100        UpdatedGoto = false;
3101
3102        RealisationGoto = true;
3103
3104        break;
3105    }
3106
3107    return true;
3108}
3109
3110
3111
3112/**************************************************************************************
3113** Connexion / Déconnexion avec le télescope
3114**
3115***************************************************************************************/
3116
3117void BAO::connect_telescope()
3118{
3119    switch (ConnectSP.sp[0].s)
3120    {
3121    case ISS_ON:
3122
3123        // Etats des voyants
3124
3125        ConnectS[0].s = ISS_ON;
3126        ConnectS[1].s = ISS_OFF;
3127        ConnectSP.s = IPS_OK;
3128        IDSetSwitch (&ConnectSP, "BAORadio is online. Retrieving basic data...");
3129
3130        // On lance le thread !
3131        // Exit ne faudra true que lorsque sera venu le moment de sortir !
3132
3133        Exit = false;
3134
3135        // Création du thread
3136
3137        if (pthread_create (&th1, NULL, (void*(*)(void*))LancementThread, this) < 0)
3138        {
3139            AfficherLog("pthread_create error for threadSocket\n");
3140        }
3141
3142        break;
3143
3144    case ISS_OFF:
3145
3146        // Etat des voyants
3147
3148        ConnectS[0].s = ISS_OFF;
3149        ConnectS[1].s = ISS_ON;
3150        ConnectSP.s = IPS_IDLE;
3151        IDSetSwitch (&ConnectSP, "BAORadio is offline.");
3152        AfficherLog("Telescope is offline.");
3153
3154        // On déconnecte tous les sockets
3155
3156        for (int i=0; i<MAXHOSTNAME; i++)
3157        {
3158            DeconnecterSocket(i);
3159        }
3160
3161        // init
3162
3163        InitAntennes();
3164
3165        SocketsNumber = 1;
3166
3167        // On sort du thread
3168
3169        // On dit au thread de sortir de la boucle
3170
3171        Exit = true;
3172
3173        // Désactiver la boucle de traitement des messages des ISPOLL
3174
3175        InitThreadOK = false;
3176
3177        // On laisse 1 s au thread pour sortir de la boucle
3178
3179        sleep(1);
3180
3181        // On détruit le thread
3182
3183        pthread_join (th1, NULL);
3184
3185        // on sort du programme
3186
3187        exit(EXIT_SUCCESS);
3188
3189        break;
3190    }
3191}
3192
3193
3194
3195
3196/**************************************************************************************
3197**  Envoie une commande sur le socket numsocket
3198**
3199***************************************************************************************/
3200
3201bool BAO::COMMANDE(int numsocket, char* Commande, char* Params)
3202{
3203    char chaine[MAXCARACTERES];
3204
3205    try
3206    {
3207        sprintf(chaine, "%s%s\n", Commande, Params);
3208
3209        Sockets[numsocket].new_sock << chaine;
3210
3211        AfficherLog("Commande envoyee a %s: %s", Sockets[numsocket].IP.c_str(), chaine);
3212    }
3213    catch (SocketException& e)
3214    {
3215        // Consignation d'une anomalie sur le socket
3216
3217        DeconnecterSocket(numsocket);
3218
3219        AfficherLog("Indi_BAO, COMMANDE exception : ");
3220        AfficherLog(e.description().c_str());
3221        AfficherLog("\n");
3222
3223        return false;
3224    }
3225
3226    return true;
3227}
3228
3229
3230/**************************************************************************************
3231** Commande POSITION
3232**
3233***************************************************************************************/
3234
3235bool BAO::POSITION(int numsocket)
3236{
3237    return COMMANDE(numsocket, (char*)"P", (char*)"");
3238}
3239
3240/**************************************************************************************
3241** Commande PARK
3242**
3243***************************************************************************************/
3244
3245bool BAO::PARK(int numsocket)
3246{
3247    return COMMANDE(numsocket, (char*)"Z", (char*)"");
3248}
3249
3250/**************************************************************************************
3251** Commande ABORT
3252**
3253***************************************************************************************/
3254
3255bool BAO::ABORT(int numsocket)
3256{
3257    return COMMANDE(numsocket, (char*)"A", (char*)"");
3258}
3259
3260
3261/**************************************************************************************
3262** Commande GOTO
3263**
3264***************************************************************************************/
3265
3266bool BAO::GOTO(int numsocket, int deltaAz, int deltaAlt)
3267{
3268    char Params[MAXCARACTERES];
3269    char sensAz;
3270    char sensAlt;
3271
3272    sensAlt = 1;
3273    sensAz  = 1;
3274
3275    // gestion des signes des deltas
3276
3277    if ( deltaAz < 0 )
3278    {
3279        deltaAz = -deltaAz;
3280        sensAz  = 0;
3281    }
3282
3283    if ( deltaAlt < 0 )
3284    {
3285        deltaAlt = -deltaAlt;
3286        sensAlt  = 0;
3287    }
3288
3289    // Vérification du nombre de pas à faire au niveau de l'axe azimut
3290    // Rappel : un tour complet autour de l'axe az fait 4000 pas codeur (voir #define NBREPASCODEURSAZ dans BAO.h)
3291
3292    // problÚme 1 : si deltaAz > à un demi-tours - soit 2000 pas codeur alors
3293    // on fait le trajet en sens inverse pour aller plus vite
3294
3295    // problÚme 2 : Passage au méridien
3296    // on se situe à quelques secondes de degrés avant le sud par exemple (nb de pas 3995 par exemple)
3297    // et on franchit le méridien (nb de pas codeur = 5 par exemple)
3298    // On risque alors de faire un tour complet en sens inverse pour rattraper l'objet -> à éviter
3299
3300    // ne pas faire des tours complets en Az pour rien...
3301
3302    // Corrections sup pour rester dans l'intervalle [-1693.. 3867]
3303
3304    AfficherLog("deltaAz1=%i\n", deltaAz, true);
3305
3306    while (deltaAz > NBREPASCODEURSAZ) deltaAz -= NBREPASCODEURSAZ;
3307
3308
3309    //TODO : a verifier en details
3310
3311    if ( !AutoriserTourComplet )
3312    {
3313
3314        // Doit résoudre tous les problÚmes concernant l'azimut...
3315
3316        if (deltaAz > NBREPASCODEURSAZ / 2 )
3317        {
3318            deltaAz = NBREPASCODEURSAZ - deltaAz;
3319
3320            sensAz = 1 - sensAz;
3321        }
3322    }
3323
3324    AfficherLog("deltaAz2=%i\n", deltaAz, true);
3325
3326    //on envoie les coordonnées au driver
3327
3328    (sensAz == 1 ) ? sensAz='f' : sensAz='b';
3329
3330    (sensAlt == 1 ) ? sensAlt='f': sensAlt='b';
3331
3332    sprintf(Params, "%c%04i%c%04i", sensAz, deltaAz, sensAlt, deltaAlt);
3333
3334    return COMMANDE(numsocket, (char*)"G", Params);
3335}
3336
3337
3338
3339/**************************************************************************************
3340** Les fonctions qui suivent sont nécessaires pour construire le pilote Indi_BAO
3341** Elles sont appelées par le noyau d'Indi
3342***************************************************************************************/
3343
3344/**************************************************************************************
3345** Initialisation du pilote BAO
3346***************************************************************************************/
3347
3348void ISInit()
3349{
3350    //Il ne faut exécuter la fonction qu'une seule fois
3351
3352    static int isInit = 0;
3353
3354    if (isInit) return;
3355
3356    if (telescope.get() == 0) telescope.reset(new BAO());
3357
3358    isInit = 1;
3359
3360    //initialisation du timer
3361
3362    IEAddTimer (POLLMS, ISPoll, NULL);
3363}
3364
3365
3366void ISGetProperties (const char *dev)
3367{
3368    ISInit();
3369
3370    telescope->ISGetProperties(dev);
3371}
3372
3373void ISNewSwitch (const char *dev, const char *name, ISState *states, char *names[], int n)
3374{
3375    ISInit();
3376    telescope->ISNewSwitch(dev, name, states, names, n);
3377}
3378
3379void ISNewText (const char *dev, const char *name, char *texts[], char *names[], int n)
3380{
3381    ISInit();
3382    telescope->ISNewText(dev, name, texts, names, n);
3383}
3384
3385void ISNewNumber (const char *dev, const char *name, double values[], char *names[], int n)
3386{
3387    ISInit();
3388    telescope->ISNewNumber(dev, name, values, names, n);
3389}
3390
3391void ISNewBLOB (const char *dev, const char *name, int sizes[], int blobsizes[], char *blobs[], char *formats[], char *names[], int n)
3392{
3393    INDI_UNUSED(dev);
3394    INDI_UNUSED(name);
3395    INDI_UNUSED(sizes);
3396    INDI_UNUSED(blobsizes);
3397    INDI_UNUSED(blobs);
3398    INDI_UNUSED(formats);
3399    INDI_UNUSED(names);
3400    INDI_UNUSED(n);
3401}
3402
3403void ISSnoopDevice (XMLEle *root)
3404{
3405    INDI_UNUSED(root);
3406}
3407
3408void ISPoll (void *p)
3409{
3410    INDI_UNUSED(p);
3411
3412    telescope->ISPoll();
3413
3414    IEAddTimer (POLLMS, ISPoll, NULL);
3415}
3416
3417
3418/**************************************************************************************
3419**
3420***************************************************************************************/
3421
3422int BAO::get_switch_index(ISwitchVectorProperty *sp)
3423{
3424    for (int i=0; i < sp->nsp ; i++)
3425        if (sp->sp[i].s == ISS_ON)
3426            return i;
3427
3428    return -1;
3429}
3430
3431
3432
3433/**************************************************************************************
3434**
3435***************************************************************************************/
3436
3437bool BAO::is_connected()
3438{
3439    // return (ConnectSP.sp[0].s == ISS_ON);
3440    return (ConnectSP.s == IPS_OK);
3441}
3442
3443/**************************************************************************************
3444**
3445***************************************************************************************/
3446void BAO::connection_lost()
3447{
3448    ConnectSP.s = IPS_IDLE;
3449    IDSetSwitch(&ConnectSP, "The connection to the telescope is lost.");
3450    AfficherLog("arret");
3451    return;
3452}
3453
3454/**************************************************************************************
3455**
3456***************************************************************************************/
3457void BAO::connection_resumed()
3458{
3459    ConnectS[0].s = ISS_ON;
3460    ConnectS[1].s = ISS_OFF;
3461    ConnectSP.s = IPS_OK;
3462
3463    IDSetSwitch(&ConnectSP, "The connection to the telescope has been resumed.");
3464}
3465
3466
3467/**************************************************************************************
3468** GÚre les erreurs de communication avec la boîte Indi
3469***************************************************************************************/
3470/*
3471void BAO::handle_error(INumberVectorProperty *nvp, int err, const char *msg)
3472{
3473    nvp->s = IPS_ALERT;
3474
3475    // If the error is a time out, then the device doesn't support this property
3476    if (err == -2)
3477    {
3478        nvp->s = IPS_ALERT;
3479        IDSetNumber(nvp, "Device timed out. Current device may be busy or does not support %s. Will retry again.", msg);
3480    }
3481    else
3482        // Changing property failed, user should retry.
3483        IDSetNumber( nvp , "%s failed.", msg);
3484
3485    fault = true;
3486}*/
3487
3488
3489/**************************************************************************************
3490**
3491***************************************************************************************/
3492/*
3493void BAO::correct_fault()
3494{
3495    fault = false;
3496    IDMessage(mydev, "Telescope is online.");
3497}*/
3498
3499
3500
3501
Note: See TracBrowser for help on using the repository browser.