/*

     PROTOCOLE TRSII
       Pour dialoguer avec les télétransmissions CLIP / FORCE (Constructeur WIT)
       http://www.wit.fr

     Marc Le Douarain , Décembre 1998
     mavati@club-internet.fr
     http://perso.club-internet.fr/mavati
 
     Dernière mise à jour : 13 mars 1999

*/



void Mem_FreeAll(void)
{
 if (Ress!=NULL)
 {
  free(Ress);
  Ress=NULL;
 }
 if (Jrnl!=NULL)
 {
  free(Jrnl);
  Jrnl=NULL;
 }
 if (MessagesBoxMemZone!=NULL)
 {
  free(MessagesBoxMemZone);
  MessagesBoxMemZone=NULL;
 }
 if(TrameRecue!=NULL)
 {
  free(TrameRecue);
  TrameRecue=NULL;
 }
}

void Mem_AllocAll(void)
{
 int i;
 Ress=(struct Ressources *)malloc(sizeof(struct Ressources)*NBR_RESSOURCES);
 if (Ress==NULL)
 {
  ErrorMessageRequest("Could not alloc enough memory (for ressources)");
  exit(0);
 }
 Jrnl=NULL;
 MessagesBoxMemZone=(char *)malloc(sizeof(char)*256*NBR_MESSAGESBOX);
 if (MessagesBoxMemZone==NULL)
 {
  ErrorMessageRequest("Could not alloc enough memory (for MessagesBox)");
  exit(0);
 }
 for (i=0;i<NBR_MESSAGESBOX;i++)
 {
  MessagesBox[i]=&MessagesBoxMemZone[i*255];
 }
 TrameRecue=(char *)malloc(10000);
 if (TrameRecue==NULL)
 {
  ErrorMessageRequest("Could not alloc enough memory (for ReceptFrame)");
  exit(0);
 }
}



/* ########################################## */
/* # Sauvegarde/Lecture des fichiers traces # */
/* ########################################## */

