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

Last change on this file since 623 was 619, checked in by frichard, 13 years ago
File size: 59.0 KB
RevLine 
[504]1/*
[501]2#############################
3##
4## BAORadio Indi driver
5## Franck RICHARD
[504]6## franckrichard033@gmail.com
[619]7## Décembre 2011
[501]8##
9#############################
[504]10*/
[501]11
12#include "BAO.h"
13
14
15auto_ptr<BAO> telescope(0);
16
[619]17const int  POLLMS = 1;                                  // Period of update, 1 ms.
[501]18
[504]19const char *mydev = "BAO";                              // Name of our device.
[501]20
21const char *BASIC_GROUP    = "Main Control";            // Main Group
22const char *OPTIONS_GROUP  = "Options";                 // Options Group
23
24/* Handy Macros */
25//#define currentRA     EquatorialCoordsRN[0].value
26//#define currentDEC    EquatorialCoordsRN[1].value
27#define targetRA        EquatorialCoordsWN[0].value
28#define targetDEC       EquatorialCoordsWN[1].value
29
30
31static void ISPoll(void *);
32
[504]33void* LancementThread(BAO * appli);
[501]34
35
36/**************************************************************************************
[504]37** Initialisation de la classe BAO
[501]38***************************************************************************************/
39
40BAO::BAO()
41{
[490]42    init_properties();
[501]43
[504]44    // télescope en état IDLE
45    ConnectSP.s    = IPS_IDLE;
[501]46
[504]47    // derniÚre actualisation
48    lastRA         = 0.0;
49    lastDEC        = 0.0;
[490]50    JJAnc          = 0.0;
[501]51
[504]52    currentSet     =  0;
53    lastSet        = -1;
54    SocketsNumber  =  1;
55    TrackingMode   =  1;
[501]56
[504]57    // délais en sec entre deux actualisations de la
58    // position dans les modes transit et tracking
[501]59
[504]60    ActualisationTM1 = 15.0 * 60.0;
[495]61    ActualisationTM2 = 5.0;
[501]62
[504]63    UpdateGoto      = true;
64    InitThreadOK    = false;
65    ActualisationPosition = false;
66    Abort           = false;
67    Park            = false;
[619]68    Suivi           = false;
[504]69    Exit            = false;
[501]70
71
[504]72    // initialisation des sockets (Antennes)
[619]73   
[490]74    for (int i=0; i<MAXHOSTNAME; i++)
75    {
[619]76        Sockets[i].Connected = false;
77        Sockets[i].IP = "";
78               
79        Sockets[i].Delta.x = 0.0;
80        Sockets[i].Delta.y = 0.0;
[490]81    }
[501]82
[504]83    // initialisations supplémentaires
[619]84   
[490]85    InitAntennes();
[501]86
[504]87    // Numéro de version
[619]88   
[490]89    IDLog("Initilizing from BAO device...\n");
[619]90    IDLog("Driver Version: 2011-12-02\n");
[501]91
[504]92    //connect_telescope();
[501]93}
94
[504]95
[501]96/**************************************************************************************
[504]97** Destructeur
98** Lorsque l'on lance indi_BAO depuis indiserver dans un terminal
[619]99** Le destructeur ne semble jamais être atteint lorsque l'on sort... A vérifier
[501]100***************************************************************************************/
101BAO::~BAO()
102{
[619]103    Exit = true;
[504]104    sleep(1);
105    pthread_join (th1, NULL);
[501]106}
107
[504]108
[619]109/************************************************************************************
110* Initialisation des paramÚtres des antennes
111*
112************************************************************************************/
113void BAO::InitAntennes()
114{
115    for (int i=0; i<MAXHOSTNAME; i++)
116    {
117        Sockets[i].status             = 0;
118        Sockets[i].sendalertes        = 0;
119        Sockets[i].AttenteExecution   = 0;
120        Sockets[i].AnomaliesExecution = 0;
121        Sockets[i].etape              = 0;
[504]122
[619]123        Sockets[i].ack_status = false;
124        Sockets[i].ack_pos    = false;
125        Sockets[i].ack_park   = false;
126        Sockets[i].ack_abort  = false;
127        Sockets[i].ack_goto   = false;
128
129        Sockets[i].PosValides = false;
130        Sockets[i].GotoOk     = false;
131    }
132}
133
134
[501]135/**************************************************************************************
136** Initialisation des boutons et des zones d'affichage dans la boîte de dialogue INDI
137***************************************************************************************/
[504]138
[501]139void BAO::init_properties()
140{
[490]141    // Connection
142    IUFillSwitch(&ConnectS[0], "CONNECT", "Connect", ISS_OFF);
143    IUFillSwitch(&ConnectS[1], "DISCONNECT", "Disconnect", ISS_ON);
144    IUFillSwitchVector(&ConnectSP, ConnectS, NARRAY(ConnectS), mydev, "CONNECTION", "Connection", BASIC_GROUP, IP_RW, ISR_1OFMANY, 60, IPS_IDLE);
[501]145
[490]146    // Coord Set
147    IUFillSwitch(&OnCoordSetS[0], "TRANSIT", "Transit", ISS_ON);
148    IUFillSwitch(&OnCoordSetS[1], "TRACKING", "Tracking", ISS_OFF);
149    IUFillSwitchVector(&OnCoordSetSP, OnCoordSetS, NARRAY(OnCoordSetS), mydev, "ON_COORD_SET", "On Set", BASIC_GROUP, IP_RW, ISR_1OFMANY, 0, IPS_IDLE);
[501]150
[490]151    // Abort
152    IUFillSwitch(&AbortSlewS[0], "ABORT", "Abort", ISS_OFF);
153    IUFillSwitchVector(&AbortSlewSP, AbortSlewS, NARRAY(AbortSlewS), mydev, "ABORT_MOTION", "Abort", BASIC_GROUP, IP_RW, ISR_ATMOST1, 0, IPS_IDLE);
[501]154
[490]155    // Park
156    IUFillSwitch(&ParkS[0], "PARK", "Park", ISS_OFF);
157    IUFillSwitchVector(&ParkSP, ParkS, NARRAY(ParkS), mydev, "", "Park", BASIC_GROUP, IP_RW, ISR_ATMOST1, 0, IPS_IDLE);
[501]158
[490]159    // Object Name
160    IUFillText(&ObjectT[0], "OBJECT_NAME", "Name", "--");
161    IUFillTextVector(&ObjectTP, ObjectT, NARRAY(ObjectT), mydev, "OBJECT_INFO", "Object", BASIC_GROUP, IP_RW, 0, IPS_IDLE);
[501]162
[490]163    // Equatorial Coords - SET
164    IUFillNumber(&EquatorialCoordsWN[0], "RA", "RA  H:M:S", "%10.6m",  0., 24., 0., 0.);
165    IUFillNumber(&EquatorialCoordsWN[1], "DEC", "Dec D:M:S", "%10.6m", -90., 90., 0., 0.);
[492]166    IUFillNumberVector(&EquatorialCoordsWNP, EquatorialCoordsWN, NARRAY(EquatorialCoordsWN), mydev, "EQUATORIAL_EOD_COORD_REQUEST" , "Equatorial JNow", BASIC_GROUP, IP_WO, 0, IPS_IDLE);
[501]167
[490]168    // Geographic coord - SET
169    IUFillNumber(&GeographicCoordsWN[0], "LAT", "Lat  D", "%10.6m",  -90., 90., 0., 0.);
170    IUFillNumber(&GeographicCoordsWN[1], "LONG", "Long D", "%10.6m", 0., 360., 0., 0.);
[492]171    IUFillNumberVector(&GeographicCoordsWNP, GeographicCoordsWN, NARRAY(GeographicCoordsWN), mydev, "GEOGRAPHIC_COORD" , "Geographic coords", OPTIONS_GROUP, IP_WO, 0, IPS_IDLE);
[501]172
[495]173    // Actualisation - SET
174    IUFillNumber(&ActualisationN1[0], "DELAY", "Transit mode delay (Sec)", "%10.6m",  0., 3600., 0., 0.);
175    IUFillNumberVector(&ActualisationNP1, ActualisationN1, NARRAY(ActualisationN1), mydev, "DELAY1" , "", OPTIONS_GROUP, IP_WO, 0, IPS_IDLE);
[501]176
[495]177    IUFillNumber(&ActualisationN2[0], "DELAY", "Tracking mode delay (Sec)", "%10.6m",  0., 3600., 0., 0.);
178    IUFillNumberVector(&ActualisationNP2, ActualisationN2, NARRAY(ActualisationN2), mydev, "DELAY2" , "", OPTIONS_GROUP, IP_WO, 0, IPS_IDLE);
[504]179}
[501]180
181
182/**************************************************************************************
183** Initialisation de la boîte de dialogue INDI (suite)
184***************************************************************************************/
[504]185
[501]186void BAO::ISGetProperties(const char *dev)
187{
188
[490]189    if (dev && strcmp (mydev, dev))
[501]190        return;
191
[490]192    // Main Control
193    IDDefSwitch(&ConnectSP, NULL);
194    IDDefText(&ObjectTP, NULL);
195    IDDefNumber(&EquatorialCoordsWNP, NULL);
196    IDDefNumber(&GeographicCoordsWNP, NULL);
197    IDDefSwitch(&OnCoordSetSP, NULL);
198    IDDefSwitch(&AbortSlewSP, NULL);
199    IDDefSwitch(&ParkSP, NULL);
[501]200
[490]201    // Options
[495]202    IDDefNumber(&ActualisationNP1, NULL);
203    IDDefNumber(&ActualisationNP2, NULL);
[619]204}
[501]205
[619]206
207/**************************************************************************************
208** Initialisation des vecteurs INDI
209***************************************************************************************/
210
211void BAO::reset_all_properties()
212{
213    ConnectSP.s                 = IPS_IDLE;
214    OnCoordSetSP.s              = IPS_IDLE;
215    AbortSlewSP.s               = IPS_IDLE;
216    ParkSP.s                    = IPS_IDLE;
217    ObjectTP.s                  = IPS_IDLE;
218    EquatorialCoordsWNP.s       = IPS_IDLE;
219    GeographicCoordsWNP.s       = IPS_IDLE;
220    ActualisationNP1.s          = IPS_IDLE;
221    ActualisationNP2.s          = IPS_IDLE;
222
223    IUResetSwitch(&OnCoordSetSP);
224    IUResetSwitch(&AbortSlewSP);
225    IUResetSwitch(&ParkSP);
226
227    OnCoordSetS[0].s = ISS_ON;
228    ConnectS[0].s = ISS_OFF;
229    ConnectS[1].s = ISS_ON;
230
231    IDSetSwitch(&ConnectSP, NULL);
232    IDSetSwitch(&OnCoordSetSP, NULL);
233    IDSetSwitch(&AbortSlewSP, NULL);
234    IDSetSwitch(&ParkSP, NULL);
235    IDSetText(&ObjectTP, NULL);
236    IDSetNumber(&EquatorialCoordsWNP, NULL);
237    IDSetNumber(&GeographicCoordsWNP, NULL);
238    IDSetNumber(&ActualisationNP1, NULL);
239    IDSetNumber(&ActualisationNP2, NULL);
[501]240}
241
[504]242
[501]243/**************************************************************************************
[619]244** En cas de changement de texte dans la boîte de dialogue (par exemple : changement du
245** nom de l'objet) alors suivre l'objet...
246** Cette fonction n'est pas encore utilisée
[501]247***************************************************************************************/
[504]248
[501]249void BAO::ISNewText (const char *dev, const char *name, char *texts[], char *names[], int n)
250{
[490]251    // Ignore if not ours
252    if (strcmp (dev, mydev))
[501]253        return;
254
[490]255    if (is_connected() == false)
256    {
[501]257        IDMessage(mydev, "Error ! Please connect before issuing any commands.");
258        reset_all_properties();
259        return;
[490]260    }
[501]261
[490]262    // ===================================
263    // Object Name
264    // ===================================
265    if (!strcmp (name, ObjectTP.name))
266    {
[501]267        if (IUUpdateText(&ObjectTP, texts, names, n) < 0)
268            return;
269
270        ObjectTP.s = IPS_OK;
271        IDSetText(&ObjectTP, NULL);
272        return;
[490]273    }
[501]274}
275
[504]276
[501]277/**************************************************************************************
278** En cas de changement d'une valeur numérique dans la boîte de dialogue Indi
[619]279** Exemple : longitude, latitude, ar, dec etc...) -> prendre en compte les modifications
[504]280**
[501]281***************************************************************************************/
[504]282
[501]283void BAO::ISNewNumber (const char *dev, const char *name, double values[], char *names[], int n)
284{
285
[490]286    // Ignore if not ours
287    if (strcmp (dev, mydev))
[501]288        return;
289
[490]290    if (is_connected() == false)
291    {
[501]292        IDMessage(mydev, "Error ! BAO is offline. Please connect before issuing any commands.");
293        reset_all_properties();
294        return;
[490]295    }
[501]296
297
[490]298    // ===================================
299    // Geographic  Coords
300    // ===================================
301    if (!strcmp (name, GeographicCoordsWNP.name))
302    {
[501]303        int i=0, nset=0, error_code=0;
304
305        Latitude=0.0;
306        Longitude=0.0;
307
308        for (nset = i = 0; i < n; i++)
309        {
310            INumber *eqp = IUFindNumber (&GeographicCoordsWNP, names[i]);
311            if (eqp == &GeographicCoordsWN[0])
312            {
313                Latitude = values[i];
314                nset += Latitude >= -90.0 && Latitude <= 90.0;
315
[504]316                Latitude *= Pidiv180;
[501]317            }
318            else if (eqp == &GeographicCoordsWN[1])
319            {
320                Longitude = values[i];
321                nset += Longitude >= 0.0 && Longitude <= 360.0;
322
[504]323                Longitude *= -Pidiv180;
[501]324            }
325        }
326
[504]327        // Si la longitude et la latitude sont correctes
[619]328        // on envoie les coordonnées à la classe Astro
[501]329        if (nset == 2)
330        {
331            //Vérification
332            //IDLog("Geographic : RA %5.2f - DEC %5.2f\n", Latitude, Longitude);
333
334            GeographicCoordsWNP.s = IPS_OK;
335            IDSetNumber(&GeographicCoordsWNP, NULL);
336        }
337        else
338        {
339            GeographicCoordsWNP.s = IPS_ALERT;
340            IDSetNumber(&GeographicCoordsWNP, "Latitude or Longitude missing or invalid");
341
342            Latitude=0.0;
343            Longitude=0.0;
344        }
345
[504]346        DefinirLongitudeLatitude(Longitude, Latitude);
347
[501]348        return;
[490]349    }
[501]350
351
[490]352    // ===================================
353    // Equatorial Coords
354    // ===================================
355    if (!strcmp (name, EquatorialCoordsWNP.name))
356    {
[501]357        int i=0, nset=0, error_code=0;
358        double newRA =0, newDEC =0;
359
360        for (nset = i = 0; i < n; i++)
361        {
362            INumber *eqp = IUFindNumber (&EquatorialCoordsWNP, names[i]);
363            if (eqp == &EquatorialCoordsWN[0])
364            {
365                newRA = values[i];
366                nset += newRA >= 0 && newRA <= 24.0;
367            }
368            else if (eqp == &EquatorialCoordsWN[1])
369            {
370                newDEC = values[i];
371                nset += newDEC >= -90.0 && newDEC <= 90.0;
372            }
373        }
374
375
[504]376        // si les coordonnées de l'objet sont correctes
[501]377        if (nset == 2)
378        {
379            char RAStr[32], DecStr[32];
380            double targetAZ, targetAlt;
381
[504]382            targetRA  = newRA;
383            targetDEC = newDEC;
384
[501]385            fs_sexa(RAStr, newRA, 2, 3600);
386            fs_sexa(DecStr, newDEC, 2, 3600);
387
388            IDLog("We received JNow RA %s - DEC %s\n", RAStr, DecStr);
389
390            // on convertit les coordonnées équatoriales de la zone du ciel observée
391            // en unités de codeurs des moteurs
392
393            ADDEC2Motor(newRA, newDEC);
394
395            if (process_coords() == false)
396            {
397                EquatorialCoordsWNP.s = IPS_ALERT;
398                IDSetNumber(&EquatorialCoordsWNP, NULL);
399            }
400        }
401        else
402        {
403            EquatorialCoordsWNP.s = IPS_ALERT;
404            IDSetNumber(&EquatorialCoordsWNP, "Error ! RA or Dec missing or invalid");
405        }
406
407        return;
[495]408    }
[501]409
[495]410    // ===================================
411    // Actualisation
412    // ===================================
413    if (!strcmp (name, ActualisationNP1.name))
414    {
[501]415        int i=0, nset=0, error_code=0;
416        double newAct1 =0;
417
418        for (nset = i = 0; i < n; i++)
419        {
420            INumber *eqp = IUFindNumber (&ActualisationNP1, names[i]);
421            if (eqp == &ActualisationN1[0])
422            {
423                newAct1 = values[i];
424
425                if (newAct1 >= 0.0 && newAct1 <= 3600.0)
426                {
[504]427                    ActualisationTM1 = newAct1;
[501]428
429                    ActualisationNP1.s = IPS_OK;
430                    IDSetNumber(&ActualisationNP1, NULL);
431                }
432                else
433                {
434                    ActualisationNP1.s = IPS_ALERT;
435                    IDSetNumber(&ActualisationNP1, "Error ! Delay invalid");
436                }
437            }
438        }
[495]439    }
[501]440
[495]441    if (!strcmp (name, ActualisationNP2.name))
442    {
[501]443        int i=0, nset=0, error_code=0;
444        double newAct2 =0;
445
446        for (nset = i = 0; i < n; i++)
447        {
448            INumber *eqp = IUFindNumber (&ActualisationNP2, names[i]);
449            if (eqp == &ActualisationN2[0])
450            {
451                newAct2 = values[i];
452
453                if (newAct2 >= 0.0 && newAct2 <= 3600.0)
454                {
[504]455                    ActualisationTM2 = newAct2;
[501]456
457                    ActualisationNP2.s = IPS_OK;
458                    IDSetNumber(&ActualisationNP2, NULL);
459                }
460                else
461                {
462                    ActualisationNP2.s = IPS_ALERT;
463                    IDSetNumber(&ActualisationNP2, "Error ! Delay invalid");
464                }
465            }
466        }
[504]467    }
[501]468}
469
[504]470
[501]471/**************************************************************************************
472** L'utilisateur clique sur l'un des boutons de la boîte Indi
473***************************************************************************************/
[504]474
[501]475void BAO::ISNewSwitch (const char *dev, const char *name, ISState *states, char *names[], int n)
476{
[490]477    // ignore if not ours //
478    if (strcmp (mydev, dev))
[501]479        return;
480
[490]481    // ===================================
482    // Connect Switch
483    // ===================================
484    if (!strcmp (name, ConnectSP.name))
485    {
[501]486        if (IUUpdateSwitch(&ConnectSP, states, names, n) < 0)
487            return;
488
489        connect_telescope();
[504]490
[501]491        return;
[490]492    }
[501]493
[490]494    if (is_connected() == false)
495    {
[501]496        IDMessage(mydev, "Error ! BAORadio is offline. Please connect before issuing any commands.");
497        reset_all_properties();
498        return;
[490]499    }
[501]500
[490]501    // ===================================
502    // Coordinate Set
503    // ===================================
504    if (!strcmp(name, OnCoordSetSP.name))
505    {
[501]506        if (IUUpdateSwitch(&OnCoordSetSP, states, names, n) < 0)
507            return;
508
509        currentSet = get_switch_index(&OnCoordSetSP);
510        OnCoordSetSP.s = IPS_OK;
511        IDSetSwitch(&OnCoordSetSP, NULL);
[490]512    }
[501]513
[490]514    // ===================================
515    // Abort slew
516    // ===================================
517    if (!strcmp (name, AbortSlewSP.name))
518    {
[501]519        Abort=true;
520
521        IUResetSwitch(&AbortSlewSP);
522
[504]523        if (EquatorialCoordsWNP.s == IPS_OK)
[501]524        {
[504]525            AbortSlewSP.s = IPS_OK;
[619]526            EquatorialCoordsWNP.s = IPS_IDLE;
[504]527            ObjectTP.s = IPS_IDLE;
[501]528
[504]529            IDSetSwitch(&ConnectSP, "Envoi de la commande Abort\n");
530            IDSetNumber(&EquatorialCoordsWNP, NULL);
531            IDSetText(&ObjectTP, NULL);
[501]532        }
[504]533
[501]534        return;
[490]535    }
[501]536
537
[490]538    // ===================================
539    // Park
540    // ===================================
541    if (!strcmp (name, ParkSP.name))
542    {
[501]543        Park=true;
544
545        IUResetSwitch(&ParkSP);
546
[504]547        if (EquatorialCoordsWNP.s == IPS_OK)
[501]548        {
[504]549            AbortSlewSP.s = IPS_OK;
[619]550            EquatorialCoordsWNP.s = IPS_IDLE;
[504]551            ObjectTP.s = IPS_IDLE;
[501]552
[504]553            IDSetSwitch(&ConnectSP, "Envoi de la commande Park\n");
554            IDSetNumber(&EquatorialCoordsWNP, NULL);
555            IDSetText(&ObjectTP, NULL);
[501]556        }
[504]557
[501]558        return;
[490]559    }
[501]560}
561
562
[504]563
[501]564/**************************************************************************************
[504]565** Gestion du thread
[619]566** permet de suivre la connexion/déconnexion des antennes toutes les secondes
[501]567**
[619]568** l'utilisation d'un thread permet de contourner le problÚme de la fonction accept
569** qui est bloquante.
[501]570***************************************************************************************/
571
[504]572void *BAO::pThreadSocket ()
[501]573{
[504]574    do
575    {
576        try
577        {
578            server.accept( Sockets[SocketsNumber].new_sock );
[501]579
[504]580            Sockets[SocketsNumber].IP = server.recupip(Sockets[SocketsNumber].new_sock);
581
582            Sockets[SocketsNumber++].Connected = true;
583
584            InitThreadOK = true;
585        }
586        catch ( SocketException& e )
587        {
588            /*IDLog("Indi_BAO, pThreadSocket exception : ");
589            IDLog(e.description().c_str());
590            IDLog("\n");*/
591        }
[619]592       
593        sleep(1); // faire une pause pour éviter de consommer trop de temps CPU -> à vérifier
[504]594    }
595    while (!Exit);
596
597    pthread_exit (0);
[501]598}
599
[504]600
601
[501]602/**************************************************************************************
[504]603** Astuce pour lancer le thread depuis la classe BAO
[501]604**
605***************************************************************************************/
[504]606
607void* LancementThread(BAO * appli)
[501]608{
[504]609    appli->pThreadSocket();
[501]610
[504]611    return 0;
[501]612}
613
614
615/**************************************************************************************
[619]616** Extraction de la position de l'antenne aprÚs l'envoi de la commande P
[504]617** Le retour de la commande P est POSITION/valeur_az/valeur_alt/
618** ExtractPosition retourne donc Valeur_az et Valeur_alt
[501]619***************************************************************************************/
620
[504]621bool BAO::ExtractPosition(string str, Position *result)
[501]622{
[504]623    string str2;
[501]624
[490]625    int pos = str.find("/");
[501]626
[492]627    if (pos != string::npos)
[490]628    {
[504]629        str2 = str.substr(pos + 1);
[501]630
631        pos = str2.find("/");
632
633        if (pos != string::npos)
634        {
[504]635            result->x = atol(str2.substr(0, pos).c_str());
[501]636
[504]637            result->y = atol(str2.substr(pos + 1).c_str());
638           
639            return true;
640        }       
641    } 
[501]642
[619]643    IDLog((str +" failed !\n").c_str());
[504]644
645    return false;
[501]646}
647
648
649
650/************************************************************************************
[504]651* cette procédure convertit les coordonnées équatoriales de l'objet visé
[501]652* en unités de codeurs des paraboles (nb de tours des deux axes moteurs depuis la position PARK)
653************************************************************************************/
[504]654
[501]655void BAO::ADDEC2Motor(double newRA, double newDEC)
656{
[490]657    double targetAz;
658    double targetAlt;
659    char AzStr[32];
660    char AltStr[32];
[501]661
[504]662
[619]663    // Calcule la hauteur et l'azimut de la zone du ciel pointée (en fonction de la date et du lieu d'observation)
[501]664
[504]665    Azimut( newRA * 15.0 * Pidiv180, newDEC * Pidiv180, &targetAz, &targetAlt);
666   
[619]667    // Correction de la réfraction atmosphérique
[504]668   
669    targetAlt = RefractionAtmospherique(targetAlt);
[501]670
[619]671    // Petit calcul pour faire en sorte que le sud soit à 0° d'azimut
[504]672
673    targetAz = VerifAngle( targetAz + Pi );
674
[619]675    // On convertit les angles précédents en degrés
[501]676
[492]677    targetAlt *= N180divPi;
[619]678    targetAz  *= N180divPi;
[501]679
[490]680    // Affichage dans les logs
[501]681
[490]682    fs_sexa(AzStr, targetAz, 2, 3600);
683    fs_sexa(AltStr, targetAlt, 2, 3600);
[501]684
[619]685    IDLog("Horizontal coords : Az = %s     Alt = %s\n", AzStr, AltStr);
[501]686
687
[504]688    //Conversion des deux angles en pas codeurs
[501]689
[619]690    if ( targetAlt < 30.0 )
[499]691    {
[504]692        // L'objet est trop bas (<30°). On annule le suivi...
[501]693
694        IDSetSwitch(&OnCoordSetSP, "Erreur ! L objet suivi est situe a moins de 30° au-dessus de l horizon. Goto annule.");
695
[504]696        Suivi = false;
[501]697
[504]698        ActualisationPosition = false;
[501]699
700        InitAntennes();
[499]701    }
[504]702    else
703    {
[619]704        // Si la hauteur est supérieure à 90°, on doit ajouter 180° à l'azimut et corriger
705        // la hauteur en appliquant hauteur=180°-hauteur
[501]706
[504]707        if (targetAlt > 90.0)
708        {
709            targetAlt = 180.0 - targetAlt;
710            targetAz += 180.0;
711        }
712
713        // On applique la formule de Marc pour convertir la hauteur en nombre de pas codeur alt
714
715        double I0 = 81.0;
[619]716        double I2 = 128279.4 - 129723.4 * sin( (targetAlt - 20.2345) * Pidiv180 );
[504]717
718        double Codalt = (sqrt(I2) - I0) / 0.078947;
719
720
721        TargetPosition.y = (int) Arrondi(Codalt);
722
723        //4000 pas pour 360° sur l'axe az
724
725        TargetPosition.x = (int) Arrondi( targetAz * 4000.0 / 360.0);
726
[619]727        IDLog("Nbre de pas codeurs Az = %i        Alt = %i\n", TargetPosition.x, TargetPosition.y);
[504]728    }
[501]729}
730
731
[619]732/**************************************************************************************
733** Le fichier file existe-t-il et n'est-il pas vide ?
734**************************************************************************************/
[501]735
[619]736bool BAO::is_readable( const std::string & file ) 
737{ 
738    std::ifstream fichier( file.c_str() ); 
739    if (fichier.fail()) return false;
740   
741    // sauvegarder la position courante
742    long pos = fichier.tellg();
743    // se placer en fin de fichier
744    fichier.seekg( 0 , std::ios_base::end );
745    // récupérer la nouvelle position = la taille du fichier
746    long size = fichier.tellg() ;
747    // restaurer la position initiale du fichier
748    fichier.seekg( pos,  std::ios_base::beg ) ;
749    return size ;
750}
751
752
753/**************************************************************************************
754** Chargement des paramÚtres d'alignement des antennes
755**************************************************************************************/
756
757bool BAO::ChargementParametresAlignement(string fileName)
[501]758{
[619]759    string value;
760   
761    stringstream os;
762   
763    char *delta_az = NULL;
764   
765    char *delta_ha = NULL;
766       
767    if (!is_readable(fileName)) return false;
768     
769    //IDLog("Chargement du fichier d alignement des antennes %s\n", fileName.c_str());
770     
771    //Chargement des corrections des antennes
772   
773    for (int i=0; i<SocketsNumber; i++)
774    {
775        if (Sockets[i].Connected)
776        {
777            os << "Alignement antenne ip x.x.x." << Sockets[i].IP.substr(Sockets[i].IP.rfind(".")+1);
[501]778
[619]779            value="delta_az";
[501]780
[619]781            if (readINI((char*)os.str().c_str(), (char*)value.c_str(), &delta_az,  (char*)fileName.c_str()))
782
783            value="delta_ha";
784
785            if (readINI((char*)os.str().c_str(), (char*)value.c_str(), &delta_ha,  (char*)fileName.c_str()))
786
787            if (delta_az && delta_ha)
788            {
789               // Si les corrections de l'antenne i ont été modifiées depuis le démarrage du programme
790               // -> on les applique...
791               if (Sockets[i].Delta.x != atol(delta_az) || Sockets[i].Delta.y != atol(delta_ha))
792               {
793                  Sockets[i].Delta.x = atol(delta_az);
794
795                  Sockets[i].Delta.y = atol(delta_ha);
796
797                  IDLog("Correction antenne ip %s  deltaAz=%i   deltaHa=%i\n", Sockets[i].IP.c_str(), Sockets[i].Delta.x, Sockets[i].Delta.y);
798               }
799            }
800
801            if (delta_az) {
802                delete [] delta_az;
803                delta_az=NULL;
804            }
805
806            if (delta_ha) {
807                delete [] delta_ha;
808                delta_ha=NULL;
809            }
810
811            os.str("");
812        }
813    }
814   
815    return true;
[501]816}
817
818
819/************************************************************************************
[619]820* Retourne le nombre d'antennes connectées
821*
[501]822************************************************************************************/
[619]823
824int BAO::AntennesConnectees()
[501]825{
[619]826    int num = 0;
[501]827
[619]828    for (int i=1; i<SocketsNumber; i++) if (Sockets[i].Connected) num++;
[501]829
[619]830    return num;
[501]831}
832
833
834/**************************************************************************************
[504]835** En cas de problÚme
836** Déconnecter l'antenne utilisant le socket num
837***************************************************************************************/
838
839void BAO::DeconnecterSocket(int num)
840{
841    IDLog("Deconnexion de l antenne : %s\n", Sockets[num].IP.c_str());
842    Sockets[num].new_sock.shutdown();
843    Sockets[num].Connected = false;
844    Sockets[num].IP = "";
845}
846
847
848/**************************************************************************************
[501]849** Procédure principale
[504]850** Elle est appelée toutes les ms
[501]851***************************************************************************************/
[504]852
[501]853void BAO::ISPoll()
854{
[619]855    static int memSocketsNumber = -1;      // Combien y avait-il d'antennes connectées lors de l'appel précédent d'ISPoll ?
856    static unsigned int compt   =  0;      // Compteur de la fonction ISPoll
[501]857
[490]858    struct tm date;
859    time_t t;
[492]860    struct timeval tv;
861    struct timezone tz;
[501]862
[504]863    //si pas de connexion avec le seveur d'indi -> on sort
864
[619]865    if (!is_connected()) return;
[501]866
867
[504]868    // toutes les 100 millisec, on actualise le jour julien
869    // le temps sidéral local etc...
[501]870
[504]871    if ( compt%100 == 0 )
[492]872    {
[501]873        //Récupération de la date et de l'heure
874
875        time(&t);
876        date=*gmtime(&t);
877        gettimeofday(&tv, &tz);
878
[504]879        double Annee=(double)(date.tm_year+1900);
880        double Mois=(double)(date.tm_mon+1);
881        double Jour=(double)date.tm_mday;
882        double Heu=(double)date.tm_hour;
883        double Min=(double)date.tm_min;
884        double Sec=(double)date.tm_sec+tv.tv_usec/1.0E6;
885        double UTCP=0.0;//(double)date.tm_isdst;
[501]886
[504]887        // On transmet la date et l'heure à la classe Astro
[501]888
[504]889        DefinirDateHeure(Annee, Mois, Jour, Heu, Min, Sec);
[501]890
[619]891        //Puis on calule le temps sidéral local, le JJ etc.
[504]892
[501]893        CalculTSL();
[493]894    }
[619]895   
896    // On chargement les paramÚtres de corrections des antennes toutes les secondes
897   
898    if ( compt%1000 == 0 ) ChargementParametresAlignement("/home/" + (string)getenv("USER") + "/AlignementAntennes.cfg");
[501]899
900
[504]901    // Il faut que le thread soit actif
[501]902
[504]903    if (InitThreadOK)
[493]904    {
[501]905
[619]906        // Nouvelle connexion sur le socket ?
[501]907
[504]908        if (SocketsNumber > memSocketsNumber)
[501]909        {
[504]910            memSocketsNumber = SocketsNumber;
[501]911
912            IDSetSwitch(&ConnectSP, "Connexion de l antenne %s. (Antennes connectees : %i)",
913                        Sockets[SocketsNumber-1].IP.c_str(), AntennesConnectees());
914        }
915
916
[504]917        /////////////////////////////////////////////////
[501]918        // Début des échanges avec les microcontrÃŽleurs
919
920        // Analyse des réponses des microcontrÃŽleurs
921
[504]922        for (int i=1; i<SocketsNumber; i++)
[501]923        {
[504]924            if (Sockets[i].Connected)
[501]925            {
[504]926                try
927                {
928                    string reponse, buffereponse;
[501]929
[504]930                    // on récupÚre la réponse du microcontrÃŽleur
[501]931
[504]932                    Sockets[i].new_sock >> reponse;
[501]933
[504]934                    // Dans le cas où plusieurs trames seraient arrivées entre deux appels de POLLMS
935                    // les traiter successivement
[501]936
[504]937                    // d'où l'intérêt de mettre un '\n' à la fin des trames
938                    // pour différencier une trame de la précédente
[501]939
[619]940                    int pos = reponse.find("\n");
[501]941
[504]942                    // S'il y a une réponse
[501]943
[504]944                    while ((pos != string::npos) && (reponse.length() > 1))
945                    {
[619]946                        // on garde en stock la deuxiÚme partie de la trame
947                        // pour un traitement ultérieur
[504]948                        buffereponse = reponse.substr(pos + 1);
[501]949
[504]950                        // Partie traitée
951                        reponse = reponse.substr(0, pos);
952                       
[619]953                        IDLog("Reponse recue de %s : %s\n", Sockets[i].IP.c_str(), reponse.c_str());
[501]954
[619]955                        // On vérifie ici les acknowledges
[504]956                        if ((reponse.find("ACK") != string::npos) && (reponse.find("NACK") == string::npos))
[501]957                        {
[504]958                            if (reponse.find("POSITION")  != string::npos)
[501]959                            {
[504]960                                Sockets[i].ack_pos=true;
[501]961                            }
[504]962                            else if (reponse.find("GOTO") != string::npos)
[501]963                            {
[504]964                                Sockets[i].ack_goto=true;
[501]965                            }
[504]966                            else if (reponse.find("PARK") != string::npos)
[501]967                            {
[504]968                                Sockets[i].ack_park=true;
[501]969                            }
[504]970                            else if (reponse.find("ABORT")!= string::npos)
[501]971                            {
[504]972                                Sockets[i].ack_abort=true;
[501]973                            }
[504]974                        }
975                        else
976                        {
977                            //réponse à la requête POSITION
[501]978
[504]979                            if (reponse.find("POSITION") != string::npos)
[501]980                            {
[504]981                                if (reponse.find("NACK") != string::npos)
982                                {
[619]983                                    //problÚme concernant la commande P
[504]984                                    OnCoordSetSP.s = IPS_ALERT;
985                                    IDSetSwitch(&OnCoordSetSP, "ALERTE antenne %s : position de l antenne inconnue !\n",
986                                                Sockets[i].IP.c_str());
987                                    Sockets[i].PosValides = false;
988                                    // Si la position de l'antenne est inconnue, on déconnecte l'antenne
989                                    Sockets[i].Connected  = false;
990                                }
991                                else if (Sockets[i].ack_pos)
992                                {                             
993                                    if ( Sockets[i].PosValides = (ExtractPosition(reponse, &Sockets[i].Pos) == true) )
994                                    {
995                                      OnCoordSetSP.s = IPS_OK;
996                                      IDSetSwitch(&OnCoordSetSP, "Antenne %s : POSITION OK  (x=%i, y=%i)\n",
997                                                Sockets[i].IP.c_str(), Sockets[i].Pos.x, Sockets[i].Pos.y);
998                                    }
999                                    else
1000                                    {
1001                                      OnCoordSetSP.s = IPS_ALERT;
1002                                      IDSetSwitch(&OnCoordSetSP, "Antenne %s : La position n est pas valide !\n",
1003                                                Sockets[i].IP.c_str());
1004                                    }
1005                                     
1006                                }
[501]1007                            }
1008
[504]1009                            //réponse à la requête PARK
1010
1011                            if (reponse.find("PARK") != string::npos)
[501]1012                            {
[504]1013                                if (reponse.find("NACK") != string::npos)
1014                                {
1015                                    ParkSP.s = IPS_ALERT;
1016                                    IDSetSwitch(&ParkSP, "ALERTE antenne %s : erreur PARK !\n", Sockets[i].IP.c_str());
1017                                }
1018                                else if (Sockets[i].ack_park && reponse.find("OK")!=string::npos)
1019                                {
1020                                    ParkSP.s = IPS_OK;
1021                                    IDSetSwitch(&ParkSP, "Antenne %s : PARK OK\n",  Sockets[i].IP.c_str());
1022                                }
[501]1023                            }
1024
[504]1025                            //réponse à la requête ABORT
1026
1027                            if (reponse.find("ABORT") != string::npos)
[501]1028                            {
[504]1029                                if (reponse.find("NACK") != string::npos)
1030                                {
1031                                    AbortSlewSP.s = IPS_ALERT;
1032                                    IDSetSwitch(&AbortSlewSP, "ALERTE antenne %s : erreur ABORT !\n",  Sockets[i].IP.c_str());
1033                                }
1034                                else if (Sockets[i].ack_abort && reponse.find("OK")!=string::npos)
1035                                {
1036                                    AbortSlewSP.s = IPS_OK;
1037                                    IDSetSwitch(&AbortSlewSP, "Antenne %s : ABORT OK\n",  Sockets[i].IP.c_str());
1038                                }
1039
[501]1040                            }
[504]1041
1042                            //réponse à la requête GOTO
1043
1044                            if (reponse.find("GOTO") != string::npos)
[501]1045                            {
[504]1046                                if (reponse.find("NACK") != string::npos)
[501]1047                                {
[504]1048                                    OnCoordSetSP.s = IPS_ALERT;
1049                                    IDSetSwitch(&OnCoordSetSP, "ALERTE antenne %s : Erreur GOTO !\n",  Sockets[i].IP.c_str());
1050                                    DeconnecterSocket(i);
1051                                }
1052                                else if (Sockets[i].ack_goto)
1053                                {
1054                                    if (reponse.find("OK") != string::npos)
1055                                    {
[619]1056                                        // On a ici la confirmation que l'antenne 'i' a bien réalisé
[504]1057                                        // le goto
[501]1058
[504]1059                                        // On prend note
[501]1060
[504]1061                                        Sockets[i].GotoOk = true;
[501]1062
[504]1063                                        // Message pour l'utilisateur
1064                                       
1065                                        OnCoordSetSP.s = IPS_OK;
1066                                        IDSetSwitch(&OnCoordSetSP, "Antenne %s : GOTO OK.\n",  Sockets[i].IP.c_str());
[501]1067
[504]1068                                        // Fin du Goto pour toutes les antennes ?
[501]1069
[504]1070                                        int num=0;
[501]1071
[504]1072                                        for (int j=1; j<SocketsNumber; j++)
1073                                        {
1074                                          if (Sockets[j].Connected)
1075                                            {
1076                                                if (Sockets[j].GotoOk) num++;
1077                                            }
1078                                        }
[501]1079
[504]1080                                        if ((num == AntennesConnectees()) && (num>0))
[501]1081                                        {
[504]1082                                            // C'est bon ! Tout marche bien...
1083                                            // On actualise l'AR et la dec dans la boîte de dialogue
[501]1084
[504]1085                                            lastRA  = targetRA;
1086                                            lastDEC = targetDEC;
[501]1087
[504]1088                                            // On a fini le mouvement. On attend le prochain goto...
1089
1090                                            ActualisationPosition=false;
1091
[619]1092                                            // Réinitialisation des paramÚtres des antennes en vue d'un prochain goto
[504]1093
1094                                            InitAntennes();
1095
[619]1096                                            // On dessine les voyants de la boîte de dialogue en vert
1097                                            OnCoordSetSP.s = IPS_OK;
1098                                            EquatorialCoordsWNP.s = IPS_OK;
1099                                            IDSetNumber (&EquatorialCoordsWNP, NULL);
[504]1100
1101                                            // Confirmation dans la boîte de dialogue que toutes
[619]1102                                            // les antennes sont OK         
[504]1103                                            OnCoordSetSP.s = IPS_OK;
1104                                            IDSetSwitch(&OnCoordSetSP, "GOTO OK !");
[619]1105                                           
1106                                            UpdateGoto=true;
[504]1107                                        }                                       
[501]1108                                    }
1109                                }
1110                            }
1111                        }
1112
[504]1113                        // On passe à la trame suivante si memreponse n'est pas vide
[501]1114
[504]1115                        reponse=buffereponse;
1116                        pos=reponse.find("\n");
1117                    }
[501]1118                }
[504]1119                catch (SocketException& e) //Aïe
1120                {
1121                    DeconnecterSocket(i);
[501]1122
[504]1123                    IDLog("Indi_BAO, SocketException IsPoll : ");
1124                    IDLog(e.description().c_str());
1125                    IDLog("\n");
[501]1126                }
1127            }
1128        }
1129
1130
[504]1131        ///////////////////////////////////////
[619]1132        // L'utilisateur a demandé l'annulation du mouvement en cours
[501]1133
1134        if (Abort)
1135        {
[504]1136            // On arrête le suivi d'un objet
[501]1137
[504]1138            Suivi = false;
[501]1139
[504]1140            // On arrête l'enchaînement des actions
1141            // pour réaliser un goto
1142
1143            ActualisationPosition = false;
1144
1145            // On envoie l'ordre ABORT à toutes les antennes
1146
1147            for (int i=1; i<SocketsNumber; i++)
1148            {
1149                if (Sockets[i].Connected)
[501]1150                {
1151                    if (!ABORT(i)) Sockets[i].sendalertes++;
1152                }
[504]1153            }
[501]1154
[504]1155            IDSetSwitch(&OnCoordSetSP, "ABORT OK !");
[501]1156
[504]1157            // Réinititialisation des paramÚtres des antennes
1158
[501]1159            InitAntennes();
1160
[504]1161            //Pour permettre de refaire un abort
1162
[501]1163            Abort=false;
1164        }
1165
[504]1166        ///////////////////////////////////////
1167        // L'utilisateur a demandé de mettre les antennes au repos
[501]1168
1169        if (Park)
1170        {
[504]1171            // On arrête le suivi d'un objet
[501]1172
[504]1173            Suivi = false;
[501]1174
[504]1175            // On arrête l'enchaînement des actions
1176            // pour réaliser un goto
1177
1178            ActualisationPosition = false;
1179
1180            // On envoie l'ordre PARK à toutes les antennes
1181
1182            for (int i=1; i<SocketsNumber; i++)
1183            {
1184                if (Sockets[i].Connected)
[501]1185                {
1186                    if (!PARK(i)) Sockets[i].sendalertes++;
1187                }
[504]1188            }
[501]1189
[504]1190            IDSetSwitch(&OnCoordSetSP, "PARK OK !");
[501]1191
[504]1192            // Réinititialisation des paramÚtres des antennes
1193
[501]1194            InitAntennes();
1195
[504]1196            //Pour permettre de refaire un park
1197
[501]1198            Park=false;
1199        }
1200
1201
[504]1202        ///////////////////////////////////////
[501]1203        // Gestion du suivi
1204
[504]1205        if ((Suivi) && (UpdateGoto))
[501]1206        {
[619]1207            // Délais entre deux actualisations
[501]1208
[504]1209            double delai=ActualisationTM1 / 3600.0 / 24.0;   // Actualisation toutes les 15 minutes en mode transit
[501]1210
[504]1211            if (TrackingMode==2) delai=ActualisationTM2 / 3600.0 / 24.0;   //et 5 secs en mode tracking
[501]1212
1213
[504]1214            // On actualise la position si le delai est dépassé
[501]1215
[504]1216            if (GetJJ() - JJAnc > delai)
[501]1217            {
[504]1218                UpdateGoto = false;
[501]1219
[504]1220                // Conversion des coordonnées en pas moteur
[501]1221
1222                ADDEC2Motor(targetRA, targetDEC);
1223
[504]1224                // On réinitialise les antennes en vue du goto
1225
[501]1226                InitAntennes();
1227
[504]1228                ActualisationPosition = true;
1229
1230                // On sauvegarde la date
1231
1232                JJAnc = GetJJ();
[501]1233            }
1234
[504]1235            //Plus d'antenne ! On arrête le suivi
[501]1236
1237            if (AntennesConnectees() == 0)
1238            {
[504]1239                if ( compt % 1000 == 0)
1240                {
1241                    IDSetSwitch(&OnCoordSetSP, "Erreur ! Plus d antennes connectees !");
[501]1242
[504]1243                    if (Suivi) IDLog("Arrêt du suivi !");
[501]1244
[504]1245                    ActualisationPosition=false;
[501]1246
[504]1247                    Suivi=false;
1248
1249                    InitAntennes();
1250                }
[501]1251            }
1252        }
1253
1254
1255
1256        // Exécution de la procédure complÚte de lecture de la position de l'antenne
1257        // puis envoi d'une commande Goto
1258
[504]1259        if (ActualisationPosition)
[501]1260        {
[504]1261            for (int i=1; i<SocketsNumber; i++)
[501]1262            {
[504]1263                if (Sockets[i].Connected)
[501]1264                {
[504]1265                    switch (Sockets[i].etape)
1266                    {
[501]1267
[504]1268                        //Envoi de la commande POS
[501]1269
[504]1270                    case 0 :
1271                    {
1272                        Sockets[i].ack_pos    = false;
1273                        Sockets[i].PosValides = false;
[501]1274
[504]1275                        if (!POSITION(i)) Sockets[i].sendalertes++;
[501]1276
1277                        Sockets[i].etape++;
1278                    }
[504]1279                    break;
[501]1280
1281
[504]1282                    // A-ton bien reçu l'ack POS ?
1283
1284                    case 1 :
1285                    {
1286                        if (Sockets[i].ack_pos)
[501]1287                        {
[504]1288                            // tout marche bien
1289                            Sockets[i].AttenteExecution = 0;
1290                            Sockets[i].AnomaliesExecution = 0;
1291                            Sockets[i].etape++;
1292                            i--; //permet de revenir sur ce même socket malgré la boucle
1293                            // -> plus rapide
[501]1294                        }
[504]1295                        else
[501]1296                        {
[504]1297                            // on réitÚre l'ordre précédent si rien ne se passe
[501]1298
[504]1299                            // On garde une trace de l'anomalie
1300                            Sockets[i].AttenteExecution++;
1301
1302                            if (Sockets[i].AttenteExecution > MAXATTENTE)
[501]1303                            {
[504]1304                                // on recommence depuis le début
1305                                Sockets[i].etape = 0;
1306                                Sockets[i].AttenteExecution = 0;
1307                                Sockets[i].AnomaliesExecution++;
1308                            }
1309
1310                            // Toujours rien -> plus sérieux : il faut déconnecter l'antenne
1311                            if (Sockets[i].AnomaliesExecution > MAXANOMALIES)
1312                            {
1313                                OnCoordSetSP.s = IPS_ALERT;
[501]1314                                IDSetSwitch(&OnCoordSetSP, "Erreur sur l antenne %s : pas d acknowledge recu apres l ordre POSITION. \
[504]1315    Deconnexion de l antenne.", Sockets[i].IP.c_str());
1316                                DeconnecterSocket(i);
[501]1317                            }
1318                        }
1319                    }
[504]1320                    break;
[501]1321
1322
[504]1323                    //Les valeurs retournées pas la commande POSITION sont-elles valides ?
[501]1324
[504]1325                    case 2 :
1326                    {
1327                        if (Sockets[i].PosValides)
[501]1328                        {
[504]1329                            Sockets[i].AttenteExecution = 0;
1330                            Sockets[i].AnomaliesExecution = 0;
1331                            Sockets[i].etape++; // on passe à l'étape suivante
[501]1332                        }
[504]1333                        else
[501]1334                        {
[504]1335                            // on réitÚre l'ordre précédent si rien ne se passe
1336                            Sockets[i].AttenteExecution++;
[501]1337
[504]1338                            if (Sockets[i].AttenteExecution > MAXATTENTE)
[501]1339                            {
[619]1340                                // on attend encore la réponse posvalides                               
[504]1341                                Sockets[i].etape = 2;
1342                                Sockets[i].AttenteExecution = 0;
1343                                Sockets[i].AnomaliesExecution++;
1344                            }
1345
1346                            if (Sockets[i].AnomaliesExecution > MAXANOMALIES)
1347                            {
1348                                OnCoordSetSP.s = IPS_ALERT;
[501]1349                                IDSetSwitch(&OnCoordSetSP, "Erreur sur l antenne %s : la position retournee n est pas valide. \
[504]1350    Deconnexion de l antenne.", Sockets[i].IP.c_str());
1351                                DeconnecterSocket(i);
[501]1352                            }
1353                        }
1354                    }
[504]1355                    break;
[501]1356
1357
[504]1358                    // A-ton reçu l'acknowledge de la commande goto ?
[501]1359
[504]1360                    case 4 :
1361                    {
1362                        if (Sockets[i].ack_goto)
[501]1363                        {
[504]1364                            Sockets[i].AttenteExecution = 0;
1365                            Sockets[i].AnomaliesExecution = 0;
1366                            Sockets[i].etape++; // on passe à l'étape suivante
[501]1367                        }
[504]1368                        else
[501]1369                        {
[504]1370                            // on réitÚre l'ordre précédent si rien ne se passe
1371                            Sockets[i].AttenteExecution++;
[501]1372
[504]1373                            if (Sockets[i].AttenteExecution > MAXATTENTE)
[501]1374                            {
[504]1375                                // On prolonge l'attente                               
1376                                Sockets[i].etape = 4;
1377                                Sockets[i].AttenteExecution = 0;
1378                                Sockets[i].AnomaliesExecution++;
1379                            }
1380
1381                            if (Sockets[i].AnomaliesExecution > MAXANOMALIES)
1382                            {
1383                                OnCoordSetSP.s = IPS_ALERT;
[501]1384                                IDSetSwitch(&OnCoordSetSP, "Erreur sur l antenne %s : pas d acknowledge recu apres l ordre GOTO. \
[504]1385    Deconnexion de l antenne.", Sockets[i].IP.c_str());
1386                                DeconnecterSocket(i);
[501]1387                            }
1388                        }
1389                    }
[504]1390                    break;
[501]1391
1392
[504]1393                    //  Confirmation goto ok ?
[501]1394
[504]1395                    case 5 :
1396                    {
1397                        if (Sockets[i].GotoOk)
[501]1398                        {
[504]1399                            Sockets[i].AttenteExecution = 0;
1400                            Sockets[i].AnomaliesExecution = 0;
1401                            Sockets[i].etape++;
[501]1402                        }
[504]1403                        else
[501]1404                        {
[504]1405                            // on réitÚre l'ordre précédent si rien ne se passe
1406                            Sockets[i].AttenteExecution++;
[501]1407
[504]1408                            if (Sockets[i].AttenteExecution > MAXATTENTE)
[501]1409                            {
[504]1410                                // On prolonge l'attente
1411                               
1412                                Sockets[i].etape = 5;
1413                                Sockets[i].AttenteExecution = 0;
1414                                Sockets[i].AnomaliesExecution++;
1415                            }
1416
[619]1417                            // On déconnecte l'antenne s'il n'y a pas de coonfirmation du goto au bout de 2 minutes   
[504]1418                            if (Sockets[i].AnomaliesExecution > MAXANOMALIESGOTO)
1419                            {
1420                                OnCoordSetSP.s = IPS_ALERT;
[501]1421                                IDSetSwitch(&OnCoordSetSP, "Erreur sur l antenne %s : l antenne n a pas renvoye GOTO/OK. \
[504]1422    Deconnexion de l antenne.", Sockets[i].IP.c_str());
1423                                DeconnecterSocket(i);
[501]1424                            }
1425                        }
1426                    }
[504]1427                    break;
1428                    }
[501]1429                }
1430            }
1431        }
1432
1433
[504]1434        ///////////////////////////////////////
1435        //On attend que toutes les antennes soient prêtes pour lancer l'ordre Goto -> meilleure synchronisation
[501]1436
[504]1437        int num=0;
[501]1438
[504]1439        for (int i=1; i<SocketsNumber; i++)
1440        {
1441            if (Sockets[i].Connected)
1442            {
1443                if (Sockets[i].etape == 3) num++; //fin de la procédure ActualisationPosition.
1444                // num antennes sont prêtes à recevoir l'ordre GOTO
1445            }
1446        }
[501]1447
[504]1448        if ((num == AntennesConnectees()) && (num>0))
1449        {
1450            for (int i=1; i<SocketsNumber; i++ )
[501]1451            {
[504]1452                if (Sockets[i].Connected)
[501]1453                {
[504]1454                    Sockets[i].ack_goto = false;
1455                    Sockets[i].AttenteExecution = 0;
1456                    Sockets[i].AnomaliesExecution = 0;
[501]1457
[619]1458                    if (!GOTO(i, TargetPosition.x - Sockets[i].Pos.x - Sockets[i].Delta.x, TargetPosition.y - Sockets[i].Pos.y - Sockets[i].Delta.y)) Sockets[i].sendalertes++;
[501]1459
[504]1460                    Sockets[i].etape++;
[501]1461                }
1462            }
[504]1463        }
[501]1464
[504]1465        ///////////////////////////////////////
1466        // Détection d'anomalies sur la socket. Déconnexion du micro-cont ?
[501]1467
[504]1468        for (int i=1; i<SocketsNumber; i++)
1469        {
1470            if (Sockets[i].Connected)
[501]1471            {
[504]1472                if (Sockets[i].sendalertes > 0)
[501]1473                {
[504]1474                    OnCoordSetSP.s = IPS_ALERT;
1475                    IDSetSwitch(&OnCoordSetSP, "Erreur sur l antenne %s : deconnexion de l antenne.", Sockets[i].IP.c_str());
[501]1476
[504]1477                    DeconnecterSocket(i);
[501]1478                }
[504]1479            }
[501]1480        }
[492]1481    }
[619]1482   
1483    //incrémentation du compteur
[504]1484    compt++;
[501]1485}
1486
1487
1488
1489/**************************************************************************************
[504]1490** Mode transit ou tracking
[501]1491***************************************************************************************/
[504]1492
[501]1493bool BAO::process_coords()
1494{
[490]1495    switch (currentSet)
1496    {
[501]1497        // Transit
1498    case BAO_TRANSIT:
1499
[504]1500        //Eteindre les voyants dans la boîte de dialogue Indi
[501]1501        EquatorialCoordsWNP.s = IPS_BUSY;
[504]1502        AbortSlewSP.s = IPS_IDLE;
1503        ParkSP.s = IPS_IDLE;
[501]1504
1505        IDSetNumber (&EquatorialCoordsWNP, NULL);
[504]1506        IDSetSwitch (&AbortSlewSP, NULL);
1507        IDSetSwitch (&ParkSP, NULL);
[501]1508
[504]1509        // On prépare les antennes pour le prochain goto
1510
[501]1511        InitAntennes();
1512
[504]1513        JJAnc = GetJJ();
1514       
1515        ADDEC2Motor(targetRA, targetDEC);
[501]1516
1517        TrackingMode = 1;
1518
[504]1519        Suivi = true;
[501]1520
[504]1521        UpdateGoto = false;
[501]1522
[504]1523        ActualisationPosition = true;
[501]1524
1525        break;
1526
1527        // Tracking
1528    case BAO_TRACKING:
1529
[504]1530        //Eteindre les voyants dans la boîte de dialogue Indi
[501]1531        EquatorialCoordsWNP.s = IPS_BUSY;
[504]1532        AbortSlewSP.s = IPS_IDLE;
1533        ParkSP.s = IPS_IDLE;
[501]1534
1535        IDSetNumber (&EquatorialCoordsWNP, NULL);
[504]1536        IDSetSwitch (&AbortSlewSP, NULL);
1537        IDSetSwitch (&ParkSP, NULL);
[501]1538
1539        InitAntennes();
1540
[504]1541        JJAnc=GetJJ();
1542       
1543        ADDEC2Motor(targetRA, targetDEC);
[501]1544
1545        TrackingMode = 2;
1546
[504]1547        Suivi = true;
[501]1548
[504]1549        UpdateGoto = false;
[501]1550
[504]1551        ActualisationPosition = true;       
[501]1552
1553        break;
[490]1554    }
[501]1555
[490]1556    return true;
[501]1557}
1558
1559
1560
1561/**************************************************************************************
[504]1562** Connexion / Déconnexion avec le télescope
[501]1563***************************************************************************************/
[504]1564
[501]1565void BAO::connect_telescope()
1566{
[490]1567    switch (ConnectSP.sp[0].s)
1568    {
[501]1569    case ISS_ON:
[504]1570
1571        // Etats des voyants
1572
[501]1573        ConnectS[0].s = ISS_ON;
1574        ConnectS[1].s = ISS_OFF;
1575        ConnectSP.s = IPS_OK;
1576        IDSetSwitch (&ConnectSP, "BAORadio is online. Retrieving basic data...");
1577
[504]1578        // Petit message
[501]1579
[504]1580        IDLog("\nHello BAORadio !\n");
1581
1582        // On lance le thread !
1583
1584        Exit=false;
1585
1586        if (pthread_create (&th1, NULL, (void*(*)(void*))LancementThread, this) < 0)
1587        {
1588            IDLog("pthread_create error for threadSocket\n");
1589        }
1590
[501]1591        break;
1592
1593    case ISS_OFF:
[504]1594
1595        // On sort du thread
1596
1597        Exit = true;
1598        sleep(1);
1599        pthread_join (th1, NULL);
1600        InitThreadOK = false;
1601
1602        // Etat des voyants
1603
[501]1604        ConnectS[0].s = ISS_OFF;
1605        ConnectS[1].s = ISS_ON;
1606        ConnectSP.s = IPS_IDLE;
[504]1607        IDSetSwitch (&ConnectSP, "BAORadio is offline.");
1608        IDLog("Telescope is offline.");
[501]1609
[504]1610        // On déconnecte tous les sockets
[501]1611
1612        for (int i=0; i<MAXHOSTNAME; i++)
1613        {
[504]1614            DeconnecterSocket(i);
[501]1615        }
1616
[504]1617        // init
1618
[501]1619        InitAntennes();
1620
[504]1621        SocketsNumber = 1;
[501]1622
1623        break;
[490]1624    }
[501]1625}
1626
1627
1628
1629
1630/**************************************************************************************
[504]1631**  Envoie une commande sur le socket numsocket
[501]1632***************************************************************************************/
1633
1634bool BAO::COMMANDE(int numsocket, char* Commande, char* Params)
1635{
[490]1636    char chaine[MAXCARACTERES];
[501]1637
[490]1638    try
1639    {
[501]1640        sprintf(chaine, "%s%s\n", Commande, Params);
[504]1641       
1642        Sockets[numsocket].new_sock << chaine;
1643       
[619]1644        IDLog("Commande envoyee a %s: %s", Sockets[numsocket].IP.c_str(), chaine);
[490]1645    }
1646    catch (SocketException& e)
[501]1647    {
[504]1648        DeconnecterSocket(numsocket);
[501]1649
[504]1650        IDLog("Indi_BAO, COMMANDE exception : ");
1651        IDLog(e.description().c_str());
1652        IDLog("\n");
[501]1653
1654        return false;
[490]1655    }
[501]1656
[490]1657    return true;
[501]1658}
1659
1660
1661/**************************************************************************************
1662** Commande POSITION
1663***************************************************************************************/
1664
1665bool BAO::POSITION(int numsocket)
1666{
[498]1667    return COMMANDE(numsocket, (char*)"P", (char*)"");
[501]1668}
1669
1670/**************************************************************************************
1671** Commande PARK
1672***************************************************************************************/
1673
1674bool BAO::PARK(int numsocket)
1675{
[498]1676    return COMMANDE(numsocket, (char*)"Z", (char*)"");
[501]1677}
1678
1679/**************************************************************************************
1680** Commande ABORT
1681***************************************************************************************/
1682
1683bool BAO::ABORT(int numsocket)
1684{
[498]1685    return COMMANDE(numsocket, (char*)"A", (char*)"");
[501]1686}
1687
1688
1689/**************************************************************************************
1690** Commande GOTO
1691***************************************************************************************/
1692
1693bool BAO::GOTO(int numsocket, int deltaAz, int deltaAlt)
1694{
[490]1695    char Params[MAXCARACTERES];
[494]1696    char sensAz;
1697    char sensAlt;
[501]1698
[504]1699    sensAlt = 1;
1700    sensAz  = 1;
[501]1701
[504]1702    if ( deltaAz < 0 )
[490]1703    {
[504]1704        deltaAz = -deltaAz;
1705        sensAz  = 0;
[490]1706    }
[501]1707
[504]1708    if ( deltaAlt < 0 )
[490]1709    {
[504]1710        deltaAlt = -deltaAlt;
1711        sensAlt  = 0;
[490]1712    }
[501]1713
[504]1714    // Vérification du nombre de pas à faire au niveau de l'axe azimut
1715    // Rappel : un tour complet autour de l'axe az fait 4000 pas codeur (#define NBREPASCODEURSAZ dans BAO.h)
1716
1717    // problÚme 1 : si deltaAz > à un demi-tours - soit 2000 pas alors
1718    // on fait le trajet dans le sens inverse pour aller plus vite
1719
1720    // problÚme 2 : Passage au méridien
1721    // on se situe à quelques secondes de degrés avant le sud par exemple (nb de pas 3995 par exemple)
1722    // et on franchit le méridien (nb de pas codeur = 5 par exemple)
1723    // On risque alors de faire un tour complet en sens inverse pour rattraper l'objet -> à éviter
1724
[619]1725    // ne pas faire des tours complets en Az pour rien...
[504]1726    while (deltaAz > NBREPASCODEURSAZ) deltaAz -= NBREPASCODEURSAZ;
1727
[619]1728    // Doit résoudre tous les problÚmes concernant l'azimut...
[504]1729    if (deltaAz > NBREPASCODEURSAZ / 2 )
1730    {
1731        deltaAz = NBREPASCODEURSAZ - deltaAz;
1732        sensAz = 1 - sensAz;
1733    }
1734
1735    //on envoie les coordonnées au driver
1736
[619]1737    if (sensAz == 1 )  sensAz='f'; else sensAz='b';
1738   
1739    if (sensAlt == 1 ) sensAlt='f'; else sensAlt='b';
[504]1740
[495]1741    sprintf(Params, "%c%04i%c%04i", sensAz, deltaAz, sensAlt, deltaAlt);
[501]1742
[498]1743    return COMMANDE(numsocket, (char*)"G", Params);
[501]1744}
1745
1746
1747
[504]1748/**************************************************************************************
[619]1749** Les fonctions qui suivent sont nécessaires pour construire le pilote Indi_BAO
[504]1750** Elles sont appelées par le noyau d'Indi
1751***************************************************************************************/
1752
1753/**************************************************************************************
1754** Initialisation du pilote BAO
1755***************************************************************************************/
1756
1757void ISInit()
1758{
1759    //Il ne faut exécuter la fonction qu'une seule fois
1760    static int isInit = 0;
1761
1762    if (isInit) return;
1763
1764    if (telescope.get() == 0) telescope.reset(new BAO());
1765
1766    isInit = 1;
1767
1768    //initialisation du timer
1769
1770    IEAddTimer (POLLMS, ISPoll, NULL);
1771}
1772
1773
1774void ISGetProperties (const char *dev)
1775{
1776    ISInit();
1777
1778    telescope->ISGetProperties(dev);
1779}
1780
1781void ISNewSwitch (const char *dev, const char *name, ISState *states, char *names[], int n)
1782{
1783    ISInit();
1784    telescope->ISNewSwitch(dev, name, states, names, n);
1785}
1786
1787void ISNewText (const char *dev, const char *name, char *texts[], char *names[], int n)
1788{
1789    ISInit();
1790    telescope->ISNewText(dev, name, texts, names, n);
1791}
1792
1793void ISNewNumber (const char *dev, const char *name, double values[], char *names[], int n)
1794{
1795    ISInit();
1796    telescope->ISNewNumber(dev, name, values, names, n);
1797}
1798
1799void ISNewBLOB (const char *dev, const char *name, int sizes[], int blobsizes[], char *blobs[], char *formats[], char *names[], int n)
1800{
1801    INDI_UNUSED(dev);
1802    INDI_UNUSED(name);
1803    INDI_UNUSED(sizes);
1804    INDI_UNUSED(blobsizes);
1805    INDI_UNUSED(blobs);
1806    INDI_UNUSED(formats);
1807    INDI_UNUSED(names);
1808    INDI_UNUSED(n);
1809}
1810
1811void ISSnoopDevice (XMLEle *root)
1812{
1813    INDI_UNUSED(root);
1814}
1815
1816void ISPoll (void *p)
1817{
1818    INDI_UNUSED(p);
1819
1820    telescope->ISPoll();
1821
1822    IEAddTimer (POLLMS, ISPoll, NULL);
1823}
1824
1825
1826/**************************************************************************************
1827**
1828***************************************************************************************/
1829
1830int BAO::get_switch_index(ISwitchVectorProperty *sp)
1831{
1832    for (int i=0; i < sp->nsp ; i++)
1833        if (sp->sp[i].s == ISS_ON)
1834            return i;
1835
1836    return -1;
1837}
1838
1839
1840/**************************************************************************************
1841**
1842***************************************************************************************/
1843void BAO::get_initial_data()
1844{
1845    //  IDSetNumber (&EquatorialCoordsRNP, NULL);
1846}
1847
1848/**************************************************************************************
1849**
1850***************************************************************************************/
1851void BAO::slew_error(int slewCode)
1852{
1853    OnCoordSetSP.s = IPS_IDLE;
1854
1855    if (slewCode == 1)
1856        IDSetSwitch (&OnCoordSetSP, "Object below horizon.");
1857    else if (slewCode == 2)
1858        IDSetSwitch (&OnCoordSetSP, "Object below the minimum elevation limit.");
1859    else
1860        IDSetSwitch (&OnCoordSetSP, "Slew failed.");
1861}
1862
1863/**************************************************************************************
1864**
1865***************************************************************************************/
1866
1867bool BAO::is_connected()
1868{
1869    // return (ConnectSP.sp[0].s == ISS_ON);
1870    return (ConnectSP.s == IPS_OK);
1871}
1872
1873/**************************************************************************************
1874**
1875***************************************************************************************/
1876void BAO::connection_lost()
1877{
1878    ConnectSP.s = IPS_IDLE;
1879    IDSetSwitch(&ConnectSP, "The connection to the telescope is lost.");
1880    IDLog("arret");
1881    return;
1882}
1883
1884/**************************************************************************************
1885**
1886***************************************************************************************/
1887void BAO::connection_resumed()
1888{
1889    ConnectS[0].s = ISS_ON;
1890    ConnectS[1].s = ISS_OFF;
1891    ConnectSP.s = IPS_OK;
1892
1893    IDSetSwitch(&ConnectSP, "The connection to the telescope has been resumed.");
1894}
1895
1896
1897/**************************************************************************************
1898** GÚre les erreurs de communication avec la boîte Indi
1899***************************************************************************************/
1900/*
1901void BAO::handle_error(INumberVectorProperty *nvp, int err, const char *msg)
1902{
1903    nvp->s = IPS_ALERT;
1904
1905    // If the error is a time out, then the device doesn't support this property
1906    if (err == -2)
1907    {
1908        nvp->s = IPS_ALERT;
1909        IDSetNumber(nvp, "Device timed out. Current device may be busy or does not support %s. Will retry again.", msg);
1910    }
1911    else
1912        // Changing property failed, user should retry.
1913        IDSetNumber( nvp , "%s failed.", msg);
1914
1915    fault = true;
1916}*/
1917
1918
1919/**************************************************************************************
1920**
1921***************************************************************************************/
1922/*
1923void BAO::correct_fault()
1924{
1925    fault = false;
1926    IDMessage(mydev, "Telescope is online.");
1927}*/
1928
1929
1930
Note: See TracBrowser for help on using the repository browser.