Files

1938 lines
96 KiB
C

//**********************************************************************************************************************************************************************************
// Fichier M_COMMANDES.C
//
// Contient toutes les fonctions liées aux commandes envoyées et reçues sur M_Bus
//**********************************************************************************************************************************************************************************/
// #define __DEBUG_M_COMMANDES_GENERALES //Décommenter cette ligne pour avoir les messages de debug concernant les commandes générales du modem
// #define __DEBUG_M_COMMANDES_GNSS //Décommenter cette ligne pour avoir les messages de debug concernant les commandes GNSS
// #define __DEBUG_M_COMMANDES_SMS //Décommenter cette ligne pour avoir les messages de debug concernant les commandes SMS
// #define __DEBUG_M_COMMANDES_FTP_GET //Décommenter cette ligne pour avoir les messages de debug concernant les commandes FTP GET
// #define __DEBUG_M_COMMANDES_FTP_LIST //Décommenter cette ligne pour avoir les messages de debug concernant les commandes FTP LIST
// #define __DEBUG_M_COMMANDES_FTP_PUT //Décommenter cette ligne pour avoir les messages de debug concernant les commandes FTP PUT
// #define __DEBUG_M_COMMANDES_HTTP //Décommenter cette ligne pour avoir les messages de debug concernant les commandes HTTP
// Includes :
#include "main.h"
// Prototypes :
int8_t m_bus_down_commande_libre(char * ptr_cde, uint8_t mode_protocole, uint16_t time_out, int8_t max_repetitions);
int8_t m_bus_down_commande_libre_binaire(uint16_t code, char * ptr_cde, uint32_t lg_cde, uint8_t mode_protocole, uint16_t time_out, int8_t max_repetitions);
int8_t m_bus_down_analyse_reponse_commande(void);
int8_t m_bus_down_recherche_code_erreur(void);
// Variables globales :
//***************************************************************************************************************************************************************
//***************************************************************************************************************************************************************
// DOWN
//***************************************************************************************************************************************************************
//***************************************************************************************************************************************************************
/*****************************************************************************************************************************************************************
Fonction : Cette fonction est intermédiaire. Elle sert juste à calculer la taille de la commande à émettre avant de la transmettre à la fonction BINAIRE
qui suit. Cela évite d'alourdir l'appel des commandes en demandant un 'strlen("AT+xxxx")' alors que la chaine est déjà passée en paramètres.
De plus, la fonction BINAIRE est parfois appelée directement avec des commandes qui ne sont pas des chaines (et dans ce cas, on passe la longueur).
Reçoit : un pointeur sur le début de la commande (la chaine doit se terminer par NULL), le mode protocole, la durée du time-out s'il doit être particulier (en x100ms)
et le nombre maxi de répétitions (-1 si valeur par défaut)
Renvoit : 0 si aucune erreur, -1 si la commande n'a pas pu être générée et stockée dans le buffer de commandes.
******************************************************************************************************************************************************************/
int8_t m_bus_down_commande_libre(char * ptr_cde, uint8_t mode_protocole, uint16_t time_out, int8_t max_repetitions)
{
uint16_t code;
if (strstr(ptr_cde, "ATE0") != NULL) code = M_COMMANDE_ATE; // Il est important de mettre le '0', sinon cette commande intercepte les SHSTATE... (ou alors, mettre ATE [après] SHSTATE)
else if (strstr(ptr_cde, "AT+CCID") != NULL) code = M_COMMANDE_CCID;
else if (strstr(ptr_cde, "AT+CFUN") != NULL) code = M_COMMANDE_CFUN;
else if (strstr(ptr_cde, "AT+CGMR") != NULL) code = M_COMMANDE_CGMR;
else if (strstr(ptr_cde, "AT+CGNAPN") != NULL) code = M_COMMANDE_CGNAPN;
else if (strstr(ptr_cde, "AT+CGNSINF") != NULL) code = M_COMMANDE_CGNSINF;
else if (strstr(ptr_cde, "AT+CGSN") != NULL) code = M_COMMANDE_CGSN;
else if (strstr(ptr_cde, "AT+CIMI") != NULL) code = M_COMMANDE_CIMI;
else if (strstr(ptr_cde, "AT+CMGL=") != NULL) code = M_COMMANDE_CMGL;
else if (strstr(ptr_cde, "AT+CNACT?") != NULL) code = M_COMMANDE_CNACT;
else if (strstr(ptr_cde, "AT+CNACT=0,") != NULL) code = M_COMMANDE_CNACT_0_X;
else if (strstr(ptr_cde, "AT+CNUM") != NULL) code = M_COMMANDE_CNUM;
else if (strstr(ptr_cde, "AT+CPSI?") != NULL) code = M_COMMANDE_CPSI;
else if (strstr(ptr_cde, "AT+CREG?") != NULL) code = M_COMMANDE_CREG;
else if (strstr(ptr_cde, "AT+CSQ") != NULL) code = M_COMMANDE_CSQ;
else if (strstr(ptr_cde, "AT+FTPGET=1") != NULL) code = M_COMMANDE_FTPGET_1;
else if (strstr(ptr_cde, "AT+FTPGET=2") != NULL) code = M_COMMANDE_FTPGET_2;
else if (strstr(ptr_cde, "AT+FTPLIST=1") != NULL) code = M_COMMANDE_FTPLIST_1;
else if (strstr(ptr_cde, "AT+FTPLIST=2") != NULL) code = M_COMMANDE_FTPLIST_2;
else if (strstr(ptr_cde, "AT+FTPPUT=1") != NULL) code = M_COMMANDE_FTPPUT_1;
else if (strstr(ptr_cde, "AT+FTPPUT=2") != NULL) code = M_COMMANDE_FTPPUT_2;
else if (strstr(ptr_cde, "AT+FTPSIZE") != NULL) code = M_COMMANDE_FTPSIZE;
else if (strstr(ptr_cde, "AT+SHREAD") != NULL) code = M_COMMANDE_SHREAD;
else if (strstr(ptr_cde, "AT+SHREQ") != NULL) code = M_COMMANDE_SHREQ;
else if (strstr(ptr_cde, "AT+SHSTATE?") != NULL) code = M_COMMANDE_SHSTATE;
else code = M_COMMANDE_INCONNUE;
return(m_bus_down_commande_libre_binaire(code, ptr_cde, strlen(ptr_cde), mode_protocole, time_out, max_repetitions));
}
/*****************************************************************************************************************************************************************
Fonction : Commande libre BINAIRE formattée et envoyée vers le modem
Vérifie que le buffer de commandes à émettre sur C-Bus a un emplacement de libre.
Si oui, génère la commande correspondante dans le buffer de commandes et met à jour la longueur de la commande ainsi que
sa priorité.
Reçoit : Le code de la commande, un pointeur sur le début de la commande (la chaine n'a PAS à se terminer par NULL), la longueur de la commande,
le mode protocole, la durée du time-out s'il doit être particulier (en x100ms) et le nombre maxi de répétitions (-1 si valeur par défaut).
Renvoit : 0 si aucune erreur, -1 si la commande n'a pas pu être générée et stockée dans le buffer de commandes.
******************************************************************************************************************************************************************/
int8_t m_bus_down_commande_libre_binaire(uint16_t code, char * ptr_cde, uint32_t lg_cde, uint8_t mode_protocole, uint16_t time_out, int8_t max_repetitions)
{
uint8_t priorite;
struct Struct_commande_m_bus *buffer_cde;
char tmp[MAX_LONGUEUR_BUFFER_TEMPORAIRE_DEBUG];
// Vérification des paramètres reçus :
if ((mode_protocole != M_BUS_PROTOCOLE_NORMAL) &&
(mode_protocole != M_BUS_PROTOCOLE_DATA_BINAIRE)) return(-1);
if (lg_cde >= M_BUS_MAX_TAILLE_CDE) return(-1);
// Préparation de la commande :
priorite = PRIORITE_CDE_M_BUS_FAIBLE;
if (m_bus_next_write_buffer_cdes(priorite) != -1) // On recherche le prochain slot de commande libre
{
m_bus.nb_refus_buffer = 0; // RAZ du compteur à chaque réussite
buffer_cde = &m_bus.down.buffer_cdes[m_bus.down.ptr_fin_buffer_cdes]; // L'utilisation du pointeur de struct simplifie l'écriture ensuite...
buffer_cde->lg_cde = 0;
// Chargement de la commande proprement-dite :
while (buffer_cde->lg_cde < lg_cde)
{
buffer_cde->cde[buffer_cde->lg_cde ++] = *(ptr_cde ++);
}
// Code de la commande :
buffer_cde->code = code;
// Priorité de la commande :
buffer_cde->priorite = priorite;
// Type de réponse attendue :
buffer_cde->mode_protocole = mode_protocole;
// Time-out à utiliser pour la commande :
if (time_out > 0) buffer_cde->time_out = time_out;
else buffer_cde->time_out = M_BUS_TIME_OUT_REPONSE_TX;
// Nombre max de répétitions :
if (max_repetitions >= 0) buffer_cde->max_repetitions = max_repetitions;
else buffer_cde->max_repetitions = M_BUS_PROTOCOLE_TX_MAX_REPETITIONS;
return(0);
}
else
{
if (++ m_bus.nb_refus_buffer > M_BUS_MAX_REFUS_BUFFER_CDES_PLEIN) // Si les refus de nouvelle commandes sur M-Bus augmentent, on va réactiver le modem car il y a un sérieux problème...
{
sprintf(tmp, "Le nombre de refus de nouvelle commande dans le buffer de M-Bus est trop important (%i). Le modem va être réactivé", m_bus.nb_refus_buffer);
affichage_debug(__FILE__, __LINE__, tmp, TYPE_MESSAGE_DEBUG_ERREUR);
// Enregistrement dans l'historique :
enregistrement_historique(TYPE_SOURCE_HISTORIQUE_SYSTEME, SYSTEME_MODEM_ERREUR_M_BUS_PLEIN, 0, m_bus.nb_refus_buffer, NULL);
modem.sequenceur.etat = ETAT_SEQUENCEUR_MODEM_DEBUT_IMPULSION_RESET; // Déclenche une impulsion >12s de reset sur POWER_KEY
}
return (-1); // Si aucun slot n'est disponible, on laisse tomber la commande...
}
}
/*****************************************************************************************************************************************************************
Fonction : Analyse la réponse à la commande et effectue, si besoin, le traitement nécessaire.
Le principe est de d'abord de détecter la présence d'un éventuel code d'erreur dans la réponse et de stocker son code.
Ensuite, on saute à la fonction (en pratique, un case d'un grand switch) correspondant à la commande qui avait été émise et donc qui déclenche
cette réponse. Là, on peut avoir les grandes tâches suivantes :
1- cas où on vient de recevoir un code d'erreur (y compris OK qui est considéré comme l'un d'eux) : dans ce cas, on décide ce qu'on doit faire
de ce code dans ce contexte. Souvent, il s'agit de ne pas tenir compte d'un OK intempestif (poru cela, on écrase l'erreur par M_BUS_ERREUR_AUCUNE).
2- On effectue le traitement de la trame reçue, selon la fonction émise et le contexte.
3- si on considère que le traitement est terminé, on écrase le code d'erreur pour le mettre à M_BUS_ERREUR_OK. Cette phase 3 est inutile pour pas
mal de commandes simples car leur trame de retour est suivie d'une trame OK qui libère le protocole tout seul.
En toute fin de fonction, on traite le code d'erreur subsistant. S'il est M_BUS_ERREUR_AUCUNE, on ne fait rien. S'il est M_BUS_ERREUR_OK on remet
le protocole au repos.
Reçoit : Rien (traite la réponse qui est stockée dans la structure m_bus.down.reponse.xxxx
Renvoit : 0 si aucune erreur, -1 si l'analyse de la réponse a rencontré une erreur.
******************************************************************************************************************************************************************/
int8_t m_bus_down_analyse_reponse_commande(void)
{
int8_t erreur;
int16_t val_16;
uint16_t i, j;
uint16_t x;
char *ptr_chaine;
int32_t ptr_reponse;
int32_t lg_parametre;
char parametre[M_COMMANDE_MAX_LONGUEUR_PARAMETRE_REPONSE];
char *ptr[M_COMMANDE_MAX_NOMBRE_PARAMETRES_REPONSE];
MYSQL_RES *result = NULL;
MYSQL_ROW row = NULL;
char requete[MAX_LONGUEUR_REQUETE_MYSQL];
char tmp[MAX_LONGUEUR_BUFFER_TEMPORAIRE_DEBUG];
m_bus.down.reponse.reponse[m_bus.down.reponse.lg_reponse] = 0; // Ajout d'un caractère NULL de fin de chaine mais sans changer la longueur des données utiles (pas de 'lg_reponse ++' après l'affectation)...
erreur = m_bus_down_recherche_code_erreur();
switch(m_bus.down.buffer_cdes[m_bus.down.ptr_debut_buffer_cdes].code)
{
//------------------------------------------------------------------------------------------------------
// Commande d'echo ATEx :
case M_COMMANDE_ATE:
{
if (erreur == M_BUS_ERREUR_OK)
{
modem.etat_liaison = ON; // Mise à jour de l'état de la liaison dès qu'on a réussi un échange de commande ATEx réussi...
modem.sequenceur.compteur = 0; // ... et on force le compteur du modem à 0 car il est inutile d'attendre plus.
sprintf(tmp, "La liaison avec le modem est établie");
affichage_debug(__FILE__, __LINE__, tmp, TYPE_MESSAGE_DEBUG_PAR_DEFAUT);
}
break;
}
//------------------------------------------------------------------------------------------------------
// Numéro d'ICCID :
case M_COMMANDE_CCID:
{
if (erreur != M_BUS_ERREUR_AUCUNE) break; // Utile, notamment lorsqu'il y a une trame OK qui passe...
// Recherche de la valeur antérieure :
sprintf(requete, "SELECT Valeur FROM TB_Systeme WHERE Validite=1 AND Nom='No_iccid' ");
mysql_query(bdd.pointeur, requete); // Envoi de la requête à MYSQL
result = mysql_store_result(bdd.pointeur); // Récup des résultats de la requête
while((row = mysql_fetch_row(result))) // Boucle sur tous les résultats de la requête
{
if (strcmp(row[0], (char *) m_bus.down.reponse.reponse) != 0) // Si la nouvelle valeur est différente de la précédente :
{
// Mise à jour du numéro d'ICCID de la carte SIM dans la BDD :
sprintf(requete, "UPDATE TB_Systeme SET Valeur='%s' WHERE Nom='No_iccid' ", m_bus.down.reponse.reponse);
mysql_query(bdd.pointeur, requete);
// Enregistrement dans l'historique :
enregistrement_historique(TYPE_SOURCE_HISTORIQUE_SYSTEME, SYSTEME_MODEM_CHANGEMENT_ICCID, 0, 0, (char *) m_bus.down.reponse.reponse);
#ifdef __DEBUG_M_COMMANDES_GENERALES
sprintf(tmp, "Réponse à la commande de lecture du n° d'ICCID (Integrated Circuit Card ID - numéro de série de la carte SIM) du modem reçue : [%s]", (char *)m_bus.down.reponse.reponse);
affichage_debug(__FILE__, __LINE__, tmp, TYPE_MESSAGE_DEBUG_PAR_DEFAUT);
#endif
}
}
mysql_free_result(result); //Libération du jeu de résultat
break;
}
//------------------------------------------------------------------------------------------------------
// Functions du Modem :
case M_COMMANDE_CFUN:
{
if (erreur != M_BUS_ERREUR_AUCUNE) break; // Utile, notamment lorsqu'il y a une trame OK qui passe...
#ifdef __DEBUG_M_COMMANDES_GENERALES
sprintf(tmp, "Réponse à la commande de lecture des Functions du modem reçue : [%s]", (char *)m_bus.down.reponse.reponse);
affichage_debug(__FILE__, __LINE__, tmp, TYPE_MESSAGE_DEBUG_PAR_DEFAUT);
#endif
break;
}
//------------------------------------------------------------------------------------------------------
// Révision du firmware :
case M_COMMANDE_CGMR:
{
if (erreur != M_BUS_ERREUR_AUCUNE) break; // Utile, notamment lorsqu'il y a une trame OK qui passe...
#ifdef __DEBUG_M_COMMANDES_GENERALES
sprintf(tmp, "Réponse à la commande de lecture de la version du modem reçue : [%s]", (char *)m_bus.down.reponse.reponse);
affichage_debug(__FILE__, __LINE__, tmp, TYPE_MESSAGE_DEBUG_PAR_DEFAUT);
#endif
// Recherche de la valeur antérieure :
sprintf(requete, "SELECT Valeur FROM TB_Systeme WHERE Validite=1 AND Nom='Version_soft_modem' ");
mysql_query(bdd.pointeur, requete); // Envoi de la requête à MYSQL
result = mysql_store_result(bdd.pointeur); // Récup des résultats de la requête
while((row = mysql_fetch_row(result))) // Boucle sur tous les résultats de la requête
{
if (strcmp(row[0], (char *) m_bus.down.reponse.reponse) != 0) // Si la nouvelle valeur est différente de la précédente :
{
// Mise à jour de la révision du firmware du modem dans la BDD :
sprintf(requete, "UPDATE TB_Systeme SET Valeur='%s' WHERE Nom='Version_soft_modem' ", m_bus.down.reponse.reponse);
mysql_query(bdd.pointeur, requete);
// Enregistrement dans l'historique :
enregistrement_historique(TYPE_SOURCE_HISTORIQUE_SYSTEME, SYSTEME_MODEM_CHANGEMENT_REVISION_FIRMWARE, 0, 0, (char *) m_bus.down.reponse.reponse);
}
}
mysql_free_result(result); //Libération du jeu de résultat
break;
}
//------------------------------------------------------------------------------------------------------
// Acces Point Name (APN) :
case M_COMMANDE_CGNAPN:
{
if (erreur != M_BUS_ERREUR_AUCUNE) break; // Utile, notamment lorsqu'il y a une trame OK qui passe...
#ifdef __DEBUG_M_COMMANDES_GENERALES
sprintf(tmp, "Réponse à la commande de lecture de l'Access Point Name (APN) reçue : [%s]", (char *)m_bus.down.reponse.reponse);
affichage_debug(__FILE__, __LINE__, tmp, TYPE_MESSAGE_DEBUG_PAR_DEFAUT);
#endif
bool flag_validite = FALSE;
ptr_chaine = strstr((char *)m_bus.down.reponse.reponse, ": ");
if (ptr_chaine != NULL) // Si NULL, c'est qu'il n'y a pas de ':' donc la trame n'est pas exploitable....
{
ptr_chaine += 2; // Le '+2' permet de démarrer la 'ptr_chaine' après le ": ".
ptr[0] = strtok(ptr_chaine, ","); // Extraction du premier segment avant le premier ','
for (i=1; ((i < M_COMMANDE_MAX_NOMBRE_PARAMETRES_REPONSE) && (ptr[(i-1)] != NULL)); i++)
{
// Traitement de chaque paramètre :
switch(i)
{
case 1 : // Validité :
{
if (atoi(ptr[i-1]) == 1) flag_validite = TRUE;
break;
}
case 2 : // APN :
{
if (!flag_validite) break; // Si le premier paramètre n'est pas 1, on ne traite pas le second
// Recherche de la valeur antérieure :
sprintf(requete, "SELECT Valeur FROM TB_Systeme WHERE Validite=1 AND Nom='Modem_apn' ");
mysql_query(bdd.pointeur, requete); // Envoi de la requête à MYSQL
result = mysql_store_result(bdd.pointeur); // Récup des résultats de la requête
while((row = mysql_fetch_row(result))) // Boucle sur tous les résultats de la requête
{
if (strcmp(row[0], (char *) ptr[i-1]) != 0) // Si la nouvelle valeur est différente de la précédente :
{
// Mise à jour de l'APN dans la BDD :
sprintf(requete, "UPDATE TB_Systeme SET Valeur='%s' WHERE Nom='Modem_apn' ", ptr[i-1]);
mysql_query(bdd.pointeur, requete);
// Enregistrement dans l'historique :
enregistrement_historique(TYPE_SOURCE_HISTORIQUE_SYSTEME, SYSTEME_MODEM_CHANGEMENT_APN, 0, 0, ptr[i-1]);
}
}
mysql_free_result(result); //Libération du jeu de résultat
break;
}
default : ;
}
ptr[i] = strtok(NULL, ",");
}
}
break;
}
//------------------------------------------------------------------------------------------------------
// GNSS Navigation Information :
// Exemples de réponse reçue sur M-Bus '+CGNSINF: 1,,,0.000000,0.000000,-18.000,,,1,,0.1,0.1,0.1,,,,9999000.0,6144.0'
// '+CGNSINF: 1,1,20201119125432.000,45.751259,4.802224,252.754,0.00,,0,,1.5,1.8,1.0,,6,,10.4,6.0'
case M_COMMANDE_CGNSINF:
{
if (erreur != M_BUS_ERREUR_AUCUNE) break; // Utile, notamment lorsqu'il y a une trame OK qui passe...
#ifdef __DEBUG_M_COMMANDES_GNSS
sprintf(tmp, "Réponse à la commande de lecture GNSS reçue : [%s]", (char *)m_bus.down.reponse.reponse);
affichage_debug(__FILE__, __LINE__, tmp, TYPE_MESSAGE_DEBUG_PAR_DEFAUT);
#endif
bool flag_sortie = FALSE;
ptr_reponse = recherche_caractere_dans_chaine((char *)m_bus.down.reponse.reponse, ':', 0);
if (ptr_reponse != -1)
{
ptr_reponse += 2; // Le '+2' permet de démarrer la 'ptr_reponse' après le ": ".
for (i=1; ((i < M_COMMANDE_MAX_NOMBRE_PARAMETRES_REPONSE) && (m_bus.down.reponse.reponse[ptr_reponse] != 0)); i++)
{
// Recherche du bloc paramètre suivant :
lg_parametre = recherche_caractere_dans_chaine((char *)m_bus.down.reponse.reponse, ',', ptr_reponse) - ptr_reponse;
if (lg_parametre >= 0) // Cas intermédiaire (on a trouvé un ',') :
{
for (j = 0; j < lg_parametre; j ++) parametre[j] = m_bus.down.reponse.reponse[ptr_reponse ++];
parametre[j] = 0;
ptr_reponse ++; // Permet d'échapper le séparateur ','
}
else // Cas du dernier paramètre (on n'a pas trouvé de nouveau ',') :
{
for (j = 0; m_bus.down.reponse.reponse[ptr_reponse] != 0; j ++) parametre[j] = m_bus.down.reponse.reponse[ptr_reponse ++];
parametre[j] = 0;
}
// Traitement du paramètre :
switch(i)
{
//=====================================================
case 1 : // Run status (0 GNSS off, 1 GNSS on) :
{
if (atoi(parametre) != 1) flag_sortie = TRUE;
break;
}
//=====================================================
case 2 : // Fix status (0 Not fixed position, 1 Fixed position.) :
{
if (atoi(parametre) != 1) flag_sortie = TRUE;
else modem.compteur_cycles_valides_gnss ++; // Le compteur est incrémenté à chaque fois qu'on reçoit une trame avec une position valide
break;
}
//=====================================================
case 3 : // UTC Date & Time :
{
if (strlen(parametre) != 0)
{
struct Struct_date date;
struct Struct_heure heure;
char chaine_temp[20];
uint8_t n, m;
n = 0; // 'n' balaie 'parametre' du début à la fin
for (m=0; m<4; m++) chaine_temp[m] = parametre[n ++]; // 'm' balaie 'paramètre' sur un nombre défini de caractères, à partir de la position actuelle de 'n'
chaine_temp[m] = 0;
date.annee = atoi(chaine_temp);
for (m=0; m<2; m++) chaine_temp[m] = parametre[n ++];
chaine_temp[m] = 0;
date.mois = atoi(chaine_temp);
for (m=0; m<2; m++) chaine_temp[m] = parametre[n ++];
chaine_temp[m] = 0;
date.jour = atoi(chaine_temp);
for (m=0; m<2; m++) chaine_temp[m] = parametre[n ++];
chaine_temp[m] = 0;
heure.heures = atoi(chaine_temp);
for (m=0; m<2; m++) chaine_temp[m] = parametre[n ++];
chaine_temp[m] = 0;
heure.minutes = atoi(chaine_temp);
for (m=0; m<2; m++) chaine_temp[m] = parametre[n ++];
chaine_temp[m] = 0;
heure.secondes = atoi(chaine_temp);
set_date_heure(date, heure); // Mise à jour de la date/heure système à partir de l'heure reçue du GNSS (toujours en UTC !)
// SDIR #107 :
// c_bus_down_commande_config_date_heure(); // Mise à jour de la date/heure du Compagnon dans la foulée (lui aussi, toujours en UTC)
#ifdef __DEBUG_M_COMMANDES_GNSS
sprintf(tmp, "\tUTC Date & Time = [%s], soit le %02i/%02i/%04i à %02i:%02i:%02i", parametre, date.jour, date.mois, date.annee, heure.heures, heure.minutes, heure.secondes);
affichage_debug(__FILE__, __LINE__, tmp, TYPE_MESSAGE_DEBUG_PAR_DEFAUT);
#endif
}
break;
}
//=====================================================
case 4 : // Latitude :
{
if (strlen(parametre) != 0)
{
val_16 = entree_no(TYPE_ENTREES_PREDEFINIES, 0, ENTREE_PREDEFINIE_LAT);
if ((val_16 >= 0) && (val_16 < MAX_NOMBRE_ENTREES_PREDEFINIES)) entrees.predefinies.entrees[val_16].valeur = atof(parametre);
#ifdef __DEBUG_M_COMMANDES_GNSS
sprintf(tmp, "\tLatitude = [%s], soit %i en millionnième de degré", parametre, entrees.predefinie.compagnon.lat);
affichage_debug(__FILE__, __LINE__, tmp, TYPE_MESSAGE_DEBUG_PAR_DEFAUT);
#endif
}
break;
break;
}
//=====================================================
case 5 : // Longitude :
{
if (strlen(parametre) != 0)
{
val_16 = entree_no(TYPE_ENTREES_PREDEFINIES, 0, ENTREE_PREDEFINIE_LON);
if ((val_16 >= 0) && (val_16 < MAX_NOMBRE_ENTREES_PREDEFINIES)) entrees.predefinies.entrees[val_16].valeur = atof(parametre);
#ifdef __DEBUG_M_COMMANDES_GNSS
sprintf(tmp, "\tLongitude = [%s], soit %i en millionnième de degré", parametre, entrees.predefinie.compagnon.lon);
affichage_debug(__FILE__, __LINE__, tmp, TYPE_MESSAGE_DEBUG_PAR_DEFAUT);
#endif
}
break;
}
//=====================================================
case 6 : // Altitude :
{
if (strlen(parametre) != 0)
{
val_16 = entree_no(TYPE_ENTREES_PREDEFINIES, 0, ENTREE_PREDEFINIE_LAT);
if ((val_16 >= 0) && (val_16 < MAX_NOMBRE_ENTREES_PREDEFINIES))
{
if (parametre[0] == '-') entrees.predefinies.entrees[val_16].valeur = 0; // Si la valeur retournée est négative, on la fixe à 0...
else entrees.predefinies.entrees[val_16].valeur = atof(parametre) / 1000;
}
#ifdef __DEBUG_M_COMMANDES_GNSS
sprintf(tmp, "\tAltitude = [%s], soit ALT = %i mm", parametre, entrees.predefinie.compagnon.alt);
affichage_debug(__FILE__, __LINE__, tmp, TYPE_MESSAGE_DEBUG_PAR_DEFAUT);
#endif
}
break;
}
//=====================================================
case 7 : // Speed over ground (km/h) :
{
if (strlen(parametre) != 0)
{
val_16 = entree_no(TYPE_ENTREES_PREDEFINIES, 0, ENTREE_PREDEFINIE_SOG);
if ((val_16 >= 0) && (val_16 < MAX_NOMBRE_ENTREES_PREDEFINIES)) entrees.predefinies.entrees[val_16].valeur = atof(parametre) / 1.852; // Conversion en Knts (noeuds)
#ifdef __DEBUG_M_COMMANDES_GNSS
sprintf(tmp, "\tVitesse fond = [%s], soit SOG = %i", parametre, entrees.predefinie.compagnon.sog);
affichage_debug(__FILE__, __LINE__, tmp, TYPE_MESSAGE_DEBUG_PAR_DEFAUT);
#endif
}
break;
}
//=====================================================
case 8 : // Course over ground :
{
if (strlen(parametre) != 0)
{
val_16 = entree_no(TYPE_ENTREES_PREDEFINIES, 0, ENTREE_PREDEFINIE_COG);
if ((val_16 >= 0) && (val_16 < MAX_NOMBRE_ENTREES_PREDEFINIES)) entrees.predefinies.entrees[val_16].valeur = atof(parametre);
#ifdef __DEBUG_M_COMMANDES_GNSS
sprintf(tmp, "\tCap réel = [%s], soit COG = %i", parametre, entrees.predefinie.compagnon.cog);
affichage_debug(__FILE__, __LINE__, tmp, TYPE_MESSAGE_DEBUG_PAR_DEFAUT);
#endif
}
break;
}
//=====================================================
case 9 : // Fix mode :
{
// sprintf(tmp, "\tConstellation utilisée = [%s]", parametre);
// affichage_debug(__FILE__, __LINE__, tmp, TYPE_MESSAGE_DEBUG_PAR_DEFAUT);
break;
}
//=====================================================
case 11 : // HDOP :
{
// sprintf(tmp, "\tHDOP = [%s]", parametre);
// affichage_debug(__FILE__, __LINE__, tmp, TYPE_MESSAGE_DEBUG_PAR_DEFAUT);
break;
}
//=====================================================
case 12 : // PDOP :
{
// sprintf(tmp, "\tPDOP = [%s]", parametre);
// affichage_debug(__FILE__, __LINE__, tmp, TYPE_MESSAGE_DEBUG_PAR_DEFAUT);
break;
}
//=====================================================
case 13 : // VDOP :
{
// sprintf(tmp, "\tVDOP = [%s]", parametre);
// affichage_debug(__FILE__, __LINE__, tmp, TYPE_MESSAGE_DEBUG_PAR_DEFAUT);
break;
}
//=====================================================
case 15 : // GNSS Satellites in view :
{
if (strlen(parametre) != 0)
{
val_16 = entree_no(TYPE_ENTREES_PREDEFINIES, 0, ENTREE_PREDEFINIE_SIV);
if ((val_16 >= 0) && (val_16 < MAX_NOMBRE_ENTREES_PREDEFINIES)) entrees.predefinies.entrees[val_16].valeur = atof(parametre);
#ifdef __DEBUG_M_COMMANDES_GNSS
sprintf(tmp, "\tNombre satellites = [%s], soit SIV = %i", parametre, entrees.predefinie.compagnon.siv);
affichage_debug(__FILE__, __LINE__, tmp, TYPE_MESSAGE_DEBUG_PAR_DEFAUT);
#endif
}
break;
}
//=====================================================
case 17 : // HPA :
{
if (strlen(parametre) != 0)
{
val_16 = entree_no(TYPE_ENTREES_PREDEFINIES, 0, ENTREE_PREDEFINIE_HPA);
if ((val_16 >= 0) && (val_16 < MAX_NOMBRE_ENTREES_PREDEFINIES)) entrees.predefinies.entrees[val_16].valeur = atof(parametre);
#ifdef __DEBUG_M_COMMANDES_GNSS
sprintf(tmp, "\tHPA = [%s], soit %i m", parametre, entrees.predefinie.compagnon.hpa);
affichage_debug(__FILE__, __LINE__, tmp, TYPE_MESSAGE_DEBUG_PAR_DEFAUT);
#endif
}
break;
}
//=====================================================
case 18 : // VPA :
{
if (strlen(parametre) != 0)
{
val_16 = entree_no(TYPE_ENTREES_PREDEFINIES, 0, ENTREE_PREDEFINIE_VPA);
if ((val_16 >= 0) && (val_16 < MAX_NOMBRE_ENTREES_PREDEFINIES)) entrees.predefinies.entrees[val_16].valeur = atof(parametre);
#ifdef __DEBUG_M_COMMANDES_GNSS
sprintf(tmp, "\tVPA = [%s], soit %i m", parametre, entrees.predefinie.compagnon.vpa);
affichage_debug(__FILE__, __LINE__, tmp, TYPE_MESSAGE_DEBUG_PAR_DEFAUT);
#endif
}
break;
}
default : ;
}
if (flag_sortie) break; // Evite de continuer à parser la réponse alors que la chaine ne sera pas exploitable...
}
modem.sequenceur.compteur_time_out = 0; // Inutile l'attendre la fin du time-out puiqu'on a reçu la réponse
}
break;
}
//------------------------------------------------------------------------------------------------------
// Numéro d'IMEI :
case M_COMMANDE_CGSN:
{
if (erreur != M_BUS_ERREUR_AUCUNE) break; // Utile, notamment lorsqu'il y a une trame OK qui passe...
#ifdef __DEBUG_M_COMMANDES_GENERALES
sprintf(tmp, "Réponse à la commande de lecture du n° d'EMEI reçue : [%s]", (char *)m_bus.down.reponse.reponse);
affichage_debug(__FILE__, __LINE__, tmp, TYPE_MESSAGE_DEBUG_PAR_DEFAUT);
#endif
// Recherche de la valeur antérieure :
sprintf(requete, "SELECT Valeur FROM TB_Systeme WHERE Validite=1 AND Nom='No_imei' ");
mysql_query(bdd.pointeur, requete); // Envoi de la requête à MYSQL
result = mysql_store_result(bdd.pointeur); // Récup des résultats de la requête
while((row = mysql_fetch_row(result))) // Boucle sur tous les résultats de la requête
{
if (strcmp(row[0], (char *) m_bus.down.reponse.reponse) != 0) // Si la nouvelle valeur est différente de la précédente :
{
// Mise à jour du numéro d'IMEI du modem dans la BDD :
sprintf(requete, "UPDATE TB_Systeme SET Valeur='%s' WHERE Nom='No_imei' ", m_bus.down.reponse.reponse);
mysql_query(bdd.pointeur, requete);
// Enregistrement dans l'historique :
enregistrement_historique(TYPE_SOURCE_HISTORIQUE_SYSTEME, SYSTEME_MODEM_CHANGEMENT_IMEI, 0, 0, (char *) m_bus.down.reponse.reponse);
}
}
mysql_free_result(result); //Libération du jeu de résultat
break;
}
//------------------------------------------------------------------------------------------------------
// Numéro d'IMSI :
case M_COMMANDE_CIMI:
{
if (erreur != M_BUS_ERREUR_AUCUNE) break; // Utile, notamment lorsqu'il y a une trame OK qui passe...
#ifdef __DEBUG_M_COMMANDES_GENERALES
sprintf(tmp, "Réponse à la commande de lecture du N° d'IMSI reçue : [%s]", (char *)m_bus.down.reponse.reponse);
affichage_debug(__FILE__, __LINE__, tmp, TYPE_MESSAGE_DEBUG_PAR_DEFAUT);
#endif
// Recherche de la valeur antérieure :
sprintf(requete, "SELECT Valeur FROM TB_Systeme WHERE Validite=1 AND Nom='No_imsi' ");
mysql_query(bdd.pointeur, requete); // Envoi de la requête à MYSQL
result = mysql_store_result(bdd.pointeur); // Récup des résultats de la requête
while((row = mysql_fetch_row(result))) // Boucle sur tous les résultats de la requête
{
if (strcmp(row[0], (char *) m_bus.down.reponse.reponse) != 0) // Si la nouvelle valeur est différente de la précédente :
{
// Mise à jour du numéro d'IMSI de la carte SIM dans la BDD :
sprintf(requete, "UPDATE TB_Systeme SET Valeur='%s' WHERE Nom='No_imsi' ", m_bus.down.reponse.reponse);
mysql_query(bdd.pointeur, requete);
// Enregistrement dans l'historique :
enregistrement_historique(TYPE_SOURCE_HISTORIQUE_SYSTEME, SYSTEME_MODEM_CHANGEMENT_IMSI, 0, 0, (char *) m_bus.down.reponse.reponse);
}
}
mysql_free_result(result); //Libération du jeu de résultat
break;
}
//------------------------------------------------------------------------------------------------------
// Lecture des SMS :
// ATTENTION : ce code ne fonctionne qu'à 3 conditions :
// 1. que la réception soit configurée en mode Texte (AT+CMGF=1)
// 2. que le message fasse moins de 140 caractèrs (sinon il semble qu'il est convertit en mode PDU automatiquement)
// 3. que le message ne comprenne pas de retour à la ligne.
case M_COMMANDE_CMGL:
{
if (erreur != M_BUS_ERREUR_AUCUNE) break; // Utile, notamment lorsqu'il y a une trame OK qui passe...
#ifdef __DEBUG_M_COMMANDES_SMS
sprintf(tmp, "Réponse à la commande de lecture des SMS reçus CMGL : [%s]", (char *)m_bus.down.reponse.reponse);
affichage_debug(__FILE__, __LINE__, tmp, TYPE_MESSAGE_DEBUG_PAR_DEFAUT);
#endif
bool flag_sortie = FALSE;
ptr_reponse = recherche_caractere_dans_chaine((char *)m_bus.down.reponse.reponse, ':', 0);
if (ptr_reponse != -1)
{
ptr_reponse += 2; // Le '+2' permet de démarrer la 'ptr_reponse' après le ": ".
for (i=1; ((i < M_COMMANDE_MAX_NOMBRE_PARAMETRES_REPONSE) && (m_bus.down.reponse.reponse[ptr_reponse] != 0)); i++)
{
// Recherche du bloc paramètre suivant :
lg_parametre = recherche_caractere_dans_chaine((char *)m_bus.down.reponse.reponse, ',', ptr_reponse) - ptr_reponse;
if (lg_parametre >= 0) // Cas intermédiaire (on a trouvé un ',') :
{
for (j = 0; j < lg_parametre; j ++) parametre[j] = m_bus.down.reponse.reponse[ptr_reponse ++];
parametre[j] = 0;
ptr_reponse ++; // Permet d'échapper le séparateur ','
}
else // Cas du dernier paramètre (on n'a pas trouvé de nouveau ',') :
{
for (j = 0; m_bus.down.reponse.reponse[ptr_reponse] != 0; j ++) parametre[j] = m_bus.down.reponse.reponse[ptr_reponse ++];
parametre[j] = 0;
}
// Traitement du paramètre :
switch(i)
{
//=====================================================
case 1 : // Index :
{
modem.sms_en_cours.index = atoi(parametre);
#ifdef __DEBUG_M_COMMANDES_SMS
sprintf(tmp, "\tIndex du message = %i", atoi(parametre));
affichage_debug(__FILE__, __LINE__, tmp, TYPE_MESSAGE_DEBUG_PAR_DEFAUT);
#endif
break;
}
//=====================================================
case 2 : // Stat :
{
#ifdef __DEBUG_M_COMMANDES_SMS
sprintf(tmp, "\tStat du message = [%s]", parametre);
affichage_debug(__FILE__, __LINE__, tmp, TYPE_MESSAGE_DEBUG_PAR_DEFAUT);
#endif
break;
}
//=====================================================
case 3 : // Emetteur du message :
{
for(j = 0; parametre[j] != 0; j ++) parametre[j] = parametre[j+1]; // Supprime les '"' de début et de fin...
if (j > 1) parametre[j-2] = 0;
strcpy(modem.sms_en_cours.numero_emetteur, parametre);
#ifdef __DEBUG_M_COMMANDES_SMS
sprintf(tmp, "\tEmetteur du message = [%s]", parametre);
affichage_debug(__FILE__, __LINE__, tmp, TYPE_MESSAGE_DEBUG_PAR_DEFAUT);
#endif
break;
}
//=====================================================
case 4 : // Alpha de l'émetteur :
{
#ifdef __DEBUG_M_COMMANDES_SMS
if (strlen(parametre) > 0)
{
sprintf(tmp, "\tAlpha de l'emetteur du message = [%s]", parametre);
affichage_debug(__FILE__, __LINE__, tmp, TYPE_MESSAGE_DEBUG_PAR_DEFAUT);
}
#endif
break;
}
//=====================================================
case 5 : // Date du message :
{
j = 0;
modem.sms_en_cours.date[j ++] = '2'; // La date n'étant fournie que sur 2 digits, on ajoute le centenaire devant (20xx)
modem.sms_en_cours.date[j ++] = '0';
modem.sms_en_cours.date[j ++] = parametre[1]; // Année (dizaines) NB : le rang 0 est occupé par le '"' de début de date
modem.sms_en_cours.date[j ++] = parametre[2]; // Année (unités)
modem.sms_en_cours.date[j ++] = '-';
modem.sms_en_cours.date[j ++] = parametre[4]; // Mois (dizaines)
modem.sms_en_cours.date[j ++] = parametre[5]; // Mois (unités)
modem.sms_en_cours.date[j ++] = '-';
modem.sms_en_cours.date[j ++] = parametre[7]; // jour (dizaines)
modem.sms_en_cours.date[j ++] = parametre[8]; // jour (unités)
modem.sms_en_cours.date[j ++] = ' '; // Séparation avec l'heure à venir
modem.sms_en_cours.date[j ++] = 0;
break;
}
//=====================================================
case 6 : // Heure du message :
{
j = 11;
modem.sms_en_cours.date[j ++] = parametre[0]; // Heures (dizaines)
modem.sms_en_cours.date[j ++] = parametre[1]; // Heures (unités)
modem.sms_en_cours.date[j ++] = ':';
modem.sms_en_cours.date[j ++] = parametre[3]; // Minutes (dizaines)
modem.sms_en_cours.date[j ++] = parametre[4]; // Minutes (unités)
modem.sms_en_cours.date[j ++] = ':';
modem.sms_en_cours.date[j ++] = parametre[6]; // Secondes (dizaines)
modem.sms_en_cours.date[j ++] = parametre[7]; // Secondes (unités)
modem.sms_en_cours.date[j ++] = 0;
#ifdef __DEBUG_M_COMMANDES_SMS
sprintf(tmp, "\tDate et heure du message = [%s]", modem.sms_en_cours.date);
affichage_debug(__FILE__, __LINE__, tmp, TYPE_MESSAGE_DEBUG_PAR_DEFAUT);
#endif
break;
}
default :
{
sprintf(tmp, "\tParamètre inconnu trouvé en [%i] position = [%s]", i, parametre);
affichage_debug(__FILE__, __LINE__, tmp, TYPE_MESSAGE_DEBUG_PAR_DEFAUT);
break;
}
}
if (flag_sortie) break; // Evite de continuer à parser la réponse alors que la chaine ne sera pas exploitable...
}
m_bus.down.buffer_cdes[m_bus.down.ptr_debut_buffer_cdes].code = M_COMMANDE_CMGL_RECEPTION_DATA_MESSAGE;
}
break;
}
//------------------------------------------------------------------------------------------------------
// APP Network Active :
case M_COMMANDE_CNACT:
{
if (erreur != M_BUS_ERREUR_AUCUNE) break;
#ifdef __DEBUG_M_COMMANDES_GENERALES
sprintf(tmp, "Une réponse a la commande CNACT? été reçue de la part du modem : [%s]", (char *)m_bus.down.reponse.reponse);
affichage_debug(__FILE__, __LINE__, tmp, TYPE_MESSAGE_DEBUG_PAR_DEFAUT);
#endif
if (strstr((char *)m_bus.down.reponse.reponse, "+CNACT: 0,1") != NULL) // Cas où le PDP #0 est actif.
{
if (modem.etat_4g_lte == OFF) enregistrement_historique(TYPE_SOURCE_HISTORIQUE_SYSTEME, SYSTEME_MODEM_ETABLISSEMENT_LIAISON_4G_LTE, 0, 0, NULL);
modem.etat_4g_lte = ON;
break;
}
if ((strstr((char *)m_bus.down.reponse.reponse, "+CNACT: 0,2") != NULL) || // Cas où l'AUTOACTIVE est toujours en cours sur PDP #0 mais pas encore activé
(strstr((char *)m_bus.down.reponse.reponse, "+CNACT: 0,0") != NULL)) // Cas où il n'y a aucune demande d'activation sur le PDP #0
{
if (modem.etat_4g_lte == ON) enregistrement_historique(TYPE_SOURCE_HISTORIQUE_SYSTEME, SYSTEME_MODEM_PERTE_LIAISON_4G_LTE, 0, 0, NULL);
modem.etat_4g_lte = OFF;
}
break;
}
//------------------------------------------------------------------------------------------------------
// Activation du PDP :
case M_COMMANDE_CNACT_0_X:
{
if (erreur != M_BUS_ERREUR_AUCUNE)
{
if (erreur == M_BUS_ERREUR_OK) erreur = M_BUS_ERREUR_AUCUNE; // Si la trame contient OK, on la neutralise afin de ne pas mettre fin à l'échange
break; // Utile, car la réponse du modem est en général une tram eOK suivie, bien plus tard, de la réponse proprement dite.
}
if (strstr((char *)m_bus.down.reponse.reponse, ",ACTIVE") != NULL) modem.sequenceur.compteur_time_out = 0; // Si on a reçu le texte "+APP PDP: 0,ACTIVE", c'est que l'activation a été effective.
if (strstr((char *)m_bus.down.reponse.reponse, ",DEACTIVE") != NULL) modem.sequenceur.compteur_time_out = 0; // Si on a reçu le texte "+APP PDP: 0,DEACTIVE", c'est que l'activation n'est pas possible mais il est inutile d'attendre plus.
#ifdef __DEBUG_M_COMMANDES_GENERALES
sprintf(tmp, "Une réponse a la commande CNACT_0_X été reçue de la part du modem : [%s]", (char *)m_bus.down.reponse.reponse);
affichage_debug(__FILE__, __LINE__, tmp, TYPE_MESSAGE_DEBUG_PAR_DEFAUT);
#endif
erreur = M_BUS_ERREUR_OK; // Le retour de cette commande comprend bien une trame CR/LF/ O K CR/LF mais AVANT la réponse proprement dite. Donc on "simule" l'arrivée de cette trame pour que le protocole soit repositionné au repos.
break;
}
//------------------------------------------------------------------------------------------------------
// Numéro de téléphone :
case M_COMMANDE_CNUM:
{
if (erreur != M_BUS_ERREUR_AUCUNE) break; // Utile, notamment lorsqu'il y a une trame OK qui passe...
#ifdef __DEBUG_M_COMMANDES_GENERALES
sprintf(tmp, "Réponse à la commande de lecture du N° de téléphone reçue : [%s]", (char *)m_bus.down.reponse.reponse);
affichage_debug(__FILE__, __LINE__, tmp, TYPE_MESSAGE_DEBUG_PAR_DEFAUT);
#endif
// Recherche de la valeur antérieure :
sprintf(requete, "SELECT Valeur FROM TB_Systeme WHERE Validite=1 AND Nom='No_telephone' ");
mysql_query(bdd.pointeur, requete); // Envoi de la requête à MYSQL
result = mysql_store_result(bdd.pointeur); // Récup des résultats de la requête
while((row = mysql_fetch_row(result))) // Boucle sur tous les résultats de la requête
{
if (strcmp(row[0], (char *)m_bus.down.reponse.reponse) != 0) // Si la nouvelle valeur est différente de la précédente :
{
// Mise à jour du numéro de téléphone de la carte SIM dans la BDD :
sprintf(requete, "UPDATE TB_Systeme SET Valeur='%s' WHERE Nom='No_telephone' ", m_bus.down.reponse.reponse);
mysql_query(bdd.pointeur, requete);
// Enregistrement dans l'historique :
enregistrement_historique(TYPE_SOURCE_HISTORIQUE_SYSTEME, SYSTEME_MODEM_CHANGEMENT_NO_TELEPHONE, 0, 0, (char *) m_bus.down.reponse.reponse);
}
}
mysql_free_result(result); //Libération du jeu de résultat
break;
}
//------------------------------------------------------------------------------------------------------
// UE System Information :
case M_COMMANDE_CPSI:
{
if (erreur != M_BUS_ERREUR_AUCUNE) break; // Utile, notamment lorsqu'il y a une trame OK qui passe...
#ifdef __DEBUG_M_COMMANDES_GENERALES
sprintf(tmp, "Réponse à la commande de lecture des informations de l'UE reçue : [%s]", (char *)m_bus.down.reponse.reponse);
affichage_debug(__FILE__, __LINE__, tmp, TYPE_MESSAGE_DEBUG_PAR_DEFAUT);
#endif
// int16_t rssi;
// int16_t sinr;
ptr_chaine = strstr((char *)m_bus.down.reponse.reponse, ": ");
if (ptr_chaine != NULL) // Si NULL, c'est qu'il n'y a pas de ':' donc la trame n'est pas exploitable....
{
ptr_chaine += 2; // Le '+2' permet de démarrer la 'ptr_chaine' après le ": ".
ptr[0] = strtok(ptr_chaine, ","); // Extraction du premier segment avant le premier ','
for (i=1; ((i < M_COMMANDE_MAX_NOMBRE_PARAMETRES_REPONSE) && (ptr[(i-1)] != NULL)); i++)
{
switch(i) // Traitement de chaque paramètre :
{
case 1 : // Champs System_mode : "NO SERVICE", "GSM", "LTE CAT-M1", "LTE NB-IOT". NB : ce n'est pas parce qu'on a une info "positive" sur ce champs que la connxion est active (cf CNACT)
{
// Archivage dans la BDD de l'état du réseau :
sprintf(requete, "UPDATE TB_Systeme SET Valeur='%s' WHERE Nom='Modem_system_mode' ", ptr[i-1]);
mysql_query(bdd.pointeur, requete);
break;
}
case 2 : // Champs Operation_mode :
{
sprintf(requete, "UPDATE TB_Systeme SET Valeur='%s' WHERE Nom='Modem_operation_mode' ", ptr[i-1]);
mysql_query(bdd.pointeur, requete);
break;
}
case 12 : // Champs RSRP (Current Reference Signal Received Power, en dbm). Cet indicateur est valable uniquement pour LTE mais est plus pertinent que RSSI (qui prend toutes sorte de signaux en compte, yc des signaux inutiles en 4G-LTE).
{
val_16 = entree_no(TYPE_ENTREES_PREDEFINIES, 0, ENTREE_PREDEFINIE_RSRP);
if ((val_16 >= 0) && (val_16 < MAX_NOMBRE_ENTREES_PREDEFINIES)) entrees.predefinies.entrees[val_16].valeur = atoi(ptr[i-1]);
break;
}
case 13 : // Champs RSSI (Current Received signal strength indicator : en dbm
{
val_16 = entree_no(TYPE_ENTREES_PREDEFINIES, 0, ENTREE_PREDEFINIE_RSSI);
if ((val_16 >= 0) && (val_16 < MAX_NOMBRE_ENTREES_PREDEFINIES)) entrees.predefinies.entrees[val_16].valeur = atoi(ptr[i-1]);
break;
}
case 14 : // Champs RSSN (Average reference signal-to-noise ratio of the serving cell. The value of SINR can be calculated according to <RSSNR>, the formula is : SINR = 2 * <RSSNR> - 20. The range of SINR is from -20 to 30
{
val_16 = entree_no(TYPE_ENTREES_PREDEFINIES, 0, ENTREE_PREDEFINIE_SINR);
if ((val_16 >= 0) && (val_16 < MAX_NOMBRE_ENTREES_PREDEFINIES))
{
entrees.predefinies.entrees[val_16].valeur = atoi(ptr[i-1]) * 4; // Permet d'obtenir une valeur entre 0 et 100%
if (entrees.predefinies.entrees[val_16].valeur > 100) entrees.predefinies.entrees[val_16].valeur = 100;
}
break;
}
default : ;
}
ptr[i] = strtok(NULL, ",");
}
}
break;
}
//------------------------------------------------------------------------------------------------------
// Network Registration :
case M_COMMANDE_CREG:
{
if (erreur != M_BUS_ERREUR_AUCUNE) break; // Utile, notamment lorsqu'il y a une trame OK qui passe...
#ifdef __DEBUG_M_COMMANDES_GENERALES
sprintf(tmp, "Réponse à la commande de lecture des informations d'enregistrement réseau reçue : [%s]", (char *)m_bus.down.reponse.reponse);
affichage_debug(__FILE__, __LINE__, tmp, TYPE_MESSAGE_DEBUG_PAR_DEFAUT);
#endif
ptr_chaine = strstr((char *)m_bus.down.reponse.reponse, ": ");
if (ptr_chaine != NULL) // Si NULL, c'est qu'il n'y a pas de ':' donc la trame n'est pas exploitable....
{
ptr_chaine += 2; // Le '+2' permet de démarrer la 'ptr_chaine' après le ": ".
ptr[0] = strtok(ptr_chaine, ","); // Extraction du premier segment avant le premier ','
for (i=1; ((i < M_COMMANDE_MAX_NOMBRE_PARAMETRES_REPONSE) && (ptr[(i-1)] != NULL)); i++)
{
switch(i) // Traitement de chaque paramètre :
{
case 1 : // Unsollicited code mode : 0 Disable network registration unsolicited result code => 1 Enable network registration unsolicited result code +CREG: <stat> 2 Enable network registration unsolicited result code with location information(2 is only for 7080 series module which support GPRS.)
{
break;
}
case 2 : // Network Regsitration Status : 0 Not registered, MT is not currently searching a new operator to register to; 1 Registered, home network; 2 Not registered, but MT is currently searching a new operator to register to; 3 Registration denied; 4 Unknown; 5 Registered, roaming
{
break;
}
default : ;
}
ptr[i] = strtok(NULL, ",");
}
}
break;
}
//------------------------------------------------------------------------------------------------------
// Signal Quality Report :
case M_COMMANDE_CSQ:
{
if (erreur != M_BUS_ERREUR_AUCUNE) break; // Utile, notamment lorsqu'il y a une trame OK qui passe...
#ifdef __DEBUG_M_COMMANDES_GENERALES
sprintf(tmp, "Réponse à la commande de lecture du niveau CSQ reçue : [%s]", (char *)m_bus.down.reponse.reponse);
affichage_debug(__FILE__, __LINE__, tmp, TYPE_MESSAGE_DEBUG_PAR_DEFAUT);
#endif
int16_t rssi;
ptr_chaine = strstr((char *)m_bus.down.reponse.reponse, ": ");
if (ptr_chaine != NULL) // Si NULL, c'est qu'il n'y a pas de ':' donc la trame n'est pas exploitable....
{
ptr_chaine += 2; // Le '+2' permet de démarrer la 'ptr_chaine' après le ": ".
ptr[0] = strtok(ptr_chaine, ","); // Extraction du premier segment avant le premier ','
for (i=1; ((i < M_COMMANDE_MAX_NOMBRE_PARAMETRES_REPONSE) && (ptr[(i-1)] != NULL)); i++)
{
// Traitement de chaque paramètre :
switch(i)
{
case 1 : // Champs RSSI :
{
x = atoi(ptr[i-1]);
if (x == 0) rssi = -115; // 0 - 115 dBm or less
else if (x == 1) rssi = -111; // 1 - 111 dBm
else if ((x >= 2) && (x <= 30)) rssi = (2 * x) -114; // 2...30 - 110... - 54 dBm
else if ((x >= 31) && (x <= 98)) rssi = -52; // 31 - 52 dBm or greater
else rssi = 99; // 99 not known or not detectable
// Mise à jour du niveau RSSI dans la BDD :
sprintf(requete, "UPDATE TB_Systeme SET Valeur='%i' WHERE Nom='Rssi' ", rssi);
mysql_query(bdd.pointeur, requete);
break;
}
case 2 : // Champs BER : Non traité...
default : ;
}
ptr[i] = strtok(NULL, ",");
}
}
break;
}
//------------------------------------------------------------------------------------------------------
// Ouverture session FTP Get :
case M_COMMANDE_FTPGET_1:
{
if (erreur != M_BUS_ERREUR_AUCUNE) break; // Permet d'ignorer le "OK" qui arrive avant la trame proprement dite
#ifdef __DEBUG_M_COMMANDES_FTP_GET
sprintf(tmp, "\tRetour de FTPGET 1 = '%s'", m_bus.down.reponse.reponse);
affichage_debug(__FILE__, __LINE__, tmp, TYPE_MESSAGE_DEBUG_PAR_DEFAUT);
#endif
ptr_chaine = strstr((char *)m_bus.down.reponse.reponse, ": ");
if (ptr_chaine != NULL) // Si NULL, c'est qu'il n'y a pas de ':' donc la trame n'est pas exploitable....
{
ptr_chaine += 2; // Le '+2' permet de démarrer la 'ptr_chaine' après le ": ".
ptr[0] = strtok(ptr_chaine, ","); // Extraction du premier segment avant le premier ','
for (i=1; ((i < M_COMMANDE_MAX_NOMBRE_PARAMETRES_REPONSE) && (ptr[(i-1)] != NULL)); i++)
{
if (i == 2) // Si on reçoit 2 paramètres en réponse à une commande de Mode 1, c'est que la commande a été correctement reçue.
{
download.status_get = atoi(ptr[i-1]); // On stocke donc ce 2ème paramètre comme étant le code de status de la fonction GET...
modem.sequenceur.compteur = MODEM_DOWNLOAD_TEMPO_DEMANDE_DATA; // ... et on force le compteur du modem à cette tempo car il faut attendre un peu (si 0, ça ne fonctionne pas...) mais il est inutile d'aller jusqu'au time-out.
}
ptr[i] = strtok(NULL, ",");
}
}
erreur = M_BUS_ERREUR_OK; // Le retour de cette commande comprend bien une trame CR/LF/ O K CR/LF mais AVANT la réponse proprement dite. Donc on "simule" l'arrivée de cette trame pour que le protocole soit repositionné au repos.
break;
}
//------------------------------------------------------------------------------------------------------
// Attente de la taille du bloc binaire à réceptionner par GET :
case M_COMMANDE_FTPGET_2:
{
if (erreur != M_BUS_ERREUR_AUCUNE) break; // Utile, notamment lorsqu'il y a une trame OK qui passe...
#ifdef __DEBUG_M_COMMANDES_FTP_GET
sprintf(tmp, "\tRetour de FTPGET 2 = '%s'", m_bus.down.reponse.reponse);
affichage_debug(__FILE__, __LINE__, tmp, TYPE_MESSAGE_DEBUG_PAR_DEFAUT);
#endif
ptr_chaine = strstr((char *)m_bus.down.reponse.reponse, ": ");
if (ptr_chaine != NULL) // Si NULL, c'est qu'il n'y a pas de ':' donc la trame n'est pas exploitable....
{
ptr_chaine += 2; // Le '+2' permet de démarrer la 'ptr_chaine' après le ": ".
ptr[0] = strtok(ptr_chaine, ","); // Extraction du premier segment avant le premier ','
for (i=1; ((i < M_COMMANDE_MAX_NOMBRE_PARAMETRES_REPONSE) && (ptr[(i-1)] != NULL)); i++)
{
if (i == 1) x = atoi(ptr[i-1]); // On récupère le premier digit de la réponse (qui doit être '2' dans 'FTPGET: 2, xxxx' mais qui peut être '1' si on est en fin d'échange aticipé via la réception de 'FTPGET: 1, 0'
if (i == 2)
{
if (x == 2) // Cas 'normal' de récepetion de 'FTPGET: 2,xxx'
{
download.taille_buffer_rx = atoi(ptr[i-1]); // On stocke donc ce 2ème paramètre comme étant la taille du buffer à recevoir...
if (download.taille_buffer_rx != 0)
{
m_bus.protocole_rx.sequenceur.etat = ETAT_SEQUENCEUR_M_BUS_PROTOCOLE_RX_FLUX_BINAIRE; // Passage du séquenceur du M-Bus en mode binaire...
m_bus.down.reponse.lg_reponse = 0; // ... avec un buffer de réception remis à 0...
m_bus.down.reponse.lg_reponse_attendue = download.taille_buffer_rx; // ... et un nombre d'octets à recevoir défini. Le protocole M-Bus va dorénavant traiter ce nombre d'octets sans se poser de question est déclarera une réponse reçu dès que le nombre de caractères aura été reçu.
m_bus.down.buffer_cdes[m_bus.down.ptr_debut_buffer_cdes].code = M_COMMANDE_FTPGET_RECEPTION_DATA; // Et lorsque cette déclaration sera faite, on reviendra dans cette fonction mais dans l'état de séquenceur ad'hoc pour récupérer ces octets.
}
else // Il arrive qu'on reçoive un 'FTPGET: 2,0' dans le flux (notamment si le modem tarde à charger les données du serveur). Dans ce cas, on passe à l'état suivant, qui va renvoyer régulièrement de nouveaux 'FTPGET:2,1024' (pour recevoir de nouveaux blocs s'il y en a) et, in fine, recevra un 'FTPGET: 1,0' indiquant la fin du transfert.
{
m_bus.down.buffer_cdes[m_bus.down.ptr_debut_buffer_cdes].code = M_COMMANDE_FTPGET_2_1;
}
}
else if (x == 1) // Cas de réception d'une fin d'échange de type 'FTPGET: 1,x'
{
download.status_get = atoi(ptr[i-1]); // On stocke donc ce 2ème paramètre comme étant le status de 'FTPGET: 1, x'... A priori, 0 indiquant la fin de l'écgange mais si c'est 1, on va continuer après passage dans 'modem.c'
modem.sequenceur.compteur = 2; // A priori, cette tempo est inutile mais dans le doute, elle est laissée...
}
}
ptr[i] = strtok(NULL, ",");
}
}
break;
}
//------------------------------------------------------------------------------------------------------
// Attente de la fin de transfert GET :
case M_COMMANDE_FTPGET_2_1:
{
if (erreur != M_BUS_ERREUR_AUCUNE)
{
if (erreur == M_BUS_ERREUR_OK) // On reçoit normalement toujours un Ok (si c'est une autre erreur, on traite l'erreur globalement)
{
download.status_get = 1; // On met donc le statut à jour pour le traitement dans 'modem.c'
if (download.taille_buffer_rx < download.taille_buffer_tx) // Cas d'un paquet qui ne correspond pas au maximum possible : il faut attendre soit le 'FTPGET:1,0' qui annonce la fin du transfert, soit 'FTPGET: 1,1' qui indique qu'on peut demander de nouveaux paquets.
{
// modem.sequenceur.compteur = 1; // Version minimale (1.08Mo en 120s)
modem.sequenceur.compteur = 3; // Version raisonnable (1.08Mo en 131s)
}
else // Si c'est un paquet complet, le modem doit avoir des données disponibles et il est inutile d'attendre avant de demander le suivant.
{
// modem.sequenceur.compteur = 0; // Version minimale (1.08Mo en 120s)
modem.sequenceur.compteur = 1; // Version raisonnable (1.08Mo en 131s)
}
}
break;
}
#ifdef __DEBUG_M_COMMANDES_FTP_GET
sprintf(tmp, "\tRetour de FTPGET 1 = '%s'", m_bus.down.reponse.reponse);
affichage_debug(__FILE__, __LINE__, tmp, TYPE_MESSAGE_DEBUG_PAR_DEFAUT);
#endif
ptr_chaine = strstr((char *)m_bus.down.reponse.reponse, ": ");
if (ptr_chaine != NULL) // Si NULL, c'est qu'il n'y a pas de ':' donc la trame n'est pas exploitable....
{
ptr_chaine += 2; // Le '+2' permet de démarrer la 'ptr_chaine' après le ": ".
ptr[0] = strtok(ptr_chaine, ","); // Extraction du premier segment avant le premier ','
for (i=1; ((i < M_COMMANDE_MAX_NOMBRE_PARAMETRES_REPONSE) && (ptr[(i-1)] != NULL)); i++)
{
if (i == 2) // Si on reçoit 2 paramètres en réponse à une commande de Mode 1, c'est que la commande a été correctement reçue.
{
download.status_get = atoi(ptr[i-1]); // On stocke donc ce 2ème paramètre comme étant le code de status de la fonction GET...
modem.sequenceur.compteur = MODEM_DOWNLOAD_TEMPO_DEMANDE_DATA; // ... et on force le compteur du modem à cette tempo car il faut attendre un peu (si 0, ça ne fonctionne pas...) mais il est inutile d'aller jusqu'au time-out.
}
ptr[i] = strtok(NULL, ",");
}
}
erreur = M_BUS_ERREUR_OK; // Le retour de cette commande comprend bien une trame CR/LF/ O K CR/LF mais AVANT la réponse proprement dite. Donc on "simule" l'arrivée de cette trame pour que le protocole soit repositionné au repos.
break;
}
//------------------------------------------------------------------------------------------------------
// Lecture du contenu d'un répertoire distant FTPLIST :
case M_COMMANDE_FTPLIST_1:
{
if (erreur != M_BUS_ERREUR_AUCUNE) break;
#ifdef __DEBUG_M_COMMANDES_FTP_LIST
sprintf(tmp, "\tRetour de FTPLIST 1 = '%s'", m_bus.down.reponse.reponse);
affichage_debug(__FILE__, __LINE__, tmp, TYPE_MESSAGE_DEBUG_PAR_DEFAUT);
#endif
ptr_chaine = strstr((char *)m_bus.down.reponse.reponse, ": ");
if (ptr_chaine != NULL) // Si NULL, c'est qu'il n'y a pas de ':' donc la trame n'est pas exploitable....
{
ptr_chaine += 2; // Le '+2' permet de démarrer la 'ptr_chaine' après le ": ".
ptr[0] = strtok(ptr_chaine, ","); // Extraction du premier segment avant le premier ','
for (i=1; ((i < M_COMMANDE_MAX_NOMBRE_PARAMETRES_REPONSE) && (ptr[(i-1)] != NULL)); i++)
{
if (i == 2)
{
download.status_get = atoi(ptr[i-1]); // On stocke donc ce 2ème paramètre comme étant le code de status de la fonction GET...
modem.sequenceur.compteur = MODEM_DOWNLOAD_TEMPO_DEMANDE_LISTE; // ... et on force le compteur du modem à cette tempo car il faut attendre un peu (si 0, ça ne fonctionne pas...!) mais il est inutile d'aller jusqu'au time-out.
}
ptr[i] = strtok(NULL, ",");
}
}
erreur = M_BUS_ERREUR_OK; // Le retour de cette commande comprend bien une trame CR/LF/ O K CR/LF mais AVANT la réponse proprement dite. Donc on "simule" l'arrivée de cette trame pour que le protocole soit repositionné au repos.
break;
}
//------------------------------------------------------------------------------------------------------
// Lecture du contenu d'un répertoire distant FTPLIST :
case M_COMMANDE_FTPLIST_2:
{
if (erreur != M_BUS_ERREUR_AUCUNE) break; // Utile, notamment lorsqu'il y a une trame OK qui passe...
#ifdef __DEBUG_M_COMMANDES_FTP_LIST
sprintf(tmp, "\tRetour de FTPLIST 2 = '%s'", m_bus.down.reponse.reponse);
affichage_debug(__FILE__, __LINE__, tmp, TYPE_MESSAGE_DEBUG_PAR_DEFAUT);
#endif
ptr_chaine = strstr((char *)m_bus.down.reponse.reponse, ": ");
if (ptr_chaine != NULL) // Si NULL, c'est qu'il n'y a pas de ':' donc la trame n'est pas exploitable....
{
ptr_chaine += 2; // Le '+2' permet de démarrer la 'ptr_chaine' après le ": ".
ptr[0] = strtok(ptr_chaine, ","); // Extraction du premier segment avant le premier ','
for (i=1; ((i < M_COMMANDE_MAX_NOMBRE_PARAMETRES_REPONSE) && (ptr[(i-1)] != NULL)); i++)
{
if (i == 1) x = atoi(ptr[i-1]); // On récupère le premier digit de la réponse (qui doit être '2' dans 'FTPGET: 2, xxxx' mais qui peut être '1' si on est en fin d'échange aticipé via la réception de 'FTPGET: 1, 0'
if (i == 2)
{
if (x == 2) // Cas 'normal' de réception de 'FTPGET: 2,xxx'
{
download.taille_buffer_rx = atoi(ptr[i-1]); // On stocke donc ce 2ème paramètre comme étant la taille du buffer à recevoir...
if (download.taille_buffer_rx != 0)
{
m_bus.protocole_rx.sequenceur.etat = ETAT_SEQUENCEUR_M_BUS_PROTOCOLE_RX_FLUX_BINAIRE; // Passage du séquenceur du M-Bus en mode binaire...
m_bus.down.reponse.lg_reponse = 0; // ... avec un buffer de réception remis à 0...
m_bus.down.reponse.lg_reponse_attendue = download.taille_buffer_rx; // ... et un nombre d'octets à recevoir défini. Le protocole M-Bus va dorénavant traiter ce nombre d'octets sans se poser de question est déclarera une réponse reçu dès que le nombre de caractères aura été reçu.
m_bus.down.buffer_cdes[m_bus.down.ptr_debut_buffer_cdes].code = M_COMMANDE_FTPLIST_RECEPTION_LISTE; // Et lorsque cette déclaration sera faite, on reviendra dans cette fonction mais dans l'état de séquenceur ad'hoc pour récupérer ces octets.
}
else // Il arrive qu'on reçoive un 'FTPGET: 2,0' dans le flux (notamment si le modem tarde à charger les données du serveur). Dans ce cas, on passe à l'état suivant, qui va renvoyer régulièrement de nouveaux 'FTPGET:2,1024' (pour recevoir de nouveaux blocs s'il y en a) et, in fine, recevra un 'FTPGET: 1,0' indiquant la fin du transfert.
{
m_bus.down.buffer_cdes[m_bus.down.ptr_debut_buffer_cdes].code = M_COMMANDE_FTPLIST_2_1;
}
}
else if (x == 1) // Cas de réception d'une fin d'échange de type 'FTPGET: 1,x'
{
download.status_get = atoi(ptr[i-1]); // On stocke donc ce 2ème paramètre comme étant le status de 'FTPGET: 1, x'... A priori, 0 indiquant la fin de l'écgange mais si c'est 1, on va continuer après passage dans 'modem.c'
sprintf(tmp, "\tRetour de FTPLIST 2 = '%s' interpreté comme un FTPLIST1:x où x=%i", m_bus.down.reponse.reponse, download.status_get);
affichage_debug(__FILE__, __LINE__, tmp, TYPE_MESSAGE_DEBUG_ERREUR);
modem.sequenceur.compteur = 2; // A priori, cette tempo est inutile mais dans le doute, elle est laissée...
}
}
ptr[i] = strtok(NULL, ",");
}
}
break;
}
//------------------------------------------------------------------------------------------------------
// Attente de la fin de transfert LIST :
case M_COMMANDE_FTPLIST_2_1:
{
if (erreur != M_BUS_ERREUR_AUCUNE)
{
if (erreur == M_BUS_ERREUR_OK) // On reçoit normalement toujours un Ok (si c'est une autre erreur, on traite l'erreur globalement)
{
download.status_get = 1; // On met donc le statut à jour pour le traitement dans 'modem.c'
if (download.taille_buffer_rx < download.taille_buffer_tx) // Cas d'un paquet qui ne correspond pas au maximum possible : il faut attendre soit le 'FTPGET:1,0' qui annonce la fin du transfert, soit 'FTPGET: 1,1' qui indique qu'on peut demander de nouveaux paquets.
{
modem.sequenceur.compteur = 40; // Cette tempo est 'importante' mais la lecture LIST est toujours de petite taille et cela permet de limiter les 'relances' après la dernère data et en attendant le 'FTPLIST: 1,0' de fin d'échange.
}
else // Si c'est un paquet complet, le modem doit avoir des données disponibles et il est inutile d'attendre avant de demander le suivant.
{
modem.sequenceur.compteur = 1; // Et on met une petite tempo entre le OK reçu et la suite (a priori, une nouvelle demande 'FTPLIST: 2,1024')
}
}
break;
}
#ifdef __DEBUG_M_COMMANDES_FTP_LIST
sprintf(tmp, "\tRetour de FTPLIST 2_1 = '%s'", m_bus.down.reponse.reponse);
affichage_debug(__FILE__, __LINE__, tmp, TYPE_MESSAGE_DEBUG_PAR_DEFAUT);
#endif
ptr_chaine = strstr((char *)m_bus.down.reponse.reponse, ": ");
if (ptr_chaine != NULL) // Si NULL, c'est qu'il n'y a pas de ':' donc la trame n'est pas exploitable....
{
ptr_chaine += 2; // Le '+2' permet de démarrer la 'ptr_chaine' après le ": ".
ptr[0] = strtok(ptr_chaine, ","); // Extraction du premier segment avant le premier ','
for (i=1; ((i < M_COMMANDE_MAX_NOMBRE_PARAMETRES_REPONSE) && (ptr[(i-1)] != NULL)); i++)
{
if (i == 2)
{
download.status_get = atoi(ptr[i-1]); // On stocke donc ce 2ème paramètre comme étant le code de status de la fonction GET...
modem.sequenceur.compteur = MODEM_DOWNLOAD_TEMPO_DEMANDE_LISTE; // ... et on force le compteur du modem à cette tempo car il faut attendre un peu (si 0, ça ne fonctionne pas...!) mais il est inutile d'aller jusqu'au time-out.
}
ptr[i] = strtok(NULL, ",");
}
}
erreur = M_BUS_ERREUR_OK; // Le retour de cette commande comprend bien une trame CR/LF/ O K CR/LF mais AVANT la réponse proprement dite. Donc on "simule" l'arrivée de cette trame pour que le protocole soit repositionné au repos.
break;
}
//------------------------------------------------------------------------------------------------------
// Ouverture session FTP Put :
case M_COMMANDE_FTPPUT_1:
{
if (erreur != M_BUS_ERREUR_AUCUNE)
{
if (erreur == M_BUS_ERREUR_OK) erreur = M_BUS_ERREUR_AUCUNE; // Si la trame contient OK, on la neutralise afin de ne pas mettre fin à l'échange
break; // Utile, car la réponse du modem est en général une trame OK suivie, bien plus tard, de la réponse proprement dite.
}
#ifdef __DEBUG_M_COMMANDES_FTP_PUT
sprintf(tmp, "\tRetour de FTPPUT = '%s'", m_bus.down.reponse.reponse);
affichage_debug(__FILE__, __LINE__, tmp, TYPE_MESSAGE_DEBUG_PAR_DEFAUT);
#endif
ptr_chaine = strstr((char *)m_bus.down.reponse.reponse, ": ");
if (ptr_chaine != NULL) // Si NULL, c'est qu'il n'y a pas de ':' donc la trame n'est pas exploitable....
{
ptr_chaine += 2; // Le '+2' permet de démarrer la 'ptr_chaine' après le ": ".
ptr[0] = strtok(ptr_chaine, ","); // Extraction du premier segment avant le premier ','
for (i=1; ((i < M_COMMANDE_MAX_NOMBRE_PARAMETRES_REPONSE) && (ptr[(i-1)] != NULL)); i++)
{
if (i == 3) // Si on reçoit 3 paramètres en réponse à une commande de Mode 1, c'est que la commande a été correctement reçue.
{
modem.max_taille_ftp_put = atoi(ptr[i-1]); // On stocke donc ce 3ème paramètre comme étant la nombre d'octet recevable par le modem...
modem.sequenceur.compteur = MODEM_UPLOAD_TEMPO_DEMANDE_ENVOI_DATA; // ... et on laisse juste une petite tempo sur le compteur du modem car il est inutile d'attendre plus (mais pas moins !)
}
ptr[i] = strtok(NULL, ",");
}
if ((i-1) < 3) // (i-1) représente le nombre de paramètres reçus au total. S'il n'est pas égal à 3, c'est qu'il y a eu une erreur.
{
// Enregistrement dans l'historique :
enregistrement_historique(TYPE_SOURCE_HISTORIQUE_SYSTEME, SYSTEME_MODEM_ERREUR_FTP, 0, atoi(ptr[1]), (char *) m_bus.down.reponse.reponse);
modem.max_taille_ftp_put = 0; // Permet d'arrêter le transfert...
modem.sequenceur.compteur = 0; // ... sans attendre plus longtemps
}
}
erreur = M_BUS_ERREUR_OK; // Le retour de cette commande comprend bien une trame CR/LF/ O K CR/LF mais AVANT la réponse proprement dite. Donc on "simule" l'arrivée de cette trame pour que le protocole soit repositionné au repos.
break;
}
//------------------------------------------------------------------------------------------------------
// Demande d'écriture de données FTP Put :
case M_COMMANDE_FTPPUT_2:
{
if (erreur != M_BUS_ERREUR_AUCUNE) break; // Utile, notamment lorsqu'il y a une trame OK qui passe...
#ifdef __DEBUG_M_COMMANDES_FTP_PUT
sprintf(tmp, "\tRetour de FTPPUT = '%s'", m_bus.down.reponse.reponse);
affichage_debug(__FILE__, __LINE__, tmp, TYPE_MESSAGE_DEBUG_PAR_DEFAUT);
#endif
ptr_chaine = strstr((char *)m_bus.down.reponse.reponse, ": ");
if (ptr_chaine != NULL) // Si NULL, c'est qu'il n'y a pas de ':' donc la trame n'est pas exploitable....
{
ptr_chaine += 2; // Le '+2' permet de démarrer la 'ptr_chaine' après le ": ".
ptr[0] = strtok(ptr_chaine, ","); // Extraction du premier segment avant le premier ','
for (i=1; ((i < M_COMMANDE_MAX_NOMBRE_PARAMETRES_REPONSE) && (ptr[(i-1)] != NULL)); i++)
{
if (i == 2) // Si on reçoit 2 paramètres en réponse à la commande, c'est que la commande a été correctement reçue.
{
modem.sequenceur.compteur = MODEM_UPLOAD_TEMPO_DEMANDE_ENVOI_DATA; // On laisse juste une petite tempo sur le compteur du modem car il est inutile d'attendre plus (mais pas moins !)
}
ptr[i] = strtok(NULL, ",");
}
}
erreur = M_BUS_ERREUR_OK; // Le retour de cette commande ne comprend pas de trame CR/LF/ O K CR/LF. Donc on "simule" l'arrivée de cette trame pour que le protocole soit repositionné au repos.
break;
}
//------------------------------------------------------------------------------------------------------
// Lecture de la taille d'un fichier FTPSIZE :
case M_COMMANDE_FTPSIZE:
{
if (erreur != M_BUS_ERREUR_AUCUNE)
{
if (erreur == M_BUS_ERREUR_OK) erreur = M_BUS_ERREUR_AUCUNE; // Si la trame contient OK, on la neutralise afin de ne pas mettre fin à l'échange
break; // Utile, car la réponse du modem est en général une trame OK suivie, bien plus tard, de la réponse proprement dite.
}
#ifdef __DEBUG_M_COMMANDES_FTP_PUT
sprintf(tmp, "\tRetour de FTPSIZE = '%s'", m_bus.down.reponse.reponse);
affichage_debug(__FILE__, __LINE__, tmp, TYPE_MESSAGE_DEBUG_PAR_DEFAUT);
#endif
ptr_chaine = strstr((char *)m_bus.down.reponse.reponse, ": "); // Positionnement sur le ':'
if (ptr_chaine != NULL) // Si NULL, c'est qu'il n'y a pas de ':' donc la trame n'est pas exploitable....
{
ptr_chaine += 2; // Le '+2' permet de démarrer la 'ptr_chaine' après le ": ".
ptr[0] = strtok(ptr_chaine, ","); // Extraction du premier segment avant le premier ','
for (i=1; ((i < M_COMMANDE_MAX_NOMBRE_PARAMETRES_REPONSE) && (ptr[(i-1)] != NULL)); i++)
{
if (i == 2) // Doit être à 0 si pas d'erreur, sinon code d'erreur
{
upload.status_get_size = atoi(ptr[i-1]);
if (upload.status_get_size != 0) // Si cette valeur est != 0, il est inutile de continuer...
{
modem.sequenceur.compteur = 0;
break;
}
}
if (i == 3) // Si le second paramètre était bien 0, ce 3ième contient la taille du fichier :
{
upload.taille_fichier_serveur = atoi(ptr[i-1]); // On stocke donc ce 3ème paramètre comme étant la taille du fichier distant
modem.sequenceur.compteur = 0; // ... et on force le compteur du modem à 0 car il est inutile d'attendre plus.
}
ptr[i] = strtok(NULL, ",");
}
}
erreur = M_BUS_ERREUR_OK; // Le retour de cette commande comprend bien une trame CR/LF/ O K CR/LF mais AVANT la réponse proprement dite. Donc on "simule" l'arrivée de cette trame pour que le protocole soit repositionné au repos.
break;
}
//------------------------------------------------------------------------------------------------------
// Attente de la taille du bloc de ecaractères à réceptionner par SHREAD :
case M_COMMANDE_SHREAD:
{
if (erreur != M_BUS_ERREUR_AUCUNE)
{
if (erreur == M_BUS_ERREUR_OK) erreur = M_BUS_ERREUR_AUCUNE; // Si la trame contient OK, on la neutralise afin de ne pas mettre fin à l'échange
break; // Utile, car la réponse du modem est en général une trame OK suivie, bien plus tard, de la réponse proprement dite.
}
#ifdef __DEBUG_M_COMMANDES_FTP_GET
sprintf(tmp, "\tRetour de SHREAD = '%s'", m_bus.down.reponse.reponse);
affichage_debug(__FILE__, __LINE__, tmp, TYPE_MESSAGE_DEBUG_PAR_DEFAUT);
#endif
ptr_chaine = strstr((char *)m_bus.down.reponse.reponse, ": ");
if (ptr_chaine != NULL) // Si NULL, c'est qu'il n'y a pas de ':' donc la trame n'est pas exploitable....
{
ptr_chaine += 2; // Le '+2' permet de démarrer la 'ptr_chaine' après le ": ".
ptr[0] = strtok(ptr_chaine, ","); // Extraction du premier segment avant le premier ','
for (i=1; ((i < M_COMMANDE_MAX_NOMBRE_PARAMETRES_REPONSE) && (ptr[(i-1)] != NULL)); i++)
{
if (i == 1)
{
modem.http.taille_buffer_rx = atoi(ptr[i-1]); // On stocke donc ce 2ème paramètre comme étant la taille du buffer à recevoir...
if (modem.http.taille_buffer_rx != 0)
{
m_bus.protocole_rx.sequenceur.etat = ETAT_SEQUENCEUR_M_BUS_PROTOCOLE_RX_FLUX_BINAIRE; // Passage du séquenceur du M-Bus en mode binaire...
m_bus.down.reponse.lg_reponse = 0; // ... avec un buffer de réception remis à 0...
m_bus.down.reponse.lg_reponse_attendue = modem.http.taille_buffer_rx; // ... et un nombre d'octets à recevoir défini. Le protocole M-Bus va dorénavant traiter ce nombre d'octets sans se poser de question est déclarera une réponse reçu dès que le nombre de caractères aura été reçu.
m_bus.down.buffer_cdes[m_bus.down.ptr_debut_buffer_cdes].code = M_COMMANDE_HTTP_GET_RECEPTION_DATA; // Et lorsque cette déclaration sera faite, on reviendra dans cette fonction mais dans l'état de séquenceur ad'hoc pour récupérer ces octets.
}
}
ptr[i] = strtok(NULL, ",");
}
}
break;
}
//------------------------------------------------------------------------------------------------------
// Requête GET en mode HTTP :
case M_COMMANDE_SHREQ:
{
if (erreur != M_BUS_ERREUR_AUCUNE)
{
if (erreur == M_BUS_ERREUR_OK) erreur = M_BUS_ERREUR_AUCUNE; // Si la trame contient OK, on la neutralise afin de ne pas mettre fin à l'échange
break; // Utile, car la réponse du modem est en général une trame OK suivie, bien plus tard, de la réponse proprement dite.
}
#ifdef __DEBUG_M_COMMANDES_HTTP
sprintf(tmp, "\tRetour de SHREQ = '%s'", m_bus.down.reponse.reponse);
affichage_debug(__FILE__, __LINE__, tmp, TYPE_MESSAGE_DEBUG_PAR_DEFAUT);
#endif
ptr_chaine = strstr((char *)m_bus.down.reponse.reponse, ": ");
if (ptr_chaine != NULL) // Si NULL, c'est qu'il n'y a pas de ':' donc la trame n'est pas exploitable....
{
ptr_chaine += 2; // Le '+2' permet de démarrer la 'ptr_chaine' après le ": ".
ptr[0] = strtok(ptr_chaine, ","); // Extraction du premier segment avant le premier ','
for (i=1; ((i < M_COMMANDE_MAX_NOMBRE_PARAMETRES_REPONSE) && (ptr[(i-1)] != NULL)); i++)
{
if (i == 1) // Doit contenir '"GET"'
{
if (strstr(ptr[i-1], "GET") == NULL) // S'il ne contient pas GET, c'est une erreur....
{
modem.http.status_get = -1;
modem.sequenceur.compteur = 0; // Inutile d'attendre
}
}
if (i == 2)
{
modem.http.status_get = atoi(ptr[i-1]); // Stocke le status de retour de la requête GET
//sprintf(tmp, "\tLe deuxième paramètre de retour de SHREQ est le status de la requête : [%i]", modem.http.status_get);
//affichage_debug(__FILE__, __LINE__, tmp, TYPE_MESSAGE_DEBUG_PAR_DEFAUT);
}
if (i == 3)
{
modem.http.taille_retour_get = atoi(ptr[i-1]); // Stocke le status de retour de la requête GET....
modem.sequenceur.compteur = 2; //MODEM_DOWNLOAD_TEMPO_DEMANDE_LISTE; // ... et on force le compteur du modem à cette tempo
//sprintf(tmp, "\tLe troisième paramètre de retour de SHREQ est la tailel de la réponse : [%i] octets", modem.http.taille_retour_get);
// affichage_debug(__FILE__, __LINE__, tmp, TYPE_MESSAGE_DEBUG_PAR_DEFAUT);
}
ptr[i] = strtok(NULL, ",");
}
}
erreur = M_BUS_ERREUR_OK; // Le retour de cette commande comprend bien une trame CR/LF/ O K CR/LF mais AVANT la réponse proprement dite. Donc on "simule" l'arrivée de cette trame pour que le protocole soit repositionné au repos.
break;
}
//------------------------------------------------------------------------------------------------------
// Retour d'état de la connexion HTTP par la commande SHSTATE? :
case M_COMMANDE_SHSTATE:
{
if (erreur != M_BUS_ERREUR_AUCUNE) break;
#ifdef __DEBUG_M_COMMANDES_HTTP
sprintf(tmp, "\tRetour de SHSTATE? = '%s'", m_bus.down.reponse.reponse);
affichage_debug(__FILE__, __LINE__, tmp, TYPE_MESSAGE_DEBUG_PAR_DEFAUT);
#endif
ptr_chaine = strstr((char *)m_bus.down.reponse.reponse, ": ");
if (ptr_chaine != NULL) // Si NULL, c'est qu'il n'y a pas de ':' donc la trame n'est pas exploitable....
{
ptr_chaine += 2; // Le '+2' permet de démarrer la 'ptr_chaine' après le ": ".
ptr[0] = strtok(ptr_chaine, ","); // Extraction du premier segment avant le premier ','
for (i=1; ((i < M_COMMANDE_MAX_NOMBRE_PARAMETRES_REPONSE) && (ptr[(i-1)] != NULL)); i++)
{
if (i == 1)
{
modem.http.status_connexion = atoi(ptr[i-1]); // Stocke le status de la connexion ...
modem.sequenceur.compteur = 2; //MODEM_DOWNLOAD_TEMPO_DEMANDE_LISTE; // ... et on force le compteur du modem à cette tempo
}
ptr[i] = strtok(NULL, ",");
}
}
erreur = M_BUS_ERREUR_OK; // Le retour de cette commande comprend bien une trame CR/LF/ O K CR/LF mais AVANT la réponse proprement dite. Donc on "simule" l'arrivée de cette trame pour que le protocole soit repositionné au repos.
break;
}
//------------------------------------------------------------------------------------------------------
// Ecriture des données FTP Put :
case M_COMMANDE_FTPPUT_ENVOI_DATA:
{
if (erreur != M_BUS_ERREUR_AUCUNE) // ATTENTION : la trame de retour normale est '\r\nOK\n\n+FTPPUT: 1,1,1360\r\n' (c'est bien un double \n\n au lieu de \r\n au milieu) donc le protocole compte une seule trame. Il ne faut donc pas traiter le Ok comme tel sinon on pert le FTPPUT qui suit... NB : en cas d'erreur, on a l'erreur d'abord (avec ses \r\n de part et d'autre) puis le FTPPUT:... complet.
{
upload.code_erreur_ftpput_data = erreur; // Mémorisation du code d'erreur pour traitement ultérieur par modem.c
if (erreur == M_BUS_ERREUR_ERROR) // Cf le 'ATTENTION' ci-dessus : si ERROR, on peut faire break car le FTPPUT qui suit sera bien encadré comme il faut par les \r\n
{
erreur = M_BUS_ERREUR_AUCUNE; // On repositionne l'erreur à AUCUNE pour que l'échange ne soit pas terminé (on attend le FTPPUT avant de revenirt à modem.c)
break; // On peut alors sortir du traitement car il ne servirait à rien à ce stade (on attend le FTPPUT...)
}
}
ptr_chaine = strstr((char *)m_bus.down.reponse.reponse, ": ");
if (ptr_chaine != NULL) // Si NULL, c'est qu'il n'y a pas de ':' donc la trame n'est pas exploitable....
{
ptr_chaine += 2; // Le '+2' permet de démarrer la 'ptr_chaine' après le ": ".
ptr[0] = strtok(ptr_chaine, ","); // Extraction du premier segment avant le premier ','
for (i=1; ((i < M_COMMANDE_MAX_NOMBRE_PARAMETRES_REPONSE) && (ptr[(i-1)] != NULL)); i++)
{
if (i == 3) // Si on reçoit 3 paramètres en réponse, c'est que la commande a été correctement reçue....
{
modem.max_taille_ftp_put = atoi(ptr[i-1]); // ... on stocke ce 3ème paramètre comme étant la nombre d'octet recevable par le modem...
modem.sequenceur.compteur = MODEM_UPLOAD_TEMPO_DEMANDE_ENVOI_DATA; // ... et on laisse juste une petite tempo sur le compteur du modem car il est inutile d'attendre plus (mais pas moins !)
erreur = M_BUS_ERREUR_OK; // ... et on force la fin de l'échange car le OK n'est pas présent dans la trame de FTPPUT
}
ptr[i] = strtok(NULL, ","); // Extraction du segment suivant
}
}
break;
}
//------------------------------------------------------------------------------------------------------
// Lecture d'un bloc de données FTP List :
case M_COMMANDE_FTPLIST_RECEPTION_LISTE:
{
if (m_bus.down.reponse.lg_reponse == m_bus.down.reponse.lg_reponse_attendue)
{
sprintf(tmp, "%s/%s", REPERTOIRE_SERVER_DOWNLOAD, NOM_FICHIER_LISTING_REPERTOIRE_DOWNLOAD_SERVEUR);
download.ptr_fichier_destination = fopen(tmp, "a"); // Ouverture du fichier en "append"...
if (download.ptr_fichier_destination != NULL)
{
for (i = 0; i < m_bus.down.reponse.lg_reponse; i ++)
{
fputc(m_bus.down.reponse.reponse[i], download.ptr_fichier_destination); // Ecriture dans le fichier de tous les caractères reçus dans le paquet
}
fseek(download.ptr_fichier_destination, 0, SEEK_END); // On profite du fait que le fichier local est ouvet pour aller...
download.taille_fichier_local = ftell(download.ptr_fichier_destination); // ... et rechercher la position du curseur => mise à jour la taille réelle du fichier local
fclose(download.ptr_fichier_destination); // Fermeture du fichier
}
else
{
sprintf(tmp, "L'ouverture du fichier [%s/%s] a échoué. Le bloc de données reçu est perdu.", REPERTOIRE_SERVER_DOWNLOAD, NOM_FICHIER_LISTING_REPERTOIRE_DOWNLOAD_SERVEUR);
affichage_debug(__FILE__, __LINE__, tmp, TYPE_MESSAGE_DEBUG_ERREUR);
}
m_bus.down.buffer_cdes[m_bus.down.ptr_debut_buffer_cdes].code = M_COMMANDE_FTPLIST_2_1; // Pour attente du 'OK' qui suit le paquet de data puis le 'FTPLIST: 1,0' de fin de transfert
erreur = M_BUS_ERREUR_AUCUNE;
}
break;
}
//------------------------------------------------------------------------------------------------------
// Lecture d'un bloc de données FTP Get :
case M_COMMANDE_FTPGET_RECEPTION_DATA:
{
if (m_bus.down.reponse.lg_reponse == m_bus.down.reponse.lg_reponse_attendue)
{
sprintf(tmp, "%s%s", download.nom_repertoire_destination, download.nom_fichier_destination);
download.ptr_fichier_destination = fopen(tmp, "a"); // Ouverture du fichier en "append"...
if (download.ptr_fichier_destination != NULL)
{
for (i = 0; i < m_bus.down.reponse.lg_reponse; i ++)
{
fputc(m_bus.down.reponse.reponse[i], download.ptr_fichier_destination); // Ecriture dans le fichier de tous les caractères reçus dans le paquet
}
fseek(download.ptr_fichier_destination, 0, SEEK_END); // On profite du fait que le fichier local est ouvet pour aller...
download.taille_fichier_local = ftell(download.ptr_fichier_destination); // ... et rechercher la position du curseur => mise à jour la taille réelle du fichier local
fclose(download.ptr_fichier_destination); // Fermeture du fichier
}
else
{
sprintf(tmp, "L'ouverture du fichier [%s%s] a échoué. Le bloc de données reçu est perdu.", download.nom_repertoire_destination, download.nom_fichier_destination);
affichage_debug(__FILE__, __LINE__, tmp, TYPE_MESSAGE_DEBUG_ERREUR);
}
m_bus.down.buffer_cdes[m_bus.down.ptr_debut_buffer_cdes].code = M_COMMANDE_FTPGET_2_1; // Pour attente du 'OK' qui suit le paquet de data puis le 'FTPGET: 1,0' de fin de transfert
erreur = M_BUS_ERREUR_AUCUNE;
}
break;
}
//------------------------------------------------------------------------------------------------------
// Lecture d'un bloc de données HTTP Get :
case M_COMMANDE_HTTP_GET_RECEPTION_DATA:
{
if (m_bus.down.reponse.lg_reponse == m_bus.down.reponse.lg_reponse_attendue)
{
sprintf(tmp, "%s/%s", modem.http.nom_repertoire_destination, modem.http.nom_fichier_destination);
modem.http.ptr_fichier_destination = fopen(tmp, "a"); // Ouverture du fichier en "append"...
if (modem.http.ptr_fichier_destination != NULL)
{
for (i = 0; i < m_bus.down.reponse.lg_reponse; i ++)
{
fputc(m_bus.down.reponse.reponse[i], modem.http.ptr_fichier_destination); // Ecriture dans le fichier de tous les caractères reçus dans le paquet
}
fseek(modem.http.ptr_fichier_destination, 0, SEEK_END); // On profite du fait que le fichier local est ouvet pour aller...
modem.http.taille_fichier_local = ftell(modem.http.ptr_fichier_destination); // ... et rechercher la position du curseur => mise à jour la taille réelle du fichier local
fclose(modem.http.ptr_fichier_destination); // Fermeture du fichier
modem.http.no_paquet ++;
}
else
{
sprintf(tmp, "L'ouverture du fichier [%s%s] a échoué. Le bloc de données reçu est perdu et le transfert HTTP GET arrêté.", modem.http.nom_repertoire_destination, modem.http.nom_fichier_destination);
affichage_debug(__FILE__, __LINE__, tmp, TYPE_MESSAGE_DEBUG_ERREUR);
erreur = M_BUS_ERREUR_ERROR;
}
if (modem.http.taille_retour_get == modem.http.taille_fichier_local)
{
modem.sequenceur.compteur = 0; // il est inutile d'attendre plus
erreur = M_BUS_ERREUR_OK; // On termine l'échange (sans erreur) pour recenir vers modem.c
}
else
{
#ifdef __DEBUG_M_COMMANDES_HTTP
sprintf(tmp, "Le paquet n° %i en retour de la requête HTTP GET a été reçu. Taille du paquet = %i octets, %i octets reçus depuis le début du transfert pour taille objectif = %i octets.", modem.http.no_paquet, m_bus.down.reponse.lg_reponse_attendue, modem.http.taille_fichier_local, modem.http.taille_retour_get);
affichage_debug(__FILE__, __LINE__, tmp, TYPE_MESSAGE_DEBUG_PAR_DEFAUT);
#endif
m_bus.down.buffer_cdes[m_bus.down.ptr_debut_buffer_cdes].code = M_COMMANDE_SHREAD; // Pour attente du 'SHREAD: <data_length>' suivant
erreur = M_BUS_ERREUR_AUCUNE; // On ne revient pas encore vers modem.c puisque d'autres blocs sont à recevoir
}
}
break;
}
//------------------------------------------------------------------------------------------------------
// Lecture des data d'un message SMS :
case M_COMMANDE_CMGL_RECEPTION_DATA_MESSAGE:
{
m_bus.down.reponse.reponse[m_bus.down.reponse.lg_reponse] = 0;
if (strlen((char *) m_bus.down.reponse.reponse) < (MODEM_MAX_TAILLE_MESSAGE_SMS - 1))
{
// strcpy(modem.sms_en_cours.message, (char *) m_bus.down.reponse.reponse); // Récupération du texte du message
// enregistrement_sms(modem.sms_en_cours.numero_emetteur, modem.sms_en_cours.date, modem.sms_en_cours.message); // Archivage du message dans la BDD
// sprintf(tmp, "SMS reçu de [%s] à [%s] avec le message : [%s]", modem.sms_en_cours.numero_emetteur, modem.sms_en_cours.date, modem.sms_en_cours.message);
// affichage_debug(__FILE__, __LINE__, tmp, TYPE_MESSAGE_DEBUG_WARNING);
//if (strstr(modem.sms_en_cours.message, "RESET_NOW") != NULL) c_bus_down_commande_reset();
}
else
{
#ifdef __DEBUG_M_COMMANDES_SMS
sprintf(tmp, "La longueur des data du message reçu est trop importante (%i). Le SMS ne peut pas être traité. Message = [%s]", strlen((char *) m_bus.down.reponse.reponse), m_bus.down.reponse.reponse);
affichage_debug(__FILE__, __LINE__, tmp, TYPE_MESSAGE_DEBUG_ERREUR);
#endif
}
sprintf(tmp, "AT+CMGD=%i", modem.sms_en_cours.index);
m_bus_down_commande_libre(tmp, M_BUS_PROTOCOLE_NORMAL, 0, -1); // Commande de suppression du SMS dans le modem
m_bus.down.buffer_cdes[m_bus.down.ptr_debut_buffer_cdes].code = M_COMMANDE_CMGL; // Pour attente du 'OK' qui suit le paquet de data de fin de transfert
break;
}
//------------------------------------------------------------------------------------------------------
// Autres commandes :
default:
{
// sprintf(tmp, "\tTrame de réponse reçue sur M-Bus = '%s'", m_bus.down.reponse.reponse);
// affichage_debug(__FILE__, __LINE__, tmp, TYPE_MESSAGE_DEBUG_PAR_DEFAUT);
break;
}
}
//------------------------------------------------------------------------------------------------------
// Traitement du code d'erreur détecté dans la commande :
//------------------------------------------------------------------------------------------------------
switch (erreur)
{
case M_BUS_ERREUR_AUCUNE : break; // La trame contenait des valeurs utiles et n'étaient pas une trame de fin d'échange. Les compteurs de time-out et de répétitions continuent de tourner librement.
default: // Cas où on a reçu un code d'erreur connu :
{
if (m_bus.down.buffer_cdes[m_bus.down.ptr_debut_buffer_cdes].mode_protocole == M_BUS_PROTOCOLE_DATA_BINAIRE)
{
sprintf(tmp, "Réponse à la commande (code = %i) en erreur (contenu non affiché pour éviter les dépassements de buffers)", m_bus.down.buffer_cdes[m_bus.down.ptr_debut_buffer_cdes].code);
}
else sprintf(tmp, "Réponse à la commande [%s] en erreur : [%s] ", m_bus.down.buffer_cdes[m_bus.down.ptr_debut_buffer_cdes].cde, m_bus.down.reponse.reponse);
// sprintf(tmp, "Réponse à la commande [");
// strncat(tmp, (char *)m_bus.down.buffer_cdes[m_bus.down.ptr_debut_buffer_cdes].cde, 10);
// strcat(tmp, "...] en erreur : [");
// strncat(tmp, (char *)m_bus.down.reponse.reponse, 10);
// strcat(tmp, "...]");
affichage_debug(__FILE__, __LINE__, tmp, TYPE_MESSAGE_DEBUG_ERREUR);
} // Pas de break volontairement....
case M_BUS_ERREUR_OK : // Si le code est "OK", c'est juste la fin des réponses à la commande
{
m_bus.down.flag_attente_reponse = FALSE; // Libération du séquenceur d'émission pour passer à la commande suivante
m_bus.protocole_tx.repetitions = 0; // RAZ du nombre de répétitions pour usage futur
m_bus.protocole_tx.sequenceur.compteur_time_out = 0; // RAZ du time-out pour éviter tout déclenchement a postériori.
break;
}
}
m_bus.down.reponse.lg_reponse = 0; // Repositionne le pointeur au début pour le traitement de la trame suivante. A faire dans tous les cas !!
return(0);
}
/*****************************************************************************************************************************************************************
Fonction : Analyse la réponse à la commande et recherche si un code d'erreur parmi la liste possible est présent.
Reçoit : Rien (traite la réponse qui est stockée dans la structure m_bus.down.reponse.xxxx)
Renvoit : -1 si aucun code erreur n'a été trouvé, la valeur du coe erreur sinon. Attention la chaine "OK" est considérée comme un code erreur (valeur 0)
******************************************************************************************************************************************************************/
int8_t m_bus_down_recherche_code_erreur(void)
{
if (strstr((char *)m_bus.down.reponse.reponse, "OK") != NULL) return(M_BUS_ERREUR_OK);
else if (strstr((char *)m_bus.down.reponse.reponse, "BUSY") != NULL) return(M_BUS_ERREUR_BUSY);
else if (strstr((char *)m_bus.down.reponse.reponse, "CONNECT") != NULL) return(M_BUS_ERREUR_CONNECT);
else if (strstr((char *)m_bus.down.reponse.reponse, "ERROR") != NULL) return(M_BUS_ERREUR_ERROR);
else if (strstr((char *)m_bus.down.reponse.reponse, "NO ANSWER") != NULL) return(M_BUS_ERREUR_NO_ANSWER);
else if (strstr((char *)m_bus.down.reponse.reponse, "NO CARRIER") != NULL) return(M_BUS_ERREUR_NO_CARRIER);
else if (strstr((char *)m_bus.down.reponse.reponse, "NO DIALTONE") != NULL) return(M_BUS_ERREUR_NO_DIALTONE);
else if (strstr((char *)m_bus.down.reponse.reponse, "PROCEEDING") != NULL) return(M_BUS_ERREUR_PROCEEDING);
else if (strstr((char *)m_bus.down.reponse.reponse, "RING") != NULL) return(M_BUS_ERREUR_RING);
else return(M_BUS_ERREUR_AUCUNE);
}