/* Sauvegarde sur disque de la trace */
/* --------------------------------- */
void save_trace_to_disk(char * Fichier,char * TrameTrace,int LgtTrameTrace)
{
 FILE * FTrace;
 time_t TimeLastSampleSaved;
 int PeriodSample;
 time_t TimeLastSampleRecup;
 time_t TimeSampleRecupBalayage;
 int NbrSamplesBalayage;
 int i;
 char * PtrTrame;
 char * CharTmp;
 struct tm DateEnClair;
 char DateEnClairSAS[6];
 int AnneePourSAS;
 DateEnClair.tm_sec  = 00;     /* seconds after the minute   */
 DateEnClair.tm_min  = 00;     /* minutes after the hour     */
 DateEnClair.tm_hour = 00;     /* hours since midnight       */
 DateEnClair.tm_mday = 1;      /* day of the month           */
 DateEnClair.tm_mon  = 1;      /* months since January       */
 DateEnClair.tm_year = 78;     /* years since 1900           */
 DateEnClair.tm_isdst = 1;     /* Daylight Savings Time flag */
 TimeLastSampleSaved=mktime(&DateEnClair);
 /* Trace en fonctionnement ? */
 CharTmp=(str_field(TrameTrace,LgtTrameTrace,4,'\t'));
 if (CharTmp[0]='M')
 {
  /* On regarde si le fichier existe ... valeur de l'horodate du dernier échantillon sauvé */
  FTrace=fopen(Fichier,"rb");
  if (FTrace)
  {
   fseek(FTrace,-(sizeof(int)+sizeof(double)),SEEK_END);
   fread(&TimeLastSampleSaved,sizeof(time_t),1,FTrace);
   fclose(FTrace);
  }
  /* Valeur de l'horodate du dernier échantillon récupéré */
//  DateEnClair.tm_hour = atoi(str_field(TrameTrace,LgtTrameTrace,9,'\t'));
//  DateEnClair.tm_min  = atoi(str_field(TrameTrace,LgtTrameTrace,10,'\t'));
//  DateEnClair.tm_sec  = atoi(str_field(TrameTrace,LgtTrameTrace,11,'\t'));
//  DateEnClair.tm_mday = atoi(str_field(TrameTrace,LgtTrameTrace,6,'\t'));
//  DateEnClair.tm_mon  = atoi(str_field(TrameTrace,LgtTrameTrace,7,'\t'));
//  DateEnClair.tm_year = atoi(str_field(TrameTrace,LgtTrameTrace,8,'\t'));
//  DateEnClair.tm_isdst = 1;
//  TimeLastSampleRecup=mktime(&DateEnClair);

  AnneePourSAS=atoi(str_field(TrameTrace,LgtTrameTrace,8,'\t'));
  /* Dernières versions de Clip (>v45?) renvoie l'année sur 4 chiffres directement !!!*/
  if (AnneePourSAS>1900)
  {
   AnneePourSAS=AnneePourSAS-1970;
  }
  else
  {
   if (AnneePourSAS>70)
	  AnneePourSAS=1900+AnneePourSAS-1970;
   else
	  AnneePourSAS=2000+AnneePourSAS-1970;
  }
  DateEnClairSAS[0]=(char)AnneePourSAS;
  DateEnClairSAS[1]=atoi(str_field(TrameTrace,LgtTrameTrace,7,'\t'));
  DateEnClairSAS[2]=atoi(str_field(TrameTrace,LgtTrameTrace,6,'\t'));
  DateEnClairSAS[3]=atoi(str_field(TrameTrace,LgtTrameTrace,9,'\t'));
  DateEnClairSAS[4]=atoi(str_field(TrameTrace,LgtTrameTrace,10,'\t'));
  DateEnClairSAS[5]=atoi(str_field(TrameTrace,LgtTrameTrace,11,'\t'));
  TimeLastSampleRecup=utpack(DateEnClairSAS);

  PeriodSample=atoi(str_field(TrameTrace,LgtTrameTrace,5,'\t'));  

  /* Vérification échantillonnage plus récent */
  if (TimeLastSampleRecup>TimeLastSampleSaved)
  {
   /* Balayage en arrière pour trouver l'échantillon à-partir d'où on effectuera le collage */
   PtrTrame=str_field(TrameTrace,LgtTrameTrace,13,'\t');
   TimeSampleRecupBalayage=TimeLastSampleRecup;
   NbrSamplesBalayage=1;
   do
   {
    TimeSampleRecupBalayage=TimeSampleRecupBalayage-PeriodSample;
    /* Recherche du champ suivant contenant le nouvel échantillon */
    do
    {
     PtrTrame++;
    }while (*PtrTrame!='\t');
    PtrTrame++;
    NbrSamplesBalayage++;
   }
   while( (*PtrTrame!='\0') && (*(PtrTrame+1)!=13) && (PtrTrame<(TrameTrace+LgtTrameTrace)) && (TimeSampleRecupBalayage>TimeLastSampleSaved) );
   /* Correction du fait qu'on a le dernier échantillon de pointé trop loin */
   if (NbrSamplesBalayage>1)
   {
    NbrSamplesBalayage--;
    /* Recherche du champ précédent */
    PtrTrame--;
    do
    {
     PtrTrame--;
    }while(*PtrTrame!='\t');
   }
   /* Sauvegarde des nouveaux échantillons */
   FTrace=fopen(Fichier,"ab");
   if (FTrace)
   {
    for (i=1;i<=NbrSamplesBalayage;i++)
    {
     double ValSample;
     /* On revient sur le champ précédent */
     do
     {
      PtrTrame--;
     }while(*PtrTrame!='\t');
     /* Sauvegarde de l'horodate de l'échantillon */
     TimeSampleRecupBalayage=TimeSampleRecupBalayage+PeriodSample;
     fwrite(&TimeSampleRecupBalayage,sizeof(time_t),1,FTrace);
     /* Sauvegarde de la valeur de l'échantillon */
     ValSample=atof(PtrTrame+1);
     fwrite(&ValSample,sizeof(double),1,FTrace);
    }
    fclose(FTrace);
   }
  }
 }
}



