Files
shipheart-appli/sources/systeme.c
T

2114 lines
108 KiB
C

// **********************************************************************************************************************************************************************************
// Fichier SYSTEME.C
//
// Contient toutes les fonctions système du projet.
// **********************************************************************************************************************************************************************************
// #define __DEBUG_SYSTEME //Décommenter cette ligne pour avoir les messages de debug concernant le système
//#define __DEBUG_SYSTEME_FICHIER_JSON //Décommenter cette ligne pour afficher le contenu du fichier JSON à l'init
// #define __DEBUG_SYSTEME_MISE_A_JOUR //Décommenter cette ligne pour avoir les messages de debug concernant les mises à jour
#define __DEBUG_SYSTEME_CHARGEMENT_CODE //Décommenter cette ligne pour avoir les messages de debug concernant le chargement de code
// Include :
#include "main.h"
// Prototypes :
int8_t init_systeme(void);
void gestion_systeme(void);
void check_mise_a_jour(void);
void gestion_chargement_code(void);
void supervision(void);
void arret_programme(void);
int8_t re_configuration_systeme(void);
int32_t commande_shell(char * commande);
struct Struct_json_version parse_json_version(char * nom_fichier, bool verbose);
int8_t send_signal (int32_t pid, int32_t signal);
int32_t get_pid_from_name (char * nom, char * parametres);
int32_t get_pid_numbers_from_name (char * nom, char * parametres);
int8_t version_compute_module(void);
void affichage_ligne_version_compute_module(char * tmp, char * titre, char * valeur);
// Variables globales :
struct Struct_download download;
struct Struct_systeme systeme;
struct Struct_chargement_code chargement_code;
struct Struct_upload upload;
struct Struct_supervision_boucle_principale supervision_boucle_principale;
//==================================================================================================================================================================
// Fonction : Fonction d'init des fonctions de plus haut niveau.
// Reçoit : Rien
// Renvoit : 0 si OK, -1 si erreur
//==================================================================================================================================================================
int8_t init_systeme(void)
{
DIR *repertoire;
char commande[MAX_TAILLE_COMMANDE_SHELL];
//------------------------------------
// Initialisation dépendant de la génération de ShipBase :
if (systeme.generation_shipbase == GENERATION_SHIPBASE_V1)
{
systeme.entree_gpio_cm_di_from_uc = CM3P_DI_FROM_UC;
systeme.sortie_gpio_cm_do_to_uc = CM3P_DO_TO_UC;
}
else
{
systeme.entree_gpio_cm_di_from_uc = CM4_DI_FROM_UC;
systeme.sortie_gpio_cm_do_to_uc = CM4_DO_TO_UC;
}
//------------------------------------
// Préparation du système de fichier :
// Important : Il faut tester les répertoires dans l'ordre descendant. On ne pourra PAS créer un répertoire 2 niveaux plus bas.
// Exemple : si /tmp et /tmp/bdd n'existent pas, on ne pourra pas créer /tmp/bdd directement (erreur de shell).
repertoire = opendir(REPERTOIRE_SERVER); // Tentative d'ouverture du répertoire...
if (repertoire == NULL) mkdir(REPERTOIRE_SERVER, 0777); // ...et création s'il n'existe pas
else closedir(repertoire);
repertoire = opendir(REPERTOIRE_SERVER_UPLOAD); // Tentative d'ouverture du répertoire...
if (repertoire == NULL) mkdir(REPERTOIRE_SERVER_UPLOAD, 0777); // ...et création s'il n'existe pas
else closedir(repertoire);
repertoire = opendir(REPERTOIRE_SERVER_DOWNLOAD); // Tentative d'ouverture du répertoire...
if (repertoire == NULL) mkdir(REPERTOIRE_SERVER_DOWNLOAD, 0777); // ...et création s'il n'existe pas
else closedir(repertoire);
repertoire = opendir(REPERTOIRE_VERSIONS); // Tentative d'ouverture du répertoire...
if (repertoire == NULL) mkdir(REPERTOIRE_VERSIONS, 0777); // ...et création s'il n'existe pas
else closedir(repertoire);
repertoire = opendir(REPERTOIRE_VERSIONS_A_VALIDER); // Tentative d'ouverture du répertoire...
if (repertoire == NULL) mkdir(REPERTOIRE_VERSIONS_A_VALIDER, 0777); // ...et création s'il n'existe pas
else closedir(repertoire);
repertoire = opendir(REPERTOIRE_VERSIONS_A_CHARGER); // Tentative d'ouverture du répertoire...
if (repertoire == NULL) mkdir(REPERTOIRE_VERSIONS_A_CHARGER, 0777); // ...et création s'il n'existe pas
else closedir(repertoire);
repertoire = opendir(REPERTOIRE_CONFIG); // Tentative d'ouverture du répertoire...
if (repertoire == NULL) mkdir(REPERTOIRE_CONFIG, 0777); // ...et création s'il n'existe pas
else closedir(repertoire);
repertoire = opendir(REPERTOIRE_CONFIG_IMAGES_ACCUEIL); // Tentative d'ouverture du répertoire...
if (repertoire == NULL) mkdir(REPERTOIRE_CONFIG_IMAGES_ACCUEIL, 0777); // ...et création s'il n'existe pas
else closedir(repertoire);
repertoire = opendir(REPERTOIRE_CONFIG_IMAGES_SILHOUETTE); // Tentative d'ouverture du répertoire...
if (repertoire == NULL) mkdir(REPERTOIRE_CONFIG_IMAGES_SILHOUETTE, 0777); // ...et création s'il n'existe pas
else closedir(repertoire);
repertoire = opendir(REPERTOIRE_CONFIG_RAPPORTS); // Tentative d'ouverture du répertoire...
if (repertoire == NULL) mkdir(REPERTOIRE_CONFIG_RAPPORTS, 0777); // ...et création s'il n'existe pas
else closedir(repertoire);
repertoire = opendir(REPERTOIRE_CONFIG_SAUVEGARDES); // Tentative d'ouverture du répertoire...
if (repertoire == NULL) mkdir(REPERTOIRE_CONFIG_SAUVEGARDES, 0777); // ...et création s'il n'existe pas
else closedir(repertoire);
repertoire = opendir(REPERTOIRE_TMP); // Tentative d'ouverture du répertoire...
if (repertoire == NULL) mkdir(REPERTOIRE_TMP, 0777); // ...et création s'il n'existe pas
else closedir(repertoire);
repertoire = opendir(REPERTOIRE_TMP_BDD); // Tentative d'ouverture du répertoire...
if (repertoire == NULL) mkdir(REPERTOIRE_TMP_BDD, 0777); // ...et création s'il n'existe pas
else closedir(repertoire);
repertoire = opendir(REPERTOIRE_TMP_CORE); // Tentative d'ouverture du répertoire...
if (repertoire == NULL) mkdir(REPERTOIRE_TMP_CORE, 0777); // ...et création s'il n'existe pas
else closedir(repertoire);
repertoire = opendir(REPERTOIRE_TMP_SAUVEGARDE); // Tentative d'ouverture du répertoire... // SDIR #162
if (repertoire == NULL) mkdir(REPERTOIRE_TMP_SAUVEGARDE, 0777); // ...et création s'il n'existe pas
else closedir(repertoire);
repertoire = opendir(REPERTOIRE_TMP_USB); // Tentative d'ouverture du répertoire...
if (repertoire == NULL) mkdir(REPERTOIRE_TMP_USB, 0777); // ...et création s'il n'existe pas
else closedir(repertoire);
repertoire = opendir(REPERTOIRE_TMP_WIFI); // Tentative d'ouverture du répertoire...
if (repertoire == NULL) mkdir(REPERTOIRE_TMP_WIFI, 0777); // ...et création s'il n'existe pas
else closedir(repertoire);
sprintf(commande, "sudo chown -R koriolan:koriolan %s", REPERTOIRE_SHIPHEART); // Affecte le propriétaire des répertoires (et sous-répertoires) de shipheart.
commande_shell(commande);
//------------------------------------
// Init de l'état du Compagnon :
if (lecture_entree(TYPE_ENTREES_GPIO, 0, systeme.entree_gpio_cm_di_from_uc, TRUE) == 0) // 0 est l'adresse de ShipBase
{
systeme.flag_compagnon_ready = FALSE;
affichage_debug(__FILE__, __LINE__, "L'entrée Compagnon_Ready est actuellement à FALSE", TYPE_MESSAGE_DEBUG_WARNING);
}
else
{
systeme.flag_compagnon_ready = TRUE;
affichage_debug(__FILE__, __LINE__, "L'entrée Compagnon_Ready est détectée à TRUE", TYPE_MESSAGE_DEBUG_OK);
}
//------------------------------------
// Init des variables générales :
systeme.sequenceur.etat = ETAT_SEQUENCEUR_SYSTEME_INIT;
systeme.sequenceur.compteur = SYSTEME_TEMPO_INIT;
chargement_code.sequenceur.etat = ETAT_SEQUENCEUR_CHARGEMENT_CODE_INIT;
chargement_code.sequenceur.compteur = CHARGEMENT_CODE_TEMPO_INIT;
systeme.compteur_sauvegarde_bdd = systeme.periode_sauvegarde_bdd;
// SDIR #301 :
/*
//------------------------------------
// Sauvegarde de la base de données :
affichage_debug(__FILE__, __LINE__, "Lancement sauvegarde BDD\t\t: OK", TYPE_MESSAGE_DEBUG_OK);
ret = sauvegarde_bdd();
if (ret != 0)
{
sprintf(tmp, "\tSauvegarde de la base de données : NOK (retour = %i)", ret);
affichage_debug(__FILE__, __LINE__, tmp, TYPE_MESSAGE_DEBUG_WARNING);
}
else affichage_debug(__FILE__, __LINE__, "Fin de sauvegarde BDD\t\t: OK", TYPE_MESSAGE_DEBUG_OK);
*/
// Fin de SDIR #301
//------------------------------------
// Affichage du message de débug :
affichage_debug(__FILE__, __LINE__, "Initialisation système\t\t: OK", TYPE_MESSAGE_DEBUG_OK);
return(0);
}
//==================================================================================================================================================================
// Fonction : Fonction de plus haut niveau du système.
// Reçoit : Rien
// Renvoit : Rien
//==================================================================================================================================================================
void gestion_systeme(void)
{
uint16_t i;
int32_t ret;
bool flag_id_complete;
char commande[MAX_TAILLE_COMMANDE_SHELL];
struct dirent *dir; // Les types 'dirent' ou 'DIR' sont déclarés dans le header <dirent.h>
DIR *repertoire;
char tmp[MAX_LONGUEUR_BUFFER_TEMPORAIRE_DEBUG];
switch(systeme.sequenceur.etat)
{
//-----------------------------------------------------------------------------------------------------------------------------------------
case ETAT_SEQUENCEUR_SYSTEME_INIT :
{
if (systeme.sequenceur.compteur == 0)
{
//--------------------------------------------------------------------
// RAZ du séquenceur de chargement de code (utile lorsqu'une reconnaissance réseau est lancée au milieu d'un téléchargement) :
if (chargement_code.id_message_user != 0)
{
maj_message_users(chargement_code.id_message_user, "", MESSAGE_USERS_ETAT_SUPPRESSION); // Suppression du message s'il y en avait encore un d'actif (cas d'un redémarrage de procédure en cours)
chargement_code.id_message_user = 0;
}
chargement_code.sequenceur.compteur = 0;
chargement_code.sequenceur.compteur_time_out = 0;
chargement_code.sequenceur.etat = ETAT_SEQUENCEUR_CHARGEMENT_CODE_REPOS;
//--------------------------------------------------------------------
// Lancement de la reconnaissance du réseau K-Bus dès qu'il est prêt :
if (c_bus.sequenceur.etat == ETAT_SEQUENCEUR_C_BUS_INIT)
{
affichage_debug(__FILE__, __LINE__, "C-Bus pas encore démarré. Attente...", TYPE_MESSAGE_DEBUG_PAR_DEFAUT);
systeme.sequenceur.compteur = SYSTEME_TEMPO_ATTENTE_DISPO_C_BUS;
}
else
{
c_bus_down_commande_lecture_date_heure(); // Lecture de la date/heure depuis le Compagnon qui est le seul à être sauvegardé
c_bus_down_commande_annuaire_k_bus(); // Lecture de l'annuaire des cartes présentes dans le système
affichage_debug(__FILE__, __LINE__, "Demande annuaire K-Bus envoyée\t: Ok", TYPE_MESSAGE_DEBUG_OK);
systeme.sequenceur.etat = ETAT_SEQUENCEUR_SYSTEME_ATTENTE_ANNUAIRE_K_BUS;
}
}
break;
}
//-----------------------------------------------------------------------------------------------------------------------------------------
case ETAT_SEQUENCEUR_SYSTEME_ATTENTE_ANNUAIRE_K_BUS :
{
if (systeme.modules_physiques[0].flag_presence) // Le flag de présence du Compagnon a dû être positionné par le retour de la commande 'c_bus_down_commande_annuaire()'
{
for (i = 0; i < MAX_NOMBRE_MODULES; i ++)
{
if (systeme.modules_physiques[i].flag_presence == FALSE) continue;
c_bus_down_commande_lecture_id_carte(i); // Envoi d'une commande de lecture_ID à chaque carte présente
}
affichage_debug(__FILE__, __LINE__, "Lecture ID des modules\t\t: Ok", TYPE_MESSAGE_DEBUG_OK);
systeme.sequenceur.compteur = SYSTEME_TEMPO_LECTURE_ID_CARTES;
systeme.sequenceur.compteur_time_out = SYSTEME_TIME_OUT_LECTURE_ID_CARTES; // SDIR #304
systeme.sequenceur.etat = ETAT_SEQUENCEUR_SYSTEME_LECTURE_ID_CARTES;
}
break;
}
//-----------------------------------------------------------------------------------------------------------------------------------------
case ETAT_SEQUENCEUR_SYSTEME_LECTURE_ID_CARTES :
{
if (systeme.sequenceur.compteur == 0)
{
flag_id_complete = TRUE;
for (i = 0; i < MAX_NOMBRE_MODULES; i ++)
{
if (systeme.modules_physiques[i].flag_presence == FALSE) continue; // On ne taite que les cartes présentes
if (systeme.modules_physiques[i].type == -1) // Si l'ID de la carte a été reçu, son type a forcément été mise à jour (>0)
{
flag_id_complete = FALSE; // S'il n'a pas été mis à jour, il faut attendre encore un peu...
break; // Inutile de continuer...
}
}
if (flag_id_complete == TRUE)
{
enregistrement_annuaire_k_bus(); // A partir de la réponse à la commande 'annuaire_k_bus()' ci-dessus puis des 'lecture_id_carte()', on défini les cartes présentes ou pas et donc les circuits disponibles ou pas.
affichage_debug(__FILE__, __LINE__, "Enregistrement annuaire K-Bus\t: Ok", TYPE_MESSAGE_DEBUG_OK);
entrees.ow.flag_maj_annuaire_en_cours = TRUE;
c_bus_down_commande_annuaire_ow(); // Lecture de l'annuaire des devices OW présents dans le système
systeme.sequenceur.compteur_time_out = SYSTEME_TIME_OUT_ANNUAIRE_ONE_WIRE;
systeme.sequenceur.etat = ETAT_SEQUENCEUR_SYSTEME_ATTENTE_ANNUAIRE_ONE_WIRE;
}
else systeme.sequenceur.compteur = SYSTEME_TEMPO_LECTURE_ID_CARTES; // Si les ID de toutes les cartes n'ont pas été reçus, on lance une petite tempo supplémentaire...
}
// SDIR #304 : Début
if (systeme.sequenceur.compteur_time_out == 0)
{
systeme.sequenceur.etat = ETAT_SEQUENCEUR_SYSTEME_INIT; // On relance le séquenceur au départ pour effectuer une configuration complète de l'application en fonction du résultat de la reconnaissance réseau faite par le Compagnon sur K-Bus
systeme.sequenceur.compteur = 0; // Pas la peine d'attendre...
}
// SDIR #304 : Fin
break;
}
//-----------------------------------------------------------------------------------------------------------------------------------------
case ETAT_SEQUENCEUR_SYSTEME_ATTENTE_ANNUAIRE_ONE_WIRE :
{
if (!entrees.ow.flag_maj_annuaire_en_cours)
{
systeme.sequenceur.compteur_time_out = 0; // Arrêt du time-out
affichage_debug(__FILE__, __LINE__, "Mise à jour annuaire One-Wire\t: Ok", TYPE_MESSAGE_DEBUG_OK);
systeme.sequenceur.etat = ETAT_SEQUENCEUR_SYSTEME_CHARGEMENT_CONFIG_CARTES;
break;
}
if (systeme.sequenceur.compteur_time_out == 0)
{
affichage_debug(__FILE__, __LINE__, "Mise à jour annuaire One-Wire\t: Erreur de time-out", TYPE_MESSAGE_DEBUG_ERREUR);
systeme.sequenceur.etat = ETAT_SEQUENCEUR_SYSTEME_CHARGEMENT_CONFIG_CARTES;
break;
}
break;
}
//-----------------------------------------------------------------------------------------------------------------------------------------
case ETAT_SEQUENCEUR_SYSTEME_CHARGEMENT_CONFIG_CARTES :
{
for (i = 0; i < MAX_NOMBRE_MODULES; i ++) // Envoi des commandes de config de chaque carte :
{
if (systeme.modules_physiques[i].flag_presence == FALSE) continue; // On ne taite que les cartes présentes
switch(systeme.modules_physiques[i].type)
{
case TYPE_CARTE_SHIPBASE :
{
c_bus_down_commande_config_carte(i, C_BUS_CONFIG_LECTURE_SEULE);
break;
}
case TYPE_CARTE_SP812 :
case TYPE_CARTE_SP4AC :
case TYPE_CARTE_SP8DC :
{
c_bus_down_commande_config_carte(i, C_BUS_CONFIG_LECTURE_SEULE);
c_bus_down_commande_config_circuits(i);
c_bus_down_commande_cde_circuits(i); // NB : le flag 'flag_changement_consigne_en_cours' de chaque circuit de la carte n'est PAS positionné à TRUE. Cela ne doit pas poser de soucis au démarrage... (Cf SDIR #179)
break;
}
case TYPE_CARTE_SBS :
{
c_bus_down_commande_config_carte(i, C_BUS_CONFIG_LECTURE_SEULE);
c_bus_down_commande_config_batteries(i);
break;
}
default : ;
}
}
affichage_debug(__FILE__, __LINE__, "Configuration des modules\t\t: Ok", TYPE_MESSAGE_DEBUG_OK);
systeme.sequenceur.compteur = SYSTEME_TEMPO_ATTENTE_CONFIG_CARTES; // Cette tempo retarde la remonté de la sortie CM3P_READY et "bloque" donc au niveau du Compagnon la remontée de certaines commandes qui ne serviraient à rien.
systeme.sequenceur.etat = ETAT_SEQUENCEUR_SYSTEME_ATTENTE_CONFIG_CARTES;
break;
}
//-----------------------------------------------------------------------------------------------------------------------------------------
case ETAT_SEQUENCEUR_SYSTEME_ATTENTE_CONFIG_CARTES :
{
if (systeme.sequenceur.compteur == 0)
{
check_mise_a_jour(); // Vérification de la cohérence des versions de chaque module. Si besoin, la fonction lancera le séquenceur de chargement_code.
maj_etat_cm3p(ON); // Maj du flag, de la BDD et de la sortie physique
affichage_debug(__FILE__, __LINE__, "La configuration est terminée. La sortie CM3P_Ready est activée vers le Compagnon", TYPE_MESSAGE_DEBUG_OK);
printf("\n----------------- Fin d'initialisation --------------------\n\n");
// SDIR #301 :
//------------------------------------
// Sauvegarde de la base de données :
affichage_debug(__FILE__, __LINE__, "Lancement sauvegarde BDD\t\t: OK", TYPE_MESSAGE_DEBUG_OK);
//ret = sauvegarde_bdd();
ret=0;
if (ret != 0)
{
sprintf(tmp, "\tSauvegarde de la base de données : NOK (retour = %i)", ret);
affichage_debug(__FILE__, __LINE__, tmp, TYPE_MESSAGE_DEBUG_WARNING);
}
else affichage_debug(__FILE__, __LINE__, "Fin de sauvegarde BDD\t\t: OK", TYPE_MESSAGE_DEBUG_OK);
// Fin de SDIR #301
systeme.sequenceur.etat = ETAT_SEQUENCEUR_SYSTEME_REPOS;
}
break;
}
//-----------------------------------------------------------------------------------------------------------------------------------------
// Cet état repos est balayé à chaque boucle principale,
// sans temporisation. Il est donc important de la garder
// la plus rapide possible dans son cas le plus général.
case ETAT_SEQUENCEUR_SYSTEME_REPOS :
{
//=============================
// Surveillance du Compagnon :
if (systeme.flag_compagnon_ready == FALSE)
{
if (lecture_entree(TYPE_ENTREES_GPIO, 0, systeme.entree_gpio_cm_di_from_uc, TRUE) != 0) // 0 est l'adresse de ShipBase
{
systeme.flag_compagnon_ready = TRUE;
affichage_debug(__FILE__, __LINE__, "L'entrée Compagnon_Ready est passée à ON", TYPE_MESSAGE_DEBUG_OK);
re_configuration_systeme(); // Génère les commandes nécessaires sur C-Bus pour reconfigurer le Compagnon et le K-Bus
}
}
else
{
if (lecture_entree(TYPE_ENTREES_GPIO, 0, systeme.entree_gpio_cm_di_from_uc, TRUE) == 0) // 0 est l'adresse de ShipBase
{
systeme.flag_compagnon_ready = FALSE;
affichage_debug(__FILE__, __LINE__, "L'entrée Compagnon_Ready est passée à OFF", TYPE_MESSAGE_DEBUG_ERREUR);
}
}
//==================================
// Sauvegarde régulière de la BDD :
if (systeme.compteur_sauvegarde_bdd == 0)
{
systeme.compteur_sauvegarde_bdd = systeme.periode_sauvegarde_bdd; // Provenance = 'Periode_sauvegarde_bdd' de TB_Configuration
// sauvegarde_bdd();
}
//======================================================
// Recherche de nouveaux fichiers downloadés à traiter :
if (systeme.compteur_check_new_download == 0) // SDIR #196 (Début)
{
systeme.compteur_check_new_download = SYSTEME_TEMPO_PERIODE_CHECK_NEW_DOWNLOAD;
systeme.flag_new_download = TRUE;
} // SDIR #196 (Fin)
if ((systeme.flag_new_download == TRUE) &&
(chargement_code.sequenceur.etat == ETAT_SEQUENCEUR_CHARGEMENT_CODE_REPOS)) // Si un chargement de code est en cours, on attend avant de traiter d'autre fichiers à downloader
{
// NB : le flag n'est remis à FALSE qu'après avoir traité tous les fichiers actuellement présents dans le répertoire download.
// Sinon, dans le cas de fréquence de Download "élevée", comme pendant les tests, on relançait un download en plein chargement de code
// => plantage car on partage les fichiers et les répertoires...
// Listing des fichiers locaux :
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 '..'
//--------------------------------------------------------
// Recherche des fichiers bash exécutables immédiatement :
// Ce sont les fichiers 'now*.sh' qui sont exécutés (en parallèle de l'application via l'utilisation d'un '&' au lancement).
// Il est important que le fichier bash se renomme lui-même avec le suffixe DONE afin de ne pas être traité à nouveau.
if ((strstr(dir->d_name, MARQUEUR_FICHIER_BASH) != NULL) &&
(strstr(dir->d_name, "now_") != NULL) && // On ne traite que les fichiers qui contiennent (en pratique, commencent par) "now_"...
(strstr(dir->d_name, MARQUEUR_FICHIER_DONE) == NULL)) // ... MAIS qui ne contiennent pas le texte ".DONE" qui indique qu'ils ont été traités.
{
#ifdef __DEBUG_SYSTEME
sprintf(tmp, "Le fichier bash [%s] a été trouvé dans le répertoire download", dir->d_name);
affichage_debug(__FILE__, __LINE__, tmp, TYPE_MESSAGE_DEBUG_PAR_DEFAUT);
#endif
// Affectation des droits d'exécution au fichier bash :
sprintf(commande, "sudo chmod +x %s/%s", REPERTOIRE_SERVER_DOWNLOAD, dir->d_name); // Sans '&' de terminaison car il faut que la commande soit terminée avant de poursuivre
commande_shell(commande);
// Exécution du fichier bash :
sprintf(commande, "%s/%s &", REPERTOIRE_SERVER_DOWNLOAD, dir->d_name); // /!\ Ne pas oublier le '&' à la fin pour ne pas bloquer l'application !!!!
if (commande_shell(commande) == 0)
{
// Enregistrement dans l'historique :
enregistrement_historique(TYPE_SOURCE_HISTORIQUE_SYSTEME, SYSTEME_EXECUTION_BASH_DEBUT_OK, 0, 0, dir->d_name);
sprintf(tmp, "Le fichier bash [%s] a été exécuté avec succès.", dir->d_name);
affichage_debug(__FILE__, __LINE__, tmp, TYPE_MESSAGE_DEBUG_OK);
}
else
{
// Enregistrement dans l'historique :
enregistrement_historique(TYPE_SOURCE_HISTORIQUE_SYSTEME, SYSTEME_EXECUTION_BASH_DEBUT_NOK, 0, 0, dir->d_name);
sprintf(tmp, "Le fichier bash [%s] n'a pas ou être exécuté correctement.", dir->d_name);
affichage_debug(__FILE__, __LINE__, tmp, TYPE_MESSAGE_DEBUG_ERREUR);
}
}
//--------------------------------------------------------
// Recherche des fichiers encodés (a priori, des fichiers de version) :
if ((strstr(dir->d_name, MARQUEUR_FICHIER_TAR_GZIP_ENC) != NULL) &&
(strstr(dir->d_name, MARQUEUR_FICHIER_DONE) == NULL)) // On ne traite que les fichiers qui ne contiennent pas le texte ".DONE" qui indique qu'ils ont été traités.
{
sprintf(tmp, "Le fichier archive [%s] a été trouvé dans le répertoire download", dir->d_name);
affichage_debug(__FILE__, __LINE__, tmp, TYPE_MESSAGE_DEBUG_PAR_DEFAUT);
// Vérification du type de MAJ à appliquer en fonction du fichier reçu :
uint8_t mode_validation = systeme.mode_validation_maj; // La variable locale sera modifié au cours de l'analyse donc on récupère une copie au départ pour ne pas altérer l'image de la BDD
if ((mode_validation == MODE_VALIDATION_MAJ_MANUELLE) || // Si le mode de MAJ est AUCUNE, il est inutile dde vérifier si la nouvelle version est valide
(mode_validation == MODE_VALIDATION_MAJ_AUTOMATIQUE))
{
// Vérification que le fichier reçu est utilisable :
char *ptr_new[MAX_NOMBRE_PARAMETRES_LISTE_DOWNLOAD]; // NB : le define utilisé pour la taille n'est pas directement lié au sujet mais pratique...
char *ptr_now[MAX_NOMBRE_PARAMETRES_LISTE_DOWNLOAD];
char version_new[MAX_LONGUEUR_NOM_FICHIER];
char version_now[MAX_LONGUEUR_NOM_FICHIER];
strcpy(version_new, dir->d_name); // Copie dans une chaine locale car on va la modifier. Nom de la forme : 'ShipHeart_v_3_2_1_uf.tar.gz.enc'
ptr_new[0] = strstr(version_new, "."); // Recherche du premier '.'
if (ptr_new[0] != NULL) // Si on a trouvé un premier '.' :
{
*ptr_new[0] = 0; // Fin de chaine au premier point. Version maintenant de la forme : 'ShipHeart_v_3_2_1_uf'
i = 0;
ptr_new[i] = strtok (version_new, "_"); // Extraction du premier segment avant le premier '_'. ATTENTION : si aucun délimiteur trouvé, la fonction renvoit la chaine entière (et pas NULL...)
while ((ptr_new[i] != NULL) && (i < MAX_NOMBRE_PARAMETRES_LISTE_DOWNLOAD))
{
i ++;
ptr_new[i] = strtok (NULL, "_"); // Extraction du segment suivant le prochain '_'
}
// Check du nombre de champs trouvés :
if (i == 6) // Valeur correcte = 6 segments autour des '_' dans 'ShipHeart_v_3_2_1_uf'
{
if ((ptr_new[5][1] != 't') && (ptr_new[5][1] != 'T')) // Si le flag 'Version_back_enable' n'est PAS 'true' (probablement 'false' donc), alors il faut vérifier l'antériorité de la version actuelle :
{
strcpy(version_now, systeme.package_no_version); // Copie dans une chaine locale car on va la modifier. Version de la forme : '3.2.1'
i = 0;
ptr_now[i] = strtok (version_now, "."); // Extraction du premier segment avant le premier '.'. ATTENTION : si aucun délimiteur trouvé, la fonction renvoit la chaine entière (et pas NULL...)
while ((ptr_now[i] != NULL) && (i < MAX_NOMBRE_PARAMETRES_LISTE_DOWNLOAD))
{
i ++;
ptr_now[i] = strtok (NULL, "."); // Extraction du segment suivant le prochain '.'
}
if (i == 3) // Valeur correcte = 3 segments autour des '.' dans '3.2.1'
{
do // Fake loop :
{
// Premier chiffre :
if (atoi(ptr_new[2]) < atoi(ptr_now[0])) // 1.y.z < 3.y.z
{
mode_validation = MODE_VALIDATION_MAJ_AUCUNE;
break;
}
if (atoi(ptr_new[2]) > atoi(ptr_now[0])) break; // 3.y.z > 1.y.z
// x = x
// Deucième chiffre :
if (atoi(ptr_new[3]) < atoi(ptr_now[1])) // 1.2.z < 1.3.z
{
mode_validation = MODE_VALIDATION_MAJ_AUCUNE;
break;
}
if (atoi(ptr_new[3]) > atoi(ptr_now[1])) break; // 1.3.z > 1.2.z
// x.y = x.y
// Troisème chiffre :
if (atoi(ptr_new[4]) < atoi(ptr_now[2])) // 1.2.3 < 1.2.4
{
mode_validation = MODE_VALIDATION_MAJ_AUCUNE;
break;
}
if (atoi(ptr_new[4]) > atoi(ptr_now[2])) break; // 1.2.4 > 1.2.3
// Egalité des versions :
mode_validation = MODE_VALIDATION_MAJ_AUCUNE; // 1.2.3 = 1.2.3
} while(0);
if (mode_validation == MODE_VALIDATION_MAJ_AUCUNE)
{
sprintf(tmp, "Le fichier archive [%s] ne peut pas être traité car sa version n'est pas strictement postérieure à la version en cours [%s] et son flag [Version_back_enable] est False.", dir->d_name, systeme.package_no_version);
affichage_debug(__FILE__, __LINE__, tmp, TYPE_MESSAGE_DEBUG_WARNING);
}
}
else // Si la structure de version n'est pas de la forme "x.y.z', on rejette le fichier car on aun problème de structure générale :
{
mode_validation = MODE_VALIDATION_MAJ_AUCUNE;
sprintf(tmp, "Le fichier archive [%s] ne peut pas être traité car la version actuelle [%s] a un format non valide.", dir->d_name, systeme.package_no_version);
affichage_debug(__FILE__, __LINE__, tmp, TYPE_MESSAGE_DEBUG_ERREUR);
}
}
else // Si le flag 'Version_back_enable' est 'true', alors il est inutile de vérifier l'antériorité de la version actuelle...
{
sprintf(tmp, "Le fichier archive [%s] est considéré comme valide puisque son flag [Version_back_enable] est True.", dir->d_name);
affichage_debug(__FILE__, __LINE__, tmp, TYPE_MESSAGE_DEBUG_PAR_DEFAUT);
}
}
else // Si la structure de nom de fichier n'a pas 6 segments autour des '_', on le rejette :
{
mode_validation = MODE_VALIDATION_MAJ_AUCUNE;
sprintf(tmp, "Le fichier archive [%s] ne peut pas être traité car son format est non valide (attendu [ShipHeart_v_3_2_1_uf.*]).", dir->d_name);
affichage_debug(__FILE__, __LINE__, tmp, TYPE_MESSAGE_DEBUG_ERREUR);
}
}
else // Si la structure de nom de fichier n'a pas de '.' dans le nom, on ne le traite pas :
// NB : ce cas ne devrait pas arriver car on a détecté MARQUEUR_FICHIER_TAR_GZIP_ENC (qui contient 3 x '.' !) dans le nom pour arriver ici... Donc pas de message de debug.
{
mode_validation = MODE_VALIDATION_MAJ_AUCUNE;
}
}
else
{
sprintf(tmp, "Le mode de validation des mises à jour étant dévalidé [%i], le fichier [%s] n'est pas traité.", mode_validation, dir->d_name);
affichage_debug(__FILE__, __LINE__, tmp, TYPE_MESSAGE_DEBUG_WARNING);
}
// Le traitement dépend du mode de validation en cours :
char nom_repertoire_destination[MAX_LONGUEUR_NOM_REPERTOIRE_LOCAL];
uint16_t code_ok = 0, code_erreur = 0; // L'init sert juste à éviter un warning...
//------------------------------------------------------------
// Attente validation manuelle => Transfert vers A_VALIDER :
if (mode_validation == MODE_VALIDATION_MAJ_MANUELLE)
{
strcpy(nom_repertoire_destination, REPERTOIRE_VERSIONS_A_VALIDER);
code_ok = SYSTEME_COPIE_ARCHIVE_A_VALIDER_OK;
code_erreur = SYSTEME_COPIE_ARCHIVE_A_VALIDER_NOK;
}
//------------------------------------------------------------------
// Validation automatique -> Transfert directement dans A_CHARGER :
else if (mode_validation == MODE_VALIDATION_MAJ_AUTOMATIQUE)
{
strcpy(nom_repertoire_destination, REPERTOIRE_VERSIONS_A_CHARGER);
code_ok = SYSTEME_COPIE_ARCHIVE_A_CHARGER_OK;
code_erreur = SYSTEME_COPIE_ARCHIVE_A_CHARGER_NOK;
}
//-----------------------------
// Aucune mise à jour :
else ;
// Vidage des répertoires A_VALIDER et A_CHARGER (la méthode choisie est un peu violente mais efficace...) :
// NB : ce vidage est fait dans les 3 cas de 'Mode_validation maj'. En effet, même dans le cas de MAJ_AUCUNE,
// on considère que si on vient de recevoir un fichier et qu'on le jette, il faut s'assurer qu'il ne reste pas
// un "vieux" fichier dans A_CHARGER ou A_VALIDER...
sprintf(commande, "sudo rm -f %s/*", REPERTOIRE_VERSIONS_A_VALIDER);
commande_shell(commande);
sprintf(commande, "sudo rm -f %s/*", REPERTOIRE_VERSIONS_A_CHARGER);
commande_shell(commande);
sprintf(tmp, "Les répertoires A_CHARGER et A_VALIDER viennent d'être vidés suite à la réception d'une nouvelle version.");
affichage_debug(__FILE__, __LINE__, tmp, TYPE_MESSAGE_DEBUG_PAR_DEFAUT);
// Copie du fichier reçu dans le répertoire ad'hoc :
if ((mode_validation == MODE_VALIDATION_MAJ_MANUELLE) ||
(mode_validation == MODE_VALIDATION_MAJ_AUTOMATIQUE))
{
// Copie du fichier reçu :
sprintf(commande, "sudo cp -f %s/%s %s/%s", REPERTOIRE_SERVER_DOWNLOAD, dir->d_name, nom_repertoire_destination, dir->d_name); // NB : l'utilisation de '&' en fin de commande pose pb (la copie ne doit pas être terminée quand on tente de renommer ensuite le fichier ?)
if (commande_shell(commande) == 0)
{
// Enregistrement dans l'historique :
enregistrement_historique(TYPE_SOURCE_HISTORIQUE_SYSTEME, code_ok, 0, 0, dir->d_name);
sprintf(tmp, "Le fichier archive [%s] a été copié avec succès dans le répertoire [%s].", dir->d_name, nom_repertoire_destination);
affichage_debug(__FILE__, __LINE__, tmp, TYPE_MESSAGE_DEBUG_OK);
}
else
{
// Enregistrement dans l'historique :
enregistrement_historique(TYPE_SOURCE_HISTORIQUE_SYSTEME, code_erreur, 0, 0, dir->d_name);
sprintf(tmp, "Le fichier archive [%s] n'a pas ou être copié correctement dans le répertoire [%s].", dir->d_name, nom_repertoire_destination);
affichage_debug(__FILE__, __LINE__, tmp, TYPE_MESSAGE_DEBUG_ERREUR);
}
}
// Renommage du fichier reçu avec le marqueur DONE (dans tous les cas) :
sprintf(commande, "mv %s/%s %s/%s%s", REPERTOIRE_SERVER_DOWNLOAD, dir->d_name, REPERTOIRE_SERVER_DOWNLOAD, dir->d_name, MARQUEUR_FICHIER_DONE);
commande_shell(commande);
// Commande de synchro afin de s'assurer que les modifications de fichier seront bien prises en compte par le système :
sprintf(commande, "sudo sync");
commande_shell(commande);
}
}
closedir(repertoire); // Fermeture du répertoire
}
systeme.flag_new_download = FALSE; // Il faut RAZ le flag pour autoriser les downloads à venir.
}
break;
}
//-----------------------------------------------------------------------------------------------------------------------------------------
case ETAT_SEQUENCEUR_SYSTEME_DEMARRAGE_IMPOSSIBLE :
{
break;
}
//-----------------------------------------------------------------------------------------------------------------------------------------
default :
{
sprintf(tmp, "L'état du séquenceur Système est inconnu [%i]. Il est repositionné au REPOS", systeme.sequenceur.etat);
affichage_debug(__FILE__, __LINE__, tmp, TYPE_MESSAGE_DEBUG_ERREUR);
systeme.sequenceur.etat = ETAT_SEQUENCEUR_SYSTEME_REPOS;
break;
}
}
//====================================
// Séquenceur de chargement du code :
gestion_chargement_code();
}
//==================================================================================================================================================================
// Fonction : Lecture du fichier JSON de la version courante puis comparaison entre les n° de version présents dans ce fichier, les fichiers présents dans CURRENT
// et, surtout, entre le fichier présent dans CURRENT et la version en cours d'éxécution sur les modules sur K-Bus. S'il y a écart, activation du
// séquenceur de chargement afin que les fichiers de current soient chargés dans les modules concernés sur K-Bus.
// Reçoit : Rien
// Renvoit : Rien
//==================================================================================================================================================================
void check_mise_a_jour(void)
{
struct dirent *dir; // Les types 'dirent' ou 'DIR' sont déclarés dans le header <dirent.h>
DIR *repertoire;
char nom_fichier[MAX_LONGUEUR_NOM_REPERTOIRE_LOCAL + MAX_LONGUEUR_NOM_FICHIER];
uint16_t i;
int16_t comp;
struct Struct_json_version json_version;
char tmp[MAX_LONGUEUR_BUFFER_TEMPORAIRE_DEBUG];
// Parse du fichier de version :
sprintf(nom_fichier, "%s/%s%s", REPERTOIRE_VERSIONS_CURRENT, systeme.package_version, MARQUEUR_FICHIER_JSON);
#ifdef __DEBUG_SYSTEME_FICHIER_JSON
json_version = parse_json_version(nom_fichier, true);
#else
json_version = parse_json_version(nom_fichier, false);
#endif
// Traitement des infos du fichier de version :
if (strstr(json_version.no_version, "ERREUR") == NULL) // Si la lecture du fichier de version s'est passée normalement
{
repertoire = opendir(REPERTOIRE_VERSIONS_CURRENT); // Ouverture du répertoire CURRENT
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 '..'
//------------------------------------------------------
// Application :
if (strstr(dir->d_name, MARQUEUR_FICHIER_APPLICATION) != NULL)
{
comp = strcmp(dir->d_name, json_version.application);
if (comp == 0)
{
#ifdef __DEBUG_SYSTEME_MISE_A_JOUR
sprintf(tmp, "Le fichier Application [%s] trouvé dans le répertoire CURRENT correspond bien au package en cours", dir->d_name);
affichage_debug(__FILE__, __LINE__, tmp, TYPE_MESSAGE_DEBUG_PAR_DEFAUT);
#endif
}
else if (comp > 0)
{
#ifdef __DEBUG_SYSTEME_MISE_A_JOUR
sprintf(tmp, "Le fichier Application [%s] trouvé dans le répertoire CURRENT est postérieur au package en cours [%s]. Une mise à jour correcte serait nécessaire...", dir->d_name, json_version.application);
affichage_debug(__FILE__, __LINE__, tmp, TYPE_MESSAGE_DEBUG_WARNING);
#endif
}
else
{
sprintf(tmp, "Le fichier Application [%s] trouvé dans le répertoire CURRENT est antérieur au package en cours [%s]. Une mise à jour est impérative !!", dir->d_name, json_version.application);
affichage_debug(__FILE__, __LINE__, tmp, TYPE_MESSAGE_DEBUG_ERREUR);
}
}
//------------------------------------------------------
// Application QT :
if (strstr(dir->d_name, MARQUEUR_FICHIER_QT) != NULL)
{
comp = strcmp(dir->d_name, json_version.qt);
if (comp == 0)
{
#ifdef __DEBUG_SYSTEME_MISE_A_JOUR
sprintf(tmp, "Le fichier QT [%s] trouvé dans le répertoire CURRENT correspond bien au package en cours", dir->d_name);
affichage_debug(__FILE__, __LINE__, tmp, TYPE_MESSAGE_DEBUG_PAR_DEFAUT);
#endif
}
else if (comp > 0)
{
#ifdef __DEBUG_SYSTEME_MISE_A_JOUR
sprintf(tmp, "Le fichier QT [%s] trouvé dans le répertoire CURRENT est postérieur au package en cours [%s]. Une mise à jour correcte serait nécessaire...", dir->d_name, json_version.qt);
affichage_debug(__FILE__, __LINE__, tmp, TYPE_MESSAGE_DEBUG_WARNING);
#endif
}
else
{
sprintf(tmp, "Le fichier QT [%s] trouvé dans le répertoire CURRENT est antérieur au package en cours [%s]. Une mise à jour est impérative !!", dir->d_name, json_version.qt);
affichage_debug(__FILE__, __LINE__, tmp, TYPE_MESSAGE_DEBUG_ERREUR);
}
}
//------------------------------------------------------
// Firmware Compagnon :
if ( ((systeme.generation_shipbase == GENERATION_SHIPBASE_V1) && (strstr(dir->d_name, MARQUEUR_FICHIER_COMPAGNON_V1) != NULL)) || // SDIR #162
(((systeme.generation_shipbase == GENERATION_SHIPBASE_V2) || (systeme.generation_shipbase == GENERATION_SHIPBASE_V3)) && (strstr(dir->d_name, MARQUEUR_FICHIER_COMPAGNON_V2) != NULL)) )
// if (strstr(dir->d_name, MARQUEUR_FICHIER_COMPAGNON) != NULL) // SDIR #162
{
comp = strcmp(dir->d_name, json_version.compagnon);
// Comparaison entre le fichier réellement présent dans CURRENT et la version de firmware indiquée dans le fichier de version :
if (comp == 0)
{
#ifdef __DEBUG_SYSTEME_MISE_A_JOUR
sprintf(tmp, "Le fichier Compagnon [%s] trouvé dans le répertoire CURRENT correspond bien au package en cours", dir->d_name);
affichage_debug(__FILE__, __LINE__, tmp, TYPE_MESSAGE_DEBUG_PAR_DEFAUT);
#endif
}
else if (comp > 0)
{
#ifdef __DEBUG_SYSTEME_MISE_A_JOUR
sprintf(tmp, "Le fichier Compagnon [%s] trouvé dans le répertoire CURRENT est postérieur au package en cours [%s]. Une mise à jour correcte serait nécessaire...", dir->d_name, json_version.compagnon);
affichage_debug(__FILE__, __LINE__, tmp, TYPE_MESSAGE_DEBUG_WARNING);
#endif
}
else
{
sprintf(tmp, "Le fichier Compagnon [%s] trouvé dans le répertoire CURRENT est antérieur au package en cours [%s]. Une mise à jour est impérative !!", dir->d_name, json_version.compagnon);
affichage_debug(__FILE__, __LINE__, tmp, TYPE_MESSAGE_DEBUG_ERREUR);
}
// Comparaison entre le fichier présent dans CURRENT et la version en cours d'éxécution sur le Compagnon :
if (systeme.generation_shipbase == GENERATION_SHIPBASE_V1) sprintf(nom_fichier, "%s_%s.bin", MARQUEUR_FICHIER_COMPAGNON_V1, systeme.modules_physiques[0].soft_version);
else sprintf(nom_fichier, "%s_%s.bin", MARQUEUR_FICHIER_COMPAGNON_V2, systeme.modules_physiques[0].soft_version);
// SDIR #137 :
if (((systeme.mode_maj_firmwares == MODE_MAJ_FIRMWARES_NORMAL) && (strcmp(dir->d_name, nom_fichier) > 0)) || // Si le fichier dans CURRRENT est plus récent que le firmware en cours d'excéution (flag de MAJ des firmwares = 0 = Normal)
((systeme.mode_maj_firmwares == MODE_MAJ_FIRMWARES_SI_DIFFERENTS) && (strcmp(dir->d_name, nom_fichier) != 0)) || // ... OU si le fichier est juste différent mais le flag de MAJ des firmwares est à 1
(systeme.mode_maj_firmwares == MODE_MAJ_FIRMWARES_TOUJOURS) ) // ... OU le flag de MAJ des firmwares est à 2
// Fin de SDIR #137
{
if ((chargement_code.sequenceur.etat == ETAT_SEQUENCEUR_CHARGEMENT_CODE_REPOS) ||
(chargement_code.sequenceur.etat == ETAT_SEQUENCEUR_CHARGEMENT_CODE_LANCEMENT))
{
strcpy(chargement_code.nom_fichier[0], dir->d_name); // Stockage du nom de fichier à utiliser pour le chargement de code
chargement_code.sequenceur.etat = ETAT_SEQUENCEUR_CHARGEMENT_CODE_LANCEMENT;
sprintf(tmp, "Le fichier Compagnon [%s] trouvé dans le répertoire CURRENT est postérieur à la version en cours d'exécution [%s]. Le fichier va être chargé sur le Compagnon", dir->d_name, nom_fichier);
affichage_debug(__FILE__, __LINE__, tmp, TYPE_MESSAGE_DEBUG_WARNING);
}
else
{
sprintf(tmp, "Le fichier Compagnon [%s] trouvé dans le répertoire CURRENT est postérieur à la version en cours d'exécution [%s]. Mais le séquenceur de chargement de code est occupé (état = %i) et le code ne peut donc pas être chargé sur le Compagnon.", dir->d_name, systeme.modules_physiques[0].soft_version, chargement_code.sequenceur.etat);
affichage_debug(__FILE__, __LINE__, tmp, TYPE_MESSAGE_DEBUG_ERREUR);
}
}
}
//------------------------------------------------------
// Firmware SP812 :
if (strstr(dir->d_name, MARQUEUR_FICHIER_SP812) != NULL)
{
comp = strcmp(dir->d_name, json_version.sp812);
// Comparaison entre le fichier réellement présent dans CURRENT et la version de firmware indiquée dans le fichier de version :
if (comp == 0)
{
#ifdef __DEBUG_SYSTEME_MISE_A_JOUR
sprintf(tmp, "Le fichier SP812 [%s] trouvé dans le répertoire CURRENT correspond bien au package en cours", dir->d_name);
affichage_debug(__FILE__, __LINE__, tmp, TYPE_MESSAGE_DEBUG_PAR_DEFAUT);
#endif
}
else if (comp > 0)
{
#ifdef __DEBUG_SYSTEME_MISE_A_JOUR
sprintf(tmp, "Le fichier SP812 [%s] trouvé dans le répertoire CURRENT est postérieur au package en cours [%s]. Une mise à jour correcte serait nécessaire...", dir->d_name, json_version.sp812);
affichage_debug(__FILE__, __LINE__, tmp, TYPE_MESSAGE_DEBUG_WARNING);
#endif
}
else
{
sprintf(tmp, "Le fichier SP812 [%s] trouvé dans le répertoire CURRENT est antérieur au package en cours [%s]. Une mise à jour est impérative !!", dir->d_name, json_version.sp812);
affichage_debug(__FILE__, __LINE__, tmp, TYPE_MESSAGE_DEBUG_ERREUR);
}
// Comparaison entre le fichier présent dans CURRENT et la version en cours d'éxécution sur chaque SP812 :
for (i = 0; i < MAX_NOMBRE_MODULES; i ++)
{
if (systeme.modules_physiques[i].flag_presence == FALSE) continue; // On ne taite que les cartes présentes
if (systeme.modules_physiques[i].type != TYPE_CARTE_SP812) continue; // On ne traite que les cartes de type SP812 pour ce type de fichier de code
sprintf(nom_fichier, "%s_%s.bin", MARQUEUR_FICHIER_SP812, systeme.modules_physiques[i].soft_version);
// SDIR #137 :
if (((systeme.mode_maj_firmwares == MODE_MAJ_FIRMWARES_NORMAL) && (strcmp(dir->d_name, nom_fichier) > 0)) || // Si le fichier dans CURRRENT est plus récent que le firmware en cours d'excéution (flag de MAJ des firmwares = 0 = Normal)
((systeme.mode_maj_firmwares == MODE_MAJ_FIRMWARES_SI_DIFFERENTS) && (strcmp(dir->d_name, nom_fichier) != 0)) || // ... OU si le fichier est juste différent mais le flag de MAJ des firmwares est à 1
(systeme.mode_maj_firmwares == MODE_MAJ_FIRMWARES_TOUJOURS) ) // ... OU le flag de MAJ des firmwares est à 2
// Fin de SDIR #137
{
if ((chargement_code.sequenceur.etat == ETAT_SEQUENCEUR_CHARGEMENT_CODE_REPOS) ||
(chargement_code.sequenceur.etat == ETAT_SEQUENCEUR_CHARGEMENT_CODE_LANCEMENT))
{
strcpy(chargement_code.nom_fichier[i], dir->d_name); // Stockage du nom de fichier à utiliser pour le chargement de code
chargement_code.sequenceur.etat = ETAT_SEQUENCEUR_CHARGEMENT_CODE_LANCEMENT;
sprintf(tmp, "Le fichier SP812 [%s] trouvé dans le répertoire CURRENT est postérieur à la version en cours d'exécution sur la carte n° %i [%s]. Le fichier va être chargé sur le SP812", dir->d_name, i, systeme.modules_physiques[i].soft_version);
affichage_debug(__FILE__, __LINE__, tmp, TYPE_MESSAGE_DEBUG_WARNING);
}
else
{
sprintf(tmp, "Le fichier SP812 [%s] trouvé dans le répertoire CURRENT est postérieur à la version en cours d'exécution sur la carte n° %i [%s]. Mais le séquenceur de chargementd e code est occupé (état = %i) et le code ne peut donc pas être chargé sur le SP812.", dir->d_name, i, systeme.modules_physiques[0].soft_version, chargement_code.sequenceur.etat);
affichage_debug(__FILE__, __LINE__, tmp, TYPE_MESSAGE_DEBUG_ERREUR);
}
}
}
}
//------------------------------------------------------
// Firmware ShipBS :
if (strstr(dir->d_name, MARQUEUR_FICHIER_SBS) != NULL)
{
comp = strcmp(dir->d_name, json_version.sbs);
// Comparaison entre le fichier réellement présent dans CURRENT et la version de firmware indiquée dans le fichier de version :
if (comp == 0)
{
#ifdef __DEBUG_SYSTEME_MISE_A_JOUR
sprintf(tmp, "Le fichier ShipBS [%s] trouvé dans le répertoire CURRENT correspond bien au package en cours", dir->d_name);
affichage_debug(__FILE__, __LINE__, tmp, TYPE_MESSAGE_DEBUG_PAR_DEFAUT);
#endif
}
else if (comp > 0)
{
#ifdef __DEBUG_SYSTEME_MISE_A_JOUR
sprintf(tmp, "Le fichier ShipBS [%s] trouvé dans le répertoire CURRENT est postérieur au package en cours [%s]. Une mise à jour correcte serait nécessaire...", dir->d_name, json_version.sbs);
affichage_debug(__FILE__, __LINE__, tmp, TYPE_MESSAGE_DEBUG_WARNING);
#endif
}
else
{
sprintf(tmp, "Le fichier ShipBS [%s] trouvé dans le répertoire CURRENT est antérieur au package en cours [%s]. Une mise à jour est impérative !!", dir->d_name, json_version.sbs);
affichage_debug(__FILE__, __LINE__, tmp, TYPE_MESSAGE_DEBUG_ERREUR);
}
// Comparaison entre le fichier présent dans CURRENT et la version en cours d'éxécution sur chaque ShipBS :
for (i = 0; i < MAX_NOMBRE_MODULES; i ++)
{
if (systeme.modules_physiques[i].flag_presence == FALSE) continue; // On ne taite que les cartes présentes
if (systeme.modules_physiques[i].type != TYPE_CARTE_SBS) continue; // On ne traite que les cartes de type ShipBS pour ce type de fichier de code
sprintf(nom_fichier, "%s_%s.bin", MARQUEUR_FICHIER_SBS, systeme.modules_physiques[i].soft_version);
// SDIR #137 :
// if (strcmp(dir->d_name, nom_fichier) > 0) // Si le fichier dans CURRRENT est plus récent que le firmware en cours d'exécution, le fichier va être chargé
if (((systeme.mode_maj_firmwares == MODE_MAJ_FIRMWARES_NORMAL) && (strcmp(dir->d_name, nom_fichier) > 0)) || // Si le fichier dans CURRRENT est plus récent que le firmware en cours d'excéution (flag de MAJ des firmwares = 0 = Normal)
((systeme.mode_maj_firmwares == MODE_MAJ_FIRMWARES_SI_DIFFERENTS) && (strcmp(dir->d_name, nom_fichier) != 0)) || // ... OU si le fichier est juste différent mais le flag de MAJ des firmwares est à 1
(systeme.mode_maj_firmwares == MODE_MAJ_FIRMWARES_TOUJOURS) ) // ... OU le flag de MAJ des firmwares est à 2
// Fin de SDIR #137
{
if ((chargement_code.sequenceur.etat == ETAT_SEQUENCEUR_CHARGEMENT_CODE_REPOS) ||
(chargement_code.sequenceur.etat == ETAT_SEQUENCEUR_CHARGEMENT_CODE_LANCEMENT))
{
strcpy(chargement_code.nom_fichier[i], dir->d_name); // Stockage du nom de fichier à utiliser pour le chargement de code
chargement_code.sequenceur.etat = ETAT_SEQUENCEUR_CHARGEMENT_CODE_LANCEMENT;
sprintf(tmp, "Le fichier ShipBS [%s] trouvé dans le répertoire CURRENT est postérieur à la version en cours d'exécution sur la carte n° %i [%s]. Le fichier va être chargé sur le ShipBS", dir->d_name, i, systeme.modules_physiques[i].soft_version);
affichage_debug(__FILE__, __LINE__, tmp, TYPE_MESSAGE_DEBUG_WARNING);
}
else
{
sprintf(tmp, "Le fichier ShipBS [%s] trouvé dans le répertoire CURRENT est postérieur à la version en cours d'exécution sur la carte n° %i [%s]. Mais le séquenceur de chargementd e code est occupé (état = %i) et le code ne peut donc pas être chargé sur le ShipBS.", dir->d_name, i, systeme.modules_physiques[0].soft_version, chargement_code.sequenceur.etat);
affichage_debug(__FILE__, __LINE__, tmp, TYPE_MESSAGE_DEBUG_ERREUR);
}
}
}
}
//------------------------------------------------------
// Firmware SP4AC :
if (strstr(dir->d_name, MARQUEUR_FICHIER_SP4AC) != NULL)
{
comp = strcmp(dir->d_name, json_version.sp4ac);
// Comparaison entre le fichier réellement présent dans CURRENT et la version de firmware indiquée dans le fichier de version :
if (comp == 0)
{
#ifdef __DEBUG_SYSTEME_MISE_A_JOUR
sprintf(tmp, "Le fichier SP4AC [%s] trouvé dans le répertoire CURRENT correspond bien au package en cours", dir->d_name);
affichage_debug(__FILE__, __LINE__, tmp, TYPE_MESSAGE_DEBUG_PAR_DEFAUT);
#endif
}
else if (comp > 0)
{
#ifdef __DEBUG_SYSTEME_MISE_A_JOUR
sprintf(tmp, "Le fichier SP4AC [%s] trouvé dans le répertoire CURRENT est postérieur au package en cours [%s]. Une mise à jour correcte serait nécessaire...", dir->d_name, json_version.sp4ac);
affichage_debug(__FILE__, __LINE__, tmp, TYPE_MESSAGE_DEBUG_WARNING);
#endif
}
else
{
sprintf(tmp, "Le fichier SP4AC [%s] trouvé dans le répertoire CURRENT est antérieur au package en cours [%s]. Une mise à jour est impérative !!", dir->d_name, json_version.sp4ac);
affichage_debug(__FILE__, __LINE__, tmp, TYPE_MESSAGE_DEBUG_ERREUR);
}
// Comparaison entre le fichier présent dans CURRENT et la version en cours d'éxécution sur chaque SP4AC :
for (i = 0; i < MAX_NOMBRE_MODULES; i ++)
{
if (systeme.modules_physiques[i].flag_presence == FALSE) continue; // On ne taite que les cartes présentes
if (systeme.modules_physiques[i].type != TYPE_CARTE_SP4AC) continue; // On ne traite que les cartes de type SP4AC pour ce type de fichier de code
sprintf(nom_fichier, "%s_%s.bin", MARQUEUR_FICHIER_SP4AC, systeme.modules_physiques[i].soft_version);
// SDIR #137 :
// if (strcmp(dir->d_name, nom_fichier) > 0) // Si le fichier dans CURRRENT est plus récent que le firmware en cours d'exécution, le fichier va être chargé
if (((systeme.mode_maj_firmwares == MODE_MAJ_FIRMWARES_NORMAL) && (strcmp(dir->d_name, nom_fichier) > 0)) || // Si le fichier dans CURRRENT est plus récent que le firmware en cours d'excéution (flag de MAJ des firmwares = 0 = Normal)
((systeme.mode_maj_firmwares == MODE_MAJ_FIRMWARES_SI_DIFFERENTS) && (strcmp(dir->d_name, nom_fichier) != 0)) || // ... OU si le fichier est juste différent mais le flag de MAJ des firmwares est à 1
(systeme.mode_maj_firmwares == MODE_MAJ_FIRMWARES_TOUJOURS) ) // ... OU le flag de MAJ des firmwares est à 2
// Fin de SDIR #137
{
if ((chargement_code.sequenceur.etat == ETAT_SEQUENCEUR_CHARGEMENT_CODE_REPOS) ||
(chargement_code.sequenceur.etat == ETAT_SEQUENCEUR_CHARGEMENT_CODE_LANCEMENT))
{
strcpy(chargement_code.nom_fichier[i], dir->d_name); // Stockage du nom de fichier à utiliser pour le chargement de code
chargement_code.sequenceur.etat = ETAT_SEQUENCEUR_CHARGEMENT_CODE_LANCEMENT;
sprintf(tmp, "Le fichier SP4AC [%s] trouvé dans le répertoire CURRENT est postérieur à la version en cours d'exécution sur la carte n° %i [%s]. Le fichier va être chargé sur le SP4AC", dir->d_name, i, systeme.modules_physiques[i].soft_version);
affichage_debug(__FILE__, __LINE__, tmp, TYPE_MESSAGE_DEBUG_WARNING);
}
else
{
sprintf(tmp, "Le fichier SP4AC [%s] trouvé dans le répertoire CURRENT est postérieur à la version en cours d'exécution sur la carte n° %i [%s]. Mais le séquenceur de chargementd e code est occupé (état = %i) et le code ne peut donc pas être chargé sur le SP4AC.", dir->d_name, i, systeme.modules_physiques[0].soft_version, chargement_code.sequenceur.etat);
affichage_debug(__FILE__, __LINE__, tmp, TYPE_MESSAGE_DEBUG_ERREUR);
}
}
}
}
//------------------------------------------------------
// Firmware SP8DC :
if (strstr(dir->d_name, MARQUEUR_FICHIER_SP8DC) != NULL)
{
comp = strcmp(dir->d_name, json_version.sp8dc);
// Comparaison entre le fichier réellement présent dans CURRENT et la version de firmware indiquée dans le fichier de version :
if (comp == 0)
{
#ifdef __DEBUG_SYSTEME_MISE_A_JOUR
sprintf(tmp, "Le fichier SP8DC [%s] trouvé dans le répertoire CURRENT correspond bien au package en cours", dir->d_name);
affichage_debug(__FILE__, __LINE__, tmp, TYPE_MESSAGE_DEBUG_PAR_DEFAUT);
#endif
}
else if (comp > 0)
{
#ifdef __DEBUG_SYSTEME_MISE_A_JOUR
sprintf(tmp, "Le fichier SP8DC [%s] trouvé dans le répertoire CURRENT est postérieur au package en cours [%s]. Une mise à jour correcte serait nécessaire...", dir->d_name, json_version.sp8dc);
affichage_debug(__FILE__, __LINE__, tmp, TYPE_MESSAGE_DEBUG_WARNING);
#endif
}
else
{
sprintf(tmp, "Le fichier SP8DC [%s] trouvé dans le répertoire CURRENT est antérieur au package en cours [%s]. Une mise à jour est impérative !!", dir->d_name, json_version.sp8dc);
affichage_debug(__FILE__, __LINE__, tmp, TYPE_MESSAGE_DEBUG_ERREUR);
}
// Comparaison entre le fichier présent dans CURRENT et la version en cours d'éxécution sur chaque SP8DC :
for (i = 0; i < MAX_NOMBRE_MODULES; i ++)
{
if (systeme.modules_physiques[i].flag_presence == FALSE) continue; // On ne taite que les cartes présentes
if (systeme.modules_physiques[i].type != TYPE_CARTE_SP8DC) continue; // On ne traite que les cartes de type SP8DC pour ce type de fichier de code
sprintf(nom_fichier, "%s_%s.bin", MARQUEUR_FICHIER_SP8DC, systeme.modules_physiques[i].soft_version);
// SDIR #137 :
// if (strcmp(dir->d_name, nom_fichier) > 0) // Si le fichier dans CURRRENT est plus récent que le firmware en cours d'exécution, le fichier va être chargé
if (((systeme.mode_maj_firmwares == MODE_MAJ_FIRMWARES_NORMAL) && (strcmp(dir->d_name, nom_fichier) > 0)) || // Si le fichier dans CURRRENT est plus récent que le firmware en cours d'excéution (flag de MAJ des firmwares = 0 = Normal)
((systeme.mode_maj_firmwares == MODE_MAJ_FIRMWARES_SI_DIFFERENTS) && (strcmp(dir->d_name, nom_fichier) != 0)) || // ... OU si le fichier est juste différent mais le flag de MAJ des firmwares est à 1
(systeme.mode_maj_firmwares == MODE_MAJ_FIRMWARES_TOUJOURS) ) // ... OU le flag de MAJ des firmwares est à 2
// Fin de SDIR #137
{
if ((chargement_code.sequenceur.etat == ETAT_SEQUENCEUR_CHARGEMENT_CODE_REPOS) ||
(chargement_code.sequenceur.etat == ETAT_SEQUENCEUR_CHARGEMENT_CODE_LANCEMENT))
{
strcpy(chargement_code.nom_fichier[i], dir->d_name); // Stockage du nom de fichier à utiliser pour le chargement de code
chargement_code.sequenceur.etat = ETAT_SEQUENCEUR_CHARGEMENT_CODE_LANCEMENT;
sprintf(tmp, "Le fichier SP8DC [%s] trouvé dans le répertoire CURRENT est postérieur à la version en cours d'exécution sur la carte n° %i [%s]. Le fichier va être chargé sur le SP8DC", dir->d_name, i, systeme.modules_physiques[i].soft_version);
affichage_debug(__FILE__, __LINE__, tmp, TYPE_MESSAGE_DEBUG_WARNING);
}
else
{
sprintf(tmp, "Le fichier SP8DC [%s] trouvé dans le répertoire CURRENT est postérieur à la version en cours d'exécution sur la carte n° %i [%s]. Mais le séquenceur de chargement de code est occupé (état = %i) et le code ne peut donc pas être chargé sur le SP8DC.", dir->d_name, i, systeme.modules_physiques[0].soft_version, chargement_code.sequenceur.etat);
affichage_debug(__FILE__, __LINE__, tmp, TYPE_MESSAGE_DEBUG_ERREUR);
}
}
}
}
}
closedir(repertoire); // Fermeture du répertoire
}
}
else ; // Si la lecture du fichier de version n'a pas pu être faite, on ne fait rien...
}
//==================================================================================================================================================================
// Fonction : Activé par la fonction 'check_mise_a_jour()' si un fichier présent dans CURRENT doit être chargé dans 1 ou plusieurs modules sur K-Bus.
// Dans ce cas, le séquenceur prend en charge pour toutes les cartes sur K-Bus concerné les phases de :
// - effacement de la flash,
// - chargement du fichier en gérant les multi-blocs
// - calcul du CRC du fichier et celui sur la cible
// - lancement procédure de reset lorsque tous les modules devant être chargés l'ont été.
// Reçoit : Rien
// Renvoit : Rien
//==================================================================================================================================================================
void gestion_chargement_code(void)
{
FILE * ptr_fic;
uint8_t llsb, lsb, msb, mmsb;
uint16_t i;
// char commande[MAX_TAILLE_COMMANDE_SHELL];
char tmp[MAX_LONGUEUR_BUFFER_TEMPORAIRE_DEBUG];
switch(chargement_code.sequenceur.etat)
{
//-----------------------------------------------------------------------------------------------------------------------------------------
case ETAT_SEQUENCEUR_CHARGEMENT_CODE_INIT :
{
if (chargement_code.sequenceur.compteur == 0)
{
chargement_code.sequenceur.etat = ETAT_SEQUENCEUR_CHARGEMENT_CODE_REPOS;
}
break;
}
//-----------------------------------------------------------------------------------------------------------------------------------------
case ETAT_SEQUENCEUR_CHARGEMENT_CODE_REPOS :
{
break;
}
//-----------------------------------------------------------------------------------------------------------------------------------------
case ETAT_SEQUENCEUR_CHARGEMENT_CODE_LANCEMENT :
{
chargement_code.nb_repetitions = 0;
sprintf(tmp, "-1;0"); // Paramètres = 'no_module';'avancement_en_%' (no_module: -1=démarrage, 0-N=No_module en cours, -2=fin)
chargement_code.id_message_user = enregistrement_message_users(MESSAGE_USERS_CODE_MAJ_EN_COURS, tmp, MESSAGE_USERS_ETAT_ALERTE);
chargement_code.sequenceur.etat = ETAT_SEQUENCEUR_CHARGEMENT_CODE_LANCEMENT_CARTE;
break;
}
//-----------------------------------------------------------------------------------------------------------------------------------------
case ETAT_SEQUENCEUR_CHARGEMENT_CODE_LANCEMENT_CARTE :
{
// Recherche de la prochaine carte à charger :
for (i = 0; i < MAX_NOMBRE_MODULES; i ++)
{
if (systeme.modules_physiques[i].flag_presence == FALSE) continue; // On ne taite que les cartes présentes
// sprintf(tmp, "\tNom de fichier pour la carte %i = %s", i, chargement_code.nom_fichier[i]);
// affichage_debug(__FILE__, __LINE__, tmp, TYPE_MESSAGE_DEBUG_PAR_DEFAUT);
if (chargement_code.nom_fichier[i][0] != 0) // Si le nom de fichier est nul, c'est qu'il n'y a rien à charger pour cette carte
{
chargement_code.adresse_module = i; // Dès qu'on trouve une carte à charger, on mémorise son numéro ...
break; // ... et on passe au chargement proprement dit
}
}
if (i == MAX_NOMBRE_MODULES)
{
#ifdef __DEBUG_SYSTEME_CHARGEMENT_CODE
sprintf(tmp, "Plus aucune carte n'a besoin d'un chargement");
affichage_debug(__FILE__, __LINE__, tmp, TYPE_MESSAGE_DEBUG_PAR_DEFAUT);
#endif
chargement_code.sequenceur.etat = ETAT_SEQUENCEUR_CHARGEMENT_CODE_FIN_CHARGEMENT;
break;
}
// Ouverture du fichier pour extraire les informations générales :
sprintf(tmp, "%s/%s", REPERTOIRE_VERSIONS_CURRENT, chargement_code.nom_fichier[chargement_code.adresse_module]);
ptr_fic = fopen(tmp, "rb"); // Ouverture du fichier en "lecture"...
if (ptr_fic == NULL) // Si l'ouverture du fichier est impossible :
{
sprintf(tmp, "L'ouverture du fichier à charger '%s' n'est pas possible. Le chargement du code est abandonné...", chargement_code.nom_fichier[chargement_code.adresse_module]);
affichage_debug(__FILE__, __LINE__, tmp, TYPE_MESSAGE_DEBUG_ERREUR);
enregistrement_historique(TYPE_SOURCE_HISTORIQUE_SYSTEME, SYSTEME_CHARGEMENT_CODE_DEBUT_NOK, chargement_code.adresse_module, 0, chargement_code.nom_fichier[chargement_code.adresse_module]);
chargement_code.sequenceur.etat = ETAT_SEQUENCEUR_CHARGEMENT_CODE_ERREUR;
break;
}
// Préparation du chargement de code :
fseek (ptr_fic, 0, SEEK_END); // Place le curseur à la fin du fichier
chargement_code.taille_fichier = ftell(ptr_fic); // Lit la position du curseur, donc la taille...
fseek (ptr_fic, -4, SEEK_END); // Place le curseur à 4 octets de la fin du fichier
llsb = (uint8_t)fgetc(ptr_fic);
lsb = (uint8_t)fgetc(ptr_fic);
msb = (uint8_t)fgetc(ptr_fic);
mmsb = (uint8_t)fgetc(ptr_fic);
chargement_code.crc_fichier = (uint32_t)(mmsb << 24) | (uint32_t)(msb << 16) | (uint32_t)(lsb << 8) | (uint32_t)llsb;
#ifdef __DEBUG_SYSTEME_CHARGEMENT_CODE
sprintf(tmp, "Fichier à charger : [%s] - %i octets - CRC = %08Xh", chargement_code.nom_fichier[chargement_code.adresse_module], chargement_code.taille_fichier, chargement_code.crc_fichier);
affichage_debug(__FILE__, __LINE__, tmp, TYPE_MESSAGE_DEBUG_PAR_DEFAUT);
#endif
chargement_code.no_bloc = 0;
chargement_code.nb_transmis = 0;
fclose(ptr_fic); // Fermeture du fichier
#ifdef __DEBUG_SYSTEME_CHARGEMENT_CODE
sprintf(tmp, "Envoi de la commande d'effacement de la flash sur carte n° %i", chargement_code.adresse_module);
affichage_debug(__FILE__, __LINE__, tmp, TYPE_MESSAGE_DEBUG_PAR_DEFAUT);
#endif
// Mise à jour du message User pour l'informer de l'avancement :
sprintf(tmp, "%i;0", chargement_code.adresse_module); // Paramètres = 'no_module';'avancement_en_%' (no_module: -1=démarrage, 0-N=No_module en cours, -2=fin)
maj_message_users(chargement_code.id_message_user, tmp, MESSAGE_USERS_ETAT_ALERTE);
enregistrement_historique(TYPE_SOURCE_HISTORIQUE_SYSTEME, SYSTEME_CHARGEMENT_CODE_DEBUT_OK, chargement_code.adresse_module, 0, chargement_code.nom_fichier[chargement_code.adresse_module]);
c_bus_down_commande_chargement_code(CHARGEMENT_CODE_MODE_EFFACEMENT_FLASH, chargement_code.adresse_module); // Commande d'effacement de la flash
chargement_code.sequenceur.compteur = CHARGEMENT_CODE_TEMPO_ATTENTE_EFFACEMENT_FLASH; // De l'ordre de 2-3 secondes
chargement_code.sequenceur.etat = ETAT_SEQUENCEUR_CHARGEMENT_CODE_EFFACEMENT_FLASH;
break;
}
//-----------------------------------------------------------------------------------------------------------------------------------------
case ETAT_SEQUENCEUR_CHARGEMENT_CODE_EFFACEMENT_FLASH :
{
if (chargement_code.sequenceur.compteur == 0)
{
if (chargement_code.status_reponse == 0)
{
c_bus_down_commande_chargement_code(CHARGEMENT_CODE_MODE_CHARGEMENT_BLOC, chargement_code.adresse_module); // Envoi du prochain bloc
#ifdef __DEBUG_SYSTEME_CHARGEMENT_CODE
sprintf(tmp, "\tChargement bloc n° %3i Ok (taille bloc = %3i octets, taille totale = %7i octets, soit %i%%)", chargement_code.no_bloc, chargement_code.taille_bloc, chargement_code.nb_transmis, ((chargement_code.nb_transmis * 100) / chargement_code.taille_fichier));
affichage_debug(__FILE__, __LINE__, tmp, TYPE_MESSAGE_DEBUG_PAR_DEFAUT);
#endif
chargement_code.sequenceur.compteur_time_out = CHARGEMENT_CODE_TIME_OUT_ATTENTE_ECRITURE_BLOC;
chargement_code.sequenceur.etat = ETAT_SEQUENCEUR_CHARGEMENT_CODE_CHARGEMENT_BLOC;
}
else
{
sprintf(tmp, "Retour d'effacement de flash en erreur sur la carte n° %i (erreur [%i])", chargement_code.adresse_module, chargement_code.status_reponse);
affichage_debug(__FILE__, __LINE__, tmp, TYPE_MESSAGE_DEBUG_ERREUR);
enregistrement_historique(TYPE_SOURCE_HISTORIQUE_SYSTEME, SYSTEME_CHARGEMENT_CODE_ERASE_FLASH_NOK, chargement_code.adresse_module, 0, chargement_code.nom_fichier[chargement_code.adresse_module]);
chargement_code.sequenceur.etat = ETAT_SEQUENCEUR_CHARGEMENT_CODE_ERREUR;
}
}
break;
}
//-----------------------------------------------------------------------------------------------------------------------------------------
case ETAT_SEQUENCEUR_CHARGEMENT_CODE_CHARGEMENT_BLOC :
{
if (chargement_code.sequenceur.compteur_time_out == 0)
{
sprintf(tmp, "Déclenchement de time-out lors du chargement du bloc n° %i sur la carte n° %i", chargement_code.no_bloc, chargement_code.adresse_module);
affichage_debug(__FILE__, __LINE__, tmp, TYPE_MESSAGE_DEBUG_ERREUR);
enregistrement_historique(TYPE_SOURCE_HISTORIQUE_SYSTEME, SYSTEME_CHARGEMENT_CODE_ECRITURE_FLASH_NOK, chargement_code.adresse_module, 0, chargement_code.nom_fichier[chargement_code.adresse_module]);
chargement_code.sequenceur.etat = ETAT_SEQUENCEUR_CHARGEMENT_CODE_ERREUR;
}
if (chargement_code.flag_reponse == TRUE)
{
if (chargement_code.status_reponse == 0)
{
if (chargement_code.nb_transmis < chargement_code.taille_fichier) // Il reste des données à transmettre
{
chargement_code.no_bloc ++;
if (chargement_code.adresse_module == 0) chargement_code.sequenceur.compteur = CHARGEMENT_CODE_TEMPO_ATTENTE_INTER_BLOCS_COMPAGNON; // Petite attente si le chargement concerne le Compagnon...
else chargement_code.sequenceur.compteur = CHARGEMENT_CODE_TEMPO_ATTENTE_INTER_BLOCS_K_BUS; // ... mais attente plus importante s'il est destiné à une carte sur K-Bus (cette tempo permet au Compagnon d'écouler sur K-Bus les commandes consécutives)
chargement_code.sequenceur.etat = ETAT_SEQUENCEUR_CHARGEMENT_CODE_ATTENTE_INTER_BLOCS;
}
else
{
#ifdef __DEBUG_SYSTEME_CHARGEMENT_CODE
sprintf(tmp, "Demande de vérification du CRC sur la carte n° %i", chargement_code.adresse_module);
affichage_debug(__FILE__, __LINE__, tmp, TYPE_MESSAGE_DEBUG_PAR_DEFAUT);
#endif
c_bus_down_commande_chargement_code(CHARGEMENT_CODE_MODE_CHECK_CRC, chargement_code.adresse_module); // Demande de vérification du CRC
chargement_code.sequenceur.compteur_time_out = CHARGEMENT_CODE_TIME_OUT_ATTENTE_ECRITURE_BLOC;
chargement_code.sequenceur.etat = ETAT_SEQUENCEUR_CHARGEMENT_CODE_VERIFICATION_CRC;
}
}
else
{
sprintf(tmp, "La dernière commande de chargement de code est revenue en erreur (code [%i]). Le séquenceur de chargement de code est repositionné au repos.", chargement_code.status_reponse);
affichage_debug(__FILE__, __LINE__, tmp, TYPE_MESSAGE_DEBUG_ERREUR);
enregistrement_historique(TYPE_SOURCE_HISTORIQUE_SYSTEME, SYSTEME_CHARGEMENT_CODE_ECRITURE_FLASH_NOK, chargement_code.adresse_module, 0, chargement_code.nom_fichier[chargement_code.adresse_module]);
chargement_code.sequenceur.etat = ETAT_SEQUENCEUR_CHARGEMENT_CODE_ERREUR;
}
}
break;
}
//-----------------------------------------------------------------------------------------------------------------------------------------
case ETAT_SEQUENCEUR_CHARGEMENT_CODE_ATTENTE_INTER_BLOCS :
{
if (chargement_code.sequenceur.compteur == 0)
{
c_bus_down_commande_chargement_code(CHARGEMENT_CODE_MODE_CHARGEMENT_BLOC, chargement_code.adresse_module); // Envoi du prochain bloc
#ifdef __DEBUG_SYSTEME_CHARGEMENT_CODE
sprintf(tmp, "\tChargement bloc n° %3i Ok (taille bloc = %3i octets, taille totale = %7i octets, soit %i%%)", chargement_code.no_bloc, chargement_code.taille_bloc, chargement_code.nb_transmis, ((chargement_code.nb_transmis * 100) / chargement_code.taille_fichier));
affichage_debug(__FILE__, __LINE__, tmp, TYPE_MESSAGE_DEBUG_PAR_DEFAUT);
#endif
// Mise à jour du message User pour l'informer de l'avancement :
sprintf(tmp, "%i;%i", chargement_code.adresse_module, (chargement_code.nb_transmis * 100) / chargement_code.taille_fichier); // Paramètres = 'no_module';'avancement_en_%' (no_module: -1=démarrage, 0-N=No_module en cours, -2=fin)
maj_message_users(chargement_code.id_message_user, tmp, MESSAGE_USERS_ETAT_ALERTE);
chargement_code.sequenceur.compteur_time_out = CHARGEMENT_CODE_TIME_OUT_ATTENTE_ECRITURE_BLOC;
chargement_code.sequenceur.etat = ETAT_SEQUENCEUR_CHARGEMENT_CODE_CHARGEMENT_BLOC;
}
break;
}
//-----------------------------------------------------------------------------------------------------------------------------------------
case ETAT_SEQUENCEUR_CHARGEMENT_CODE_VERIFICATION_CRC :
{
if (chargement_code.sequenceur.compteur_time_out == 0)
{
sprintf(tmp, "Déclenchement de time-out lors de la vérification du CRC sur la carte n° %i", chargement_code.adresse_module);
affichage_debug(__FILE__, __LINE__, tmp, TYPE_MESSAGE_DEBUG_ERREUR);
enregistrement_historique(TYPE_SOURCE_HISTORIQUE_SYSTEME, SYSTEME_CHARGEMENT_CODE_CRC_FLASH_NOK, chargement_code.adresse_module, 0, chargement_code.nom_fichier[chargement_code.adresse_module]);
chargement_code.sequenceur.etat = ETAT_SEQUENCEUR_CHARGEMENT_CODE_ERREUR;
}
if (chargement_code.flag_reponse == TRUE)
{
if (chargement_code.status_reponse == 0)
{
#ifdef __DEBUG_SYSTEME_CHARGEMENT_CODE
sprintf(tmp, "Le CRC de la nouvelle version de logiciel chargé sur la carte n° %i est valide", chargement_code.adresse_module);
affichage_debug(__FILE__, __LINE__, tmp, TYPE_MESSAGE_DEBUG_PAR_DEFAUT);
#endif
chargement_code.sequenceur.etat = ETAT_SEQUENCEUR_CHARGEMENT_CODE_FIN_CARTE;
}
else
{
sprintf(tmp, "Retour de vérification de CRC en erreur sur la carte n° %i. Le séquenceur de chargement est repositionné au repos. ", chargement_code.adresse_module);
affichage_debug(__FILE__, __LINE__, tmp, TYPE_MESSAGE_DEBUG_ERREUR);
enregistrement_historique(TYPE_SOURCE_HISTORIQUE_SYSTEME, SYSTEME_CHARGEMENT_CODE_ECRITURE_FLASH_NOK, chargement_code.adresse_module, 0, chargement_code.nom_fichier[chargement_code.adresse_module]);
chargement_code.sequenceur.etat = ETAT_SEQUENCEUR_CHARGEMENT_CODE_ERREUR;
}
}
break;
}
//-----------------------------------------------------------------------------------------------------------------------------------------
case ETAT_SEQUENCEUR_CHARGEMENT_CODE_FIN_CARTE :
{
for (i = (chargement_code.adresse_module + 1); i < MAX_NOMBRE_MODULES; i ++)
{
if (systeme.modules_physiques[i].flag_presence == FALSE) continue; // On ne taite que les cartes présentes
if (strcmp(chargement_code.nom_fichier[i], chargement_code.nom_fichier[chargement_code.adresse_module]) == 0) break; // Si une carte à venir doit recevoir le même fichier
}
systeme.modules_physiques[chargement_code.adresse_module].maj_soft_disponible = 1; // Mise à jour du flag de disponibilité d'une nouvelle version pour la carte
chargement_code.nom_fichier[chargement_code.adresse_module][0] = 0; // Suppression du besoin pour cette carte
#ifdef __DEBUG_SYSTEME_CHARGEMENT_CODE
sprintf(tmp, "Le chargement de la nouvelle version de logiciel pour la carte n° %i est terminé", chargement_code.adresse_module);
affichage_debug(__FILE__, __LINE__, tmp, TYPE_MESSAGE_DEBUG_PAR_DEFAUT);
#endif
chargement_code.nb_repetitions = 0;
chargement_code.sequenceur.etat = ETAT_SEQUENCEUR_CHARGEMENT_CODE_LANCEMENT_CARTE;
break;
}
//-----------------------------------------------------------------------------------------------------------------------------------------
case ETAT_SEQUENCEUR_CHARGEMENT_CODE_FIN_CHARGEMENT:
{
// RAZ de tous les noms de fichier de chargements (dans le doute) :
for (i = 0; i < MAX_NOMBRE_MODULES; i ++) chargement_code.nom_fichier[i][0] = 0;
// Activation de la nouvelle version sur toutes les cartes ayant reçu une nouvelle version de firmware :
bool flag_carte_chargee = false;
for (i = 0; i < MAX_NOMBRE_MODULES; i ++)
{
if (systeme.modules_physiques[i].flag_presence == FALSE) continue; // On ne taite que les cartes présentes
if (systeme.modules_physiques[i].maj_soft_disponible != 0)
{
flag_carte_chargee = TRUE;
c_bus_down_commande_chargement_code(CHARGEMENT_CODE_MODE_VALIDATION_VERSION, i); // Demande d'activation de la nouvelle version chargée
systeme.modules_physiques[i].maj_soft_disponible = 0; // RAZ du flag
enregistrement_historique(TYPE_SOURCE_HISTORIQUE_SYSTEME, SYSTEME_CHARGEMENT_CODE_FIN_OK, 0, 0, chargement_code.nom_fichier[i]);
sprintf(tmp, "Activation de la nouvelle version de firmware adressée à la carte n° %i", i);
affichage_debug(__FILE__, __LINE__, tmp, TYPE_MESSAGE_DEBUG_WARNING);
}
}
if (flag_carte_chargee)
{
sprintf(tmp, "Une ou plusieurs cartes ont été chargées avec une nouvelle version de firmware => réinitialisation du système pour prise en compte par leur bootloader");
affichage_debug(__FILE__, __LINE__, tmp, TYPE_MESSAGE_DEBUG_WARNING);
sprintf(tmp, "-2;0"); // Paramètres = 'id_module';'avancement_en_%' (id_module: -1=démarrage, 0-N=Id_module en cours, -2=fin)
maj_message_users(chargement_code.id_message_user, tmp, MESSAGE_USERS_ETAT_ALERTE);
chargement_code.sequenceur.compteur = CHARGEMENT_CODE_TEMPO_ATTENTE_FIN_ACTIVATION;
chargement_code.sequenceur.etat = ETAT_SEQUENCEUR_CHARGEMENT_CODE_FIN_ACTIVATION;
}
else
{
sprintf(tmp, "Aucune carte n'a été chargée avec une nouvelle version de firmware => la mise à jour est terminée");
affichage_debug(__FILE__, __LINE__, tmp, TYPE_MESSAGE_DEBUG_WARNING);
maj_message_users(chargement_code.id_message_user, "", MESSAGE_USERS_ETAT_SUPPRESSION); // Suppression du message devenu inutile
chargement_code.id_message_user = 0;
chargement_code.sequenceur.etat = ETAT_SEQUENCEUR_CHARGEMENT_CODE_REPOS; // Probablement inutile
}
break;
}
//-----------------------------------------------------------------------------------------------------------------------------------------
case ETAT_SEQUENCEUR_CHARGEMENT_CODE_FIN_ACTIVATION:
{
if (chargement_code.sequenceur.compteur == 0)
{
maj_message_users(chargement_code.id_message_user, "", MESSAGE_USERS_ETAT_SUPPRESSION); // Suppression du message juste avant la réinit...
chargement_code.id_message_user = 0;
lancement_reinit(0); // La valeur 0 indique d'utiliser la valeur par défaut
chargement_code.sequenceur.etat = ETAT_SEQUENCEUR_CHARGEMENT_CODE_REPOS; // Probablement inutile
}
break;
}
//-----------------------------------------------------------------------------------------------------------------------------------------
case ETAT_SEQUENCEUR_CHARGEMENT_CODE_ERREUR:
{
if ((++ chargement_code.nb_repetitions) >= MAX_REPETITIONS_CHARGEMENT_CODE)
{
sprintf(tmp, "Le nombre de répétitions maximal a été atteint (%i). Le chargement de code est abandonné.", MAX_REPETITIONS_CHARGEMENT_CODE);
affichage_debug(__FILE__, __LINE__, tmp, TYPE_MESSAGE_DEBUG_ERREUR);
enregistrement_historique(TYPE_SOURCE_HISTORIQUE_SYSTEME, SYSTEME_CHARGEMENT_CODE_FIN_NOK, chargement_code.adresse_module, 0, chargement_code.nom_fichier[chargement_code.adresse_module]);
maj_message_users(chargement_code.id_message_user, "", MESSAGE_USERS_ETAT_SUPPRESSION); // Suppression du message de mise à jour
chargement_code.id_message_user = 0;
chargement_code.sequenceur.etat = ETAT_SEQUENCEUR_CHARGEMENT_CODE_REPOS;
}
else
{
sprintf(tmp, "Le chargement de code est relancé pour le %i ème fois sur cette carte", chargement_code.nb_repetitions);
affichage_debug(__FILE__, __LINE__, tmp, TYPE_MESSAGE_DEBUG_WARNING);
chargement_code.sequenceur.etat = ETAT_SEQUENCEUR_CHARGEMENT_CODE_LANCEMENT_CARTE;
}
break;
}
//-----------------------------------------------------------------------------------------------------------------------------------------
default :
{
sprintf(tmp, "L'état du séquenceur de Chargement de Code est inconnu [%i]. Il est repositionné au REPOS", chargement_code.sequenceur.etat);
affichage_debug(__FILE__, __LINE__, tmp, TYPE_MESSAGE_DEBUG_ERREUR);
chargement_code.sequenceur.etat = ETAT_SEQUENCEUR_CHARGEMENT_CODE_REPOS;
break;
}
}
}
//==================================================================================================================================================================
// Fonction : Fonction appelée à la fin de chaque boucle principale. Elle commence par faire une courte attente pour éviter que l'application de consomme 100%
// de temps CPU !
// Reçoit : Rien
// Renvoit : Rien
//==================================================================================================================================================================
void supervision(void)
{
struct timespec gettime_now;
// Attente pour ralentir la boucle principale :
delai_nano_sec(SYSTEME_ATTENTE_BOUCLE_PRINCIPALE_TEMPO);
// Supervision de la vitesse de boucle principale :
clock_gettime(CLOCK_REALTIME, &gettime_now);
if (supervision_boucle_principale.last_second == gettime_now.tv_sec) supervision_boucle_principale.nb_en_cours ++;
else
{
supervision_boucle_principale.last_second = gettime_now.tv_sec;
if (supervision_boucle_principale.attente_premieres_mesures == 0) // Si on n'est plus dans la phase d'attente initiale :
{
supervision_boucle_principale.nb_boucles += supervision_boucle_principale.nb_en_cours;
supervision_boucle_principale.nb_secondes ++;
//printf("Compteur de boucles principales = %i\n", supervision_boucle_principale.nb_en_cours);
}
else supervision_boucle_principale.attente_premieres_mesures --; // En phase d'attente initiale, on décrémente le compteur d'attente...
supervision_boucle_principale.nb_en_cours = 0;
}
}
//==================================================================================================================================================================
// Fonction : Fonction appelée suite à la sortie de la boucle principale (suite à réception d'un signal d'arrêt - de la part d'un utilisateur ou par une erreur
// majeure). Elle enregistre l'arrêt dans le fichier de log et l'historique (autant que possbible). Puis elle libère au maximum les ressources matérielles
// utilisées par l'application.
// Reçoit : Rien
// Renvoit : Rien
//==================================================================================================================================================================
void arret_programme(void)
{
char tmp[MAX_LONGUEUR_BUFFER_TEMPORAIRE_DEBUG];
// Enregistrement dans le fichier de debug :
sprintf(tmp, "Arrêt du programme demandé. Fermeture en cours...");
affichage_debug(__FILE__, __LINE__, tmp, TYPE_MESSAGE_DEBUG_WARNING);
// Enregistrement dans l'historique :
enregistrement_historique(TYPE_SOURCE_HISTORIQUE_SYSTEME, SYSTEME_ARRET, 0, 0, NULL);
// Info au Compagnon et MAJ dans la BDD avant fermeture :
maj_etat_cm3p(OFF); // Maj du flag, de la BDD et de la sortie physique
//Fermeture de MySQL :
mysql_close(bdd.pointeur);
// Désactivation des sorties de commandes d'alimentations :
// ecriture_sortie(TYPE_SORTIE_GPIO, 0, CM3P_DO_USBPWR_EN, OFF); // Coupure de l'alim des USB /!\ Il ne faut PAS couper en mode debuug ous peine de ne plus avoir accès au réseau Ethernet via le routeur USB/Ethernet....!
// ecriture_sortie(TYPE_SORTIE_GPIO, 0, audio.cle_primaire_sortie_cm_do_audio_sd, OFF); // Coupure du circuit audio
// ecriture_sortie(TYPE_SORTIE_GPIO, 0, ecran.cle_primaire_sortie_cm_pdown_hdmi_cmd_n, OFF); // Coupure de la sortie du flux HDMI
// ecriture_sortie(TYPE_SORTIE_GPIO, 0, ecran.cle_primaire_sortie_cm_do_lcd_en_vgx, OFF); // Coupure de l'alim VGx
// ecriture_sortie(TYPE_SORTIE_GPIO, 0, ecran.cle_primaire_sortie_cm_do_lcd_en_vdd, OFF); // Coupure de l'alim VDD (après VGx !)
// Libération des ports série :
if ((config_serial0.validite == 1) && (config_serial0.filestream != -1)) close(config_serial0.filestream);
if ((config_serial1.validite == 1) && (config_serial1.filestream != -1)) close(config_serial1.filestream);
// Libération des projections dans l'espace virtuel d'adressage (normalement fait automatiquement à la fermeture du processus mais on ne sait jamais...) :
munmap((uint32_t *)hardware.gpio_base, BLOCK_SIZE);
}
//==================================================================================================================================================================
// Fonction : Fonction générant toutes les commandes lorsqu'une mise à jour de la confguration est nécessaire.
// Elle est notamment appelée lorsqu'une modif de configuration a été faite dans la BDD ou que le K-Bus a été réinitialisé
// Reçoit : Rien
// Renvoit : 0 si aucune erreur, -1 si une erreur a été détectée
//==================================================================================================================================================================
int8_t re_configuration_systeme(void)
{
// Forçage d'un enregistrement des mesures avant la reconfiguration (qui va RAZ tous les cumuls) (SDIR #174) :
bdd.compteur_enregistrement_mesures = 0;
enregistrement_mesures(BDD_ENREGISTREMENT_MESURE_NORMAL); // NB : le timer de mesure est rechargé à l'occasion avec la période normale
// Rechargement (presque) complet de la BDD :
init_bdd(BDD_MODE_INIT_RELOAD); // Appelle 'maj_etat_cm3p()' puis réinitialise les fonctions CARTES et CIRCUITS.
// Relance du séquenceur d'init :
systeme.sequenceur.etat = ETAT_SEQUENCEUR_SYSTEME_INIT; // On relance le séquenceur au départ pour effectuer une configuration complète de l'application en fonction du résultat de la reconnaissance réseau faite par le Compagnon sur K-Bus
systeme.sequenceur.compteur = 0; // Pas la peine d'attendre...
// Mise à jour des fonctions audio :
set_volume(audio.consigne_volume, AUDIO_SET_VOLUME_ECHO_OFF); // Mise à jour du volume au niveau matériel. NB : l'alimentation de l'ampli est faite en fin de 'set_volume()' et tient compte de l'état de 'Fonction_jack'
// Commandes spécifiques Compagnon :
c_bus_down_commande_config_level_sensors(); // Utile dans la cas où la configuration des Level Sensors aurait changé (par exempe de via QT et la BDD)
return(0);
}
//==================================================================================================================================================================
// Fonction : Lance l'exécution de la commande reçue en paramètre et vérifie son exécution.
// Reçoit : La chaine de la commande
// Renvoit : 0 si aucune erreur, -1 si une erreur a été détectée
//==================================================================================================================================================================
int32_t commande_shell(char * commande)
{
int32_t retour;
char tmp[MAX_LONGUEUR_BUFFER_TEMPORAIRE_DEBUG];
retour = system(commande);
if (retour != 0)
{
sprintf(tmp, "Le retour de la commande shell [%s] est en erreur (code = %i)", commande, retour);
affichage_debug(__FILE__, __LINE__, tmp, TYPE_MESSAGE_DEBUG_ERREUR);
}
/* else
{
sprintf(tmp, "La commande shell [%s] a été lancée sans erreur.", commande);
affichage_debug(__FILE__, __LINE__, tmp, TYPE_MESSAGE_DEBUG_PAR_DEFAUT);
}
*/
return (retour);
}
//==================================================================================================================================================================
// Fonction : Lit le fichier dont le nom est reçu en paramètre et récupère les champs d'un fichier de version.
// Reçoit : Le nom du fichier JSON à parser + un flag de verbose
// Renvoit : Une structure contenant les champs d'un fichier de version. NB : si erreur, le champ 'no_version' contient la chaine "ERREUR"
//==================================================================================================================================================================
struct Struct_json_version parse_json_version(char * nom_fichier, bool verbose)
{
FILE *fp;
char buffer[MAX_TAILLE_FICHIER_JSON];
struct json_object *parsed_json;
struct json_object *obj_no_version;
struct json_object *obj_updater;
struct json_object *obj_application;
struct json_object *obj_qt;
struct json_object *obj_compagnon;
struct json_object *obj_sp812;
struct json_object *obj_sbs;
struct json_object *obj_sp4ac;
struct json_object *obj_sp8dc;
struct json_object *obj_sql;
struct json_object *obj_force;
struct json_object *obj_description;
struct Struct_json_version json_version;
char tmp[MAX_LONGUEUR_BUFFER_TEMPORAIRE_DEBUG];
fp = fopen(nom_fichier,"r");
if (fp == NULL)
{
sprintf(tmp, "Erreur d'ouverture du fichier [%s]\n", nom_fichier);
affichage_debug(__FILE__, __LINE__, tmp, TYPE_MESSAGE_DEBUG_ERREUR);
strcpy(json_version.no_version, "ERREUR"); // Marqueur d'erreur
return (json_version);
}
fread(&buffer, 1, MAX_TAILLE_FICHIER_JSON, fp); // Lecture du fichier dans Buffer.
fclose(fp);
parsed_json = json_tokener_parse(buffer);
if (parsed_json == NULL)
{
sprintf(tmp, "Erreur de parse du fichier [%s].\n", nom_fichier);
affichage_debug(__FILE__, __LINE__, tmp, TYPE_MESSAGE_DEBUG_ERREUR);
strcpy(json_version.no_version, "ERREUR"); // Marqueur d'erreur
return (json_version);
}
json_object_object_get_ex(parsed_json, "NoVersion", &obj_no_version);
json_object_object_get_ex(parsed_json, "Updater", &obj_updater);
json_object_object_get_ex(parsed_json, "Application", &obj_application);
json_object_object_get_ex(parsed_json, "QT", &obj_qt);
if (systeme.generation_shipbase == GENERATION_SHIPBASE_V1) json_object_object_get_ex(parsed_json, "Compagnon_v1", &obj_compagnon);
else json_object_object_get_ex(parsed_json, "Compagnon_v2", &obj_compagnon);
json_object_object_get_ex(parsed_json, "SP812", &obj_sp812);
json_object_object_get_ex(parsed_json, "SBS", &obj_sbs);
json_object_object_get_ex(parsed_json, "SP4AC", &obj_sp4ac);
json_object_object_get_ex(parsed_json, "SP8DC", &obj_sp8dc);
json_object_object_get_ex(parsed_json, "SQL", &obj_sql);
json_object_object_get_ex(parsed_json, "Force", &obj_force);
json_object_object_get_ex(parsed_json, "Description", &obj_description);
if (obj_no_version != NULL) strcpy(json_version.no_version, json_object_get_string(obj_no_version));
else strcpy(json_version.no_version, "...inconnue...");
if (obj_updater != NULL) strcpy(json_version.updater, json_object_get_string(obj_updater));
else strcpy(json_version.updater, "...inconnue...");
if (obj_application != NULL) strcpy(json_version.application, json_object_get_string(obj_application));
else strcpy(json_version.application, "...inconnue...");
if (obj_qt != NULL) strcpy(json_version.qt, json_object_get_string(obj_qt));
else strcpy(json_version.qt, "...inconnue...");
if (obj_compagnon != NULL) strcpy(json_version.compagnon, json_object_get_string(obj_compagnon));
else strcpy(json_version.compagnon, "...inconnue...");
if (obj_sp812 != NULL) strcpy(json_version.sp812, json_object_get_string(obj_sp812));
else strcpy(json_version.sp812, "...inconnue...");
if (obj_sbs != NULL) strcpy(json_version.sbs, json_object_get_string(obj_sbs));
else strcpy(json_version.sbs, "...inconnue...");
if (obj_sp4ac != NULL) strcpy(json_version.sp4ac, json_object_get_string(obj_sp4ac));
else strcpy(json_version.sp4ac, "...inconnue...");
if (obj_sp8dc != NULL) strcpy(json_version.sp8dc, json_object_get_string(obj_sp8dc));
else strcpy(json_version.sp8dc, "...inconnue...");
if (obj_sql != NULL) strcpy(json_version.sql, json_object_get_string(obj_sql));
else strcpy(json_version.sql, "...inconnue...");
if (obj_force != NULL) json_version.force = json_object_get_boolean(obj_force);
else json_version.force = FALSE;
if (obj_description != NULL) strcpy(json_version.description, json_object_get_string(obj_description));
else strcpy(json_version.description, "...inconnue...");
if (verbose)
{
printf("Fichier de version\t\t: [%s]\n", nom_fichier);
printf("\tNo de version\t\t: [%s]\n", json_version.no_version);
printf("\tUpdater\t\t\t: [%s]\n", json_version.updater);
printf("\tApplication\t\t: [%s]\n", json_version.application);
printf("\tQT\t\t\t: [%s]\n", json_version.qt);
printf("\tCompagnon\t\t: [%s]\n", json_version.compagnon);
printf("\tSP812\t\t\t: [%s]\n", json_version.sp812);
printf("\tSBS\t\t\t: [%s]\n", json_version.sbs);
printf("\tSP4AC\t\t\t: [%s]\n", json_version.sp4ac);
printf("\tSP8DC\t\t\t: [%s]\n", json_version.sp8dc);
printf("\tSQL\t\t\t: [%s]\n", json_version.sql);
printf("\tFlag force\t\t: [%s]\n", json_version.force ? "true" : "false");
printf("\tDescription\t\t: [%s]\n", json_version.description);
printf("\n");
}
return(json_version);
}
//==================================================================================================================================================================
// Fonction : Envoi le signal reçu au PID reçu (NB : àa peut être SIGKILL ou SIGTERM pour tuer le processus mais ça peut aussi être SIGHUP pour lui demander
// de recharger sa config (comme 'hostapd' par exemple).
// Reçoit : Le PID du processus à qui envoyer le signal et le signal à envoyer
// Renvoit : -1 si erreur, >=0 si Ok (si >0, cela doit représenter le nombre de processus à qui le signel a été envoyé - utilisable si PID est < 0. Pas testé...)
//==================================================================================================================================================================
int8_t send_signal (int32_t pid, int32_t signal)
{
int32_t ret;
ret = kill(pid, signal);
// printf("ret : %d",ret);
if ((ret < 0) || (ret > 127)) return(-1); // Ret contient -1 si erreur ou >=0 si Ok
else return(ret);
}
//==================================================================================================================================================================
// Fonction : Recherche le PID du processus dont le nom est passé en paramètre
// de recharger sa config (comme 'hostapd' par exemple).
// Reçoit : Le nom du processus à rechercher, les paramètres éventuels à rechercher
// Renvoit : -1 si erreur, >0=PID du processus trouvé
//==================================================================================================================================================================
int32_t get_pid_from_name (char * nom, char * parametres)
{
#define MAX_LONGUEUR_NOM_PROCESSUS 50
#define MAX_LONGUEUR_PARAMETRES_PROCESSUS 200
#define MAX_BUFFER 1500
char buf[MAX_BUFFER];
char cde[MAX_LONGUEUR_NOM_PROCESSUS + MAX_LONGUEUR_PARAMETRES_PROCESSUS + 50];
if (strlen(nom) > MAX_LONGUEUR_NOM_PROCESSUS) return(-1);
if (strlen(parametres) > MAX_LONGUEUR_PARAMETRES_PROCESSUS) return(-1);
// sprintf(cde, "pidof -s %s", nom);
sprintf(cde, "pgrep -f '%s.*%s' ", nom, parametres); // Le '.' indique n'importe quel caractère et le '*' s'applique au '.' pou rindiquer "peu importe ne nombre".
// char tmp[MAX_LONGUEUR_BUFFER_TEMPORAIRE_DEBUG];
// sprintf(tmp, "\tCommande de 'get_pid_from_name' = [ %s ]", cde);
// affichage_debug(__FILE__, __LINE__, tmp, TYPE_MESSAGE_DEBUG_WARNING);
FILE *cmd_pipe = popen(cde, "r");
fgets(buf, MAX_BUFFER, cmd_pipe);
int32_t pid = strtoul(buf, NULL, 10);
pclose(cmd_pipe);
return(pid);
}
//==================================================================================================================================================================
// Fonction : Recherche le nombre de PID actifs dont le nom est passé en paramètre
// Reçoit : Le nom du processus à rechercher, les paramètres éventuels à rechercher
// Renvoit : -1 si erreur, >0=nombre de PID incluant le nom recherché
//==================================================================================================================================================================
int32_t get_pid_numbers_from_name (char * nom, char * parametres)
{
#define MAX_LONGUEUR_NOM_PROCESSUS 50
#define MAX_LONGUEUR_PARAMETRES_PROCESSUS 200
#define MAX_BUFFER 1500
char buf[MAX_BUFFER];
char cde[MAX_LONGUEUR_NOM_PROCESSUS + MAX_LONGUEUR_PARAMETRES_PROCESSUS + 50];
if (strlen(nom) > MAX_LONGUEUR_NOM_PROCESSUS) return(-1);
if (strlen(parametres) > MAX_LONGUEUR_PARAMETRES_PROCESSUS) return(-1);
sprintf(cde, "ps aux | grep %s | grep ' %s' | grep -cv grep", nom, parametres); // Le '-c' permet d'obtenir uniquement le nombre d'occurences, le '-v' permet d'éliminer les lignes contenant GREP.
FILE *cmd_pipe = popen(cde, "r");
fgets(buf, MAX_BUFFER, cmd_pipe);
int32_t pid_nb = strtoul(buf, NULL, 10);
pclose(cmd_pipe);
return(pid_nb);
}
//==================================================================================================================================================================
// Fonction : Recherche la révision du module sur lequel on est en cours d'exécution et en déduit le type et la version de module.
// Cf https://www.raspberrypi.com/documentation/computers/raspberry-pi.html#new-style-revision-codes pour plus de précisions (ou des updates...)
// Reçoit : Rien
// Renvoit : 0 si aucune erreur, -1 si une erreur a été détectée
//==================================================================================================================================================================
int8_t version_compute_module(void)
{
FILE *fp;
char revcode[32];
uint32_t code;
char chaine_valeur[300];
char tmp[MAX_LONGUEUR_BUFFER_TEMPORAIRE_DEBUG];
fp = popen("cat /proc/cpuinfo | awk '/Revision/ {print $3}'", "r"); // récupération du code de Révision via la commande "cat /proc/cpuinfo | awk '/Revision/ {print $3}'". Exemple de retour : "c03141"
if (fp == NULL) return(-1); // Cas où la commande n'a pas pu être exécutée correctement
fgets(revcode, sizeof(revcode), fp); // Lecture de la ligne
pclose(fp); // Fermeturre du fichier
code = strtol(revcode, NULL, 16); // Conversion en entier long depuis la chaine en hexa
systeme.cm.overvoltage_allowed = (code >> 31) & 0x1;
systeme.cm.otp_programming_allowed = (code >> 30) & 0x1;
systeme.cm.otp_reading_allowed = (code >> 29) & 0x1;
systeme.cm.warranty_bit = (code >> 25) & 0x1;
systeme.cm.new_style_revision = (code >> 23) & 0x1;
systeme.cm.memory_size = (code >> 20) & 0x7;
systeme.cm.manufacturer = (code >> 16) & 0x0F;
systeme.cm.processor = (code >> 12) & 0x0F;
systeme.cm.type = (code >> 4) & 0xFF;
systeme.cm.revision = (code >> 0) & 0x0F;
if (systeme.cm.new_style_revision == 0) // Ce bit indique le format du code de révision. Le 'new' type est actif depuis le RaspberryPi2 donc on devrait toujours être dans ce cas...
{
sprintf(tmp, "/!\\ Le bit de style de révision indique un ancien style de révision qui ne peut pas être lu...!");
affichage_debug(__FILE__, __LINE__, tmp, TYPE_MESSAGE_DEBUG_ERREUR);
return (-1);
}
else
{
systeme.cm.chaine_version[0] = 0; // Chaine vide.
sprintf(tmp, "Caractéristiques du module :");
//---------------------------------------------------------------
switch (systeme.cm.type)
{
case 0x00 : { strcpy(chaine_valeur, "A"); break; }
case 0x01 : { strcpy(chaine_valeur, "B"); break; }
case 0x02 : { strcpy(chaine_valeur, "A+"); break; }
case 0x03 : { strcpy(chaine_valeur, "B+"); break; }
case 0x04 : { strcpy(chaine_valeur, "2B"); break; }
case 0x05 : { strcpy(chaine_valeur, "Alpha"); break; }
case 0x06 : { strcpy(chaine_valeur, "CM1"); break; }
case 0x08 : { strcpy(chaine_valeur, "3B"); break; }
case 0x09 : { strcpy(chaine_valeur, "Zero"); break; }
case 0x0A : { strcpy(chaine_valeur, "CM3"); break; }
case 0x0C : { strcpy(chaine_valeur, "Zero W"); break; }
case 0x0D : { strcpy(chaine_valeur, "3B+"); break; }
case 0x0E : { strcpy(chaine_valeur, "3A+"); break; }
case 0x0F : { strcpy(chaine_valeur, "Internal Use only"); break; }
case 0x10 : { strcpy(chaine_valeur, "CM3+"); break; }
case 0x11 : { strcpy(chaine_valeur, "4B"); break; }
case 0x12 : { strcpy(chaine_valeur, "Zero 2W"); break; }
case 0x13 : { strcpy(chaine_valeur, "400"); break; }
case 0x14 : { strcpy(chaine_valeur, "CM4"); break; }
case 0x15 : { strcpy(chaine_valeur, "CM4S"); break; }
case 0x18 : { strcpy(chaine_valeur, "CM5"); break; }
case 0x07 :
case 0x0B :
default :
{
sprintf(chaine_valeur, "Inconnu [code = %i]", systeme.cm.type);
break;
}
}
affichage_ligne_version_compute_module(tmp, "Type de module", chaine_valeur);
strcat(systeme.cm.chaine_version, chaine_valeur);
//---------------------------------------------------------------
switch (systeme.cm.memory_size)
{
case 0 : { strcpy(chaine_valeur, "256Mo"); break; }
case 1 : { strcpy(chaine_valeur, "512Mo"); break; }
case 2 : { strcpy(chaine_valeur, "1Go"); break; }
case 3 : { strcpy(chaine_valeur, "2Go"); break; }
case 4 : { strcpy(chaine_valeur, "4Go"); break; }
case 5 : { strcpy(chaine_valeur, "8Go"); break; }
default :
{
sprintf(chaine_valeur, "Inconnue [code = %i]", systeme.cm.memory_size);
break;
}
}
affichage_ligne_version_compute_module(tmp, "Taille RAM", chaine_valeur);
strcat(systeme.cm.chaine_version, "-");
strcat(systeme.cm.chaine_version, chaine_valeur);
//---------------------------------------------------------------
switch (systeme.cm.manufacturer)
{
case 0 : { strcpy(chaine_valeur, "SonyUK"); break; } // Eviter les espaces car moins ces chaines sont utilisées pour remonter la version de Compute Module dans TB_Systeme...
case 1 : { strcpy(chaine_valeur, "Egoman"); break; }
case 2 : { strcpy(chaine_valeur, "Embest"); break; }
case 3 : { strcpy(chaine_valeur, "SonyJapan"); break; }
case 4 : { strcpy(chaine_valeur, "Embest"); break; }
case 5 : { strcpy(chaine_valeur, "Stadium"); break; }
default :
{
sprintf(chaine_valeur, "Inconnu [code = %i]", systeme.cm.manufacturer);
break;
}
}
affichage_ligne_version_compute_module(tmp, "Fabricant", chaine_valeur);
strcat(systeme.cm.chaine_version, "-");
strcat(systeme.cm.chaine_version, chaine_valeur);
//---------------------------------------------------------------
sprintf(chaine_valeur, "%i", systeme.cm.revision);
affichage_ligne_version_compute_module(tmp, "Revision", chaine_valeur);
strcat(systeme.cm.chaine_version, "-Rev");
strcat(systeme.cm.chaine_version, chaine_valeur);
//---------------------------------------------------------------
if (systeme.cm.overvoltage_allowed == 0) strcpy(chaine_valeur, "Allowed");
else strcpy(chaine_valeur, "Forbidden");
affichage_ligne_version_compute_module(tmp, "Overvoltage", chaine_valeur);
strcat(systeme.cm.chaine_version, "-");
if (systeme.cm.overvoltage_allowed == 0) strcat(systeme.cm.chaine_version, "A");
else strcat(systeme.cm.chaine_version, "F");
//---------------------------------------------------------------
if (systeme.cm.otp_programming_allowed == 0) strcpy(chaine_valeur, "Allowed");
else strcpy(chaine_valeur, "Forbidden");
affichage_ligne_version_compute_module(tmp, "OTP Programming", chaine_valeur);
if (systeme.cm.otp_programming_allowed == 0) strcat(systeme.cm.chaine_version, "A");
else strcat(systeme.cm.chaine_version, "F");
//---------------------------------------------------------------
if (systeme.cm.otp_reading_allowed == 0) strcpy(chaine_valeur, "Allowed");
else strcpy(chaine_valeur, "Forbidden");
affichage_ligne_version_compute_module(tmp, "OTP Reading", chaine_valeur);
if (systeme.cm.otp_reading_allowed == 0) strcat(systeme.cm.chaine_version, "A");
else strcat(systeme.cm.chaine_version, "F");
//---------------------------------------------------------------
if (systeme.cm.warranty_bit == 0) strcpy(chaine_valeur, "Intact");
else strcpy(chaine_valeur, "Warranty has been voided by overclocking");
affichage_ligne_version_compute_module(tmp, "Warranty bit", chaine_valeur);
if (systeme.cm.warranty_bit == 0) strcat(systeme.cm.chaine_version, "I");
else strcat(systeme.cm.chaine_version, "V");
//---------------------------------------------------------------
switch (systeme.cm.processor)
{
case 0 : { strcpy(chaine_valeur, "BCM2835"); break; }
case 1 : { strcpy(chaine_valeur, "BCM2836"); break; }
case 2 : { strcpy(chaine_valeur, "BCM2837"); break; }
case 3 : { strcpy(chaine_valeur, "BCM2711"); break; }
case 4 : { strcpy(chaine_valeur, "BCM2712"); break; }
default :
{
sprintf(chaine_valeur, "Inconnu [code = %i]", systeme.cm.processor);
break;
}
}
affichage_ligne_version_compute_module(tmp, "Processeur", chaine_valeur);
//---------------------------------------------------------------
affichage_debug(__FILE__, __LINE__, tmp, TYPE_MESSAGE_DEBUG_OK);
//---------------------------------------------------------------
// Détermination de la génération de ShipBase utilisée :
if (systeme.cm.type == 0x10)
{
systeme.generation_shipbase = GENERATION_SHIPBASE_V1;
affichage_debug(__FILE__, __LINE__, "Génération de ShipBase\t\t\t\t\t\t\t: Première génération", TYPE_MESSAGE_DEBUG_OK);
return 0;
}
else if (systeme.cm.type == 0x14)
{
systeme.generation_shipbase = GENERATION_SHIPBASE_V2;
affichage_debug(__FILE__, __LINE__, "Génération de ShipBase\t\t\t\t\t\t\t: Seconde génération", TYPE_MESSAGE_DEBUG_OK);
return 0;
}
else if (systeme.cm.type == 0x18)
{
systeme.generation_shipbase = GENERATION_SHIPBASE_V3;
affichage_debug(__FILE__, __LINE__, "Génération de ShipBase\t\t\t\t\t\t\t: Troisième génération", TYPE_MESSAGE_DEBUG_OK);
return 0;
}
else
{
systeme.generation_shipbase = GENERATION_SHIPBASE_INCONNUE;
sprintf(tmp, "Génération de ShipBase inconnue [type de Compute Module = %02Xh]. L'initialisation est arrêtée...", systeme.cm.type);
affichage_debug(__FILE__, __LINE__, tmp, TYPE_MESSAGE_DEBUG_ERREUR);
return(-1);
}
}
}
//==================================================================================================================================================================
// Fonction : Met en forme et affiche une ligne de version de comupte module
// Reçoit : Rien
// Renvoit : 0 si aucune erreur, -1 si une erreur a été détectée
//==================================================================================================================================================================
void affichage_ligne_version_compute_module(char * tmp, char * titre, char * valeur)
{
char chaine[MAX_LONGUEUR_BUFFER_TEMPORAIRE_DEBUG];
sprintf(chaine, "\n\t\t\t\t\t\t\t%-20s %s", titre, valeur);
strcat(tmp, chaine);
}