Files
shipheart-appli/sources/modem.c
T

1604 lines
94 KiB
C

//**********************************************************************************************************************************************************************************
// Fichier MODEM.C
//
// Contient toutes les fonctions liées à la gestion du Modem SIM7070G, y compris GNSS
//**********************************************************************************************************************************************************************************/
// #define __DEBUG_MODEM //Décommenter cette ligne pour avoir les messages de debug du MODEM
// #define __DEBUG_MODEM_GNSS //Décommenter cette ligne pour avoir les messages de debug du MODEM en mode GNSS
// #define __DEBUG_MODEM_HTTP_GET // Décommenter cette ligne pour avoir les messages de debug du MODEM en mode HTTP GET
#define __DEBUG_MODEM_FTP_UPLOAD //Décommenter cette ligne pour avoir les messages de debug du MODEM en mode FTP
#define __DEBUG_MODEM_FTP_DOWNLOAD //Décommenter cette ligne pour avoir les messages de debug du MODEM en mode DOWNLOAD de fichiers sur le serveur
// Includes :
#include "main.h"
// Prototypes :
int8_t init_modem(void);
void gestion_modem(void);
// Variables globales :
struct Struct_modem modem;
/**********************************************************************************************************************************************************************************
Fonction INIT_MODEM
Fonction d'initialisation du MODEM
**********************************************************************************************************************************************************************************/
int8_t init_modem(void)
{
if (systeme.generation_shipbase == GENERATION_SHIPBASE_V1)
{
modem.consigne = ON; // Etat demandé pour le modem.
// 'mode.etat' est récupéré de la base de données au démarrage. Il sera ensuite mis à jour par le gestionnaire après démarrage.
// 'modem.etat_presence_sim' est récupéré de la base de données au démarrage. Il sera ensuite mis à jour par le gestionnaire après démarrage.
modem.etat_liaison = OFF; // Par défaut, la liaison série n'est PAS établie avec le modem
modem.etat_4g_lte = OFF; // Par défaut, la liaison 4G-LTE n'est PAS disponible
gnss.etat = OFF; // Par défaut.
modem.compteur_periode_gnss = 15; // Permet que plusieurs (a priori, 15) boucles de surveillance modem soient faites avant de déclencher la première acquisition GNSS
modem.compteur_periode_download = modem.compteur_periode_gnss + 10; // Permet que le premier Download soit fait avant tout upload (utile si on est bloqué sur les upload...)
modem.compteur_periode_upload = modem.compteur_periode_download + 10; // Permet que la première recherche d'upload se fasse après le premier download si nécessaire
// ecriture_sortie(TYPE_SORTIE_GPIO, 0, CM3P_DO_MOD_WKUP, ON); // Activation immédiate de la sortie DTR qui n'est pas utilisée mais qui doit être positionnée à 1 pour pouvoir fonctionner
modem.sequenceur.etat = ETAT_SEQUENCEUR_MODEM_DEBUT_IMPULSION_RESET; // Déclenche systématiquement une impulsion >12s de reset sur POWER_KEY
modem.sequenceur.compteur = MODEM_TEMPO_INIT;
// Affichage du message de débug :
affichage_debug(__FILE__, __LINE__, "Initialisation du MODEM\t\t: OK", TYPE_MESSAGE_DEBUG_OK);
}
else
{
// Affichage du message de débug :
affichage_debug(__FILE__, __LINE__, "Initialisation du Modem\t\t: Devalidé car non valide sur cette version de ShipBase", TYPE_MESSAGE_DEBUG_WARNING);
}
return(0);
}
//==================================================================================================================================================================
// Fonction : Appelée en tâche de fond, cette fonction gère les fonctions du modem SIM7070G dans son ensemble. Il s'appuie sur les fonctions M-Bus pour y accéder.
// Reçoit : Rien
// Renvoit : Rien
//==================================================================================================================================================================
void gestion_modem(void)
{
uint16_t i;
uint32_t t;
uint8_t s, m;
int32_t type;
int32_t taille;
char nom[MAX_LONGUEUR_NOM_FICHIER];
char tmp[MAX_LONGUEUR_BUFFER_TEMPORAIRE_DEBUG];
if (systeme.generation_shipbase != GENERATION_SHIPBASE_V1) return;
switch(modem.sequenceur.etat)
{
//=========================================================================================================================================================
// INITIALISATION :
//=========================================================================================================================================================
//----------------------------------------------------------------------------------------------------------------------------------------------------------
case ETAT_SEQUENCEUR_MODEM_INIT :
//----------------------------------------------------------------------------------------------------------------------------------------------------------
{
if (modem.sequenceur.compteur == 0)
{
//-------------------------------------------------------------------
// RAZ du M-Bus. Utile notamment dans le cas d'un overflow qui aurait déclenché un reset du modem :
m_bus.sequenceur.compteur = 0;
m_bus.sequenceur.etat = ETAT_SEQUENCEUR_M_BUS_INIT;
//-------------------------------------------------------------------
// Vérification de l'état actuel du modem et comparaison au demandé :
// Mise à jour de l'état actuel du modem :
if (lecture_entree(TYPE_ENTREES_GPIO, 0, CM3P_DI_STATUS_MOD, FALSE) == 0) modem.etat = OFF; // 0 est l'adresse de ShipBase
else modem.etat = ON;
// Check si la consigne est différente de l'état demandé :
if (modem.etat == modem.consigne) modem.sequenceur.etat = ETAT_SEQUENCEUR_MODEM_INIT_LIAISON; // Si non, on passe directemetn au repos
else modem.sequenceur.etat = ETAT_SEQUENCEUR_MODEM_CHANGEMENT_ETAT_INIT; // Si oui, on passe par une phase de changement d'état (identique que ce soit pour passer à On ou à Off)
#ifdef __DEBUG_MODEM
sprintf(tmp, "L'entrée Status du modem SIM7070G est à %i et sa consigne à %i. le séquenceur passe à l'état %i", modem.etat, modem.consigne, modem.sequenceur.etat);
affichage_debug(__FILE__, __LINE__, tmp, TYPE_MESSAGE_DEBUG_PAR_DEFAUT);
#endif
modem.etat_liaison = OFF; // Par défaut, la liaison n'est PAS établie (permet de bien vérifier que l'autobaud fonctionne)
}
break;
}
//----------------------------------------------------------------------------------------------------------------------------------------------------------
case ETAT_SEQUENCEUR_MODEM_CHANGEMENT_ETAT_INIT :
//----------------------------------------------------------------------------------------------------------------------------------------------------------
{
ecriture_sortie(TYPE_SORTIE_GPIO, 0, CM3P_DO_PWKEY_MOD, ON); // Activation immédiate de la sortie PowerKey. 0 est l'adresse de ShipBase
modem.sequenceur.compteur = MODEM_TEMPO_IMPULSION_CHANGEMENT_ETAT; // Lancement de la durée de l'impulsion
#ifdef __DEBUG_MODEM
sprintf(tmp, "Envoi d'une impulsion sur PowerKey du modem de %ims", (modem.sequenceur.compteur * 100));
affichage_debug(__FILE__, __LINE__, tmp, TYPE_MESSAGE_DEBUG_PAR_DEFAUT);
#endif
modem.sequenceur.etat = ETAT_SEQUENCEUR_MODEM_CHANGEMENT_ETAT_IMPULSION; // Passage à l'attente de la fin de l'impulsion
break;
}
//----------------------------------------------------------------------------------------------------------------------------------------------------------
case ETAT_SEQUENCEUR_MODEM_CHANGEMENT_ETAT_IMPULSION :
//----------------------------------------------------------------------------------------------------------------------------------------------------------
{
if (modem.sequenceur.compteur == 0) // L'impulsion est terminée
{
ecriture_sortie(TYPE_SORTIE_GPIO, 0, CM3P_DO_PWKEY_MOD, OFF); // Désactivation immédiate de la sortie PowerKey. 0 est l'adresse de ShipBase
#ifdef __DEBUG_MODEM
sprintf(tmp, "Fin de l'impulsion sur PowerKey du modem. Attente du changement de son Status");
affichage_debug(__FILE__, __LINE__, tmp, TYPE_MESSAGE_DEBUG_PAR_DEFAUT);
#endif
modem.repetitions = 0;
modem.sequenceur.compteur = MODEM_TEMPO_ATTENTE_CHANGEMENT_ETAT; // Chargement d'un quantum de temps avant de venir relire l'état du Status du modem (ce quatum n'est pas critique, c'est le temps total de relecture qui est important)
modem.sequenceur.etat = ETAT_SEQUENCEUR_MODEM_CHANGEMENT_ETAT_ATTENTE_STATUS; // Passage à l'attente de la mise à jour de Status
}
break;
}
//----------------------------------------------------------------------------------------------------------------------------------------------------------
case ETAT_SEQUENCEUR_MODEM_CHANGEMENT_ETAT_ATTENTE_STATUS :
//----------------------------------------------------------------------------------------------------------------------------------------------------------
{
if (modem.sequenceur.compteur == 0)
{
if (lecture_entree(TYPE_ENTREES_GPIO, 0, CM3P_DI_STATUS_MOD, FALSE) != modem.consigne) // Si le modem n'est pas encore dans l'état souhaité : 0 est l'adresse de ShipBase
{
if (++ modem.repetitions >= MODEM_MAX_REPETITIONS_TEMPO_ATTENTE_CHANGEMENT_ETAT) // Vérification que la durée maximale d'attente n'est pas atteinte. Si oui :
{
#ifdef __DEBUG_MODEM
sprintf(tmp, "Le Status du modem SIM7070G n'est toujours pas à la consigne malgré une attente de %i ms. Une nouvelle impulsion de PowerKey va être envoyée\n", (modem.repetitions * MODEM_TEMPO_ATTENTE_CHANGEMENT_ETAT * 100));
affichage_debug(__FILE__, __LINE__, tmp, TYPE_MESSAGE_DEBUG_WARNING);
#endif
// Enregistrement dans l'historique :
enregistrement_historique(TYPE_SOURCE_HISTORIQUE_SYSTEME, SYSTEME_MODEM_ERREUR_CHANGEMENT_ETAT, 0, modem.consigne, NULL);
modem.sequenceur.etat = ETAT_SEQUENCEUR_MODEM_CHANGEMENT_ETAT_INIT; // Relance d'un cycle avec renvoit d'une impulsion
}
else modem.sequenceur.compteur = MODEM_TEMPO_ATTENTE_CHANGEMENT_ETAT; // Si non, nouveau quantum d'attente lancé
}
else // Si le modem est dans l'état souhaité :
{
#ifdef __DEBUG_MODEM
sprintf(tmp, "L'entrée Status du modem SIM7070G est passée à %i, comme demandé, après %ims.", modem.etat, ((++ modem.repetitions) * M_BUS_TEMPO_POST_IMPULSION_ACTIVATION_MODEM * 100));
affichage_debug(__FILE__, __LINE__, tmp, TYPE_MESSAGE_DEBUG_PAR_DEFAUT);
#endif
modem.etat = modem.consigne;
modem.repetitions = 0; // Utile pour vérifier que la liaison est bien établie ensuite.
// Enregistrement dans l'historique :
enregistrement_historique(TYPE_SOURCE_HISTORIQUE_SYSTEME, SYSTEME_MODEM_CHANGEMENT_ETAT, 0, modem.etat, NULL);
modem.sequenceur.etat = ETAT_SEQUENCEUR_MODEM_INIT_LIAISON;
}
}
break;
}
//----------------------------------------------------------------------------------------------------------------------------------------------------------
case ETAT_SEQUENCEUR_MODEM_INIT_LIAISON :
//----------------------------------------------------------------------------------------------------------------------------------------------------------
{
if (lecture_entree(TYPE_ENTREES_GPIO, 0, CM3P_DI_SIM_SW, FALSE) == 0) modem.etat_presence_sim = OFF; // Lecture du switch de présence de la carte SIM. 0 est l'adresse de ShipBase
else modem.etat_presence_sim = ON;
if (lecture_entree(TYPE_ENTREES_GPIO, 0, CM3P_DI_STATUS_MOD, FALSE) == 0) modem.etat = OFF; // Lecture de l'état actuel du modem. 0 est l'adresse de ShipBase
else modem.etat = ON;
//--------------------------------------------------------------------------------------------
// Préparation des commandes lorsque le modem est ON :
if (modem.etat == ON)
{
//=====================================
// Commandes liées à la liaison série :
// m_bus_down_commande_libre("AT+IPR=?", M_BUS_PROTOCOLE_NORMAL, 0, -1); // Retourne la vitesse de communication
// m_bus_down_commande_libre("AT+IPR=0", M_BUS_PROTOCOLE_NORMAL, 0, -1); // Défini la vitesse de communication (0=AUTOBAUD). Attention : la modif est conservée après Reset donc la seule façon de revenir en arrière est d'envoyer une nouvelle commande IPR à la bonne vitesse !!!!
// m_bus_down_commande_libre("AT+ICF=?", M_BUS_PROTOCOLE_NORMAL, 0, -1); // Retourne le format (nb de bits, parité et nb de stops) de la communication
// m_bus_down_commande_libre("AT+ICF=3", M_BUS_PROTOCOLE_NORMAL, 0, -1); // Défini le format (nb de bits, parité et nb de stops) de communication (défaut=3: 8N1). Attention : la modif est conservée après Reset donc la seule façon de revenir en arrière est d'envoyer une nouvelle commande IPR à la bonne vitesse !!!!
m_bus_down_commande_libre("ATE0", M_BUS_PROTOCOLE_NORMAL, 0, -1); // Echo OFF
}
modem.sequenceur.compteur = MODEM_TEMPO_CHECK_INIT_LIAISON;
modem.sequenceur.etat = ETAT_SEQUENCEUR_MODEM_COMMANDES_INIT;
break;
}
//----------------------------------------------------------------------------------------------------------------------------------------------------------
case ETAT_SEQUENCEUR_MODEM_COMMANDES_INIT :
//----------------------------------------------------------------------------------------------------------------------------------------------------------
{
if (modem.sequenceur.compteur == 0)
{
if (modem.etat_liaison == OFF) // Si la liaison n'est pas encore établie :
{
if (++ modem.repetitions >= MODEM_MAX_REPETITIONS_TEMPO_CHECK_INIT_LIAISON) // Vérification que la durée maximale d'attente n'est pas atteinte. Si oui :
{
#ifdef __DEBUG_MODEM
sprintf(tmp, "La liaison avec le modem SIM7070G n'est toujours étabie malgré une attente de %i ms. Une nouvelle impulsion de PowerKey va être envoyée\n", (modem.repetitions * MODEM_TEMPO_CHECK_INIT_LIAISON * 100));
affichage_debug(__FILE__, __LINE__, tmp, TYPE_MESSAGE_DEBUG_WARNING);
#endif
// Enregistrement dans l'historique :
enregistrement_historique(TYPE_SOURCE_HISTORIQUE_SYSTEME, SYSTEME_MODEM_ERREUR_ETABLISSEMENT_LIAISON, 0, 0, NULL);
modem.sequenceur.etat = ETAT_SEQUENCEUR_MODEM_CHANGEMENT_ETAT_INIT; // Relance d'un cycle avec renvoit d'une impulsion
}
else modem.sequenceur.etat = ETAT_SEQUENCEUR_MODEM_INIT_LIAISON; // Si non, envoi d'une nouvelle commande et nouveau quantum d'attente lancé
break;
}
else ; // Si la liaison est établie, on poursuit sur cet état de séquenceur
//--------------------------------------------------------------------------------------------
// Préparation des commandes lorsque le modem est ON :
if (modem.etat == ON)
{
//=====================================
// Commandes liées à la liaison série :
m_bus_down_commande_libre("AT+IFC=2,2", M_BUS_PROTOCOLE_NORMAL, 0, -1); // Défini le contrôle du flux dans le sens modem => UC puis UC=>modem (0:pas de ctrl de flux, 1=Xon-Xoff, 2=hardware)
// m_bus_down_commande_libre("AT+IFC?", M_BUS_PROTOCOLE_NORMAL, 0, -1); // Retourne l'état actuel du contrôle de flux
m_bus_down_commande_libre("AT+CFGRI=1", M_BUS_PROTOCOLE_NORMAL, 0, -1); // Défini le fonctionnement de la ligne RI (0: Off=default, 1:TCPIP, FGTP and URC, 2:only TCPIP). Important pour le traitement FTP.
//==========================================
// Commandes de lecture de la configuation :
// m_bus_down_commande_libre("AT+CGMI", M_BUS_PROTOCOLE_NORMAL, 0, -1); // Retourne le nom du fabricant du modem. En l'occurrence, 'SIMCOM_Ltd'. NB : supprimé car info visible dans CGMR
// m_bus_down_commande_libre("AT+CGMM", M_BUS_PROTOCOLE_NORMAL, 0, -1); // Retourne le nom du modèle du modem. En l'occurrence, 'SIMCOM_SIM7070'. NB : supprimé car info visible dans CGMR
m_bus_down_commande_libre("AT+CGMR", M_BUS_PROTOCOLE_NORMAL, 0, -1); // Retourne la version de soft du modem. En septembre 2020, 'Revision:1951B04SIM7070'.
m_bus_down_commande_libre("AT+CGSN", M_BUS_PROTOCOLE_NORMAL, 0, -1); // Retourne le n° d'IMEI (International mobile equipment identity) du modem (et pas de la carte SIM). Exemple : 869777046749118
//==========================================
// Mise à l'heure du modem :
char dt_tmp[MAX_LONGUEUR_DATE_COURANTE];
date_courante(dt_tmp, FALSE, FORMAT_DATE_COURANTE_MODEM);
sprintf(tmp, "AT+CCLK=\"%s\"", dt_tmp);
m_bus_down_commande_libre(tmp, M_BUS_PROTOCOLE_NORMAL, 0, -1); // Configuration de la date et de l'heure du modem
//===========================
// Commandes d'init du GNSS :
// Attention : a priori, la configuration du GNSS doit se faire avant de l'avoir activé
// m_bus_down_commande_libre("AT+SGNSCFG=?", M_BUS_PROTOCOLE_NORMAL, 0, -1);
m_bus_down_commande_libre("AT+SGNSCFG=\"MODE\",0", M_BUS_PROTOCOLE_NORMAL, 0, -1); // 0: Start GPS and GLONASS constellation,
// 1: Start GPS and GALILEO constellation,
// 2: Start GPS and BEIDOU constellation,
// 3: Start GPS and QZSS constellation.
// m_bus_down_commande_libre("AT+SGNSCFG=\"ADSS\",0", M_BUS_PROTOCOLE_NORMAL, 0, -1); // 0: Do not delete any data. Perform hot start if the conditions are permitted after starting GNSS,
// 1: Delete some related data. Perform warm start if the conditions are permitted after starting GNSS,
// 2: Delete all assistance data except almanac data. Enforce cold start after starting GNSS,
// 3: Delete all assistance data except almanac and sv health data. Enforce xtra cold start after starting GNSS, 4: Delete all assistance data. Enforce reset start after starting GNSS.
// Attention : la commande 'AT+SGNSCFG=\"ADSS\",0' est acceptée mais génère ensuite des ERRORS dès qu'on essaie d'activer l'alimentation du GNSS (CGNSPWR=1)...!!
// m_bus_down_commande_libre("AT+SGNSCFG?", M_BUS_PROTOCOLE_NORMAL, 0, -1);
// m_bus_down_commande_libre("AT+CGNSPWR?", M_BUS_PROTOCOLE_NORMAL, 0, -1); // Demande de l'état actuel de la commande
}
//-----------------------------------------------------------------------------------
// Préparation des commandes lorsque le modem est ON et dispose d'une carte SIM :
if ((modem.etat == ON) && (modem.etat_presence_sim == ON))
{
//==========================================
// Commandes de lecture de la configuation :
m_bus_down_commande_libre("AT+CPIN?", M_BUS_PROTOCOLE_NORMAL, 0, -1); // Retourne l'état de la carte SIM. En l'occurence, 'READY' indiquant qu'elle n'attend ni user ni pwd.
m_bus_down_commande_libre("AT+CIMI", M_BUS_PROTOCOLE_NORMAL, 0, -1); // Retourne le n° d'IMSI (International Mobile Subscriber Identity - code utilisé par l'opérateur pour identifier la carte SIM sur le réseau). Exemple : 204080811667681
m_bus_down_commande_libre("AT+CCID", M_BUS_PROTOCOLE_NORMAL, 0, -1); // Retourne le n° d'ICCID (Integrated Circuit Card ID - numéro de série de la carte SIM). Exemple : 8931080119091427723 (attention : il y a souvent un 'f' à la fin....)
// m_bus_down_commande_libre("AT+CNUM", M_BUS_PROTOCOLE_NORMAL, 0, -1); // Retourne le n° de téléphone associé à la carte. ATTENTION : cette commande ne fonctionne pas sur la plupart des cartes SIM...
//========================================
// Commandes d'init des SMS :
m_bus_down_commande_libre("AT+CMGF=1", M_BUS_PROTOCOLE_NORMAL, 0, -1); // Défini le mode de traitement des SMS en PDU (0=default) ou TEXTE (1)
// m_bus_down_commande_libre("AT+CMGF?", M_BUS_PROTOCOLE_NORMAL, 0, -1); // Reli le mode traitement des SMS en cours
// m_bus_down_commande_libre("AT+CSMS?", M_BUS_PROTOCOLE_NORMAL, 0, -1); // Retourne le type de SMS qui sont acceptés (par défaut, tous).
// m_bus_down_commande_libre("AT+CSCA?", M_BUS_PROTOCOLE_NORMAL, 0, -1); // Retourne le Service Center Address (SCA) soit le numéro de téléphone servant de serveur de SMS. A priori : +31653131313
// m_bus_down_commande_libre("AT+CPMS?", M_BUS_PROTOCOLE_NORMAL, 0, -1); // Retourne l'état de la mémoire dédiée aux SMS. Exemple de réponse : '+CPMS: "SM",0,25,"SM",0,25,"SM",0,25' soit 0 présents et 25 de capacité dans les 3 zones (qui n'en n'est qu'une si je comprends bien...)
// m_bus_down_commande_libre("AT+CNMI=0,0?", M_BUS_PROTOCOLE_NORMAL, 0, -1); // Positionne le New SMS Message Indications : mode=0 pas d'envoi de code non sollicité, mt=0 No SMS-DELIVER indications are routed to the TE.
//========================================
// Commandes d'init de la liaison 4G-LTE :
modem.etat_4g_lte = OFF;
// m_bus_down_commande_libre("AT+CGATT?", M_BUS_PROTOCOLE_NORMAL, 0, -1); // Demande de l'état d'attachement au réseau GPRS (0: detached, 1:attached)
// m_bus_down_commande_libre("AT+CFUN?", M_BUS_PROTOCOLE_NORMAL, 0, -1); // Permet de visualiser le mode de fonctionnement (0: Minimum, 1:Normal, 4:Avion, 6: Reset, 7:Offline). Default=1.
// m_bus_down_commande_libre("AT+CNACT?", M_BUS_PROTOCOLE_NORMAL, 0, -1);
m_bus_down_commande_libre("AT+CNACT=0,2", M_BUS_PROTOCOLE_NORMAL, MODEM_TIME_OUT_ATTENTE_FIN_INIT, 0); // Activation du PDP #0 (ils vont de 0 à 3) en mode AUTOACTIVE (nécessaire dans le cas où l'activation n'est pas possible immédiatement ; en particulier lors de la première mise en service de la carte SIM).
// m_bus_down_commande_libre("AT+CNACT?", M_BUS_PROTOCOLE_NORMAL, 0, -1); // Relecture de l'état des PDP
modem.sequenceur.compteur_time_out = MODEM_TIME_OUT_ATTENTE_FIN_INIT; // Permet de s'assurer qu'on reçoit bien le "+APP PDP: 0,ACTIVE" ou "+APP PDP: 0,DEACTIVE" dans un délai acceptable (cf explications sur le define de la constante dans 'modem.h')
}
else modem.sequenceur.compteur_time_out = 0; // Dans le cas où on n'a pas de carte SIM (ou pas de modem actif), il ne faut pas lancer le time-out car personne ne le remettra à 0 par anticipation (fonctionnement normal à la réception de "+APP PDP: 0,ACTIVE" par exemple).
modem.sequenceur.etat = ETAT_SEQUENCEUR_MODEM_ATTENTE_FIN_INIT;
}
break;
}
//----------------------------------------------------------------------------------------------------------------------------------------------------------
case ETAT_SEQUENCEUR_MODEM_ATTENTE_FIN_INIT :
//----------------------------------------------------------------------------------------------------------------------------------------------------------
{
if ((m_bus.down.ptr_debut_buffer_cdes == m_bus.down.ptr_fin_buffer_cdes) && // Attente que toutes les commandes dans le buffer de cdes soient traitées...
(m_bus.down.flag_attente_reponse == FALSE) && // ... et que la commande en cours ait fini d'être émise (tout cela n'est pas obligatoire mais permet d'évitre d'empiler trop de commandes)
(modem.sequenceur.compteur_time_out == 0))
{
modem.sequenceur.compteur = MODEM_PERIODE_SURVEILLANCE_MODEM; // Permet de temporiser un peu la première demande
modem.sequenceur.etat = ETAT_SEQUENCEUR_MODEM_REPOS;
}
break;
}
//=========================================================================================================================================================
// Tache de Fond :
//=========================================================================================================================================================
//----------------------------------------------------------------------------------------------------------------------------------------------------------
case ETAT_SEQUENCEUR_MODEM_REPOS :
//----------------------------------------------------------------------------------------------------------------------------------------------------------
{
if (modem.sequenceur.compteur == 0)
{
modem.sequenceur.compteur = MODEM_PERIODE_SURVEILLANCE_MODEM; // Relance du timer
//-------------------------------------------------------------------
// Présence de la carte SIM :
if (lecture_entree(TYPE_ENTREES_GPIO, 0, CM3P_DI_SIM_SW, FALSE) == 0) // Lecture du switch de présence de la carte SIM. 0 est l'adresse de ShipBase
{
modem.etat_presence_sim = OFF;
modem.etat_4g_lte = OFF;
}
else modem.etat_presence_sim = ON;
//-------------------------------------------------------------------
// Surveillance de l'état du modem :
if (lecture_entree(TYPE_ENTREES_GPIO, 0, CM3P_DI_STATUS_MOD, FALSE) == 0) // Lecture de l'état actuel du modem. 0 est l'adresse de ShipBase
{
modem.etat = OFF;
modem.etat_4g_lte = OFF;
}
else modem.etat = ON;
//-------------------------------------------------------------------
// Détection d'un changement d'état non sollicité du modem :
if (modem.etat != modem.consigne) // On vérifie que l'état actuel correspond bien à la consigne demandée (changement de consigne ou changement d'état non sollicité)
{
// Enregistrement dans l'historique :
enregistrement_historique(TYPE_SOURCE_HISTORIQUE_SYSTEME, SYSTEME_MODEM_CHANGEMENT_ETAT_NON_SOLLICITE, 0, modem.etat, NULL);
modem.sequenceur.etat = ETAT_SEQUENCEUR_MODEM_CHANGEMENT_ETAT_INIT; // Lancement d'une séquence d'activation selon la consigne demandée
break; // Pas la peine de traiter la suite...
}
#ifdef __DEBUG_MODEM
sprintf(tmp, "Surveillance du modem : présence SIM= %i, état_4G= %i, niveau RSRP=%i dbm, état_gnss=%i, compteur GNSS= %i, compteur Upload= %i, compteur Download= %i", modem.etat_presence_sim, modem.etat_4g_lte, entrees.predefinie.compagnon.rsrp, gnss.etat, modem.compteur_periode_gnss, modem.compteur_periode_upload, modem.compteur_periode_download);
affichage_debug(__FILE__, __LINE__, tmp, TYPE_MESSAGE_DEBUG_PAR_DEFAUT);
#endif
//-------------------------------------------------------------------
// GNSS :
if (modem.etat == ON)
{
if (modem.compteur_periode_gnss > 0) modem.compteur_periode_gnss --;
if (modem.compteur_periode_gnss == 0)
{
if (modem.etat_4g_lte == ON) modem.compteur_periode_gnss = ((MODEM_GNSS_PERIODE_ACQUISITION_AVEC_4G_LTE * 10) / MODEM_PERIODE_SURVEILLANCE_MODEM); // Le x10 = x1000ms / 100ms et provient du fait que la période de check est en secondes alors que MODEM_PERIODE_SURVEILLANCE_MODEM est en 100ms
else modem.compteur_periode_gnss = ((MODEM_GNSS_PERIODE_ACQUISITION_SANS_4G_LTE * 10) / MODEM_PERIODE_SURVEILLANCE_MODEM); // Le x10 = x1000ms / 100ms et provient du fait que la période de check est en secondes alors que MODEM_PERIODE_SURVEILLANCE_MODEM est en 100ms
modem.sequenceur.etat = ETAT_SEQUENCEUR_MODEM_GNSS_ACTIVATION;
break; // Permet de ne pas traiter les tâches suivantes si on lance un cycle GNSS
}
}
//-------------------------------------------------------------------
// Vérification si des fichiers doivent être uploadés et upload :
if (modem.etat_4g_lte == ON)
{
if (modem.compteur_periode_upload > 0) modem.compteur_periode_upload --;
if (modem.compteur_periode_upload == 0)
{
#ifdef __DEBUG_MODEM_FTP_UPLOAD
affichage_debug(__FILE__, __LINE__, "---------------------Début accès FTP PUT---------------------------------------", TYPE_MESSAGE_DEBUG_PAR_DEFAUT);
#endif
strcpy(upload.nom_fichier_source, "");
struct dirent *dir; // Les types 'dirent' ou 'DIR' sont déclarés dans le header <dirent.h>
DIR *repertoire = opendir(REPERTOIRE_SERVER_UPLOAD); // Ouverture du répertoire
if (repertoire != NULL)
{
while ((dir = readdir(repertoire)) != NULL) // Lecture de tous les fichiers du répertoire pour rechercher le plus ancien :
{
if (strcmp(dir->d_name, ".") == 0) continue; // On ne traite pas le répertoire '.' ...
if (strcmp(dir->d_name, "..") == 0) continue; // ... ni le répertoire '..'
if (strcmp(upload.nom_fichier_source, "") == 0) strcpy(upload.nom_fichier_source, dir->d_name); // Cas où c'est le premier fichier valide trouvé
else if (strcmp(upload.nom_fichier_source, dir->d_name) > 0) strcpy(upload.nom_fichier_source, dir->d_name); // Si ce n'est pas le premier fichier, on garde le plus ancien (par son nom, ATTENTION).
}
closedir(repertoire); // Fermeture du répertoire
}
// Préparation de l'upload quand il y a un fichier disponible :
if (strcmp(upload.nom_fichier_source, "") != 0)
{
sprintf(upload.nom_repertoire_source, "%s/", REPERTOIRE_SERVER_UPLOAD);
sprintf(upload.nom_repertoire_destination, "%s/%s%s/", REPERTOIRE_SERVEUR, conversion_adresse_mac_chaine(systeme.modules_physiques[0].adresse_mac, tmp, '_'), REPERTOIRE_UPLOAD_DESTINATION);
strcpy(upload.nom_fichier_destination, upload.nom_fichier_source); // Par défaut, le nom est conservé lors du transfert
modem.sequenceur.etat = ETAT_SEQUENCEUR_MODEM_FTP_PUT_LANCEMENT;
break; // Si on part sur du FTP PUT, on ne traite pas les fonctions de tâche de fond suivantes
}
else // On ne relance la tempo que lorsque'on n'a plus de fichier à envoyer (on en envoi donc 1 à chaque MODEM_PERIODE_SURVEILLANCE_MODEM tant qu'il y en a - et si un période GNSS n'est pas arrivée entre temps). Cela évite d'attendre trop longtemps quand on a du retard d'envoi...
{
modem.compteur_periode_upload = ((MODEM_UPLOAD_PERIODE_CHECK * 10) / MODEM_PERIODE_SURVEILLANCE_MODEM);
}
}
}
//----------------------------------------------------------------------------
// Vérification si des fichiers doivent être downloadés et download :
if ((modem.etat_4g_lte == ON) && (systeme.flag_new_download == FALSE)) // Tant que le chargement précédent n'est pas terminé, on ne regarde pas si un autre doit être fait...
{
if (modem.compteur_periode_download > 0) modem.compteur_periode_download --;
if (modem.compteur_periode_download == 0)
{
modem.compteur_periode_download = ((MODEM_DOWNLOAD_PERIODE_CHECK * 10) / MODEM_PERIODE_SURVEILLANCE_MODEM); // Le x10 = x1000ms / 100ms et provient du fait que la période de check est en secondes alors que MODEM_PERIODE_SURVEILLANCE_MODEM est en 100ms
sprintf(download.nom_repertoire_source, "%s/%s%s/", REPERTOIRE_SERVEUR, conversion_adresse_mac_chaine(systeme.modules_physiques[0].adresse_mac, tmp, '_'), REPERTOIRE_DOWNLOAD_SOURCE);
modem.sequenceur.etat = ETAT_SEQUENCEUR_MODEM_FTP_GET_LANCEMENT;
break;
}
}
//-------------------------------------------------------------------
// Suivi du modem en tâche de fond :
if (modem.etat_presence_sim == ON)
{
// Demandes d'infos sur le réseau 4G-LTE :
m_bus_down_commande_libre("AT+CPSI?", M_BUS_PROTOCOLE_NORMAL, 0, -1); // Demande des informations de connexions au réseau
m_bus_down_commande_libre("AT+CGNAPN", M_BUS_PROTOCOLE_NORMAL, 0, -1); // Retourne le nom du réseau APN. En l'occurence "fixedip.m2m" ou " matooma.m2m"
m_bus_down_commande_libre("AT+CNACT?", M_BUS_PROTOCOLE_NORMAL, 0, -1); // Relecture de l'état des PDP
// Lecture des SMS :
m_bus_down_commande_libre("AT+CMGL=\"REC UNREAD\", 1", M_BUS_PROTOCOLE_NORMAL, 200, -1); // Demande la liste des SMS Reçus et Non Lus, et 0= on les passe en 'lus' (default) ou 1= on ne change pas leur état
}
else
{
// m_bus_down_commande_libre("AT+CCLK?", M_BUS_PROTOCOLE_NORMAL, 0, -1); // Lecture de la date et de l'heure du modem (NB : le retour n'est pas traité...! Sert uniquement à l'analyseur)
}
}
break;
}
//=========================================================================================================================================================
// GNSS :
//=========================================================================================================================================================
//----------------------------------------------------------------------------------------------------------------------------------------------------------
case ETAT_SEQUENCEUR_MODEM_GNSS_ACTIVATION:
//----------------------------------------------------------------------------------------------------------------------------------------------------------
{
#ifdef __DEBUG_MODEM_GNSS
affichage_debug(__FILE__, __LINE__, "---------------------Début acquisition GNSS---------------------------------------", TYPE_MESSAGE_DEBUG_PAR_DEFAUT);
#endif
// Coupure de la connexion 4G car le GNSS ne peut fonctionner simultanément :
modem.etat_4g_lte = OFF;
m_bus_down_commande_libre("AT+CFUN=4", M_BUS_PROTOCOLE_NORMAL, 0, -1); // Turn Off RF modem part (permet au GNSS de fonctionner)
modem.compteur_cycles_gnss = 0;
modem.compteur_cycles_valides_gnss = 0;
modem.sequenceur.compteur = MODEM_GNSS_TEMPO_ATTENTE_COUPURE_4G_LTE;
modem.sequenceur.etat = ETAT_SEQUENCEUR_MODEM_GNSS_ATTENTE_COUPURE_4G_LTE;
break;
}
//----------------------------------------------------------------------------------------------------------------------------------------------------------
case ETAT_SEQUENCEUR_MODEM_GNSS_ATTENTE_COUPURE_4G_LTE:
//----------------------------------------------------------------------------------------------------------------------------------------------------------
{
if (modem.sequenceur.compteur == 0)
{
m_bus_down_commande_libre("AT+CGNSPWR=1", M_BUS_PROTOCOLE_NORMAL, 0, -1); // Turn On GNSS power supply
modem.sequenceur.compteur = MODEM_GNSS_TEMPO_ATTENTE_ACTIVATION;
modem.sequenceur.etat = ETAT_SEQUENCEUR_MODEM_GNSS_ATTENTE_LECTURE;
}
break;
}
//----------------------------------------------------------------------------------------------------------------------------------------------------------
case ETAT_SEQUENCEUR_MODEM_GNSS_ATTENTE_LECTURE:
//----------------------------------------------------------------------------------------------------------------------------------------------------------
{
if (modem.sequenceur.compteur == 0)
{
#ifdef __DEBUG_MODEM_GNSS
sprintf(tmp, "Lancement du cycle GNSS n° %3i (%2i sont déjà valides)", modem.compteur_cycles_gnss, modem.compteur_cycles_valides_gnss);
affichage_debug(__FILE__, __LINE__, tmp, TYPE_MESSAGE_DEBUG_PAR_DEFAUT);
#endif
m_bus_down_commande_libre("AT+CGNSINF", M_BUS_PROTOCOLE_NORMAL, 0, -1); // Lecture des infos de localisation
modem.sequenceur.compteur_time_out = MODEM_GNSS_TIME_OUT_ATTENTE_LECTURE;
modem.sequenceur.etat = ETAT_SEQUENCEUR_MODEM_GNSS_LECTURE;
}
break;
}
//----------------------------------------------------------------------------------------------------------------------------------------------------------
case ETAT_SEQUENCEUR_MODEM_GNSS_LECTURE:
//----------------------------------------------------------------------------------------------------------------------------------------------------------
{
if (modem.sequenceur.compteur_time_out == 0)
{
//=======================================
// Fin de la période d'acquisition GNSS :
if (modem.compteur_cycles_valides_gnss >= MODEM_GNSS_NOMBRE_CYCLES_VALIDES)
{
gnss.etat = ON;
// SDIR #107 :
c_bus_down_commande_config_date_heure(); // Mise à jour de la date/heure du Compagnon (toujours en UTC)
// Fin SDIR
m_bus_down_commande_libre("AT+CGNSPWR=0", M_BUS_PROTOCOLE_NORMAL, 0, -1); // Turn Off GNSS power supply
sprintf(tmp, "L'acquisition GNSS vient de se terminer avec %i cycles valides sur %i cycles au total", modem.compteur_cycles_valides_gnss, (modem.compteur_cycles_gnss+1));
affichage_debug(__FILE__, __LINE__, tmp, TYPE_MESSAGE_DEBUG_PAR_DEFAUT);
// Réactivation de la connexion 4G :
m_bus_down_commande_libre("AT+CFUN=1,1", M_BUS_PROTOCOLE_NORMAL, 0, -1); // Reset soft du modem, obligatoire après la coupure au début de la période GNSS
modem.sequenceur.compteur = MODEM_TEMPO_APRES_RESET_SOFT;
modem.sequenceur.etat = ETAT_SEQUENCEUR_MODEM_INIT;
}
else
{
//===================================
// Nouveau cycle d'acquisition GNSS :
if (++ modem.compteur_cycles_gnss <= MODEM_GNSS_MAX_NOMBRE_CYCLES)
{
modem.sequenceur.compteur = MODEM_GNSS_TEMPO_ENTRE_LECTURES; // Petite temporisation pour éviter d'envoyer les commandes en rafale...
modem.sequenceur.etat = ETAT_SEQUENCEUR_MODEM_GNSS_ATTENTE_LECTURE;
}
//===========================================
// Abandon de la période d'acquisition GNSS :
else
{
sprintf(tmp, "Abandon de l'acquisition GNSS car %i cycles au total (pour %i valides)", modem.compteur_cycles_gnss, modem.compteur_cycles_valides_gnss);
affichage_debug(__FILE__, __LINE__, tmp, TYPE_MESSAGE_DEBUG_ERREUR);
gnss.etat = OFF;
enregistrement_historique(TYPE_SOURCE_HISTORIQUE_SYSTEME, SYSTEME_MODEM_ERREUR_GNSS, 0, modem.compteur_cycles_valides_gnss, NULL);
m_bus_down_commande_libre("AT+CGNSPWR=0", M_BUS_PROTOCOLE_NORMAL, 0, -1); // Turn Off GNSS power supply
// Réactivation de la connexion 4G :
m_bus_down_commande_libre("AT+CFUN=1,1", M_BUS_PROTOCOLE_NORMAL, 0, -1); // Reset soft du modem, obligatoire après la coupure au début de la période GNSS
modem.sequenceur.compteur = MODEM_TEMPO_APRES_RESET_SOFT;
modem.sequenceur.etat = ETAT_SEQUENCEUR_MODEM_INIT;
}
}
}
break;
}
//=========================================================================================================================================================
// FTP GET :
// Cette séquence consiste à :
// - créer un fichier '__list_download_serveur.txt' dans le répertoire local 'download'
// - le remplir avec le retour du serveur sur son répertoire 'download' (format texte du type 'ls -l)
// - établir la liste des fichiers à télécharger (ceux présents sur le serveur et pas localement OU ceux présents sur le serveur et localement mais
// avec des tailles différentes) et des fichiers à supprimer localement (présents localement mais plus présents sur le serveur).
// - supprimer localement les fichiers à supprimer
// - télécharger les fichiers à télécharger.
// NB : l'historique contient toutes les opérations de téléchargement et de suppression. C'est la seule trace après ces opérations.
//=========================================================================================================================================================
//----------------------------------------------------------------------------------------------------------------------------------------------------------
case ETAT_SEQUENCEUR_MODEM_FTP_GET_LANCEMENT:
//----------------------------------------------------------------------------------------------------------------------------------------------------------
{
#ifdef __DEBUG_MODEM_FTP_DOWNLOAD
affichage_debug(__FILE__, __LINE__, "---------------------Début accès FTP GET---------------------------------------", TYPE_MESSAGE_DEBUG_PAR_DEFAUT);
#endif
// Ouverture du fichier à écrire localement :
sprintf(tmp, "%s/%s", REPERTOIRE_SERVER_DOWNLOAD, NOM_FICHIER_LISTING_REPERTOIRE_DOWNLOAD_SERVEUR);
download.ptr_fichier_destination = fopen(tmp, "w"); // Ouverture du fichier en "écriture"...
if (download.ptr_fichier_destination == NULL)
{
sprintf(tmp, "L'ouverture du fichier de LIST '%s/%s' n'est pas possible. La liste du répertoire download du serveur est abandonnée...", REPERTOIRE_SERVER_DOWNLOAD, NOM_FICHIER_LISTING_REPERTOIRE_DOWNLOAD_SERVEUR);
affichage_debug(__FILE__, __LINE__, tmp, TYPE_MESSAGE_DEBUG_ERREUR);
// Enregistrement dans l'historique :
sprintf(tmp, "%s", download.nom_fichier_destination);
enregistrement_historique(TYPE_SOURCE_HISTORIQUE_SYSTEME, SYSTEME_FTP_DOWNLOAD_LIST_NOK, 0, 0, tmp);
modem.sequenceur.etat = ETAT_SEQUENCEUR_MODEM_REPOS;
break;
}
else
{
fclose(download.ptr_fichier_destination); // Fermeture du fichier
download.taille_fichier_local = 0;
download.no_paquet = 0;
}
m_bus_down_commande_libre("AT+FTPCID=0", M_BUS_PROTOCOLE_NORMAL, 0, -1); // Bearer profile identifier refer to AT+CNACT
sprintf(tmp, "AT+FTPSERV=\"%s\"", SERVEUR_FTP_ADRESSE);
m_bus_down_commande_libre(tmp, M_BUS_PROTOCOLE_NORMAL, 0, -1); // Défini l'adresse du serveur FTP à joindre
sprintf(tmp, "AT+FTPUN=\"%s\"", SERVEUR_FTP_USER);
m_bus_down_commande_libre(tmp, M_BUS_PROTOCOLE_NORMAL, 0, -1); // Défini le nom d'utilisateur sur le serveur FTP
sprintf(tmp, "AT+FTPPW=\"%s\"", SERVEUR_FTP_PASSWORD);
m_bus_down_commande_libre(tmp, M_BUS_PROTOCOLE_NORMAL, 0, -1); // Défini le pwd de l'utilisateur sur le serveur FTP
sprintf(tmp, "AT+FTPGETPATH=\"%s\"", download.nom_repertoire_source);
m_bus_down_commande_libre(tmp, M_BUS_PROTOCOLE_NORMAL, 0, -1); // Défini le path du répertoire à lister
m_bus_down_commande_libre("AT+FTPLIST=1", M_BUS_PROTOCOLE_NORMAL, MODEM_DOWNLOAD_TIME_OUT_ATTENTE_INFO, 0);
download.nb_fichiers_liste = 0; // Permet de démarrer le cycle à jour
download.fichier_en_cours = -1; // Marqueur pour indiquer qu'aucun fichier n'a été téléchargé pour le moment
download.taille_buffer_rx = 0; // Est nécessaire pour que la fonction M_COMMANDE_FTPLIST_1 de m_commandes.c focntionne correctement au démarrage
download.taille_buffer_tx = MODEM_MAX_TAILLE_TRAME_FTPLIST; // Idem.
download.status_get = -1; // Idem.
modem.sequenceur.compteur = MODEM_DOWNLOAD_TIME_OUT_ATTENTE_INFO;
modem.sequenceur.etat = ETAT_SEQUENCEUR_MODEM_FTP_GET_ATTENTE_INFORMATION;
break;
}
//----------------------------------------------------------------------------------------------------------------------------------------------------------
case ETAT_SEQUENCEUR_MODEM_FTP_GET_ATTENTE_INFORMATION:
//----------------------------------------------------------------------------------------------------------------------------------------------------------
{
if (modem.sequenceur.compteur == 0)
{
switch(download.status_get)
{
case 1: // Cas normal, l'échange peut continuer :
{
download.taille_buffer_tx = MODEM_MAX_TAILLE_TRAME_FTPLIST;
sprintf(tmp, "AT+FTPLIST=2,%i", download.taille_buffer_tx);
m_bus_down_commande_libre(tmp, M_BUS_PROTOCOLE_NORMAL, MODEM_DOWNLOAD_TIME_OUT_ATTENTE_LISTE, 0);
modem.sequenceur.compteur = MODEM_DOWNLOAD_TIME_OUT_ATTENTE_LISTE;
modem.sequenceur.etat = ETAT_SEQUENCEUR_MODEM_FTP_GET_ATTENTE_LISTE;
break;
}
case -1 : // Aucun retour n'a été reçu à la fin du time-out :
{
sprintf(tmp, "Aucun retour de la fonction LIST à l'expiration du time-out. Le transfert est arrêté.");
affichage_debug(__FILE__, __LINE__, tmp, TYPE_MESSAGE_DEBUG_ERREUR);
modem.sequenceur.etat = ETAT_SEQUENCEUR_MODEM_REPOS;
break;
}
case 0 : // Aucune donnée n'est dispo. Le transfert est terminé :
{
sprintf(tmp, "Retour de la fonction LIST indiquant qu'aucune données n'est disponible. Le transfert est arrêté.");
affichage_debug(__FILE__, __LINE__, tmp, TYPE_MESSAGE_DEBUG_ERREUR);
modem.sequenceur.etat = ETAT_SEQUENCEUR_MODEM_REPOS;
break;
}
default : // Si > 1, erreur de GET
{
sprintf(tmp, "Retour en erreur de la fonction LIST (code d'erreur = %i). Le transfert est arrêté.", download.status_get);
affichage_debug(__FILE__, __LINE__, tmp, TYPE_MESSAGE_DEBUG_ERREUR);
modem.sequenceur.etat = ETAT_SEQUENCEUR_MODEM_REPOS;
break;
}
}
}
break;
}
//----------------------------------------------------------------------------------------------------------------------------------------------------------
case ETAT_SEQUENCEUR_MODEM_FTP_GET_ATTENTE_LISTE:
//----------------------------------------------------------------------------------------------------------------------------------------------------------
{
if (modem.sequenceur.compteur == 0)
{
switch(download.status_get)
{
case 1: // Cas normal, l'échange peut continuer immédiatement :
{
if (download.taille_buffer_rx > 0) // On passe ici plusieurs fois en fin de transfert en attente de 'FTPGET: 1,0' et dans ce cas, ce ne sont pas de 'vrais' blocs qui sont reçus...
{
if ((download.no_paquet ++) >= MODEM_MAX_NOMBRE_PAQUETS_LIST)
{
sprintf(tmp, "Le nombre de paquets reçus par la fonction LIST est trop important (nombre = %i). Le transfert est arrêté.", download.no_paquet);
affichage_debug(__FILE__, __LINE__, tmp, TYPE_MESSAGE_DEBUG_ERREUR);
modem.sequenceur.etat = ETAT_SEQUENCEUR_MODEM_REPOS;
}
#ifdef __DEBUG_MODEM_FTP_DOWNLOAD
sprintf(tmp, "Réception du paquet n° %4i avec %4i octets (total reçu = %8i octets)", download.no_paquet, download.taille_buffer_rx, download.taille_fichier_local);
affichage_debug(__FILE__, __LINE__, tmp, TYPE_MESSAGE_DEBUG_PAR_DEFAUT);
#endif
}
modem.sequenceur.etat = ETAT_SEQUENCEUR_MODEM_FTP_GET_ATTENTE_INFORMATION;
// NB : on ne recharge pas le compteur car on veut que la prochaine commande FTPLIST=2,xxx soit faite dès que possible.
// NB 2 : on ne peut pas faire tout à fait comme en mode GET car on ne connait pas à l'avance la taille des données à recevoir...
break;
}
case 0 : // Plus aucune donnée n'est dispo. Le transfert est terminé :
{
// On s'assure que la libération du protocole M-Bus a bien été faite (on risque sinon de rester bloqué en mode FLUX_BINAIRE) :
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.
// Listing des fichiers locaux :
struct dirent *dir; // Les types 'dirent' ou 'DIR' sont déclarés dans le header <dirent.h>
FILE *ptr_fic;
char nom_fic[MAX_LONGUEUR_NOM_FICHIER];
DIR *repertoire = opendir(REPERTOIRE_SERVER_DOWNLOAD); // Ouverture du répertoire
if (repertoire != NULL)
{
while ((dir = readdir(repertoire)) != NULL) // Lecture de tous les fichiers du répertoire :
{
if (strcmp(dir->d_name, ".") == 0) continue; // On ne traite pas le répertoire '.' ...
if (strcmp(dir->d_name, "..") == 0) continue; // ... ni le répertoire '..'
strcpy(download.liste_fichiers[download.nb_fichiers_liste].nom, dir->d_name);
sprintf(nom_fic, "%s/%s", REPERTOIRE_SERVER_DOWNLOAD, download.liste_fichiers[download.nb_fichiers_liste].nom);
ptr_fic=fopen(nom_fic,"rb");
if(ptr_fic)
{
fseek (ptr_fic, 0, SEEK_END); // Place le curseur à la fin du fichier
download.liste_fichiers[download.nb_fichiers_liste].taille_locale = ftell(ptr_fic); // Lit la position du curseur, donc la taille...
fclose (ptr_fic);
}
char * p;
p = strstr(download.liste_fichiers[download.nb_fichiers_liste].nom, MARQUEUR_FICHIER_DONE); // Si le fichier local contient l'extension '.DONE'...
if (p != NULL) *p = 0; // ... on supprime le suffixe. Cela permet de ne pas recharger un fichier traité, sauf si sa taille a changée.
download.liste_fichiers[download.nb_fichiers_liste].taille_serveur = 0; // Par défaut.
download.liste_fichiers[download.nb_fichiers_liste].flag_a_telecharger = FALSE; // Par défaut (si on ne trouve pas de fichier identique sur le serveur) : on ne télécharge pas le fichier...
download.liste_fichiers[download.nb_fichiers_liste].flag_a_supprimer = TRUE; // ... et on le supprime à la fin.
// Cas particulier du fichier contenant le listing du serveur et qu'on conserve (alors qu'il n'est pas présent sur le serveur) :
if (strcmp(dir->d_name, NOM_FICHIER_LISTING_REPERTOIRE_DOWNLOAD_SERVEUR) == 0) download.liste_fichiers[download.nb_fichiers_liste].flag_a_supprimer = FALSE;
if (++ download.nb_fichiers_liste >= MAX_NOMBRE_FICHIERS_DOWNLOAD) // Cas où le nombre de fichiers est trop important dans le épertoire pour pouvoir être traité...
{
enregistrement_historique(TYPE_SOURCE_HISTORIQUE_SYSTEME, SYSTEME_FTP_DOWNLOAD_NOMBRE_FICHIERS_LOCAUX_TROP_ELEVE, 0, MAX_NOMBRE_FICHIERS_DOWNLOAD, NULL);
break;
}
}
closedir(repertoire); // Fermeture du répertoire
}
// Ouverture du fichier de LIST :
sprintf(tmp, "%s/%s", REPERTOIRE_SERVER_DOWNLOAD, NOM_FICHIER_LISTING_REPERTOIRE_DOWNLOAD_SERVEUR);
download.ptr_fichier_destination = fopen(tmp, "r"); // Ouverture du fichier en "lecture"...
if (download.ptr_fichier_destination == NULL)
{
sprintf(tmp, "L'ouverture du fichier de LIST '%s/%s' n'est pas possible en lecture. L'utilisation de LIST est abandonnée...", REPERTOIRE_SERVER_DOWNLOAD, NOM_FICHIER_LISTING_REPERTOIRE_DOWNLOAD_SERVEUR);
affichage_debug(__FILE__, __LINE__, tmp, TYPE_MESSAGE_DEBUG_ERREUR);
// Enregistrement dans l'historique :
sprintf(tmp, "%s", download.nom_fichier_destination);
enregistrement_historique(TYPE_SOURCE_HISTORIQUE_SYSTEME, SYSTEME_FTP_DOWNLOAD_LIST_NOK, 0, 0, tmp);
modem.sequenceur.etat = ETAT_SEQUENCEUR_MODEM_REPOS;
break;
}
else
{
while (fscanf(download.ptr_fichier_destination,"%*s %d %*s %*s %d %*s %*s %*s %s", &type, &taille, nom) != EOF)
{
if (type != 1) continue; // Seul les lignes avec 'type=1' correspondent à des fichiers (2= sous-répertoire, 3= répertoire actuel (.) et 4= répertoire parent (..))
if (taille == 0) // Si le fichier est de taille nulle, on ne stocke pas cette entrée (on ne télécharge pas des fichiers vides...) :
{
sprintf(tmp, "Le fichier [%s] a une taille de 0 octets => le fichier ne pourra pas être téléchargé...\n", nom);
affichage_debug(__FILE__, __LINE__, tmp, TYPE_MESSAGE_DEBUG_ERREUR);
continue;
}
else if (taille > MAX_TAILLE_FICHIER_DOWNLOAD) // Si le fichier est trop gros, on ne stocke pas cette entrée car on ne pourra pas télécharger un tel fichier :
{
sprintf(tmp, "Le fichier [%s] a une taille de %i octets => le fichier est trop gros (max = %i octets) et ne pourra pas être téléchargé...\n", nom, taille, MAX_TAILLE_FICHIER_DOWNLOAD);
affichage_debug(__FILE__, __LINE__, tmp, TYPE_MESSAGE_DEBUG_ERREUR);
continue;
}
else // Si c'est un fichier "normal", on vérifie s'il existe localement ou pas pour savoir s'il va falloir le télécharger
{
for (i = 0; i < download.nb_fichiers_liste; i++) // Boucle sur tous les fichiers locaux :
{
if (strcmp(nom, download.liste_fichiers[i].nom) == 0) // Cas où le fichier existe localement ET sur le serveur :
{
download.liste_fichiers[i].taille_serveur = taille;
if (download.liste_fichiers[i].taille_locale == taille) // Si les tailles sont identiques :
{
download.liste_fichiers[i].flag_a_supprimer = FALSE; // On va conserver le fichier local (et ne pas télécharger celui du serveur, tel que prévu par défaut)
}
else // Si les tailles sont différentes :
{
download.liste_fichiers[i].flag_a_telecharger = TRUE; // on va télécharger la version du serveur (et la version locale sera supprimée, prévu par défaut).
}
break;
}
}
if (i == download.nb_fichiers_liste) // Si on ne l'a pas trouvé dans la liste, c'est qu'il existe sur le serveur mais PAS localement :
{
strcpy(download.liste_fichiers[download.nb_fichiers_liste].nom, nom); // On mémorise son nom
download.liste_fichiers[download.nb_fichiers_liste].taille_serveur = taille; // ... et sa taille
download.liste_fichiers[download.nb_fichiers_liste].taille_locale = 0;
download.liste_fichiers[download.nb_fichiers_liste].flag_a_telecharger = TRUE; // Et on mentionne qu'il doit être chargé depuis le serveur
download.liste_fichiers[download.nb_fichiers_liste].flag_a_supprimer = FALSE; // .. et qu'on n'a pas à le supprimer localement (en même temps, il n'existe pas encore...).
if (++ download.nb_fichiers_liste >= MAX_NOMBRE_FICHIERS_DOWNLOAD) // Cas où le nombre de fichiers est trop important dans le répertoire distant pour pouvoir être traité...
{
enregistrement_historique(TYPE_SOURCE_HISTORIQUE_SYSTEME, SYSTEME_FTP_DOWNLOAD_NOMBRE_FICHIERS_SERVEUR_TROP_ELEVE, 0, MAX_NOMBRE_FICHIERS_DOWNLOAD, NULL);
break;
}
}
}
}
fclose(download.ptr_fichier_destination); // Fermeture du fichier
}
#ifdef __DEBUG_MODEM_FTP_DOWNLOAD
char chaine_tmp[50];
sprintf(tmp, "Synthèse de l'état des répertoires de download, local et distant AVANT traitement :");
affichage_debug(__FILE__, __LINE__, tmp, TYPE_MESSAGE_DEBUG_OK);
for (i = 0; i < download.nb_fichiers_liste; i++) // Boucle sur tous les fichiers locaux pour supprimer ceux qui doivent l'être
{
sprintf(tmp, "\t%-25s\t", download.liste_fichiers[i].nom);
if (download.liste_fichiers[i].taille_locale != 0) sprintf(chaine_tmp, "\tlocal = %8i octets", download.liste_fichiers[i].taille_locale);
else sprintf(chaine_tmp, "\t.......................");
strcat(tmp, chaine_tmp);
if (download.liste_fichiers[i].taille_serveur != 0) sprintf(chaine_tmp, "\t\tserveur = %8i octets", download.liste_fichiers[i].taille_serveur);
else sprintf(chaine_tmp, "\t\t.........................");
strcat(tmp, chaine_tmp);
if (download.liste_fichiers[i].flag_a_supprimer == TRUE) sprintf(chaine_tmp, "\tLocal à supprimer");
else sprintf(chaine_tmp, "\t.................");
strcat(tmp, chaine_tmp);
if (download.liste_fichiers[i].flag_a_telecharger == TRUE) sprintf(chaine_tmp, "\tServeur à télécharger");
else sprintf(chaine_tmp, "\t.....................");
strcat(tmp, chaine_tmp);
affichage_debug(__FILE__, __LINE__, tmp, TYPE_MESSAGE_DEBUG_OK);
}
#endif
// Suppression des fichiers locaux qui doivent l'être :
for (i = 0; i < download.nb_fichiers_liste; i++) // Boucle sur tous les fichiers locaux pour supprimer ceux qui doivent l'être
{
if (download.liste_fichiers[i].flag_a_supprimer == TRUE)
{
sprintf(tmp, "%s/%s", REPERTOIRE_SERVER_DOWNLOAD, download.liste_fichiers[i].nom);
remove(tmp);
strcat(tmp, MARQUEUR_FICHIER_DONE);
remove(tmp);
}
}
modem.sequenceur.etat = ETAT_SEQUENCEUR_MODEM_FTP_GET_RECHERCHE_FICHIER; // Poursuite avec la recherche d'un fichier à récupérer
break;
}
case -1 : // Aucun retour n'a été reçu à la fin du time-out :
{
#ifdef __DEBUG_MODEM_FTP_DOWNLOAD
sprintf(tmp, "Aucun retour de la fonction LIST à l'expiration du time-out. Le transfert est arrêté.");
affichage_debug(__FILE__, __LINE__, tmp, TYPE_MESSAGE_DEBUG_ERREUR);
#endif
modem.sequenceur.etat = ETAT_SEQUENCEUR_MODEM_REPOS;
break;
}
default : // Si > 1, erreur de GET. On va attendre qu'un retour de status_get=1 revienne (cas le plus fréquent)
{
#ifdef __DEBUG_MODEM_FTP_DOWNLOAD
sprintf(tmp, "Retour en erreur de la fonction LIST (code d'erreur = %i). Le transfert est arrêté.", download.status_get);
affichage_debug(__FILE__, __LINE__, tmp, TYPE_MESSAGE_DEBUG_ERREUR);
#endif
modem.sequenceur.etat = ETAT_SEQUENCEUR_MODEM_REPOS;
break;
}
}
}
break;
}
//----------------------------------------------------------------------------------------------------------------------------------------------------------
case ETAT_SEQUENCEUR_MODEM_FTP_GET_RECHERCHE_FICHIER:
//----------------------------------------------------------------------------------------------------------------------------------------------------------
{
// Recherche dans la liste des fichiers, le prochain à télécharger du serveur :
download.taille_fichier_serveur = 0;
for (i = 0; i < download.nb_fichiers_liste; i++)
{
if (download.liste_fichiers[i].flag_a_telecharger == TRUE)
{
strcpy(download.nom_fichier_source, download.liste_fichiers[i].nom);
download.taille_fichier_serveur = download.liste_fichiers[i].taille_serveur;
download.fichier_en_cours = i; // Permettra de mettre son flag à 0 si le téléchargement est bien allé à son terme (et, indirectement car != -1, permettra de savoir qu'un moins un téléchargement a été réalisé et informer 'systeme.c')
break; // On s'arrête dès qu'on a trouvé un fichier à télécharger
}
}
if (download.taille_fichier_serveur > 0) // Si la taille est > 0, c'est qu'un fichier à télécharger a été trouvé
{
sprintf(download.nom_repertoire_source, "%s/%s%s/", REPERTOIRE_SERVEUR, conversion_adresse_mac_chaine(systeme.modules_physiques[0].adresse_mac, tmp, '_'), REPERTOIRE_DOWNLOAD_SOURCE);
sprintf(download.nom_repertoire_destination, "%s/", REPERTOIRE_SERVER_DOWNLOAD);
strcpy(download.nom_fichier_destination, download.nom_fichier_source); // Par défaut, le nom est conservé lors du transfert
modem.sequenceur.etat = ETAT_SEQUENCEUR_MODEM_FTP_GET_DEBUT_FICHIER;
}
else // Sinon, c'est qu'il n'y a plus de fichier à télécharger
{
systeme.flag_new_download = TRUE; // Le principe retenu est qu'après chaque séquence de GET, on alerte gestion_systeme() pour qu'il vérifie si des chargements de code ne sont pas nécessaires.
modem.sequenceur.etat = ETAT_SEQUENCEUR_MODEM_REPOS;
}
break;
}
//----------------------------------------------------------------------------------------------------------------------------------------------------------
case ETAT_SEQUENCEUR_MODEM_FTP_GET_DEBUT_FICHIER:
//----------------------------------------------------------------------------------------------------------------------------------------------------------
{
#ifdef __DEBUG_MODEM_FTP_DOWNLOAD
sprintf(tmp, "Connexion FTP pour download du fichier '%s%s' vers le fichier '%s%s'", download.nom_repertoire_source, download.nom_fichier_source, download.nom_repertoire_destination, download.nom_fichier_destination);
affichage_debug(__FILE__, __LINE__, tmp, TYPE_MESSAGE_DEBUG_PAR_DEFAUT);
#endif
download.secondes_debut = timestamp_secondes(); // Stockage du timestamp de départ
// Ouverture du fichier à écrire localement :
sprintf(tmp, "%s%s", download.nom_repertoire_destination, download.nom_fichier_destination);
download.ptr_fichier_destination = fopen(tmp, "wb"); // Ouverture du fichier en "écriture"...
if (download.ptr_fichier_destination == NULL)
{
sprintf(tmp, "L'ouverture du fichier '%s%s' n'est pas possible. Le download du fichier est abandonné...", download.nom_repertoire_destination, download.nom_fichier_destination);
affichage_debug(__FILE__, __LINE__, tmp, TYPE_MESSAGE_DEBUG_ERREUR);
// Enregistrement dans l'historique :
sprintf(tmp, "%s", download.nom_fichier_destination);
enregistrement_historique(TYPE_SOURCE_HISTORIQUE_SYSTEME, SYSTEME_FTP_DOWNLOAD_FICHIER_DEBUT_NOK, 0, 0, tmp);
modem.sequenceur.etat = ETAT_SEQUENCEUR_MODEM_REPOS;
break;
}
else
{
fclose(download.ptr_fichier_destination); // Fermeture du fichier
download.taille_fichier_local = 0;
download.no_paquet = 0;
// Enregistrement dans l'historique :
sprintf(tmp, "%s", download.nom_fichier_destination);
enregistrement_historique(TYPE_SOURCE_HISTORIQUE_SYSTEME, SYSTEME_FTP_DOWNLOAD_FICHIER_DEBUT_OK, 0, 0, tmp);
}
m_bus_down_commande_libre("AT+FTPCID=0", M_BUS_PROTOCOLE_NORMAL, 0, -1); // Bearer profile identifier refer to AT+CNACT
sprintf(tmp, "AT+FTPSERV=\"%s\"", SERVEUR_FTP_ADRESSE);
m_bus_down_commande_libre(tmp, M_BUS_PROTOCOLE_NORMAL, 0, -1); // Défini l'adresse du serveur FTP à joindre
sprintf(tmp, "AT+FTPUN=\"%s\"", SERVEUR_FTP_USER);
m_bus_down_commande_libre(tmp, M_BUS_PROTOCOLE_NORMAL, 0, -1); // Défini le nom d'utilisateur sur le serveur FTP
sprintf(tmp, "AT+FTPPW=\"%s\"", SERVEUR_FTP_PASSWORD);
m_bus_down_commande_libre(tmp, M_BUS_PROTOCOLE_NORMAL, 0, -1); // Défini le pwd de l'utilisateur sur le serveur FTP
sprintf(tmp, "AT+FTPGETNAME=\"%s\"", download.nom_fichier_source);
m_bus_down_commande_libre(tmp, M_BUS_PROTOCOLE_NORMAL, 0, -1); // Défini le nom du fichier à downloader sur le serveur FTP
sprintf(tmp, "AT+FTPGETPATH=\"%s\"", download.nom_repertoire_source);
m_bus_down_commande_libre(tmp, M_BUS_PROTOCOLE_NORMAL, 0, -1); // Défini le path du répertoire sur lequel chercher le fichier
m_bus_down_commande_libre("AT+FTPGET=1", M_BUS_PROTOCOLE_NORMAL, MODEM_DOWNLOAD_TIME_OUT_ATTENTE_DISPO_DATA, 0);
download.taille_buffer_rx = 0; // Est nécessaire pour que la fonction M_COMMANDE_FTPGET_1 de m_commandes.c focntionne correctement au démarrage
download.taille_buffer_tx = MODEM_MAX_TAILLE_TRAME_FTPGET; // Idem.
download.status_get = -1; // Idem.
modem.sequenceur.compteur = MODEM_DOWNLOAD_TIME_OUT_ATTENTE_DISPO_DATA;
modem.sequenceur.etat = ETAT_SEQUENCEUR_MODEM_FTP_GET_ATTENTE_DISPO_DATA;
break;
}
//----------------------------------------------------------------------------------------------------------------------------------------------------------
case ETAT_SEQUENCEUR_MODEM_FTP_GET_ATTENTE_DISPO_DATA:
//----------------------------------------------------------------------------------------------------------------------------------------------------------
{
if (modem.sequenceur.compteur == 0)
{
switch(download.status_get)
{
case 1: // Cas normal, l'échange peut continuer :
{
download.taille_buffer_tx = MODEM_MAX_TAILLE_TRAME_FTPGET;
sprintf(tmp, "AT+FTPGET=2,%i", download.taille_buffer_tx);
m_bus_down_commande_libre(tmp, M_BUS_PROTOCOLE_NORMAL, MODEM_DOWNLOAD_TIME_OUT_ATTENTE_RECEPTION_DATA, 0);
modem.sequenceur.compteur = MODEM_DOWNLOAD_TIME_OUT_ATTENTE_RECEPTION_DATA;
modem.sequenceur.etat = ETAT_SEQUENCEUR_MODEM_FTP_GET_ATTENTE_RECEPTION_DATA;
break;
}
case -1 : // Aucun retour n'a été reçu à la fin du time-out :
{
sprintf(tmp, "Aucun retour de la fonction GET à l'expiration du time-out. Le transfert est arrêté.");
affichage_debug(__FILE__, __LINE__, tmp, TYPE_MESSAGE_DEBUG_ERREUR);
modem.sequenceur.etat = ETAT_SEQUENCEUR_MODEM_REPOS;
break;
}
case 0 : // Plus aucune donnée n'est dispo. Le transfert est terminé :
{
#ifdef __DEBUG_MODEM_FTP_DOWNLOAD
sprintf(tmp, "Retour de la fonction GET indiquant qu'aucune données n'est plus disponible. Le transfert est arrêté.");
affichage_debug(__FILE__, __LINE__, tmp, TYPE_MESSAGE_DEBUG_PAR_DEFAUT);
#endif
modem.sequenceur.etat = ETAT_SEQUENCEUR_MODEM_REPOS;
break;
}
default : // Si > 1, erreur de GET. Retour au repos dans le doute.
{
sprintf(tmp, "Retour en erreur de la fonction GET (code d'erreur = %i). Le transfert est arrêté.", download.status_get);
affichage_debug(__FILE__, __LINE__, tmp, TYPE_MESSAGE_DEBUG_ERREUR);
modem.sequenceur.etat = ETAT_SEQUENCEUR_MODEM_REPOS;
break;
}
}
}
break;
}
//----------------------------------------------------------------------------------------------------------------------------------------------------------
case ETAT_SEQUENCEUR_MODEM_FTP_GET_ATTENTE_RECEPTION_DATA:
//----------------------------------------------------------------------------------------------------------------------------------------------------------
{
if (modem.sequenceur.compteur == 0)
{
switch(download.status_get)
{
case 1: // Cas normal, l'échange peut continuer immédiatement :
{
download.secondes_fin = timestamp_secondes();
if (download.secondes_fin == download.secondes_debut) download.secondes_fin = download.secondes_debut + 1; // évite les divisions par 0...
if (download.taille_buffer_rx > 0) // On passe ici plusieurs fois en fin de transfert en attente de 'FTPGET: 1,0' et dans ce cas, ce ne sont pas de 'vrais' blocs qui sont reçus...
{
download.no_paquet ++;
#ifdef __DEBUG_MODEM_FTP_DOWNLOAD
sprintf(tmp, "Réception du paquet n° %4i avec %4i octets (total reçu = %8i octets en %4i secondes, soit %5i octets/secondes)", download.no_paquet, download.taille_buffer_rx, download.taille_fichier_local, (uint32_t)(download.secondes_fin - download.secondes_debut), download.taille_fichier_local/(uint32_t)(download.secondes_fin - download.secondes_debut));
affichage_debug(__FILE__, __LINE__, tmp, TYPE_MESSAGE_DEBUG_PAR_DEFAUT);
#endif
}
if (download.taille_fichier_local < download.taille_fichier_serveur) modem.sequenceur.etat = ETAT_SEQUENCEUR_MODEM_FTP_GET_ATTENTE_DISPO_DATA; // Cas où le chargement n'est pas terminé, on relance une commande FTPGET=2,1024 pour demander des données supplémentaires.
else modem.sequenceur.compteur = MODEM_DOWNLOAD_TIME_OUT_ATTENTE_RECEPTION_DATA; // Cas où on a déjà récupéré toutes les data. Dans ce cas, on réarme juste le time-out puisqu'on devrait recevoir d'ici quelques secondes (8-15s souvent) une réponse 'FTPGET: 1,0' indiquant la fin de l'échange.
break;
}
case 0 : // Plus aucune donnée n'est dispo. Le transfert est terminé :
{
// On s'assure que la libération du protocole M-Bus a bien été faite (on risque sinon de rester bloqué en mode FLUX_BINAIRE) :
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.
if (download.taille_fichier_local != download.taille_fichier_serveur) // Erreur de téléchargement :
{
sprintf(tmp, "L'ouverture du fichier '%s%s' indique une taille [%i] différente du fichier sur le serveur [%i]. Le fichier local va être supprimé et le download abandonné...", download.nom_repertoire_destination, download.nom_fichier_destination, download.taille_fichier_local, download.taille_fichier_serveur);
affichage_debug(__FILE__, __LINE__, tmp, TYPE_MESSAGE_DEBUG_ERREUR);
// Enregistrement dans l'historique :
sprintf(tmp, "%s", download.nom_fichier_destination);
enregistrement_historique(TYPE_SOURCE_HISTORIQUE_SYSTEME, SYSTEME_FTP_DOWNLOAD_FICHIER_FIN_NOK, 0, 0, tmp);
// Suppression du fichier :
sprintf(tmp, "%s%s", download.nom_repertoire_destination, download.nom_fichier_destination);
remove(tmp);
modem.sequenceur.etat = ETAT_SEQUENCEUR_MODEM_REPOS;
}
else // Téléchargement Ok :
{
download.secondes_fin = timestamp_secondes();
if (download.secondes_fin == download.secondes_debut) download.secondes_fin = download.secondes_debut + 1; // évite les divisions par 0...
download.liste_fichiers[download.fichier_en_cours].flag_a_telecharger = FALSE;
// Enregistrement dans l'historique :
sprintf(tmp, "%s", download.nom_fichier_destination);
enregistrement_historique(TYPE_SOURCE_HISTORIQUE_SYSTEME, SYSTEME_FTP_DOWNLOAD_FICHIER_FIN_OK, 0, (uint16_t)(download.secondes_fin - download.secondes_debut), tmp);
t = (uint32_t)(download.secondes_fin - download.secondes_debut);
m = (uint8_t)(t / 60);
s = (uint8_t)(t % 60);
sprintf(tmp, "Le téléchargement du fichier [%s] est terminé en %2i minutes et %2i secondes (soit %i octets à %5i octets/secondes)", download.nom_fichier_source, m, s, download.taille_fichier_local, (download.taille_fichier_local / (uint32_t)(download.secondes_fin - download.secondes_debut)));
affichage_debug(__FILE__, __LINE__, tmp, TYPE_MESSAGE_DEBUG_OK);
}
modem.sequenceur.etat = ETAT_SEQUENCEUR_MODEM_FTP_GET_RECHERCHE_FICHIER;
break;
}
case -1 : // Aucun retour n'a été reçu à la fin du time-out :
{
#ifdef __DEBUG_MODEM_FTP_DOWNLOAD
sprintf(tmp, "Aucun retour de la fonction GET à l'expiration du time-out. Le transfert est arrêté.");
affichage_debug(__FILE__, __LINE__, tmp, TYPE_MESSAGE_DEBUG_ERREUR);
#endif
modem.sequenceur.etat = ETAT_SEQUENCEUR_MODEM_REPOS;
break;
}
default : // Si > 1, erreur de GET. On va attendre qu'un retour de status_get=1 revienne (cas le plus fréquent)
{
#ifdef __DEBUG_MODEM_FTP_DOWNLOAD
sprintf(tmp, "Retour en erreur de la fonction GET (code d'erreur = %i). Le transfert est arrêté.", download.status_get);
affichage_debug(__FILE__, __LINE__, tmp, TYPE_MESSAGE_DEBUG_ERREUR);
#endif
modem.sequenceur.etat = ETAT_SEQUENCEUR_MODEM_REPOS;
break;
}
}
}
break;
}
//=========================================================================================================================================================
// FTP PUT :
//=========================================================================================================================================================
//----------------------------------------------------------------------------------------------------------------------------------------------------------
case ETAT_SEQUENCEUR_MODEM_FTP_PUT_LANCEMENT:
//----------------------------------------------------------------------------------------------------------------------------------------------------------
{
#ifdef __DEBUG_MODEM_FTP_UPLOAD
sprintf(tmp, "Connexion FTP pour upload du fichier '%s%s' vers le fichier '%s%s'", upload.nom_repertoire_source, upload.nom_fichier_source, upload.nom_repertoire_destination, upload.nom_fichier_destination);
affichage_debug(__FILE__, __LINE__, tmp, TYPE_MESSAGE_DEBUG_PAR_DEFAUT);
#endif
// Ouverture du fichier à lire :
// (NB : cette ouverture n'est pas utile à ce moment-là mais il est inutile d'engager une ouverture de session FTP et tout le reste si le fichier n'est pas accessible...) :
sprintf(tmp, "%s%s", upload.nom_repertoire_source, upload.nom_fichier_source);
upload.ptr_fichier_source = fopen(tmp, "rb"); // Ouverture du fichier en "lecture"...
if (upload.ptr_fichier_source == NULL)
{
sprintf(tmp, "L'ouverture du fichier '%s%s' n'est pas possible. L'upload du fichier est abandonné...", upload.nom_repertoire_source, upload.nom_fichier_source);
affichage_debug(__FILE__, __LINE__, tmp, TYPE_MESSAGE_DEBUG_PAR_DEFAUT);
// Enregistrement dans l'historique :
sprintf(tmp, "%s", upload.nom_fichier_source);
enregistrement_historique(TYPE_SOURCE_HISTORIQUE_SYSTEME, SYSTEME_FTP_UPLOAD_FICHIER_DEBUT_NOK, 0, 0, tmp);
// RAZ de la tempo d'UPLOAD pour éviter de boucler sur une situation d'erreur (on refera une tendtative mais au prochain cycle) :
modem.compteur_periode_upload = ((MODEM_UPLOAD_PERIODE_CHECK * 10) / MODEM_PERIODE_SURVEILLANCE_MODEM);
modem.sequenceur.etat = ETAT_SEQUENCEUR_MODEM_REPOS;
break;
}
else
{
fseek(upload.ptr_fichier_source, 0, SEEK_END); // Aller à la fin du fichier
upload.taille_theorique_fichier = ftell(upload.ptr_fichier_source); // Recherche de la position du curseur (donc la taille du fichier)
fclose(upload.ptr_fichier_source); // Fermeture du fichier
if ((upload.taille_theorique_fichier == 0) || (upload.taille_theorique_fichier > MAX_TAILLE_FICHIER_UPLOAD))
{
if (upload.taille_theorique_fichier == 0) sprintf(tmp, "L'ouverture du fichier '%s%s' indique une taille nulle. Le fichier va être supprimé et l'upload abandonné...", upload.nom_repertoire_source, upload.nom_fichier_source);
else sprintf(tmp, "L'ouverture du fichier '%s%s' indique une taille trop importante (%i octets pour max = %i octets). Le fichier va être supprimé et l'upload abandonné...", upload.nom_repertoire_source, upload.nom_fichier_source, upload.taille_theorique_fichier, MAX_TAILLE_FICHIER_UPLOAD);
affichage_debug(__FILE__, __LINE__, tmp, TYPE_MESSAGE_DEBUG_PAR_DEFAUT);
// Enregistrement dans l'historique :
sprintf(tmp, "%s", upload.nom_fichier_source);
enregistrement_historique(TYPE_SOURCE_HISTORIQUE_SYSTEME, SYSTEME_FTP_UPLOAD_FICHIER_DEBUT_NOK, 0, upload.taille_theorique_fichier, tmp);
// Suppression du fichier s'il a une taille nulle ou trop importante :
sprintf(tmp, "%s%s", upload.nom_repertoire_source, upload.nom_fichier_source);
remove(tmp);
modem.sequenceur.etat = ETAT_SEQUENCEUR_MODEM_REPOS;
break;
}
// Enregistrement dans l'historique :
sprintf(tmp, "%s", upload.nom_fichier_source);
enregistrement_historique(TYPE_SOURCE_HISTORIQUE_SYSTEME, SYSTEME_FTP_UPLOAD_FICHIER_DEBUT_OK, 0, upload.taille_theorique_fichier, tmp);
}
upload.secondes_debut = timestamp_secondes(); // Stockage du timestamp de départ
// m_bus_down_commande_libre("AT+FTPTYPE?", M_BUS_PROTOCOLE_NORMAL, 0, -1); // Indique le type de données transmises (default = "I" = Binary, "A" = Ascii)
// m_bus_down_commande_libre("AT+FTPMODE?", M_BUS_PROTOCOLE_NORMAL, 0, -1); // Indique dans quel FTP Mode on est (default = 1 = passive, 0 = active). En pratique, Active ne semble pas accepté...
m_bus_down_commande_libre("AT+FTPCID=0", M_BUS_PROTOCOLE_NORMAL, 0, -1); // Bearer profile identifier refer to AT+CNACT
sprintf(tmp, "AT+FTPSERV=\"%s\"", SERVEUR_FTP_ADRESSE);
m_bus_down_commande_libre(tmp, M_BUS_PROTOCOLE_NORMAL, 0, -1); // Défini l'adresse du serveur FTP à joindre
sprintf(tmp, "AT+FTPUN=\"%s\"", SERVEUR_FTP_USER);
m_bus_down_commande_libre(tmp, M_BUS_PROTOCOLE_NORMAL, 0, -1); // Défini le nom d'utilisateur sur le serveur FTP
sprintf(tmp, "AT+FTPPW=\"%s\"", SERVEUR_FTP_PASSWORD);
m_bus_down_commande_libre(tmp, M_BUS_PROTOCOLE_NORMAL, 0, -1); // Défini le pwd de l'utilisateur sur le serveur FTP
sprintf(tmp, "AT+FTPPUTNAME=\"%s\"", upload.nom_fichier_destination);
m_bus_down_commande_libre(tmp, M_BUS_PROTOCOLE_NORMAL, 0, -1); // Défini le nom du fichier à charger sur le serveur
sprintf(tmp, "AT+FTPPUTPATH=\"%s\"", upload.nom_repertoire_destination);
m_bus_down_commande_libre(tmp, M_BUS_PROTOCOLE_NORMAL, 0, -1); // Défini le path du fichier à charger sur le serveur
m_bus_down_commande_libre("AT+FTPPUT=1", M_BUS_PROTOCOLE_NORMAL, MODEM_UPLOAD_TEMPO_ATTENTE_OUVERTURE_SESSION, 0); // Ouverture de la session FTP.
upload.ptr_debut = 0; // Début du fichier qui va être lu puis uploadé
upload.ptr_fin = 0; // Fin du fichier qui va être lu puis uploadé
upload.no_paquet = 0;
modem.max_taille_ftp_put = 0; // Permet de vérifier ensuite qu'on a bien reçu une réponse à FTPPUT:1 avec la taille maxi à émettre.
upload.taille_fichier_local = 0;
upload.taille_fichier_serveur = 0;
upload.code_erreur_ftpput_data = M_BUS_ERREUR_AUCUNE;
upload.nb_repetitions_total = 0;
modem.sequenceur.compteur = MODEM_UPLOAD_TEMPO_ATTENTE_OUVERTURE_SESSION; // Cette tempo sera RAZ par la réception d'une réponse '+FTPPUT: 1,1,xxxx'. C'est donc plutôt un time-out...
modem.sequenceur.etat = ETAT_SEQUENCEUR_MODEM_FTP_PUT_ATTENTE_OUVERTURE_SESSION;
break;
}
//----------------------------------------------------------------------------------------------------------------------------------------------------------
case ETAT_SEQUENCEUR_MODEM_FTP_PUT_ATTENTE_OUVERTURE_SESSION:
//----------------------------------------------------------------------------------------------------------------------------------------------------------
{
if (modem.sequenceur.compteur == 0)
{
if ((upload.code_erreur_ftpput_data == M_BUS_ERREUR_AUCUNE) ||
(upload.code_erreur_ftpput_data == M_BUS_ERREUR_OK))
{
if (modem.max_taille_ftp_put == 0) // Si la taille maxi du buffer d'émission n'a pas encore été mis à jour au moins une fois, on va juste demander la fermeture du port car on ne sait pas comment le traiter.
{
modem.sequenceur.etat = ETAT_SEQUENCEUR_MODEM_FTP_PUT_ATTENTE_FIN_TRANSFERT;
break;
}
upload.nb_repetitions = 0;
upload.ptr_debut = upload.ptr_fin;
upload.no_paquet ++;
// Ouverture du fichier à lire :
sprintf(tmp, "%s%s", upload.nom_repertoire_source, upload.nom_fichier_source);
upload.ptr_fichier_source = fopen(tmp, "rb"); // Ouverture du fichier en "lecture"...
if (upload.ptr_fichier_source == NULL)
{
sprintf(tmp, "L'ouverture du fichier '%s%s' n'est pas possible. L'upload du fichier est abandonné...", upload.nom_repertoire_source, upload.nom_fichier_source);
affichage_debug(__FILE__, __LINE__, tmp, TYPE_MESSAGE_DEBUG_PAR_DEFAUT);
modem.sequenceur.etat = ETAT_SEQUENCEUR_MODEM_REPOS;
break;
}
fseek(upload.ptr_fichier_source, upload.ptr_debut, SEEK_SET); // Positionne le curseur à 'ptr_debut' du début du fichier
upload.lg_buffer = 0;
int16_t c; // Ce n'est pas intuitif, mais 'fgetc' retourne un entier (soit 0-255 si un caractère a été lu, soit -1=EOF si erreur)
do
{
c = fgetc(upload.ptr_fichier_source);
if (c != EOF) upload.buffer[upload.lg_buffer ++] = (uint8_t) c;
else break;
} while ((upload.lg_buffer < (MAX_TAILLE_BUFFER_UPLOAD - 2)) && (upload.lg_buffer < (modem.max_taille_ftp_put - 2)));
fclose(upload.ptr_fichier_source); // Fermeture du fichier
upload.taille_fichier_local += upload.lg_buffer; // Mise à jour de la taille du fichier en cours de transmission
if (upload.lg_buffer == 0) // Si le buffer d'émission est vide, c'est qu'on est arrivés à la fin du fichier et on va juste demander la fermeture du port.
{
upload.secondes_fin = timestamp_secondes(); // Stockage du timestamp de fin
if (upload.secondes_fin == upload.secondes_debut) upload.secondes_fin ++; // Permet d'éviter les divisions par 0....
sprintf(tmp, "Le fichier [%s] a été uploadé complètement : %i paquets transférés (dont %i répétés), pour un total de %i octets, en %i secondes (soit %i octets/s) ", upload.nom_fichier_source, upload.no_paquet, upload.nb_repetitions_total, upload.taille_fichier_local, (uint32_t)(upload.secondes_fin - upload.secondes_debut), (uint32_t)(upload.taille_fichier_local/(uint32_t)(upload.secondes_fin - upload.secondes_debut)));
affichage_debug(__FILE__, __LINE__, tmp, TYPE_MESSAGE_DEBUG_OK);
modem.sequenceur.etat = ETAT_SEQUENCEUR_MODEM_FTP_PUT_ATTENTE_FIN_TRANSFERT;
break;
}
else
{
#ifdef __DEBUG_MODEM_FTP_UPLOAD
sprintf(tmp, "Demande d'émission du paquet n° %i avec %i octets (total transmis = %i octets, soit %.1f%%)", upload.no_paquet, upload.lg_buffer, upload.taille_fichier_local, (float) ((float)(upload.taille_fichier_local * 100)/ (float)upload.taille_theorique_fichier));
affichage_debug(__FILE__, __LINE__, tmp, TYPE_MESSAGE_DEBUG_PAR_DEFAUT);
#endif
}
upload.ptr_fin = upload.ptr_debut + upload.lg_buffer; // Mise à jour du ptr_fin
}
else
{
upload.code_erreur_ftpput_data = M_BUS_ERREUR_AUCUNE;
upload.nb_repetitions_total ++;
if (++upload.nb_repetitions >= MODEM_MAX_REPETITIONS_PAQUET_UPLOAD) // Si on a déjà répété plusieurs fois ce bloc, on fini par arrêter...
{
sprintf(tmp, "L'émission du paquet n° %i a été répétée %i fois. L'upload est arrêté.", upload.no_paquet, upload.nb_repetitions);
affichage_debug(__FILE__, __LINE__, tmp, TYPE_MESSAGE_DEBUG_ERREUR);
modem.sequenceur.etat = ETAT_SEQUENCEUR_MODEM_FTP_PUT_ATTENTE_FIN_TRANSFERT;
break;
}
else // Sinon, on répête une fois de plus
{
sprintf(tmp, "L'émission du paquet n° %i a rencontré une erreur. Il est réémis.", upload.no_paquet);
affichage_debug(__FILE__, __LINE__, tmp, TYPE_MESSAGE_DEBUG_WARNING);
}
}
sprintf(tmp, "AT+FTPPUT=2,%i", upload.lg_buffer); // Demande d'envoi de N octets, correspondant à la longueur du buffer chargé
m_bus_down_commande_libre(tmp, M_BUS_PROTOCOLE_NORMAL, 0, -1); // NB : la réponse du modem ne comprenant pas de CR/LF/OK/CR/LF, il faut dire au protocole de ne PAS attendre de réponse. C'est ici qu'on gère l'attente avant de poursuivre.
modem.sequenceur.compteur = MODEM_UPLOAD_TEMPO_ATTENTE_ACCEPTATION_DONNEES; // Cette tempo est plus un time-out car la tempo sera remise à 0 par la réception de '+FTPPUT: 2,1358'
modem.sequenceur.etat = ETAT_SEQUENCEUR_MODEM_FTP_PUT_ATTENTE_ACCEPTATION_DONNEES;
}
break;
}
//----------------------------------------------------------------------------------------------------------------------------------------------------------
case ETAT_SEQUENCEUR_MODEM_FTP_PUT_ATTENTE_ACCEPTATION_DONNEES:
//----------------------------------------------------------------------------------------------------------------------------------------------------------
{
if (modem.sequenceur.compteur == 0)
{
upload.code_erreur_ftpput_data = M_BUS_ERREUR_AUCUNE;
m_bus_down_commande_libre_binaire(M_COMMANDE_FTPPUT_ENVOI_DATA, (char *)upload.buffer, upload.lg_buffer, M_BUS_PROTOCOLE_DATA_BINAIRE, MODEM_UPLOAD_TIME_OUT_ENVOI_DONNEES, 0); // Envoi des N octets.
modem.sequenceur.compteur = MODEM_UPLOAD_TIME_OUT_ENVOI_DONNEES;
modem.sequenceur.etat = ETAT_SEQUENCEUR_MODEM_FTP_PUT_ATTENTE_OUVERTURE_SESSION; // Retour vers l'envoi du paquet suivant.
}
break;
}
//----------------------------------------------------------------------------------------------------------------------------------------------------------
case ETAT_SEQUENCEUR_MODEM_FTP_PUT_ATTENTE_FIN_TRANSFERT:
//----------------------------------------------------------------------------------------------------------------------------------------------------------
{
if (modem.sequenceur.compteur == 0)
{
m_bus_down_commande_libre("AT+FTPPUT=2,0", M_BUS_PROTOCOLE_NORMAL, 0, -1); // Demande de fermeture de la session FTP
modem.sequenceur.compteur = MODEM_UPLOAD_TEMPO_ATTENTE_FIN_TRANSFERT; // Cette tempo est en fait un time-out car dès qu'on recevra le retour 'AT+FTTPUT: 1,0', la tempo sera forcée à 0 par 'm_commandes.c'.
modem.sequenceur.etat = ETAT_SEQUENCEUR_MODEM_FTP_PUT_LANCEMENT_CHECK;
}
break;
}
//----------------------------------------------------------------------------------------------------------------------------------------------------------
case ETAT_SEQUENCEUR_MODEM_FTP_PUT_LANCEMENT_CHECK:
//----------------------------------------------------------------------------------------------------------------------------------------------------------
{
if (modem.sequenceur.compteur == 0)
{
upload.status_get_size = 0; // Valeur par défaut (pas d'erreur)
sprintf(tmp, "AT+FTPGETNAME=\"%s\"", upload.nom_fichier_destination);
m_bus_down_commande_libre(tmp, M_BUS_PROTOCOLE_NORMAL, 0, -1); // Défini le nom du fichier à charger sur le serveur
sprintf(tmp, "AT+FTPGETPATH=\"%s\"", upload.nom_repertoire_destination);
m_bus_down_commande_libre(tmp, M_BUS_PROTOCOLE_NORMAL, 0, -1); // Défini le path du fichier à charger sur le serveur
m_bus_down_commande_libre("AT+FTPSIZE", M_BUS_PROTOCOLE_NORMAL, MODEM_UPLOAD_TIME_OUT_ATTENTE_GETSIZE, -1); // Demande de la taille du fichier sur le serveur. NB : la réponse du modem comprenant un CR/LF/OK/CR/LF situé AVANT la réponse proprement dite, il faut dire au protocole de ne PAS attendre de réponse. C'est ici qu'on gère l'attente avant de poursuivre.
modem.sequenceur.compteur = MODEM_UPLOAD_TIME_OUT_ATTENTE_GETSIZE;
modem.sequenceur.etat = ETAT_SEQUENCEUR_MODEM_FTP_PUT_ATTENTE_GETSIZE;
}
break;
}
//----------------------------------------------------------------------------------------------------------------------------------------------------------
case ETAT_SEQUENCEUR_MODEM_FTP_PUT_ATTENTE_GETSIZE:
//----------------------------------------------------------------------------------------------------------------------------------------------------------
{
if (modem.sequenceur.compteur == 0)
{
if (upload.status_get_size == 0) // Le code de retour doit être nul (2ième paramètre de retour de la réponse à FTPSIZE)
{
if (upload.taille_fichier_serveur != upload.taille_fichier_local)
{
sprintf(tmp, "La taille du fichier sur le serveur FTP (%i) est différente de la taille du fichier uploadé (%i). La transmission est relancée au début...", upload.taille_fichier_serveur, upload.taille_fichier_local);
affichage_debug(__FILE__, __LINE__, tmp, TYPE_MESSAGE_DEBUG_ERREUR);
// Enregistrement dans l'historique :
sprintf(tmp, "%s", upload.nom_fichier_source);
enregistrement_historique(TYPE_SOURCE_HISTORIQUE_SYSTEME, SYSTEME_FTP_UPLOAD_FICHIER_FIN_NOK, 0, 0, tmp);
}
else
{
sprintf(tmp, "L'upload du fichier [%s] a été vérifié (la taille du fichier sur le serveur FTP est identique à la taille du fichier uploadé, soit %i octets). Le fichier source est donc supprimé.", upload.nom_fichier_source, upload.taille_fichier_serveur);
affichage_debug(__FILE__, __LINE__, tmp, TYPE_MESSAGE_DEBUG_OK);
// Suppression du fichier puisqu'il a été correctement uploadé :
if (upload.taille_fichier_serveur != 0) // Ne devrait pas arriver mais permet de ne pas effacer un fichier si sa taille est nulle
{
// Enregistrement dans l'historique :
sprintf(tmp, "%s", upload.nom_fichier_source);
enregistrement_historique(TYPE_SOURCE_HISTORIQUE_SYSTEME, SYSTEME_FTP_UPLOAD_FICHIER_FIN_OK, 0, upload.taille_fichier_serveur, tmp);
sprintf(tmp, "%s%s", upload.nom_repertoire_source, upload.nom_fichier_source);
remove(tmp);
}
else // Si la taille du fichier est détectée nulle, on enregistre juste la fin du transfert en erreur (cela laisse une chance de l'uploader à nouveau lors du prochain transfert)
{
// Enregistrement dans l'historique :
sprintf(tmp, "%s", upload.nom_fichier_source);
enregistrement_historique(TYPE_SOURCE_HISTORIQUE_SYSTEME, SYSTEME_FTP_UPLOAD_FICHIER_FIN_NOK, 0, upload.taille_fichier_serveur, tmp);
}
}
}
else
{
sprintf(tmp, "La taille du fichier distant n'a pas pu être établie (retour de FTPSIZE avec code d'erreur : %i). L'upload est abandonné et le fichier local n'est PAS supprimé...", upload.status_get_size);
affichage_debug(__FILE__, __LINE__, tmp, TYPE_MESSAGE_DEBUG_ERREUR);
// Enregistrement dans l'historique :
sprintf(tmp, "%s", upload.nom_fichier_source);
enregistrement_historique(TYPE_SOURCE_HISTORIQUE_SYSTEME, SYSTEME_FTP_UPLOAD_FICHIER_FIN_NOK, 0, 0, tmp);
// RAZ de la tempo d'UPLOAD pour éviter de boucler sur une situation d'erreur (on refera une tendtative mais au prochain cycle) :
modem.compteur_periode_upload = ((MODEM_UPLOAD_PERIODE_CHECK * 10) / MODEM_PERIODE_SURVEILLANCE_MODEM);
}
modem.sequenceur.etat = ETAT_SEQUENCEUR_MODEM_FTP_PUT_ATTENTE_FERMETURE_SESSION; // Même en cas d'erreur, on revient au repos. Le fichier sera identifié à nouveau et rechargé plus tard.
}
break;
}
//----------------------------------------------------------------------------------------------------------------------------------------------------------
case ETAT_SEQUENCEUR_MODEM_FTP_PUT_ATTENTE_FERMETURE_SESSION:
//----------------------------------------------------------------------------------------------------------------------------------------------------------
{
if (modem.sequenceur.compteur == 0)
{
modem.sequenceur.etat = ETAT_SEQUENCEUR_MODEM_REPOS;
}
break;
}
//=========================================================================================================================================================
// Reset du Modem :
//=========================================================================================================================================================
//----------------------------------------------------------------------------------------------------------------------------------------------------------
case ETAT_SEQUENCEUR_MODEM_DEBUT_IMPULSION_RESET:
//----------------------------------------------------------------------------------------------------------------------------------------------------------
{
if (modem.sequenceur.compteur == 0)
{
ecriture_sortie(TYPE_SORTIE_GPIO, 0, CM3P_DO_PWKEY_MOD, ON); // 0 est l'adresse de ShipBase
#ifdef __DEBUG_MODEM
affichage_debug(__FILE__, __LINE__, "Début de l'impulsion de reset du modem SIM7070G", TYPE_MESSAGE_DEBUG_WARNING);
#endif
modem.sequenceur.compteur = MODEM_TEMPO_IMPULSION_RESET;
modem.sequenceur.etat = ETAT_SEQUENCEUR_MODEM_FIN_IMPULSION_RESET;
}
break;
}
//----------------------------------------------------------------------------------------------------------------------------------------------------------
case ETAT_SEQUENCEUR_MODEM_FIN_IMPULSION_RESET:
//----------------------------------------------------------------------------------------------------------------------------------------------------------
{
if (modem.sequenceur.compteur == 0)
{
ecriture_sortie(TYPE_SORTIE_GPIO, 0, CM3P_DO_PWKEY_MOD, OFF); // 0 est l'adresse de ShipBase
#ifdef __DEBUG_MODEM
affichage_debug(__FILE__, __LINE__, "Fin de l'impulsion de reset du modem SIM7070G", TYPE_MESSAGE_DEBUG_WARNING);
#endif
modem.sequenceur.compteur = MODEM_TEMPO_ATTENTE_RESET;
modem.sequenceur.etat = ETAT_SEQUENCEUR_MODEM_INIT;
}
break;
}
//----------------------------------------------------------------------------------------------------------------------------------------------------------
default :
//----------------------------------------------------------------------------------------------------------------------------------------------------------
{
sprintf(tmp, "L'état du séquenceur Modem est inconnu [%i]. Il est repositionné au REPOS", modem.sequenceur.etat);
affichage_debug(__FILE__, __LINE__, tmp, TYPE_MESSAGE_DEBUG_ERREUR);
modem.sequenceur.etat = ETAT_SEQUENCEUR_MODEM_REPOS;
break;
}
}
}