/* ######################################## */
/* # Calculating the checksum of a string # */
/* # with the protocol TRSII              # */
/* ######################################## */
unsigned int calcul_checksum_trsii(char * string,int Lgt)
{
 unsigned int chk=0;
 int i;
 for(i=0;i<Lgt;i++)
 {
  chk=chk+string[i];
 }
 chk=chk&63;
 if (chk==0)
 {
  chk=64;
 }
 chk=64-chk;
 chk=chk+64;
 return chk;
}

/* ########################################## */
/* # Creating a TRSII request to send       # */
/* # and saving which request was requested # */
/* ########################################## */
int send_request_trsii(char * CurRequestStr,int * CurRequestLgt,char * QuestStr,char * Param1Str,char * Param2Str,unsigned long * MemoTimeLaunchReq, int * TimeOutMaxi)
{
 int RequeteOk=False;
 char TrameEnvoi[64];
 int LgtParam1;
 int LgtParam2;

 LgtParam1=strlen(Param1Str);
 LgtParam2=strlen(Param2Str);
 
 /* REQUEST 'ACCES' 'Password' */
 /*----------------------------*/
 if (strcmp(QuestStr,"ACCES")==0)
 {

/* !!!!!!!!!!!!!!!!!!!!!! METTRE LA TRAME COMPLETE DANS CurRequestStr... (pour ETAT servira à
   !!!!!!!!!!!!!!!!!!!!!! savoir si 1 ou 2 params demandés !!!!!!!!!!!!
                          + réenvoi trame sur time-out!!!!
*/


  strcpy(TrameEnvoi,"ACCES\t");
  strcpy(TrameEnvoi+6,Param1Str);
  TrameEnvoi[6+LgtParam1]='\t';
  TrameEnvoi[6+LgtParam1+1]=calcul_checksum_trsii(TrameEnvoi,6+LgtParam1+1);
  strcpy(TrameEnvoi+6+LgtParam1+2,"\n\0");
  *TimeOutMaxi=3;
  RequeteOk=True;
 }

 /* REQUETE 'IDENT?' */
 /*------------------*/
 if (strcmp(QuestStr,"IDENT?")==0)
 {
  strcpy(TrameEnvoi,"IDENT?\t");
  TrameEnvoi[7]=calcul_checksum_trsii(TrameEnvoi,7);
  strcpy(TrameEnvoi+8,"\n\0");
  *TimeOutMaxi=3;
  RequeteOk=True;  
 }

 /* REQUETE 'ETAT?' '1ère ressource' ['nbr de ressources'] */
 /*---------------------------------------------------------*/
 if (strcmp(QuestStr,"ETAT?")==0)
 {
  strcpy(TrameEnvoi,"ETAT?\t");
  strcpy(TrameEnvoi+6,Param1Str);
  TrameEnvoi[6+LgtParam1]='\t';
  TrameEnvoi[6+LgtParam1+1]=calcul_checksum_trsii(TrameEnvoi,6+LgtParam1+1);
  strcpy(TrameEnvoi+6+LgtParam1+2,"\n\0");
  *TimeOutMaxi=3;
  RequeteOk=True;
 }

 /* REQUETE 'RESS?' '1ère ressource' ['nbr de ressources'] */
 /*---------------------------------------------------------*/
 if (strcmp(QuestStr,"RESS?")==0)
 {
  strcpy(TrameEnvoi,"RESS?\t");
  strcpy(TrameEnvoi+6,Param1Str);
  TrameEnvoi[6+LgtParam1]='\t';
  TrameEnvoi[6+LgtParam1+1]=calcul_checksum_trsii(TrameEnvoi,6+LgtParam1+1);
  strcpy(TrameEnvoi+6+LgtParam1+2,"\n\0");
  *TimeOutMaxi=4;
  RequeteOk=True;
 }

 /* REQUETE 'TP?' '1ère trace' ['nbr de traces'] */
 /*----------------------------------------------*/
 if (strcmp(QuestStr,"TP?")==0)
 {
  strcpy(TrameEnvoi,"TP?\t");
  strcpy(TrameEnvoi+4,Param1Str);
  TrameEnvoi[4+LgtParam1]='\t';
  TrameEnvoi[4+LgtParam1+1]=calcul_checksum_trsii(TrameEnvoi,4+LgtParam1+1);
  strcpy(TrameEnvoi+4+LgtParam1+2,"\n\0");
  *TimeOutMaxi=4;
  RequeteOk=True;
 }

 /* REQUETE 'T?' 'n° de la trace' ['nbr d'échantillons à récupérer']*/
 /*-----------------------------------------------------------------*/
 if (strcmp(QuestStr,"T?")==0)
 {
  strcpy(TrameEnvoi,"T?\t");
  strcpy(TrameEnvoi+3,Param1Str);
  TrameEnvoi[3+LgtParam1]='\t';
  TrameEnvoi[3+LgtParam1+1]=calcul_checksum_trsii(TrameEnvoi,3+LgtParam1+1);
  strcpy(TrameEnvoi+3+LgtParam1+2,"\n\0");
  *TimeOutMaxi=30;
  RequeteOk=True;
 }

 /* REQUETE 'MESS?' 'n° de la boite aux lettres' */
 /*-----------------------------------*/
 if (strcmp(QuestStr,"MESS?")==0)
 {
  strcpy(TrameEnvoi,"MESS?\t");
  strcpy(TrameEnvoi+6,Param1Str);
  TrameEnvoi[6+LgtParam1]='\t';
  TrameEnvoi[6+LgtParam1+1]=calcul_checksum_trsii(TrameEnvoi,6+LgtParam1+1);
  strcpy(TrameEnvoi+6+LgtParam1+2,"\n\0");
  *TimeOutMaxi=20;
  RequeteOk=True;
 }

 /* REQUETE 'DATE?' */
 /*-----------------*/
 if (strcmp(QuestStr,"DATE?")==0)
 {
  strcpy(TrameEnvoi,"DATE?\t");
  TrameEnvoi[6]=calcul_checksum_trsii(TrameEnvoi,6);  
  strcpy(TrameEnvoi+7,"\n\0");
  *TimeOutMaxi=3;
  RequeteOk=True;  
 }

 /* REQUETE 'TIME?' */
 /*-----------------*/
 if (strcmp(QuestStr,"TIME?")==0)
 {
  strcpy(TrameEnvoi,"TIME?\t");
  TrameEnvoi[6]=calcul_checksum_trsii(TrameEnvoi,6);  
  strcpy(TrameEnvoi+7,"\n\0");
  *TimeOutMaxi=3;
  RequeteOk=True;
 }

 /* REQUETE 'J?' ['#xxxxxx:N°Evenement'] ou [AAAAMMJJHHMMSS:DateHeure]   
    /!\  CLIP uniquement : lecture du journal */
 /*-------------------------------------------*/
 if (strcmp(QuestStr,"J?")==0)
 {
  strcpy(TrameEnvoi,"J?\t");
  if(LgtParam1>0)
  {
   strcpy(TrameEnvoi+3,Param1Str);
   TrameEnvoi[3+LgtParam1]='\t';
   TrameEnvoi[3+LgtParam1+1]=calcul_checksum_trsii(TrameEnvoi,3+LgtParam1+1);
   strcpy(TrameEnvoi+3+LgtParam1+2,"\n\0");
  }
  else
  {
   TrameEnvoi[3]=calcul_checksum_trsii(TrameEnvoi,3);
   strcpy(TrameEnvoi+4,"\n\0");
  }
  *TimeOutMaxi=5;
  RequeteOk=True;
 }

 /* AUTRE... (Par-exemple Forçage mode TRSII 'ESC'W06) /!\ Pas-de réponse attendue */
 if (strcmp(QuestStr,"OTHER")==0)
 {
  strcpy_limited(TrameEnvoi,Param1Str,LgtParam1);
  RequeteOk=True;
 }
  


 if (RequeteOk==True)
 {
  /* On mémorise la requête fraichement crée + sa longueur */
  /* En cas d'erreur de Checksum/TimeOut, on la renverra... */
  strcpy_limited(CurRequestStr,TrameEnvoi,strlen(TrameEnvoi)+1);
  *CurRequestLgt=strlen(TrameEnvoi)+1;
  /* Mémorisation de l'heure à laquelle on va lancer la requête pour le 'time-out' */
  *MemoTimeLaunchReq=get_timer_secs();
  /* Envoie la requête au port série */
  Serial_Write(SerialIO,TrameEnvoi,strlen(TrameEnvoi));
 }
 else
 {
if(MoniteurActif)
printf("Unknown request in TRSII send\n");
   hangup_modem();
   TeletransOnLine=False;
 }  
}


/* ############################# */
/* # Receiving a TRSII request # */
/* ############################# */
int receive_request_trsii(char * CurRequestStr,int CurRequestLgt,unsigned long *MemoLaunchTime,int * Attemps,char * Trame,int * LgtTrame,int TimeOutToLook)
{
 int ReponseOk=False;
 int TraitementReponseExistant=False;
 int DemandeReenvoi=False;
 int TrameComplete;
 char *ExtracChamp;
 char NbrEnChaine[16];
 int StatutRecu;
 int StatutNotError;
 int NumRess;
 char LibelleRessource[LGT_LIBELLE_RESS];
 char EtatRessource[LGT_ETAT_RESS];
 char carac;
 int i;

 TrameComplete=Serial_StringCompose(10,Trame,LgtTrame,MemoLaunchTime,TimeOutToLook);

 /* Trame complète reçue */
 if (TrameComplete==True)
 {

  StatutRecu=0;
  StatutNotError=True;

  /* MESSAGE RECU 'STATUT' */
  if (strcmp_limited(Trame,"STATUT",6)==0)
  {
   TraitementReponseExistant=True;
   ExtracChamp=str_field(Trame,*LgtTrame,2,'\t');
   strcpy_termnotnull(NbrEnChaine,ExtracChamp,13,9);
   StatutRecu=atoi(NbrEnChaine);
   StatutNotError=False;
   switch(StatutRecu)
   {
     /* Erreur de checksum */
     case 130:  DemandeReenvoi=True;
if (MoniteurActif)
printf("Erreur checksum envoyé par la télétrans\n");
                break;
     /* Accès interdit */
     case 132:  hangup_modem();
                ErrorMessageRequest("ACCES INTERDIT!!!");
                TeletransOnLine=False;
                break;
     /* Err.Parametre */
     case 133:
                if (strcmp_termnotnull(CurRequestStr,"TP?",13,9)==0)
                {
                 StatutNotError=True;
                }
                break;
     /* OK */
     case 0:    StatutNotError=True;
                break;
     /* FIN */
     case 1:    StatutNotError=True;
                break;
     /* AUTRE... */   
     default:
if (MoniteurActif)
printf("Erreur n°%d renvoyée par la télétrans\n",StatutRecu);
       
   }
  }

  /* Pas reçu de statut d'erreur ? */
  if (StatutNotError)
  {

   /* VERIFICATION DU CHECKSUM POUR LA TRAME RECUE */
   if (calcul_checksum_trsii(Trame,*LgtTrame-3)!=Trame[*LgtTrame-3])
   {
if (MoniteurActif)
{
printf("Détection erreur de checksum\n");
printf("Checksum attendu:%d\n",calcul_checksum_trsii(Trame,*LgtTrame-3));
}
    DemandeReenvoi=True;
   }    
   else
   {
    /* REQUEST 'ACCES' 'Password' */
    /*----------------------------*/
    if (strcmp_termnotnull(CurRequestStr,"ACCES",13,9)==0)
    {
     TraitementReponseExistant=True;
     if (str_pos(Trame,*LgtTrame,"OK",2)!=NULL)
     {
      ReponseOk=True;
     }
    }

    /* REQUEST 'IDENT?' */
    /*------------------*/
    if (strcmp_termnotnull(CurRequestStr,"IDENT?",13,9)==0)
    {
     TraitementReponseExistant=True;
     if (strcmp_limited(Trame,"IDENT=",6)!=0)
     {
      DemandeReenvoi=True;
     }
     else
     {
      ExtracChamp=str_field(Trame,*LgtTrame,2,'\t');
      if (ExtracChamp!=NULL)
      {
       strcpy_termnotnull(Teletrans.SiteName,ExtracChamp,13,9);
      }
      ExtracChamp=str_field(Trame,*LgtTrame,4,'\t');
      if (ExtracChamp!=NULL)
      {
       strcpy(Teletrans.Type,"INCONNU");
       Teletrans.TRSII_Extended_Clip=False;
       Teletrans.NumRessourcesMax=100;
       Teletrans.NumTracesMax=0;
       if (strcmp_termnotnull(ExtracChamp,"2A",13,9)==0)
       {
        strcpy(Teletrans.Type,"CLIP");
        Teletrans.TRSII_Extended_Clip=True;
        Teletrans.NumRessourcesMax=255;
        Teletrans.NumTracesMax=72;
       }
       if (strcmp_termnotnull(ExtracChamp,"29",13,9)==0)
       {
        strcpy(Teletrans.Type,"CLIP NANO");
        Teletrans.TRSII_Extended_Clip=True;
        Teletrans.NumRessourcesMax=40;
        Teletrans.NumTracesMax=12;
       }
       if (strcmp_termnotnull(ExtracChamp,"24",13,9)==0)
       {
        strcpy(Teletrans.Type,"FORCE X");
       }
       if (strcmp_termnotnull(ExtracChamp,"27",13,9)==0)
       {
        strcpy(Teletrans.Type,"FORCE PLUS");
        Teletrans.NumRessourcesMax=128;
       }
       if (strcmp_termnotnull(ExtracChamp,"26",13,9)==0)
       {
        strcpy(Teletrans.Type,"FORCE MINI");
        Teletrans.NumRessourcesMax=36;
       }
      }
      ExtracChamp=str_field(Trame,*LgtTrame,3,'\t');
      if (ExtracChamp!=NULL)
      {
       strcpy_termnotnull(Teletrans.Version,ExtracChamp,13,9);
      }
      ReponseOk=True;
      RefreshType=RFH_IDENTITE;
     }
    }

    /* REQUETE 'ETAT?' '1ère ressources' ['nbr de ressources'] */
    /*---------------------------------------------------------*/
    if (strcmp_termnotnull(CurRequestStr,"ETAT?",13,9)==0)
    {
     TraitementReponseExistant=True;
     if (strcmp_limited(Trame,"ETAT=",5)!=0)
     {
      DemandeReenvoi=True;
     }
     else
     {
      ExtracChamp=str_field(Trame,*LgtTrame,4,'\t');
      if (ExtracChamp!=NULL)
      {
       strcpy_termnotnull(EtatRessource,ExtracChamp,13,9);
       ExtracChamp=str_field(Trame,*LgtTrame,2,'\t');
       if (ExtracChamp!=NULL)
       {
        strcpy_termnotnull(NbrEnChaine,ExtracChamp,13,9);
        NumRess=atoi(NbrEnChaine);
        strcpy(Ress[NumRess].Etat,EtatRessource);
        ReponseOk=True;
        RefreshType=RFH_ETAT_RESS;
        RefreshParam=NumRess;
       }
      }
     }
    }

    /* REQUETE 'RESS?' '1ère ressources' ['nbr de ressources'] */
    /*---------------------------------------------------------*/
    if (strcmp_termnotnull(CurRequestStr,"RESS?",13,9)==0)
    {
     TraitementReponseExistant=True;
     if (strcmp_limited(Trame,"RESS=",5)!=0)
     {
      DemandeReenvoi=True;
     }
     else
     {
      ExtracChamp=str_field(Trame,*LgtTrame,6,'\t');
      if (ExtracChamp!=NULL)
      {
       strcpy_termnotnull(LibelleRessource,ExtracChamp,13,9);
       /* Suppression des espaces en fin de chaine */
       i=strlen(LibelleRessource);
       if (i>0)
       {
        i--;
        do
        {
         carac=LibelleRessource[i];
         if (carac==32)
         {
          LibelleRessource[i]=0;
         }
         i--;
        }
        while((carac==32)&&(i>0));
       }
       ExtracChamp=str_field(Trame,*LgtTrame,2,'\t');
       if (ExtracChamp!=NULL)
       {
        strcpy_termnotnull(NbrEnChaine,ExtracChamp,13,9);
        NumRess=atoi(NbrEnChaine);
        strcpy(Ress[NumRess].Libelle,LibelleRessource);
        ReponseOk=True;
        RefreshType=RFH_LIBELLE_RESS;
        RefreshParam=NumRess;
       }
      }
     }
    }

    /* REQUETE 'TP?' 'Numéro de la trace' */
    /*------------------------------------*/
    if (strcmp_termnotnull(CurRequestStr,"TP?",13,9)==0)
    {
     TraitementReponseExistant=True;
     /* Plus de trace ? : STATUS 133 Err.Parametre */
     if (StatutRecu==133)
     {
      ReponseOk=True;
      RefreshType=RFH_PARAM_TRACE;
      RefreshParam=0;     // indique qu'il ne faut plus lire les traces suivantes
     }
     else
     {
      if (strcmp_limited(Trame,"TP=",3)!=0)
      {
       DemandeReenvoi=True;
      }
      else
      {
       /* Récupération du n° de trace depuis trame envoyée */
       /* => si trace non paramétrée, trame réponse vide... */
       ExtracChamp=str_field(CurRequestStr,CurRequestLgt,2,'\t');
       if (ExtracChamp!=NULL)
       {
        strcpy_termnotnull(NbrEnChaine,ExtracChamp,13,9);
        NumRess=atoi(NbrEnChaine);
       }
       /* Trace non paramétrée ? */
       if ( (Trame[5])== 13) // 'CR'
       {
        strcpy(Param_Trace,"");
        Tra[NumRess].Used='A';
       }
       else
       {
        char *StrTraceOffset;
        /* Servira à la sauvegarde sur disque */
        strcpy_limited(Param_Trace,Trame+4,*LgtTrame-8);
        Param_Trace[*LgtTrame-9]=0;
        /* Ecriture dans la structure */
        Tra[NumRess].Used='M';
        strcpy_termnotnull(Tra[NumRess].NumMenu,Trame+4,9,0);
        Tra[NumRess].NumMenu[3]=' ';
        Tra[NumRess].NumMenu[4]='-';
        Tra[NumRess].NumMenu[5]=' ';
        StrTraceOffset=str_field(Trame+4,128,10,9);
        if (StrTraceOffset)
        {
         strcpy_termnotnull(Tra[NumRess].Libelle,StrTraceOffset,9,0);
        }
       }
       ReponseOk=True;
       RefreshType=RFH_PARAM_TRACE;
       RefreshParam=NumRess;
      }
     }
    }

    /* REQUETE 'T?' 'Numéro de la trace' */
    /*-----------------------------------*/
    if (strcmp_termnotnull(CurRequestStr,"T?",13,9)==0)
    {
     TraitementReponseExistant=True;
     /* Pas de trace paramétrée ? : STATUS 001 FIN */
     if (StatutRecu==1)
     {
      ReponseOk=True;
     }
     else
     {
      if (strcmp_limited(Trame,"T=",2)!=0)
      {
       DemandeReenvoi=True;
      }
      else
      {
       ExtracChamp=str_field(Trame,*LgtTrame,2,'\t');
       if (ExtracChamp!=NULL)
       {
        char NomFichier[256];
        strcpy_termnotnull(NbrEnChaine,ExtracChamp,13,9);
        NumRess=atoi(NbrEnChaine);
        sprintf(NomFichier,"Sites/%s/Trace%03d",Teletrans.SiteName,NumRess);
        save_trace_to_disk(NomFichier,Trame,*LgtTrame);
        ReponseOk=True;
        RefreshType=RFH_TRACE;
        RefreshParam=NumRess;
       }
      }
     }
    }

    /* REQUETE 'MESS?' 'Numéro de la boite aux lettres' */
    /*--------------------------------------------------*/
    if (strcmp_termnotnull(CurRequestStr,"MESS?",13,9)==0)
    {
     TraitementReponseExistant=True;
     if (strcmp_limited(Trame,"MESS=",5)!=0)
     {
      DemandeReenvoi=True;
     }
     else
     {
      ExtracChamp=str_field(Trame,*LgtTrame,2,'\t');
      if (ExtracChamp!=NULL)
      {
       strcpy_termnotnull(NbrEnChaine,ExtracChamp,13,9);
       NumRess=atoi(NbrEnChaine);
       ExtracChamp=str_field(Trame,*LgtTrame,3,'\t');
       if (ExtracChamp!=NULL)
       {
        strcpy_termnotnull(MessagesBox[NumRess],ExtracChamp,13,9);
        ReponseOk=True;
        RefreshType=RFH_MESSAGEBOX;
        RefreshParam=NumRess;
       }
      }
     }
    }

    /* REQUETE 'DATE?' */
    /*-----------------*/
    if (strcmp_termnotnull(CurRequestStr,"DATE?",13,9)==0)
    {
     TraitementReponseExistant=True;
     if (strcmp_limited(Trame,"DATE=",5)!=0)
     {
      DemandeReenvoi=True;
     }
     else
     {
      ExtracChamp=str_field(Trame,*LgtTrame,2,'\t');
      if (ExtracChamp!=NULL)
      {
       strcpy_termnotnull(Teletrans.LocalDate,ExtracChamp,13,9);
       ReponseOk=True;
       RefreshType=RFH_DATE;
      }
     }
    }

    /* REQUETE 'TIME?' */
    /*-----------------*/
    if (strcmp_termnotnull(CurRequestStr,"TIME?",13,9)==0)
    {
     TraitementReponseExistant=True;
     if (strcmp_limited(Trame,"TIME=",5)!=0)
     {
      DemandeReenvoi=True;
     }
     else
     {
      ExtracChamp=str_field(Trame,*LgtTrame,2,'\t');
      if (ExtracChamp!=NULL)
      {
       strcpy_termnotnull(Teletrans.LocalTime,ExtracChamp,13,9);
       ReponseOk=True;
       RefreshType=RFH_TIME;
      }
     }
    }

    /* REQUETE 'J?' */
    /*--------------*/
    if (strcmp_termnotnull(CurRequestStr,"J?",13,9)==0)
    {
     TraitementReponseExistant=True;
     /* Fin du journal ? : Statut 001 FIN */
     if (StatutRecu==1)
     {
      strcpy(Even_Journal,"FIN");
      ReponseOk=True;
      RefreshType=RFH_JOURNAL;
     }
     else
     {
      if (strcmp_limited(Trame,"J=",2)!=0)
      {
       DemandeReenvoi=True;
      }
      else
      {
       strcpy_limited(Even_Journal,Trame+4,*LgtTrame-4);
       Even_Journal[*LgtTrame-8]=0;
       ReponseOk=True;
       RefreshType=RFH_JOURNAL;
      }
     }
    }


    if (!(TraitementReponseExistant))
    {
     ErrorMessageRequest("Pas de traitement implémenté pour la demande envoyée...");
     ErrorMessageRequest("Ce programme a planté...bouhhhh...");
     exit(30);
    }
    if (!(ReponseOk))
    {
     DemandeReenvoi=True;
    }

   } 
  }
 }
 if (ReponseOk==True)
 {
  strcpy(CurRequestStr,"");
 }
 /* Time Out */
 if (*MemoLaunchTime==NULL)
 {
  DemandeReenvoi=True;
 }
 /* Réenvoyer la trame requête car problème dans la réponse ou TimeOut*/
 if (DemandeReenvoi==True)
 {
  *Attemps=*Attemps-1;
  /* Il reste des essais ? */
  if (*Attemps>0)
  {
   *MemoLaunchTime=get_timer_secs();
   *LgtTrame=0;
   if (MoniteurActif)
    Print_Monitor("¤",1,0,0);
   Serial_Write(SerialIO,CurRequestStr,CurRequestLgt);
  }
  else
  {
   /* Trop de merdes, on raccroche */
   hangup_modem();
   TeletransOnLine=False;
  }
 }
 return ReponseOk;
}

